fix conflicts

This commit is contained in:
qyzh 2020-07-23 09:06:24 +08:00
commit 0f5712eb0e
305 changed files with 9652 additions and 35125 deletions

1207
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,7 @@
"dependencies": {
"@monaco-editor/react": "^2.3.0",
"@novnc/novnc": "^1.1.0",
"actioncable": "^5.2.4-3",
"antd": "^3.26.15",
"array-flatten": "^2.1.2",
"autoprefixer": "7.1.6",
@ -84,9 +85,10 @@
"react-hot-loader": "^4.12.20",
"react-infinite-scroller": "^1.2.4",
"react-loadable": "^5.3.1",
"react-monaco-editor": "0.36",
"react-monaco-editor": "0.37",
"react-player": "^1.15.3",
"react-redux": "5.0.7",
"react-resizable": "^1.10.1",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"react-split-pane": "^0.1.91",

View File

@ -538,10 +538,6 @@ a:hover.leftnav-box-inner .btn-cir {
/*右侧头部*/
/*右侧内容*/
.content {
min-width: 1000px;
}
/* tab */
@ -1270,14 +1266,16 @@ a.shixun-task-btn {
/*-------------学员统计 通关排行榜------------*/
/*-----------实训配置、评测脚本-------------*/body {
/*-----------实训配置、评测脚本-------------*/
html body {
font-size: 14px;
line-height: 2.0;
background: #fafafa !important;
background: #fafafa;
font-family: "微软雅黑", "宋体";
color: #05101a;
height: 100%;
position: relative;
padding-right: 0px!important;
}
html,
@ -1568,6 +1566,10 @@ a.edu-txt-w80,
.font-50 {
font-size: 50px !important;
}
.font-80 {
font-size: 80px !important;
}
.color-grey-b{color: #bbb !important}
/*a标签的下划线*/
a.decoration {
@ -1615,7 +1617,7 @@ a.decoration {
}
.mt8 {
margin-top: 8px;
margin-top: 8px !important;
}
.mt9 {
@ -2662,7 +2664,18 @@ a.color-green:hover {
.width89 {
width: 89%;
}
.width50 {
width: 50%;
}
.width40 {
width: 40%;
}
.width45 {
width: 45%;
}
.width10 {
width: 10%;
}
.width20 {
width: 20%;
}
@ -3913,6 +3926,7 @@ html>body #ajax-indicator {
.markdown-body {
text-align: justify;
word-break: break-all;
width:100%;
}
.RightPaneDrawer .ant-drawer-content {
@ -6701,4 +6715,7 @@ ul.count_ul li:not(:last-child):after {
.ant-notification {
z-index: 10001 !important;
}
input.ant-input-lg::placeholder{
font-size: 14px !important;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,244 @@
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "15792809",
"name": "准备中",
"font_class": "zhunbeizhong",
"unicode": "e797",
"unicode_decimal": 59287
},
{
"icon_id": "15792805",
"name": "运行中",
"font_class": "yunhangzhong",
"unicode": "e796",
"unicode_decimal": 59286
},
{
"icon_id": "15792803",
"name": "已通过",
"font_class": "yitongguo",
"unicode": "e795",
"unicode_decimal": 59285
},
{
"icon_id": "15792796",
"name": "未通过",
"font_class": "weitongguo",
"unicode": "e794",
"unicode_decimal": 59284
},
{
"icon_id": "15762732",
"name": "工作流",
"font_class": "gongzuoliu",
"unicode": "e793",
"unicode_decimal": 59283
},
{
"icon_id": "15689245",
"name": "更新成绩",
"font_class": "gengxinchengji",
"unicode": "e790",
"unicode_decimal": 59280
},
{
"icon_id": "15605136",
"name": "文件",
"font_class": "wenjian1",
"unicode": "e78e",
"unicode_decimal": 59278
},
{
"icon_id": "15605133",
"name": "编辑",
"font_class": "bianji6",
"unicode": "e78d",
"unicode_decimal": 59277
},
{
"icon_id": "15591171",
"name": "统计",
"font_class": "tongji2",
"unicode": "e78c",
"unicode_decimal": 59276
},
{
"icon_id": "15591167",
"name": "签到",
"font_class": "qiandao",
"unicode": "e78b",
"unicode_decimal": 59275
},
{
"icon_id": "15591165",
"name": "分班",
"font_class": "fenban1",
"unicode": "e78a",
"unicode_decimal": 59274
},
{
"icon_id": "15591163",
"name": "讨论",
"font_class": "taolun1",
"unicode": "e789",
"unicode_decimal": 59273
},
{
"icon_id": "15591161",
"name": "视频直播",
"font_class": "shipinzhibo",
"unicode": "e788",
"unicode_decimal": 59272
},
{
"icon_id": "15591155",
"name": "学习资源",
"font_class": "xuexiziyuan",
"unicode": "e787",
"unicode_decimal": 59271
},
{
"icon_id": "15591132",
"name": "考试问卷",
"font_class": "kaoshiwenjuan",
"unicode": "e786",
"unicode_decimal": 59270
},
{
"icon_id": "15590984",
"name": "考试试卷",
"font_class": "kaoshishijuan",
"unicode": "e785",
"unicode_decimal": 59269
},
{
"icon_id": "15590922",
"name": "毕业作业",
"font_class": "biyezuoye",
"unicode": "e784",
"unicode_decimal": 59268
},
{
"icon_id": "15590919",
"name": "分组作业",
"font_class": "fenzuzuoye1",
"unicode": "e783",
"unicode_decimal": 59267
},
{
"icon_id": "15590916",
"name": "普通作业",
"font_class": "putongzuoye1",
"unicode": "e782",
"unicode_decimal": 59266
},
{
"icon_id": "15590913",
"name": "实训作业",
"font_class": "shixunzuoye",
"unicode": "e781",
"unicode_decimal": 59265
},
{
"icon_id": "15590860",
"name": "公告栏",
"font_class": "gonggaolan",
"unicode": "e780",
"unicode_decimal": 59264
},
{
"icon_id": "15465934",
"name": "组织项目",
"font_class": "zuzhixiangmu",
"unicode": "e77f",
"unicode_decimal": 59263
},
{
"icon_id": "15465923",
"name": "组织成员",
"font_class": "zuzhichengyuan",
"unicode": "e774",
"unicode_decimal": 59252
},
{
"icon_id": "14332762",
"name": "合并请求",
"font_class": "hebingqingqiu",
"unicode": "e7f2",
"unicode_decimal": 59378
},
{
"icon_id": "15226856",
"name": "实训详情",
"font_class": "shixunxiangqing",
"unicode": "e775",
"unicode_decimal": 59253
},
{
"icon_id": "15226857",
"name": "立即发布",
"font_class": "lijifabu",
"unicode": "e776",
"unicode_decimal": 59254
},
{
"icon_id": "15226858",
"name": "开启中",
"font_class": "kaiqizhong",
"unicode": "e777",
"unicode_decimal": 59255
},
{
"icon_id": "15226859",
"name": "导出",
"font_class": "daochu",
"unicode": "e778",
"unicode_decimal": 59256
},
{
"icon_id": "15226860",
"name": "一键点评",
"font_class": "yijiandianping",
"unicode": "e779",
"unicode_decimal": 59257
},
{
"icon_id": "15226861",
"name": "查看实训报告",
"font_class": "chakanshixunbaogao",
"unicode": "e77a",
"unicode_decimal": 59258
},
{
"icon_id": "15226862",
"name": "提交总结",
"font_class": "tijiaozongjie",
"unicode": "e77b",
"unicode_decimal": 59259
},
{
"icon_id": "15226863",
"name": "代码查重",
"font_class": "daimachazhong",
"unicode": "e77c",
"unicode_decimal": 59260
},
{
"icon_id": "15226864",
"name": "编辑作业",
"font_class": "bianjizuoye",
"unicode": "e77d",
"unicode_decimal": 59261
},
{
"icon_id": "15226865",
"name": "立即截止",
"font_class": "lijijiezhi",
"unicode": "e77e",
"unicode_decimal": 59262
},
{
"icon_id": "15115208",
"name": "镜像",

View File

@ -20,6 +20,108 @@ Created by iconfont
/>
<missing-glyph />
<glyph glyph-name="zhunbeizhong" unicode="&#59287;" d="M512 384m-480 0a480 480 0 1 1 960 0 480 480 0 1 1-960 0ZM512-128c-281.6 0-512 230.4-512 512s230.4 512 512 512 512-230.4 512-512-230.4-512-512-512zM512 832C262.4 832 64 633.6 64 384s198.4-448 448-448 448 198.4 448 448-198.4 448-448 448zM320 384m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM512 384m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM704 384m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0Z" horiz-adv-x="1024" />
<glyph glyph-name="yunhangzhong" unicode="&#59286;" d="M512 384m-480 0a480 480 0 1 1 960 0 480 480 0 1 1-960 0ZM512-128c-281.6 0-512 230.4-512 512s230.4 512 512 512 512-230.4 512-512-230.4-512-512-512zM512 832C262.4 832 64 633.6 64 384s198.4-448 448-448 448 198.4 448 448-198.4 448-448 448zM505.6 640v-313.6h294.4c-19.2-128-134.4-230.4-268.8-230.4-153.6 0-275.2 121.6-275.2 268.8C256 512 364.8 627.2 505.6 640z" horiz-adv-x="1024" />
<glyph glyph-name="yitongguo" unicode="&#59285;" d="M512 384m-480 0a480 480 0 1 1 960 0 480 480 0 1 1-960 0ZM512-128c-281.6 0-512 230.4-512 512s230.4 512 512 512 512-230.4 512-512-230.4-512-512-512zM512 832C262.4 832 64 633.6 64 384s198.4-448 448-448 448 198.4 448 448-198.4 448-448 448zM486.4 172.8c-6.4 0-19.2 6.4-25.6 12.8L294.4 358.4c-12.8 12.8-12.8 32 0 44.8 12.8 12.8 32 12.8 44.8 0L486.4 256l262.4 281.6c12.8 12.8 32 12.8 44.8 0 12.8-12.8 12.8-32 0-44.8L512 185.6c-6.4-6.4-12.8-6.4-25.6-12.8z" horiz-adv-x="1024" />
<glyph glyph-name="weitongguo" unicode="&#59284;" d="M512 384m-480 0a480 480 0 1 1 960 0 480 480 0 1 1-960 0ZM512-128c-281.6 0-512 230.4-512 512s230.4 512 512 512 512-230.4 512-512-230.4-512-512-512zM512 832C262.4 832 64 633.6 64 384s198.4-448 448-448 448 198.4 448 448-198.4 448-448 448zM678.4 172.8L544 332.8l-134.4-160-51.2 38.4L499.2 384 358.4 556.8l51.2 38.4 134.4-160 134.4 160 51.2-38.4L588.8 384l140.8-172.8z" horiz-adv-x="1024" />
<glyph glyph-name="gongzuoliu" unicode="&#59283;" d="M837.270588 600.847059H499.952941C421.647059 600.847059 355.388235 667.105882 355.388235 745.411765 349.364706 829.741176 415.623529 896 499.952941 896H843.294118c78.305882 0 144.564706-66.258824 144.564706-144.564706-6.023529-84.329412-72.282353-150.588235-150.588236-150.588235zM499.952941 805.647059c-30.117647 0-54.211765-24.094118-54.211765-54.211765s24.094118-54.211765 54.211765-54.211765H843.294118c30.117647 0 54.211765 24.094118 54.211764 54.211765s-24.094118 54.211765-54.211764 54.211765H499.952941zM548.141176-128H204.8C126.494118-128 60.235294-61.741176 60.235294 16.564706s66.258824 144.564706 144.564706 144.564706h343.341176c78.305882 0 144.564706-66.258824 144.564706-144.564706S626.447059-128 548.141176-128z m-343.341176 204.8c-30.117647 0-54.211765-24.094118-54.211765-54.211765s24.094118-54.211765 54.211765-54.211764h343.341176c30.117647 0 54.211765 24.094118 54.211765 54.211764s-24.094118 54.211765-54.211765 54.211765H204.8zM903.529412-49.694118h-210.82353v90.352942H903.529412c42.164706 0 72.282353 36.141176 72.282353 72.282352v150.588236c0 42.164706-36.141176 72.282353-72.282353 72.282353H180.705882C90.352941 335.811765 12.047059 408.094118 12.047059 498.447059V655.058824C12.047059 745.411765 84.329412 823.717647 180.705882 823.717647h168.658824v-90.352941H180.705882C138.541176 727.341176 108.423529 697.223529 108.423529 655.058824v-144.564706c0-42.164706 36.141176-72.282353 72.282353-72.282353h722.82353c90.352941 0 168.658824-72.282353 168.658823-162.635294v-150.588236c0-102.4-78.305882-174.682353-168.658823-174.682353zM493.929412 384a120.470588 120.470588 0 1 1 240.941176 0 120.470588 120.470588 0 1 1-240.941176 0Z" horiz-adv-x="1084" />
<glyph glyph-name="gengxinchengji" unicode="&#59280;" d="M768-84.8c-96 0-166.4 70.4-166.4 166.4v25.6l64-6.4v-12.8c0-57.6 44.8-102.4 102.4-102.4 19.2 0 44.8 6.4 57.6 19.2l38.4-57.6c-25.6-25.6-64-32-96-32z m147.2 89.6l-57.6 25.6c6.4 19.2 12.8 32 12.8 51.2 0 57.6-44.8 102.4-102.4 102.4-19.2 0-32-6.4-44.8-12.8l-32 57.6c25.6 12.8 51.2 19.2 76.8 19.2 89.6 0 166.4-76.8 166.4-166.4 0-25.6-6.4-57.6-19.2-76.8zM633.6 158.4l57.6-76.8H569.6zM908.8-14.4l64 76.8h-128zM544-57.6H64V864h537.6L864 601.6v-275.2h-64V576L576 800h-448v-793.6H544zM243.2 614.4h198.4v-64H243.2zM242.624 438.08l383.936 6.976 1.152-64-383.936-6.912zM243.2 275.2h326.4v-64H243.2zM857.6 550.4h-320l6.4 320 313.6-320z m-256 64h102.4L601.6 716.8v-102.4z" horiz-adv-x="1024" />
<glyph glyph-name="wenjian1" unicode="&#59278;" d="M574.330435-119.095652H151.373913c-44.521739 0-84.591304 40.069565-84.591304 84.591304V811.408696C66.782609 855.930435 106.852174 896 151.373913 896h681.182609c44.521739 0 84.591304-40.069565 84.591304-84.591304v-436.313044c0-26.713043-17.808696-44.521739-44.521739-44.521739s-44.521739 17.808696-44.521739 44.521739V806.956522H155.826087v-837.008696h418.504348c26.713043 0 44.521739-17.808696 44.521739-44.521739s-22.26087-44.521739-44.521739-44.521739zM249.321739 410.713043h471.930435v-66.782608H249.321739zM512 148.034783m-44.521739 0a44.521739 44.521739 0 1 1 89.043478 0 44.521739 44.521739 0 1 1-89.043478 0ZM690.086957 148.034783m-44.52174 0a44.521739 44.521739 0 1 1 89.043479 0 44.521739 44.521739 0 1 1-89.043479 0ZM850.365217 148.034783m-44.521739 0a44.521739 44.521739 0 1 1 89.043479 0 44.521739 44.521739 0 1 1-89.043479 0ZM249.321739 655.582609h471.930435v-66.782609H249.321739zM249.321739 188.104348h146.921739v-66.782609H249.321739z" horiz-adv-x="1024" />
<glyph glyph-name="bianji6" unicode="&#59277;" d="M803.044865-97.363698H154.576481c-86.802855 0-153.181508 66.378654-153.181508 153.181508V740.028546c0 86.802855 66.378654 153.181508 153.181508 153.181508h403.377971c30.636302 0 51.060503-20.424201 51.060503-51.060503s-20.424201-51.060503-51.060503-51.060502H154.576481c-30.636302 0-51.060503-20.424201-51.060503-51.060503v-684.210736c0-30.636302 20.424201-51.060503 51.060503-51.060503h648.468384c30.636302 0 51.060503 20.424201 51.060503 51.060503V438.77158c0 30.636302 20.424201 51.060503 51.060503 51.060503s51.060503-20.424201 51.060503-51.060503v-382.95377c0-86.802855-71.484704-153.181508-153.181509-153.181508zM476.257648 362.180826c-10.212101 0-25.530251 5.10605-35.742352 20.424201-20.424201 20.424201-15.318151 51.060503 5.10605 71.484704L930.696122 882.997954c20.424201 20.424201 51.060503 15.318151 71.484704-5.106051 20.424201-20.424201 15.318151-51.060503-5.10605-71.484703L512 377.498977c-10.212101-10.212101-20.424201-15.318151-35.742352-15.318151z" horiz-adv-x="1024" />
<glyph glyph-name="tongji2" unicode="&#59276;" d="M9.142857 896h1024v-1024H9.142857zM873.142857 377.6H514.742857V736c0 6.4-6.4 6.4-6.4 6.4h-25.6c-51.2 0-108.8-12.8-153.6-32-51.2-19.2-96-44.8-128-83.2S137.142857 550.4 117.942857 499.2C92.342857 448 79.542857 396.8 79.542857 345.6S92.342857 236.8 111.542857 192s51.2-89.6 83.2-128 76.8-64 128-83.2c51.2-19.2 102.4-32 153.6-32s108.8 12.8 153.6 32 89.6 51.2 128 83.2c38.4 38.4 64 76.8 83.2 128 19.2 51.2 32 102.4 32 153.6v25.6c6.4 6.4 6.4 6.4 0 6.4zM713.142857 108.8c-64-64-147.2-96-236.8-96-89.6 0-172.8 32-230.4 96-64 64-96 147.2-96 236.8S181.942857 518.4 245.942857 576c57.6 57.6 128 89.6 198.4 96v-364.8h364.8c-6.4-70.4-38.4-147.2-96-198.4z m249.6 326.4v25.6C949.942857 556.8 911.542857 640 841.142857 704 777.142857 768 687.542857 812.8 597.942857 819.2h-25.6c-6.4 0-6.4 0-6.4-6.4v-384c0-6.4 6.4-6.4 6.4-6.4h384s6.4 6.4 6.4 12.8z m-332.8 57.6v256c64-12.8 121.6-44.8 166.4-89.6s76.8-102.4 89.6-166.4h-256z" horiz-adv-x="1170" />
<glyph glyph-name="qiandao" unicode="&#59275;" d="M9.142857 896h1024v-1024H9.142857zM892.342857 710.4h-166.4v64c0 6.4-6.4 6.4-6.4 6.4h-57.6c-6.4 0-6.4-6.4-6.4-6.4v-64H393.142857v64c0 6.4-6.4 6.4-6.4 6.4H329.142857c-6.4 0-6.4-6.4-6.4-6.4v-64H149.942857c-12.8 0-25.6-12.8-25.6-32v-665.6c0-19.2 12.8-32 32-32h736c19.2 0 32 12.8 32 32V678.4c-6.4 19.2-19.2 32-32 32z m-44.8-652.8H194.742857V640h128v-51.2c0-6.4 6.4-6.4 6.4-6.4h57.6l6.4 6.4V640h256v-51.2c0-6.4 6.4-6.4 6.4-6.4h57.6c6.4 0 6.4 6.4 6.4 6.4V640h128v-582.4zM700.342857 473.6h-57.6c-6.4 0-12.8 0-12.8-6.4L476.342857 262.4l-64 89.6c0 6.4-6.4 6.4-12.8 6.4h-57.6c-6.4 0-12.8-6.4-6.4-12.8l128-172.8c6.4-6.4 19.2-6.4 25.6 0l211.2 294.4c6.4 0 6.4 6.4 0 6.4z" horiz-adv-x="1170" />
<glyph glyph-name="fenban1" unicode="&#59274;" d="M9.142857 896h1024v-1024H9.142857zM834.742857 198.4c-25.6 25.6-57.6 44.8-89.6 57.6 44.8 38.4 76.8 89.6 76.8 153.6 0 108.8-89.6 204.8-204.8 198.4-108.8 0-198.4-89.6-198.4-198.4 0-64 32-121.6 76.8-153.6-32-12.8-64-32-83.2-57.6-57.6-57.6-83.2-128-89.6-204.8 0-6.4 6.4-6.4 6.4-6.4h57.6c6.4 0 6.4 6.4 6.4 6.4 0 57.6 25.6 115.2 64 153.6 44.8 44.8 102.4 64 160 64s115.2-25.6 160-64c38.4-38.4 64-96 64-153.6 0-6.4 6.4-6.4 6.4-6.4h57.6c6.4 0 6.4 6.4 6.4 6.4 6.4 76.8-25.6 147.2-76.8 204.8zM623.542857 281.6c-38.4 0-70.4 12.8-96 38.4-19.2 25.6-32 57.6-32 96 0 32 12.8 64 38.4 89.6 19.2 19.2 51.2 32 83.2 32s64-12.8 89.6-38.4c25.6-25.6 38.4-57.6 38.4-89.6 0-32-12.8-64-38.4-89.6-19.2-25.6-51.2-38.4-83.2-38.4zM367.542857 384v25.6c0 12.8 0 32 6.4 44.8 0 6.4 0 6.4-6.4 6.4-12.8 12.8-25.6 19.2-38.4 32-25.6 25.6-38.4 57.6-38.4 96 0 32 12.8 64 38.4 83.2 25.6 25.6 57.6 38.4 96 38.4 32 0 64-12.8 83.2-32 6.4-6.4 12.8-19.2 19.2-25.6 0 0 6.4-6.4 6.4 0 19.2 6.4 38.4 12.8 57.6 12.8 6.4 0 6.4 6.4 6.4 12.8C565.942857 742.4 501.942857 787.2 425.142857 787.2 316.342857 787.2 220.342857 697.6 220.342857 588.8c0-64 32-121.6 76.8-153.6-32-19.2-64-38.4-89.6-64-57.6-57.6-83.2-128-89.6-204.8 0-6.4 6.4-6.4 6.4-6.4h57.6c6.4 0 6.4 6.4 6.4 6.4 0 57.6 25.6 115.2 64 153.6 32 32 64 51.2 102.4 57.6 12.8 0 19.2 6.4 12.8 6.4z" horiz-adv-x="1170" />
<glyph glyph-name="taolun1" unicode="&#59273;" d="M9.142857 896h1024v-1024H9.142857zM469.942857 384c0-25.6 19.2-51.2 51.2-51.2 25.6 0 51.2 19.2 51.2 51.2 0 25.6-19.2 51.2-51.2 51.2-25.6 0-51.2-25.6-51.2-51.2z m204.8 0c0-25.6 19.2-51.2 51.2-51.2s51.2 19.2 51.2 51.2c0 25.6-19.2 51.2-51.2 51.2s-51.2-25.6-51.2-51.2zM271.542857 384c0-25.6 19.2-51.2 51.2-51.2s44.8 25.6 44.8 51.2-19.2 51.2-51.2 51.2-44.8-25.6-44.8-51.2z m665.6 172.8c-25.6 57.6-57.6 102.4-96 147.2-38.4 38.4-89.6 76.8-140.8 96C642.742857 819.2 578.742857 832 521.142857 832 457.142857 832 399.542857 819.2 341.942857 793.6c-51.2-19.2-96-51.2-140.8-96S130.742857 608 105.142857 556.8C85.942857 499.2 73.142857 441.6 73.142857 384c0-70.4 19.2-140.8 51.2-198.4v-153.6c0-25.6 19.2-44.8 44.8-44.8h153.6c64-32 128-44.8 198.4-51.2 57.6 0 115.2 12.8 172.8 32 51.2 19.2 102.4 51.2 140.8 96 38.4 38.4 76.8 89.6 96 140.8 25.6 57.6 38.4 115.2 38.4 179.2 0 57.6-12.8 115.2-32 172.8z m-153.6-435.2C713.142857 51.2 617.142857 12.8 521.142857 12.8c-57.6 0-121.6 12.8-172.8 44.8l-6.4 6.4H194.742857V204.8l-6.4 6.4C162.742857 262.4 149.942857 320 149.942857 384c0 102.4 38.4 192 108.8 262.4C329.142857 716.8 418.742857 755.2 521.142857 755.2c51.2 0 96-12.8 147.2-32 44.8-19.2 83.2-44.8 121.6-76.8 32-32 64-76.8 76.8-121.6 19.2-44.8 32-96 32-147.2-6.4-96-44.8-185.6-115.2-256z" horiz-adv-x="1170" />
<glyph glyph-name="shipinzhibo" unicode="&#59272;" d="M21.333333 896h1024v-1024H21.333333zM930.133333 595.2l-128-76.8V672c0 38.4-25.6 64-64 64H149.333333c-38.4 0-64-25.6-64-64v-576c0-38.4 25.6-64 64-64h588.8c38.4 0 64 25.6 64 64V249.6l128-76.8c19.2-12.8 51.2 0 51.2 25.6V563.2c0 25.6-25.6 44.8-51.2 32z m-198.4-492.8h-576V665.6h576v-563.2z m179.2 166.4l-102.4 57.6V435.2l102.4 57.6v-224zM226.133333 537.6H341.333333c6.4 0 6.4 6.4 6.4 6.4v44.8c0 6.4-6.4 6.4-6.4 6.4H226.133333c-6.4 0-6.4-6.4-6.4-6.4v-51.2h6.4z" horiz-adv-x="1365" />
<glyph glyph-name="xuexiziyuan" unicode="&#59271;" d="M9.142857 896h1024v-1024H9.142857zM969.142857-19.2H73.142857V780.8h332.8l128-128c6.4-6.4 12.8-6.4 25.6-6.4H969.142857v-665.6zM143.542857 57.6h755.2V576H559.542857c-25.6 0-51.2 6.4-76.8 25.6L373.942857 710.4H143.542857v-652.8zM834.742857 710.4h-256c-19.2 0-38.4 19.2-38.4 38.4s19.2 38.4 38.4 38.4h256c19.2 0 38.4-19.2 38.4-38.4s-19.2-38.4-38.4-38.4zM937.142857 403.2H117.942857c-19.2 0-38.4 19.2-38.4 38.4s19.2 38.4 38.4 38.4h819.2c19.2 0 38.4-19.2 38.4-38.4s-19.2-38.4-38.4-38.4zM431.542857 121.6H245.942857c-19.2 0-38.4 19.2-38.4 38.4s19.2 32 38.4 32h185.6c19.2 0 38.4-19.2 38.4-38.4s-19.2-32-38.4-32z" horiz-adv-x="1170" />
<glyph glyph-name="kaoshiwenjuan" unicode="&#59270;" d="M18.285714 896h1024v-1024H18.285714zM709.485714 582.4v51.2c0 6.4-6.4 6.4-6.4 6.4h-384c-6.4 0-12.8-6.4-12.8-6.4v-51.2l6.4-6.4h384c6.4 0 12.8 6.4 12.8 6.4zM312.685714 499.2c-6.4 0-6.4-6.4-6.4-6.4v-51.2c0-6.4 6.4-6.4 6.4-6.4h185.6c6.4 0 6.4 6.4 6.4 6.4v44.8c0 6.4-6.4 6.4-6.4 6.4H312.685714z m147.2-454.4H223.085714v704H786.285714v-345.6c0-6.4 6.4-6.4 6.4-6.4h57.6c6.4 0 6.4 6.4 6.4 6.4v384c0 19.2-12.8 32-32 32H184.685714C165.485714 819.2 152.685714 806.4 152.685714 787.2v-780.8c0-19.2 12.8-32 32-32h268.8c6.4 0 6.4 6.4 6.4 6.4v57.6c6.4 0 0 6.4 0 6.4z m441.6-51.2l-96 96c19.2 32 38.4 64 38.4 108.8 0 96-76.8 179.2-179.2 179.2S491.885714 288 491.885714 192s76.8-179.2 179.2-179.2c38.4 0 70.4 12.8 96 32l96-96h12.8l32 32c0 6.4 0 6.4-6.4 12.8z m-230.4 83.2c-64 0-115.2 51.2-115.2 115.2s51.2 115.2 115.2 115.2S786.285714 256 786.285714 192s-51.2-115.2-115.2-115.2z" horiz-adv-x="1170" />
<glyph glyph-name="kaoshishijuan" unicode="&#59269;" d="M18.285714 896h1024v-1024H18.285714zM709.485714 633.6c0 6.4-6.4 6.4-6.4 6.4h-384c-6.4 0-12.8-6.4-12.8-6.4v-51.2l6.4-6.4h384c6.4 0 6.4 6.4 6.4 6.4v51.2z m-12.8-134.4h-384c-6.4 0-6.4-6.4-6.4-6.4v-51.2c0-6.4 6.4-6.4 6.4-6.4h384c6.4 0 6.4 6.4 6.4 6.4v44.8c6.4 6.4 0 12.8-6.4 12.8zM498.285714 352H312.685714c-6.4 0-6.4-6.4-6.4-6.4v-51.2c0-6.4 6.4-6.4 6.4-6.4h185.6c6.4 0 6.4 6.4 6.4 6.4v51.2s0 6.4-6.4 6.4z m-44.8-307.2H223.085714v704H786.285714v-345.6c0-6.4 6.4-6.4 6.4-6.4h57.6c6.4 0 6.4 6.4 6.4 6.4v384c0 19.2-12.8 32-32 32H184.685714C165.485714 819.2 152.685714 806.4 152.685714 787.2v-780.8c0-19.2 12.8-32 32-32h262.4c6.4 0 6.4 6.4 6.4 6.4v57.6c6.4 0 0 6.4 0 6.4z m352 76.8c32 25.6 44.8 64 44.8 108.8 0 76.8-64 140.8-140.8 140.8s-140.8-64-140.8-140.8c0-44.8 19.2-83.2 44.8-108.8-57.6-32-96-89.6-102.4-160 0-6.4 6.4-6.4 6.4-6.4h51.2c6.4 0 6.4 6.4 6.4 6.4 6.4 70.4 64 121.6 134.4 121.6s128-57.6 134.4-121.6c0-6.4 6.4-6.4 6.4-6.4h51.2c6.4 0 6.4 6.4 6.4 6.4-6.4 64-44.8 121.6-102.4 160zM709.485714 307.2c44.8 0 76.8-38.4 76.8-76.8s-38.4-76.8-76.8-76.8-76.8 38.4-76.8 76.8 32 76.8 76.8 76.8z" horiz-adv-x="1170" />
<glyph glyph-name="biyezuoye" unicode="&#59268;" d="M9.142857 896h1024v-1024H9.142857zM521.142857 326.4c-12.8 0-19.2 0-32 6.4L111.542857 518.4c-12.8 6.4-25.6 19.2-32 38.4-6.4 19.2-6.4 38.4 0 51.2 6.4 12.8 19.2 25.6 32 32l377.6 185.6c19.2 6.4 44.8 6.4 64 0L930.742857 640c32-19.2 44.8-57.6 32-89.6-6.4-12.8-19.2-25.6-32-32L553.142857 332.8c-12.8 0-19.2-6.4-32-6.4z m-371.2 256L521.142857 403.2l371.2 179.2L521.142857 761.6 149.942857 582.4zM783.542857 121.6c-12.8 6.4-19.2 12.8-38.4 12.8s-32 12.8-32 32 12.8 32 32 32c70.4 0 128-57.6 128-121.6 0-19.2-12.8-32-32-32s-32 12.8-32 32c0 12.8-6.4 32-12.8 38.4 0-6.4-6.4-19.2-12.8-32-64-89.6-160-147.2-275.2-147.2-115.2 0-211.2 57.6-268.8 140.8-19.2 25.6-12.8 57.6 0 44.8 70.4-57.6 166.4-102.4 268.8-102.4 108.8 0 204.8 44.8 275.2 102.4zM130.742857 217.6m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM105.142857 544h57.6v-326.4h-57.6z" horiz-adv-x="1170" />
<glyph glyph-name="fenzuzuoye1" unicode="&#59267;" d="M21.333333 896h1024v-1024H21.333333zM949.333333 736H718.933333c-51.2 0-96-12.8-140.8-38.4l-44.8-32-51.2 25.6C443.733333 723.2 392.533333 736 347.733333 736H117.333333C98.133333 736 85.333333 723.2 85.333333 704v-569.6c0-19.2 12.8-32 32-32h230.4c51.2 0 96-12.8 140.8-38.4l44.8-25.6h12.8l38.4 25.6c38.4 25.6 89.6 38.4 140.8 38.4h230.4c19.2 0 32 12.8 32 32V704c-6.4 19.2-19.2 32-38.4 32zM347.733333 172.8h-192V665.6H341.333333c38.4 0 70.4-12.8 102.4-32l51.2-32 6.4-6.4v-460.8c-44.8 25.6-102.4 38.4-153.6 38.4z m563.2 0H725.333333c-57.6 0-108.8-12.8-153.6-38.4V595.2l6.4 6.4 51.2 32c32 19.2 64 32 102.4 32H917.333333v-492.8zM418.133333 537.6H232.533333c-6.4 0-6.4-6.4-6.4-6.4v-44.8c0-6.4 0-6.4 6.4-6.4h185.6c6.4 0 6.4 6.4 6.4 6.4v38.4c0 6.4 0 12.8-6.4 12.8z m224-12.8v-44.8c0-6.4 6.4-6.4 6.4-6.4h185.6c6.4 0 6.4 6.4 6.4 6.4v44.8c0 6.4-6.4 6.4-6.4 6.4H648.533333c-6.4 6.4-6.4 0-6.4-6.4z m-224-128H232.533333c-6.4 0-6.4-6.4-6.4-6.4v-44.8c0-6.4 0-6.4 6.4-6.4h185.6c6.4 0 6.4 6.4 6.4 6.4v44.8s0 6.4-6.4 6.4z m416 0H648.533333c-6.4 0-6.4-6.4-6.4-6.4v-44.8c0-6.4 6.4-6.4 6.4-6.4h185.6c6.4 0 6.4 6.4 6.4 6.4v44.8s0 6.4-6.4 6.4z" horiz-adv-x="1365" />
<glyph glyph-name="putongzuoye1" unicode="&#59266;" d="M4.266667 896h1024v-1024H4.266667zM650.666667 832v-70.4h-512v-755.2h652.8v320h70.4v-358.4c0-19.2-12.8-32-32-32H100.266667c-19.2 0-32 12.8-32 32v832c0 19.2 12.8 32 32 32h550.4zM420.266667 454.4H260.266667c-19.2 0-38.4 19.2-38.4 38.4s19.2 32 38.4 32h160c19.2 0 32-12.8 32-32s-12.8-38.4-32-38.4zM516.266667 601.6H260.266667c-19.2 0-38.4 19.2-38.4 38.4s19.2 32 38.4 32h256c19.2 0 38.4-19.2 38.4-38.4s-19.2-32-38.4-32zM714.666667 89.6H260.266667c-19.2 0-38.4 19.2-38.4 38.4s19.2 38.4 38.4 38.4h454.4c19.2 0 38.4-19.2 38.4-38.4s-19.2-38.4-38.4-38.4zM522.666667 185.6c-25.6 0-51.2 19.2-64 44.8-6.4 12.8-6.4 19.2-6.4 32l12.8 134.4c0 12.8 6.4 25.6 12.8 32l236.8 345.6c19.2 32 51.2 51.2 89.6 57.6 38.4 6.4 70.4 0 102.4-19.2l12.8-6.4c57.6-44.8 70.4-128 32-185.6L708.266667 268.8c-6.4-12.8-19.2-19.2-32-25.6l-134.4-51.2c-6.4 0-12.8-6.4-19.2-6.4z m300.8 576h-12.8c-19.2 0-32-12.8-38.4-25.6L535.466667 390.4l-6.4-128L644.266667 307.2l243.2 345.6c19.2 25.6 12.8 64-12.8 89.6l-6.4 6.4 19.2 25.6-25.6-25.6c-12.8 6.4-25.6 12.8-38.4 12.8z" horiz-adv-x="1092" />
<glyph glyph-name="shixunzuoye" unicode="&#59265;" d="M4.266667 896h1024v-1024H4.266667zM964.266667 128H68.266667V832h896v-704zM138.666667 204.8h755.2V761.6H138.666667v-556.8zM708.266667-64H324.266667c-19.2 0-38.4 19.2-38.4 38.4s19.2 38.4 38.4 38.4h384c19.2 0 38.4-19.2 38.4-38.4s-19.2-38.4-38.4-38.4zM708.266667 403.2c-12.8 0-19.2 6.4-25.6 12.8-12.8 12.8-12.8 38.4 6.4 51.2L772.266667 544 682.666667 620.8c-12.8 12.8-12.8 38.4 0 51.2 12.8 12.8 38.4 12.8 51.2 0l89.6-83.2c12.8-12.8 19.2-32 19.2-44.8 0-19.2-6.4-38.4-19.2-51.2l-6.4-6.4-83.2-76.8c-12.8 0-19.2-6.4-25.6-6.4zM330.666667 403.2c-6.4 0-19.2 0-25.6 6.4L215.466667 492.8c-25.6 25.6-25.6 70.4 0 96l89.6 83.2c12.8 12.8 38.4 12.8 51.2 0 12.8-12.8 12.8-38.4 0-51.2L266.666667 537.6l83.2-70.4c12.8-12.8 19.2-38.4 6.4-51.2-6.4-6.4-19.2-12.8-25.6-12.8zM465.066667 384H452.266667c-19.2 12.8-25.6 32-19.2 51.2l102.4 243.2c6.4 19.2 25.6 32 44.8 19.2 19.2-6.4 25.6-25.6 19.2-44.8L503.466667 409.6c-6.4-12.8-19.2-25.6-38.4-25.6zM925.866667 256H119.466667c-19.2 0-38.4 19.2-38.4 38.4s19.2 38.4 38.4 38.4h800c19.2 0 38.4-19.2 38.4-38.4s-12.8-38.4-32-38.4zM401.066667 160h70.4V-64H401.066667zM586.666667 160h70.4V-64H586.666667z" horiz-adv-x="1092" />
<glyph glyph-name="gonggaolan" unicode="&#59264;" d="M870.4-119.466667L426.666667 153.6c-8.533333 0-17.066667 8.533333-25.6 8.533333H0V614.4h409.6c8.533333 0 17.066667 0 25.6 8.533333L870.4 887.466667v-1006.933334zM93.866667 256h307.2c25.6 0 51.2-8.533333 68.266666-17.066667l307.2-187.733333V716.8L486.4 537.6c-25.6-17.066667-51.2-25.6-76.8-25.6H93.866667v-256zM998.4 699.733333c-17.066667 0-42.666667 17.066667-42.666667 34.133334-8.533333 25.6 8.533333 51.2 34.133334 59.733333l153.6 42.666667c25.6 8.533333 51.2-8.533333 59.733333-34.133334 8.533333-25.6-8.533333-51.2-34.133333-59.733333l-153.6-42.666667h-17.066667zM1152-59.733333h-8.533333l-153.6 42.666666c-25.6 8.533333-42.666667 34.133333-34.133334 59.733334 8.533333 25.6 34.133333 42.666667 59.733334 34.133333l153.6-42.666667c25.6-8.533333 42.666667-34.133333 34.133333-59.733333-17.066667-17.066667-34.133333-34.133333-51.2-34.133333zM1152 332.8h-153.6c-25.6 0-51.2 25.6-51.2 51.2s25.6 51.2 51.2 51.2h153.6c25.6 0 42.666667-25.6 42.666667-51.2s-17.066667-51.2-42.666667-51.2zM375.466667 554.666667h93.866666v-349.866667H375.466667z" horiz-adv-x="1205" />
<glyph glyph-name="zuzhixiangmu" unicode="&#59263;" d="M487.619048-128c-243.809524 0-438.857143 195.047619-438.857143 438.857143s195.047619 438.857143 438.857143 438.857143 438.857143-195.047619 438.857142-438.857143-195.047619-438.857143-438.857142-438.857143z m0 799.695238c-199.92381 0-360.838095-160.914286-360.838096-360.838095 0-199.92381 160.914286-360.838095 360.838096-360.838095 199.92381 0 360.838095 160.914286 360.838095 360.838095 0 199.92381-160.914286 360.838095-360.838095 360.838095zM195.047619 67.047619m-156.038095 0a156.038095 156.038095 0 1 1 312.07619 0 156.038095 156.038095 0 1 1-312.07619 0ZM195.047619-128c-107.27619 0-195.047619 87.771429-195.047619 195.047619s87.771429 195.047619 195.047619 195.047619 195.047619-87.771429 195.047619-195.047619-87.771429-195.047619-195.047619-195.047619z m0 312.07619c-63.390476 0-117.028571-53.638095-117.028571-117.028571s53.638095-117.028571 117.028571-117.028571 117.028571 53.638095 117.028571 117.028571-53.638095 117.028571-117.028571 117.028571zM390.095238 700.952381m-156.038095 0a156.038095 156.038095 0 1 1 312.07619 0 156.038095 156.038095 0 1 1-312.07619 0ZM390.095238 505.904762C282.819048 505.904762 195.047619 593.67619 195.047619 700.952381s87.771429 195.047619 195.047619 195.047619 195.047619-87.771429 195.047619-195.047619-87.771429-195.047619-195.047619-195.047619z m0 312.07619C326.704762 817.980952 273.066667 764.342857 273.066667 700.952381S326.704762 583.92381 390.095238 583.92381s117.028571 53.638095 117.028572 117.028571S453.485714 817.980952 390.095238 817.980952zM926.47619 310.857143m-156.038095 0a156.038095 156.038095 0 1 1 312.076191 0 156.038095 156.038095 0 1 1-312.076191 0ZM926.47619 115.809524c-107.27619 0-195.047619 87.771429-195.047619 195.047619s87.771429 195.047619 195.047619 195.047619 195.047619-87.771429 195.04762-195.047619-87.771429-195.047619-195.04762-195.047619z m0 312.07619c-63.390476 0-117.028571-53.638095-117.028571-117.028571s53.638095-117.028571 117.028571-117.028572 117.028571 53.638095 117.028572 117.028572-53.638095 117.028571-117.028572 117.028571z" horiz-adv-x="1121" />
<glyph glyph-name="zuzhichengyuan" unicode="&#59252;" d="M1029.389474-117.221053H231.747368c-70.063158 0-123.957895 53.894737-123.957894 123.957895v102.4h86.231579v-102.4c0-21.557895 16.168421-37.726316 37.726315-37.726316h797.642106c21.557895 0 37.726316 16.168421 37.726315 37.726316v754.526316c0 21.557895-16.168421 37.726316-37.726315 37.726316H231.747368c-16.168421 0-32.336842-16.168421-32.336842-37.726316v-199.410526H113.178947V761.263158c0 70.063158 53.894737 123.957895 123.957895 123.957895h797.642105c70.063158 0 123.957895-53.894737 123.957895-123.957895v-759.91579c-5.389474-64.673684-59.284211-118.568421-129.347368-118.568421zM635.742316 305.152c-102.4 0-188.631579 86.231579-188.631579 188.631579s86.231579 188.631579 188.631579 188.631579 188.631579-86.231579 188.631579-188.631579-86.231579-188.631579-188.631579-188.631579z m0 291.031579c-53.894737 0-102.4-48.505263-102.4-102.4 0-53.894737 48.505263-102.4 102.4-102.4 53.894737 0 102.4 48.505263 102.4 102.4 0 53.894737-48.505263 102.4-102.4 102.4zM872.879158 78.794105c-21.557895 0-43.115789 21.557895-43.11579 43.11579 0 107.789474-86.231579 194.021053-194.021052 194.021052s-194.021053-86.231579-194.021053-194.021052c0-21.557895-21.557895-43.115789-43.115789-43.11579s-43.115789 21.557895-43.11579 43.11579c0 156.294737 129.347368 280.252632 280.252632 280.252631 156.294737 0 280.252632-129.347368 280.252631-280.252631 0-26.947368-21.557895-43.115789-43.115789-43.11579zM231.747368 518.736842h-161.68421c-21.557895 0-43.115789 21.557895-43.11579 43.11579s21.557895 43.115789 43.11579 43.115789h161.68421c21.557895 0 43.115789-21.557895 43.11579-43.115789s-16.168421-43.115789-43.11579-43.11579zM231.747368 82.189474h-161.68421c-21.557895 0-43.115789 21.557895-43.11579 43.115789s21.557895 43.115789 43.11579 43.11579h161.68421c21.557895 0 43.115789-21.557895 43.11579-43.11579s-16.168421-43.115789-43.11579-43.115789zM231.747368 319.326316h-161.68421c-21.557895 0-43.115789 21.557895-43.11579 43.115789s21.557895 43.115789 43.11579 43.11579h161.68421c21.557895 0 43.115789-21.557895 43.11579-43.11579s-16.168421-43.115789-43.11579-43.115789z" horiz-adv-x="1185" />
<glyph glyph-name="hebingqingqiu" unicode="&#59378;" d="M224 832c88.366 0 160-71.634 160-160 0-75.987-52.97-139.602-124-155.934v-264.132C331.03 235.602 384 171.987 384 96c0-88.366-71.634-160-160-160S64 7.634 64 96c0 75.987 52.97 139.602 124 155.934V516.066C116.97 532.398 64 596.013 64 672c0 88.366 71.634 160 160 160z m0-648c-48.601 0-88-39.399-88-88s39.399-88 88-88 88 39.399 88 88-39.399 88-88 88z m0 576c-48.601 0-88-39.399-88-88s39.399-88 88-88 88 39.399 88 88-39.399 88-88 88z m416-232.855c0-11.046-8.954-20-20-20a20 20 0 0 0-12.925 4.737L436.023 656.737c-8.43 7.139-9.476 19.759-2.338 28.188a20 20 0 0 0 2.338 2.338L607.075 832.118c8.43 7.138 21.05 6.091 28.188-2.338A20 20 0 0 0 640 816.855V708h68c69.986 0 126.853-56.167 127.983-125.883L836 580v-328.066C907.03 235.602 960 171.987 960 96c0-88.366-71.634-160-160-160s-160 71.634-160 160c0 75.987 52.97 139.602 124 155.934V580c0 30.619-24.573 55.498-55.074 55.992L708 636h-68v-108.855zM800 184c-48.601 0-88-39.399-88-88s39.399-88 88-88 88 39.399 88 88-39.399 88-88 88z" horiz-adv-x="1024" />
<glyph glyph-name="shixunxiangqing" unicode="&#59253;" d="M928.036571 832c17.627429 0 31.963429-14.336 31.963429-32.036571v-636.928a31.963429 31.963429 0 0 0-32.036571-32.036572l-272.822858 0.073143v-126.171429h47.835429a35.986286 35.986286 0 0 0 6.509714-71.460571l-6.509714-0.585143H322.998857a35.986286 35.986286 0 0 0-6.436571 71.387429l6.436571 0.585143 74.093714 0.073142v126.171429l-301.129142-0.073143a31.963429 31.963429 0 0 0-31.963429 32.036572V800.036571c0 17.627429 14.336 31.963429 32.036571 31.963429h831.926858zM583.021714 4.9005710000000136v126.171429H469.138286v-126.171429h113.956571z m304.859429 248.978286H135.972571v-50.834286H887.954286v50.834286z m0 506.148572H135.972571v-434.176H887.954286V760.027429z m-310.125714-60.269715c16.237714-6.729143 25.014857-24.137143 21.357714-40.813714l-1.901714-6.217143-101.010286-244.004571a35.986286 35.986286 0 0 0-68.461714 21.357714l1.901714 6.217143L530.724571 680.228571a35.986286 35.986286 0 0 0 47.030858 19.456z m114.541714-29.184a35.986286 35.986286 0 0 0 50.907428 1.682286l86.674286-81.188571 5.851429-6.217143a68.022857 68.022857 0 0 0-2.706286-89.965715c-2.267429-2.340571-2.267429-2.340571-4.754286-4.608l-85.942857-75.337142-5.266286-3.803429a35.986286 35.986286 0 0 0-45.568 7.094857l-3.803428 5.266286a35.986286 35.986286 0 0 0 7.168 45.568l82.651428 72.484571-83.529142 78.189715-4.388572 4.827428a35.986286 35.986286 0 0 0 2.706286 46.08z m-342.601143 0a35.986286 35.986286 0 0 0 2.633143-46.006857l-4.315429-4.827428-83.529143-78.189715 82.651429-72.411428c13.312-11.702857 15.945143-31.012571 7.168-45.641143l-3.803429-5.266286a35.986286 35.986286 0 0 0-45.568-7.094857l-5.266285 3.803429-87.771429 77.019428-2.925714 2.925714a68.022857 68.022857 0 0 0-2.706286 89.965715l5.851429 6.217143 86.674285 81.188571a35.986286 35.986286 0 0 0 50.907429-1.682286z" horiz-adv-x="1024" />
<glyph glyph-name="lijifabu" unicode="&#59254;" d="M846.375385 822.902154a70.262154 70.262154 0 0 0 98.067692-73.255385l-1.890462-9.452307-188.022153-691.357539a70.262154 70.262154 0 0 0-100.43077-43.795692l-6.537846 3.938461-107.047384 71.837539-51.751385-134.537846a70.262154 70.262154 0 0 0-82.471385-42.929231l-8.428307 2.599384a70.262154 70.262154 0 0 0-44.347077 56.083693l-0.630154 9.452307V239.852308c0 18.904615 7.640615 37.021538 20.952615 50.09723l7.089231 6.144 303.261538 227.485539a37.179077 37.179077 0 0 0 49.624616-55.059692l-4.962462-4.489847-301.607384-226.146461v-244.105846l45.686154 118.626461a70.262154 70.262154 0 0 0 3.308307 7.168l3.938462 6.774154a70.262154 70.262154 0 0 0 89.954461 23.630769l7.561846-4.489846 106.496-71.364923 184.241231 677.415385L137.058462 428.268308l131.623384-84.519385c15.36-9.846154 21.031385-29.144615 14.336-45.449846l-3.150769-5.907692a37.179077 37.179077 0 0 0-45.449846-14.336l-5.907693 3.150769L90.427077 369.82153800000003a70.262154 70.262154 0 0 0 2.284308 119.729231l7.325538 3.702154L846.375385 822.902154z" horiz-adv-x="1024" />
<glyph glyph-name="kaiqizhong" unicode="&#59255;" d="M941.312 625.493333h-298.666667V757.333333a37.290667 37.290667 0 0 1-37.290666 37.376H129.365333V841.301333a9.386667 9.386667 0 0 1-9.386666 9.386667H54.698667a9.386667 9.386667 0 0 1-9.386667-9.386667v-914.602666c0-5.12 4.266667-9.386667 9.386667-9.386667h65.28c5.12 0 9.386667 4.266667 9.386666 9.386667V234.666667h289.28v-131.84c0-20.650667 16.725333-37.290667 37.376-37.290667h485.290667a37.290667 37.290667 0 0 1 37.376 37.290667V588.202667a37.290667 37.290667 0 0 1-37.376 37.290666zM129.365333 318.634667V710.656h429.226667v-392.021333h-429.226667z m765.269334-169.130667H502.698667V234.666667h130.56c5.205333 0 9.386667 4.266667 9.386666 9.386666V541.44h251.989334v-392.021333z" horiz-adv-x="1024" />
<glyph glyph-name="daochu" unicode="&#59256;" d="M651.946667 166.656l165.546666 130.645333a9.386667 9.386667 0 0 1 0 14.677334L651.946667 442.709333a9.386667 9.386667 0 0 1-15.104-7.338666v-88.746667h-378.026667a9.386667 9.386667 0 0 1-9.386667-9.301333v-65.365334c0-5.12 4.266667-9.301333 9.386667-9.301333h378.026667V174.08a9.386667 9.386667 0 0 1 15.189333-7.338667z m304.896 472.490667L767.146667 828.842667a74.325333 74.325333 0 0 1-31.146667 18.688V850.688H82.688A37.290667 37.290667 0 0 1 45.226667 813.226667v-324.266667c0-5.12 4.266667-9.386667 9.386666-9.386667h65.28c5.12 0 9.386667 4.266667 9.386667 9.386667V766.549333h158.634667v-158.634666c0-20.650667 16.725333-37.376 37.376-37.376h373.248a37.290667 37.290667 0 0 1 37.376 37.376V741.205333l158.72-158.634666V488.96c0-5.12 4.181333-9.301333 9.301333-9.301333h65.28c5.12 0 9.386667 4.266667 9.386667 9.386666V586.325333a74.410667 74.410667 0 0 1-21.845334 52.736zM661.333333 645.290667h-298.666666V766.634667h298.666666v-121.258667z m308.053334-508.586667h-65.365334a9.386667 9.386667 0 0 1-9.386666-9.386667v-125.952H129.365333V127.317333a9.386667 9.386667 0 0 1-9.386666 9.386667H54.698667a9.386667 9.386667 0 0 1-9.386667-9.386667v-172.629333c0-20.650667 16.725333-37.376 37.376-37.376H941.226667a37.290667 37.290667 0 0 1 37.376 37.376V127.317333a9.386667 9.386667 0 0 1-9.386667 9.386667z" horiz-adv-x="1024" />
<glyph glyph-name="yijiandianping" unicode="&#59257;" d="M260.010667 689.664a9.386667 9.386667 0 0 1-9.386667-9.386667v-55.978666c0-5.12 4.266667-9.301333 9.386667-9.301334h448c5.12 0 9.386667 4.266667 9.386666 9.386667v55.978667a9.386667 9.386667 0 0 1-9.386666 9.301333h-448z m214.613333-168.021333H260.010667a9.386667 9.386667 0 0 1-9.386667-9.386667v-55.893333c0-5.12 4.266667-9.386667 9.386667-9.386667h214.613333c5.12 0 9.386667 4.266667 9.386667 9.386667v55.978666a9.386667 9.386667 0 0 1-9.386667 9.386667z m-55.978667-534.272H157.354667V808.704H810.666667v-373.333333c0-5.12 4.266667-9.386667 9.386666-9.386667h65.28c5.12 0 9.386667 4.266667 9.386667 9.386667V855.296a37.290667 37.290667 0 0 1-37.376 37.376h-746.666667a37.290667 37.290667 0 0 1-37.376-37.376v-914.602667c0-20.650667 16.725333-37.376 37.376-37.376h308.053334c5.12 0 9.301333 4.266667 9.301333 9.386667v65.28a9.386667 9.386667 0 0 1-9.386667 9.386667z m513.365334 102.656H763.989333v42.666666a130.730667 130.730667 0 1 1-74.666666 0v-42.666666H521.386667a18.773333 18.773333 0 0 1-18.602667-18.773334v-177.237333c0-10.24 8.362667-18.688 18.602667-18.688h410.709333a18.773333 18.773333 0 0 1 18.688 18.688V71.33866699999999a18.773333 18.773333 0 0 1-18.773333 18.688z m-263.68 167.936a58.368 58.368 0 1 0 116.736 0 58.368 58.368 0 0 0-116.736 0z m210.005333-310.272H574.976v69.973333h303.36v-69.973333z" horiz-adv-x="1024" />
<glyph glyph-name="chakanshixunbaogao" unicode="&#59258;" d="M717.312 673.28a9.386667 9.386667 0 0 1-9.386667 9.386667h-448a9.386667 9.386667 0 0 1-9.216-9.386667v-55.978667c0-5.12 4.181333-9.301333 9.301334-9.301333h448c5.12 0 9.386667 4.266667 9.386666 9.386667V673.28z m-9.386667-158.634667h-448a9.386667 9.386667 0 0 1-9.216-9.386666v-55.893334c0-5.12 4.181333-9.386667 9.301334-9.386666h448c5.12 0 9.386667 4.266667 9.386666 9.386666v55.978667a9.386667 9.386667 0 0 1-9.386666 9.386667zM474.794667 346.709333H259.925333a9.386667 9.386667 0 0 1-9.386666-9.386666v-55.978667c0-5.12 4.266667-9.386667 9.386666-9.386667h214.613334c5.12 0 9.386667 4.266667 9.386666 9.386667v55.978667a9.386667 9.386667 0 0 1-9.386666 9.386666z m-56.064-359.338666H157.354667V808.704H810.666667v-401.408c0-5.12 4.266667-9.301333 9.386666-9.301333h65.28c5.12 0 9.386667 4.266667 9.386667 9.386666V855.296a37.290667 37.290667 0 0 1-37.376 37.290667h-746.666667a37.290667 37.290667 0 0 1-37.376-37.376v-914.602667c0-20.650667 16.725333-37.376 37.376-37.376h308.053334c5.12 0 9.301333 4.266667 9.301333 9.386667v65.28a9.386667 9.386667 0 0 1-9.386667 9.386666z m416.256 86.784a168.106667 168.106667 0 1 1-225.877334 0 229.290667 229.290667 0 0 1-115.712-189.098667 9.386667 9.386667 0 0 1 9.386667-9.728h56.064a9.386667 9.386667 0 0 1 9.386667 8.874667c4.522667 80.725333 71.850667 145.066667 153.856 145.066666s149.333333-64.341333 153.856-145.066666a9.386667 9.386667 0 0 1 9.386666-8.874667h56.064a9.301333 9.301333 0 0 1 9.386667 9.728 228.864 228.864 0 0 1-115.797333 189.098667z m-112.896 217.6a93.269333 93.269333 0 1 0 0-186.538667 93.269333 93.269333 0 0 0 0 186.624z" horiz-adv-x="1024" />
<glyph glyph-name="tijiaozongjie" unicode="&#59259;" d="M717.312 617.301333v56.064a9.386667 9.386667 0 0 1-9.386667 9.301334h-448a9.386667 9.386667 0 0 1-9.216-9.386667v-55.978667c0-5.12 4.181333-9.301333 9.301334-9.301333h448c5.12 0 9.386667 4.266667 9.386666 9.386667z m-457.386667-102.656a9.386667 9.386667 0 0 1-9.216-9.386666v-55.893334c0-5.12 4.181333-9.386667 9.301334-9.386666h214.613333c5.12 0 9.386667 4.266667 9.386667 9.386666v55.978667a9.386667 9.386667 0 0 1-9.386667 9.386667H260.010667z m438.784-135.338666a251.989333 251.989333 0 1 1 0-503.978667 251.989333 251.989333 0 0 1 0 503.978667z m125.44-377.429334a176.213333 176.213333 0 0 0-125.44-51.882666 176.213333 176.213333 0 0 0-125.44 51.882666 176.213333 176.213333 0 0 0-51.968 125.44c0 47.36 18.432 91.989333 51.968 125.44a176.213333 176.213333 0 0 0 125.44 51.882667c47.36 0 91.904-18.432 125.44-51.882667 33.450667-33.450667 51.882667-78.08 51.882667-125.44 0-47.36-18.432-91.904-51.968-125.44z m-21.674666 214.186667H750.933333a9.216 9.216 0 0 1-7.68-3.925333l-73.984-102.4-26.965333 37.205333a9.216 9.216 0 0 1-7.68 3.84h-51.370667a9.386667 9.386667 0 0 1-7.594666-14.848l86.186666-119.125333c3.669333-5.12 11.264-5.12 14.933334 0l133.290666 184.32a9.301333 9.301333 0 0 1-7.509333 14.848z m-374.442667-228.693333H157.354667V808.704H810.666667v-401.408c0-5.12 4.266667-9.301333 9.386666-9.301333h65.28c5.12 0 9.386667 4.266667 9.386667 9.386666V855.296a37.290667 37.290667 0 0 1-37.376 37.290667h-746.666667a37.290667 37.290667 0 0 1-37.376-37.376v-914.602667c0-20.650667 16.725333-37.376 37.376-37.376h317.354667c5.12 0 9.301333 4.266667 9.301333 9.386667v65.28a9.386667 9.386667 0 0 1-9.386666 9.386666z" horiz-adv-x="1024" />
<glyph glyph-name="daimachazhong" unicode="&#59260;" d="M810.377846 284.435692c97.910154 0 171.480615-51.672615 219.136-152.339692a46.158769 46.158769 0 0 0-0.078769-38.990769c-47.576615-100.352-121.147077-152.182154-218.978462-152.182154-97.988923 0-171.480615 51.672615-219.136 152.024615a46.473846 46.473846 0 0 0 0 39.384616c47.655385 100.352 121.147077 152.103385 219.057231 152.103384z m0-68.923077c-66.875077 0-115.790769-32.295385-151.945846-102.793846 36.233846-70.577231 85.070769-102.872615 152.024615-102.872615 66.796308 0 115.712 32.295385 151.867077 102.872615-36.233846 70.498462-85.070769 102.793846-151.945846 102.793846z m0.551385-43.086769a60.337231 60.337231 0 1 0 0-120.516923 60.337231 60.337231 0 0 0 0 120.516923zM947.593846 836.923077c19.062154 0 34.500923-15.438769 34.500923-34.500923v-315.470769h-77.587692V759.414154H146.510769V147.692308h336.029539v-77.508923H103.345231a34.422154 34.422154 0 0 0-34.422154 34.422153v697.895385c0 18.983385 15.438769 34.422154 34.500923 34.422154zM667.805538 622.907077l2.756924-1.181539 152.260923-120.123076a11.342769 11.342769 0 0 0 0-17.644308L670.562462 363.756308a5.513846 5.513846 0 0 0-3.465847-1.181539 5.592615 5.592615 0 0 0-5.513846 5.592616v57.028923c0 1.811692 0.787692 3.387077 2.126769 4.411077l79.95077 63.172923-79.95077 63.094154a5.513846 5.513846 0 0 0-2.126769 4.411076v57.028924a5.513846 5.513846 0 0 0 1.181539 3.465846 5.513846 5.513846 0 0 0 7.798154 0.94523z m-304.521846-1.181539a5.513846 5.513846 0 0 0 7.798154-0.94523 5.513846 5.513846 0 0 0 1.181539-3.465846v-57.028924c0-1.732923-0.787692-3.387077-2.12677-4.411076l-80.029538-63.094154 80.029538-63.172923a5.513846 5.513846 0 0 0 2.12677-4.411077V368.246154c0-3.072-2.520615-5.513846-5.513847-5.513846a5.513846 5.513846 0 0 0-3.465846 1.102769L211.101538 484.036923a11.421538 11.421538 0 0 0 0 17.644308z m226.776616-0.94523l-22.134154-64.827077-18.825846-55.217231-1.417846-4.174769-1.181539-3.387077-1.181538-3.465846-1.024-3.072-0.945231-2.678154-18.510769-54.272-1.496616-4.411077-19.456-57.028923-0.787692-2.205539-0.551385-1.732923-0.157538-0.472615-0.315077-0.787692v-0.07877l-35.682462-104.448-0.315077-0.866461-0.315076-0.945231v-0.393846l-0.551385-1.417846a5.592615 5.592615 0 0 0-5.277539-3.859693h-47.104a5.592615 5.592615 0 0 0-5.513846 5.671385c0 0.630154 0 1.260308 0.236308 1.811692l160.925538 471.197539a5.592615 5.592615 0 0 0 5.277539 3.859692h46.946461a5.671385 5.671385 0 0 0 5.356308-7.561846l-5.198769-14.966154-0.236308-1.181538-29.932307-87.276308-0.630154-1.811692z" horiz-adv-x="1102" />
<glyph glyph-name="bianjizuoye" unicode="&#59261;" d="M969.386667 384h-65.365334a9.386667 9.386667 0 0 1-9.386666-9.386667v-373.248H129.365333V766.634667H502.613333c5.12 0 9.301333 4.266667 9.301334 9.386666V841.301333a9.386667 9.386667 0 0 1-9.386667 9.386667H82.773333A37.290667 37.290667 0 0 1 45.226667 813.226667V-45.226667c0-20.650667 16.725333-37.376 37.376-37.376H941.226667a37.290667 37.290667 0 0 1 37.376 37.376V374.613333a9.386667 9.386667 0 0 1-9.386667 9.301334zM329.898667 357.290667L327.68 218.453333a18.773333 18.773333 0 0 1 18.688-18.858666h0.426667l137.642666 3.413333a9.642667 9.642667 0 0 1 6.314667 2.56l485.205333 484.266667a9.386667 9.386667 0 0 1 0 13.141333L830.890667 847.957333a9.642667 9.642667 0 0 1-13.312 0L332.629333 363.776a9.728 9.728 0 0 1-2.645333-6.485333z m74.069333-27.562667L824.32 749.226667l52.736-52.565334-420.608-419.669333-53.333333-1.28 0.853333 54.101333z" horiz-adv-x="1024" />
<glyph glyph-name="lijijiezhi" unicode="&#59262;" d="M1018.53952 500.650667h-298.666667a9.386667 9.386667 0 0 1-9.386666-9.386667v-55.893333c0-5.12 4.266667-9.386667 9.386666-9.386667h298.666667c5.12 0 9.386667 4.266667 9.386667 9.386667v55.978666a9.386667 9.386667 0 0 1-9.386667 9.386667z m-156.330667-158.72H719.872853a9.386667 9.386667 0 0 1-9.386666-9.301334v-55.978666c0-5.12 4.266667-9.386667 9.386666-9.386667h142.336c5.12 0 9.386667 4.266667 9.386667 9.386667v55.978666a9.386667 9.386667 0 0 1-9.386667 9.386667zM472.918187 605.184h-50.517334a13.056 13.056 0 0 1-13.141333-13.056v-289.28c0-4.266667 2.048-8.106667 5.376-10.581333L588.45952 165.461333c5.802667-4.181333 13.994667-2.986667 18.176 2.816l30.037333 40.96v0.085334a13.056 13.056 0 0 1-2.901333 18.261333L485.80352 334.421333V592.042667a12.970667 12.970667 0 0 1-12.885333 13.056z m382.037333-409.941333h-67.413333a19.2 19.2 0 0 1-16.213334-9.045334 374.528 374.528 0 0 0-170.154666-144.64 369.664 369.664 0 0 0-144.64-29.184 370.005333 370.005333 0 0 0-262.826667 108.885334A370.005333 370.005333 0 0 0 84.822187 384a369.237333 369.237333 0 0 0 108.885333 262.826667 370.005333 370.005333 0 0 0 262.826667 108.885333 370.005333 370.005333 0 0 0 262.826666-108.885333c19.882667-19.797333 37.12-41.472 51.968-64.938667a19.2 19.2 0 0 1 16.213334-9.045333h67.413333a10.666667 10.666667 0 0 1 9.557333 15.530666A456.277333 456.277333 0 0 1 461.99552 840.106667C209.920853 843.093333 0.512853 636.757333 0.000853 384.853333a456.362667 456.362667 0 0 1 456.448-457.130666 456.362667 456.362667 0 0 1 408.064 251.733333 10.666667 10.666667 0 0 1-9.557333 15.616z" horiz-adv-x="1110" />
<glyph glyph-name="jingxiang" unicode="&#59251;" d="M776.084211 1.347368H258.694737c-75.452632 0-134.736842 59.284211-134.736842 134.736843V734.315789C123.957895 809.768421 183.242105 869.052632 258.694737 869.052632h517.389474c75.452632 0 134.736842-59.284211 134.736842-134.736843v-598.231578c0-75.452632-59.284211-134.736842-134.736842-134.736843zM258.694737 815.157895c-43.115789 0-80.842105-37.726316-80.842105-80.842106v-598.231578c0-43.115789 37.726316-80.842105 80.842105-80.842106h517.389474c43.115789 0 80.842105 37.726316 80.842105 80.842106V734.315789c0 43.115789-37.726316 80.842105-80.842105 80.842106H258.694737zM334.147368 146.863158h194.021053v-264.084211l-97.010526 70.063158-97.010527-70.063158zM420.378947 772.042105h107.789474v-107.789473h-107.789474zM420.378947 637.305263h107.789474v-107.789474h-107.789474zM420.378947 507.957895h107.789474v-107.789474h-107.789474zM420.378947 378.610526h107.789474v-107.789473h-107.789474zM123.957895 286.989474h776.08421v-53.894737H123.957895zM274.863158 847.494737h53.894737v-609.010526h-53.894737z" horiz-adv-x="1024" />

Before

Width:  |  Height:  |  Size: 467 KiB

After

Width:  |  Height:  |  Size: 506 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,166 +1,40 @@
.CodeMirror-merge {
position: relative;
white-space: pre;
}
.CodeMirror-merge,
.CodeMirror-merge .CodeMirror {
min-height: 50px;
.maxW50{max-width: 50%;}
.minW50{min-width: 50%;}
.width70{width: 70%;}
.width30{width: 30%;}
.custom-commit-tabs .ant-tabs-bar{border-bottom: none;}
.maxW200px{max-width: 200px;}
.pr_tags_open{
background: #28BD6C !important;
color: #fff !important;
border: none !important;
}
.CodeMirror-merge-2pane .CodeMirror-merge-pane {
width: 48%;
.pr_tags_closed{
background: #FA6400 !important;
color: #fff !important;
border: none !important;
}
.CodeMirror-merge-2pane .CodeMirror-merge-gap {
width: 4%;
.pr_tags_merged{
background: #4C9ED3 !important;
color: #fff !important;
border: none !important;
}
.CodeMirror-merge-3pane .CodeMirror-merge-pane {
width: 31%;
.ant-btn-success{
border: 1px solid #28BD6C !important;
color: #28BD6C !important;
}
.CodeMirror-merge-3pane .CodeMirror-merge-gap {
width: 3.5%;
.ant-btn-success:hover{
background: #28BD6C !important;
color:#fff !important;
}
.CodeMirror-merge-pane {
display: inline-block;
white-space: normal;
vertical-align: top;
}
.CodeMirror-merge-pane-rightmost {
position: absolute;
right: 0px;
z-index: 1;
}
.CodeMirror-merge-gap {
z-index: 2;
display: inline-block;
height: 100%;
-moz-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
position: relative;
background: #515151;
}
.CodeMirror-merge-scrolllock-wrap {
position: absolute;
bottom: 0;
left: 50%;
}
.CodeMirror-merge-scrolllock {
position: relative;
left: -50%;
cursor: pointer;
color: #d8d8d8;
line-height: 1;
}
.CodeMirror-merge-copybuttons-left,
.CodeMirror-merge-copybuttons-right {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
line-height: 1;
}
.CodeMirror-merge-copy {
position: absolute;
cursor: pointer;
color: #ce374b;
z-index: 3;
}
.CodeMirror-merge-copy-reverse {
position: absolute;
cursor: pointer;
color: #44c;
}
.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy {
left: 2px;
}
.CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy {
right: 2px;
}
.CodeMirror-merge-r-inserted,
.CodeMirror-merge-l-inserted {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);
background-position: bottom left;
background-repeat: repeat-x;
}
.CodeMirror-merge-r-deleted,
.CodeMirror-merge-l-deleted {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);
background-position: bottom left;
background-repeat: repeat-x;
}
.CodeMirror-merge-r-chunk {
background: #9a6868;
}
.CodeMirror-merge-r-connect {
fill: #9a6868;
}
.CodeMirror-merge-l-chunk {
background: #eef;
}
.CodeMirror-merge-l-chunk-start {
border-top: 1px solid #88e;
}
.CodeMirror-merge-l-chunk-end {
border-bottom: 1px solid #88e;
}
.CodeMirror-merge-l-connect {
fill: #eef;
stroke: #88e;
stroke-width: 1px;
}
.CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk {
background: #dfd;
}
.CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start {
border-top: 1px solid #4e4;
}
.CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end {
border-bottom: 1px solid #4e4;
}
.CodeMirror-merge-collapsed-widget:before {
content: "(...)";
}
.CodeMirror-merge-collapsed-widget {
cursor: pointer;
color: #88b;
background: #eef;
border: 1px solid #ddf;
font-size: 90%;
padding: 0 3px;
border-radius: 4px;
}
.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt {
display: none;
}
.color-grey {
color: #888 !important;
.display-flex{display: flex !important;}
.merge-flex1{flex:1}
.ant-tag.pr-branch-tag{
border-radius: 12px;
height: 24px;
background: rgba(241,248,255,1);
border: none;
font-size: 13px;
padding: 0 10px;
}

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,6 @@ import LoginDialog from './modules/login/LoginDialog';
import Notcompletedysl from './modules/user/Notcompletedysl';
import Trialapplicationysl from './modules/login/Trialapplicationysl';
import Trialapplicationreview from './modules/user/Trialapplicationreview';
import Addcourses from "./modules/courses/coursesPublic/Addcourses";
import AccountProfile from "./modules/user/AccountProfile";
import Accountnewprofile from './modules/user/Accountnewprofile';
import Certifiedprofessional from './modules/modals/Certifiedprofessional';
@ -20,8 +19,7 @@ import Certifiedprofessional from './modules/modals/Certifiedprofessional';
import Loading from './Loading'
import Loadable from 'react-loadable';
import marked from './common/marked'
import marked from './common/marked';
import moment from 'moment'
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
@ -48,14 +46,16 @@ const Projects = Loadable({
loader: () => import('./forge/Index'),
loading: Loading,
})
//forge项目-devOps详情
const OpsDetail = Loadable({
loader: () => import('./forge/DevOps/opsDetail'),
loading: Loading,
})
//403页面
const Shixunauthority = Loadable({
loader: () => import('./modules/403/Shixunauthority'),
loading: Loading,
})
//404页面
const Shixunnopage = Loadable({
loader: () => import('./modules/404/Shixunnopage'),
@ -67,13 +67,8 @@ const http500 = Loadable({
loader: () => import('./modules/500/http500'),
loading: Loading,
})
// 个人主页
// const InfosIndex = Loadable({
// loader: () => import('./modules/user/usersInfo/InfosIndex'),
// loading: Loading,
// })
const InfosIndex = Loadable({
loader: () => import('./forge/users/Infos'),
loader: () => import('./forge/users/Index'),
loading: Loading,
})
// 组织
@ -89,7 +84,7 @@ const Sponsor = Loadable({
class App extends Component {
constructor(props) {
super(props)
super(props);
this.state = {
Addcoursestype: false,
Addcoursestypes: false,
@ -97,8 +92,8 @@ class App extends Component {
occupation: 0,
mygetHelmetapi: null,
}
}
HideAddcoursestypess = (i) => {
this.setState({
Addcoursestype: false,
@ -161,7 +156,7 @@ class App extends Component {
this.setState({
mygetHelmetapi: undefined
});
document.title = "EduCoder";
document.title = "Forge";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
@ -190,8 +185,6 @@ class App extends Component {
getAppdata = () => {
let url = "/setting.json";
axios.get(url).then((response) => {
// console.log("app.js开始请求/setting.json");
// console.log("获取当前定制信息");
if (response) {
if (response.data) {
this.setState({
@ -209,27 +202,18 @@ class App extends Component {
} catch (e) {
this.gettablogourlnull();
}
} else {
this.gettablogourlnull();
}
} else {
this.gettablogourlnull();
}
}).catch((error) => {
this.gettablogourlnull();
});
};
render() {
let { mygetHelmetapi } = this.state;
return (
<Provider store={store}>
<ConfigProvider locale={zhCN}>
@ -239,40 +223,47 @@ class App extends Component {
<Notcompletedysl {...this.props} {...this.state}></Notcompletedysl>
<Trialapplicationysl {...this.props} {...this.state}></Trialapplicationysl>
<Trialapplicationreview {...this.props} {...this.state}></Trialapplicationreview>
<Addcourses {...this.props} {...this.state} HideAddcoursestypess={(i) => this.HideAddcoursestypess(i)} />
<AccountProfile {...this.props} {...this.state} />
<Certifiedprofessional {...this.props} {...this.state} ModalCancelsy={this.ModalCancelsy} ModalshowCancelsy={this.ModalshowCancelsy} />
<Router>
<Switch>
{/*项目*/}
<Route
path={"/projects"}
render={
(props) => {
return (<Projects {...this.props} {...props} {...this.state} />)
}
}>
</Route>
{/*项目*/}
<Route
path={"/projects/:projectId/ops/:opsId/detail"}
render={
(props) => {
return (<OpsDetail {...this.props} {...props} {...this.state} />)
}
}>
</Route>
{/*项目*/}
<Route
path={"/projects"}
render={
(props) => {
return (<Projects {...this.props} {...props} {...this.state} />)
}
}>
</Route>
{/*403*/}
<Route path="/403" component={Shixunauthority} />
<Route path="/500" component={http500} />
<Route
path={"/organize"}
render={
(props) => {
return (<OrganizeIndex {...this.props} {...props} {...this.state} />)
}
}>
</Route>
{/*404*/}
<Route path="/nopage" component={Shixunnopage} />
{/* 个人主页 */}
<Route path="/users/:username"
<Route path={"/organize"}
render={
(props) => {
return (<InfosIndex {...this.props} {...props} {...this.state} />)
return (<OrganizeIndex {...this.props} {...props} {...this.state} />)
}
}>
</Route>
{/*404*/}
<Route path="/nopage" component={Shixunnopage} />
{/* 个人主页 */}
<Route path="/users/:username"
render={
(props) => {
return (<InfosIndex {...this.props} {...this.state} />)
}
}></Route>
<Route exact path="/sponsor/:username"
@ -282,11 +273,12 @@ class App extends Component {
</Route>
<Route exact path="/"
render={
(props) => (<Projects {...this.props} {...props} {...this.state}></Projects>)
(props) => (
<Projects {...this.props} {...props} {...this.state}></Projects>
)
}
/>
<Route component={Shixunnopage} />
</Switch>
</Router>
</MuiThemeProvider>

View File

@ -59,51 +59,14 @@ function setpostcookie() {
}
setpostcookie();
function railsgettimes(proxy) {
clearAllCookie()
if (timestamp && checkSubmitFlg === false) {
$.ajax({
url: proxy, async: true, success: function (data) {
if (data.status === 0) {
timestamp = data.message;
setpostcookie();
}
}
})
checkSubmitFlg = true
window.setTimeout(() => {
checkSubmitFlg = false;
}, 2000);
} else if (checkSubmitFlg === false) {
$.ajax({
url: proxy, async: true, success: function (data) {
if (data.status === 0) {
timestamp = data.message;
setpostcookie();
}
}
})
checkSubmitFlg = true
window.setTimeout(() => {
checkSubmitFlg = false;
}, 2000);
}
}
window._debugType = debugType;
export function initAxiosInterceptors(props) {
initOnlineOfflineListener()
// TODO 避免重复的请求 https://github.com/axios/axios#cancellation
// TODO 读取到package.json中的配置
var proxy = "http://localhost:3000"
// proxy = "https://pre-newweb.educoder.net"
proxy = "https://testforgeplus.trustie.net/"
var
proxy = "http://localhost:3000"
proxy = "https://testforgeplus.trustie.net"
// 在这里使用requestMap控制避免用户通过双击等操作发出重复的请求
// 如果需要支持重复的请求考虑config里面自定义一个allowRepeat参考来控制
const requestMap = {};
window.setfalseInRequestMap = function (keyName) {
requestMap[keyName] = false;
@ -114,23 +77,17 @@ export function initAxiosInterceptors(props) {
setpostcookie()
clearAllCookie()
if (config.url.indexOf(proxy) != -1 || config.url.indexOf(':') != -1) {
if (config.url.indexOf(proxy) !== -1 || config.url.indexOf(':') !== -1) {
return config
}
requestProxy(config)
let url = `/api${config.url}`;
//qq登录去掉api
if (config.params && config.params.redirect_uri != undefined) {
if (config.params.redirect_uri.indexOf('otherloginqq') != -1) {
url = `${config.url}`;
}
}
if (`${config[0]}` != `true`) {
if (`${config[0]}` !== `true`) {
if (window.location.port === "3007") {
config.url = `${proxy}${url}`;
if (config.url.indexOf('?') == -1) {
if (config.url.indexOf('?') === -1) {
config.url = `${config.url}?debug=${debugType}`;
} else {
config.url = `${config.url}&debug=${debugType}`;

View File

@ -14,6 +14,7 @@ export default ({ value = "", is_md = true, className, style = {} }) => {
}
html = html.replace(/▁/g, "▁▁▁");
// html = html.replace(/\n/g,"<br/>");
const el = useRef();
function onAncherHandler(e) {

View File

@ -1,6 +1,6 @@
import React , { Component } from 'react';
import { Dropdown , Menu , Icon , Pagination , Spin } from 'antd';
import '../css/index.css';
import '../css/index.scss';
import '../Branch/branch.css';
import './activity.css';
import NoneData from '../Nodata';
@ -27,7 +27,6 @@ const ARRAY = [
name:'1个月'
}
]
// const dataformat="YYYY-MM-DD HH:mm";
class Activity extends Component{
constructor(props){
@ -97,27 +96,22 @@ class Activity extends Component{
const { time,type,status } = this.state;
this.getInfo(time,type,status,page);
}
menu =()=> (
<Menu>
{
ARRAY && ARRAY.map((item,key)=>{
return(
<Menu.Item key={item.id} onClick={this.changeTime}>{item.name}</Menu.Item>
)
})
}
</Menu>
)
render(){
const { time , data , page , project_trends , isSpin } = this.state;
const menu = (
<Menu>
{
ARRAY && ARRAY.map((item,key)=>{
return(
<Menu.Item key={item.id} onClick={this.changeTime}>{item.name}</Menu.Item>
)
})
}
</Menu>
);
let name = time && ARRAY.filter(item=>item.id === parseInt(time)) ;
// console.log(name);
const second_per = (parseInt(data && data.close_issues_count)/parseInt(data && data.issues_count)*100)+'%';
const third_per = (parseInt(data && data.close_issues_count)/parseInt(data && data.issues_count)*100)+'%';
const fourth_per = (parseInt(data && data.open_issues_count)/parseInt(data && data.issues_count)*100)+'%';
return(
@ -162,7 +156,7 @@ class Activity extends Component{
</div>
<div className="df trendsTop mt20">
<div className="branchDropdown f-wrap-alignCenter">
<Dropdown overlay={menu} trigger={['click']} placement="bottomLeft">
<Dropdown overlay={this.menu()} trigger={['click']} placement="bottomLeft">
<a className="ant-dropdown-link">
<span className="color-grey-9 mr3">周期:</span>
{name && name.length>0 && name[0].name} <Icon type="down" />

View File

@ -1,46 +1,45 @@
import React , { Component } from 'react';
import {Link} from 'react-router-dom';
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import './activity.css';
import { getImageUrl } from 'educoder';
class ActivityItem extends Component{
render(){
class ActivityItem extends Component {
render() {
const { projectsId } = this.props.match.params;
const { item } = this.props;
return(
<div className="activity_item">
<div className="flex1">
return (
<div className="activity_item">
<div className="flex1">
{/* 如果是版本发布 */}
{ item.trend_type==="VersionRelease"? 
<p className="itemLine">
<Link to={`/projects/${projectsId}/version`} className="color-blue font-16">{item.name}</Link>
<span className="activity_type">{item.trend_type}</span>
{item.trend_type === "VersionRelease" ?
<p className="itemLine">
<Link to={`/projects/${projectsId}/version`} className="color-blue font-16">{item.name}</Link>
<span className="activity_type">{item.trend_type}</span>
</p >
:
// 如果是任务
item.trend_type==="Issue"?
<p className="itemLine">
<Link to={`/projects/${projectsId}/orders/${item.trend_id}/detail`} className="color-blue font-16">{item.name}</Link>
<span className="activity_type">{item.trend_type}</span>
</p >
:
// 如果是合并请求
<p className="itemLine">
<Link to={`/projects/${projectsId}/merge/${item.trend_id}/Messagecount`} className="color-blue font-16">{item.name}</Link>
<span className="activity_type">{item.trend_type}</span>
</p >
}
<p className="itemLine mt15">
<Link to={`/users/${item && item.login}`} className="show-user-link">
<img alt="" src={getImageUrl(`images/${item.user_avatar}`)} className="createImage"/>
<span className="mr20">{item.user_name}</span>
</Link>
{ item.created_at && <span className="color-grey-9">创建于<span className="ml2 color-grey-6">{item.created_at}</span></span>}
item.trend_type === "Issue" ?
<p className="itemLine">
<Link to={`/projects/${projectsId}/orders/${item.trend_id}/detail`} className="color-blue font-16">{item.name}</Link>
<span className="activity_type">{item.trend_type}</span>
</p >
</div>
</div>
:
// 如果是合并请求
<p className="itemLine">
<Link to={`/projects/${projectsId}/merge/${item.trend_id}/Messagecount`} className="color-blue font-16">{item.name}</Link>
<span className="activity_type">{item.trend_type}</span>
</p >
}
<p className="itemLine mt15">
<Link to={`/users/${item && item.login}`} className="show-user-link">
<img alt="" src={getImageUrl(`images/${item.user_avatar}`)} className="createImage" />
<span className="mr20">{item.user_name}</span>
</Link>
{item.created_at && <span className="color-grey-9">创建于<span className="ml2 color-grey-6">{item.created_at}</span></span>}
</p >
</div>
</div>
)
}
}

View File

@ -14,6 +14,7 @@ class CloneAddress extends Component {
const { http_url, downloadUrl } = this.props;
return (
<div className="gitAddressClone">
<p className="addressTips"><span>版本库地址已变更请基于新地址提交代码</span></p>
{
http_url && <span>HTTP</span>
}

View File

@ -1,172 +0,0 @@
import React , { Component } from 'react';
import { Dropdown , Icon , Input } from 'antd';
import { getBranch } from '../GetData/getData';
import "./branch.css"
import axios from 'axios';
const $ = window.$;
class SelectBranch extends Component{
constructor(props){
super(props);
this.state={
visible:false,
value:undefined,
search:"branch",
tags:undefined,
branchsFilter:undefined,
data:undefined
}
}
componentDidMount() {
this.getTagList();
document.body.addEventListener('click', e => {
let v= this.state.visible;
if(e.target.className && e.target.className.animVal!=undefined) return;
let s = e.target && e.target.className && e.target.className.indexOf('showtag')> -1;
let classF =e.target && e.target.className && e.target.className.indexOf("downobject") > -1 || e.target.className==="ant-input OptionsInput";
if(e.target && e.target.className === "ant-dropdown-trigger" || s){
this.setState({
visible:!v,
value:undefined
})
if(!v){
this.getBranchs();
}
return;
}else if (classF) {
return;
} else{
this.setState({
visible:false,
value:undefined
})
}
});
}
componentDidUpdate=(prevProps)=>{
if(this.props.repo_id && this.props.repo_id!=prevProps.repo_id){
this.getTagList();
}
}
// 获取分支
getBranchs=()=>{
debugger;
const { projectsId } = this.props;
let result = getBranch(projectsId);
if(result){
this.setState({
data:result.data
})
if(result.data && result.data.length>0){
this.setState({
search:"branch"
})
}
}
}
getTagList=()=>{
const { repo_id } = this.props;
if(repo_id){
const url = `/repositories/${repo_id}/tags.json`;
axios.get(url).then((result)=>{
if(result){
this.setState({
tags:result.data
})
}
}).catch(error=>{
console.log(error);
})
}
}
InputClick=(e)=>{
this.stopPropagations(e);
}
stopPropagations=(e)=>{
e.stopPropagation();
}
// 输入搜索内容
changeValue=(e)=>{
this.setState({
value:e.target.value
})
let { branchs } = this.props;
const { tags } = this.state;
let array = branchs;
if(search === "tag" && tags.length>0){
array = tags;
}
let branchsFilter = e.target.value ? (array && array.length>0 && array.filter(item=>item.name.indexOf(e.target.value)>-1)) : array;
this.setState({
branchsFilter
})
}
// 选择分支
changeBranchs=(e,value)=>{
e.stopPropagation();
this.setState({
visible:false,
value
})
const { changeBranch } = this.props;
changeBranch && changeBranch(value);
}
// 切换搜索的列表
changeSearch=(search)=>{
this.setState({
search
})
}
render(){
const { visible , value , search , tags , branchsFilter , data } = this.state;
const { branchs , branch } = this.props;
console.log(data);
const menu = (
<div className="branchOptions" id="m-btn" onClick={this.stopPropagations}>
<div className="downobject padding10 bor-bottom-greyE">
<Input placeholder="请输入分支或标签名称搜索" autocomplete="off" id="input-btn" value={value} className="OptionsInput" onChange={this.changeValue} onClick={this.InputClick}/>
<ul className="navUl" id="navUl-btn">
<li className={search ==="branch"?"downobject active":"downobject"} onClick={()=>this.changeSearch("branch")}><i className="iconfont icon-fenzhi1 font-14 mr3"></i></li>
<li className={search ==="tag"?"downobject active":"downobject"} onClick={()=>this.changeSearch("tag")}><i className="iconfont icon-biaoqian3 font-14 mr3"></i></li>
</ul>
</div>
<ul className="OptionsUl" id="ul-btn">
{
data && data.length> 0 ? data.map((item,key)=>{
return(
<li key={key}><a className="task-hide ulALink" onClick={(e)=>this.changeBranchs(e,`${item.name}`)}>{item.name}</a></li>
)
})
:
<p className="listTips">暂无{value}{search === "tag" ?"标签":"分支"}~</p>
}
</ul>
</div>
);
return(
<div className="branchDropdown f-wrap-alignCenter" >
<Dropdown overlay={menu} trigger={['click']} placement="bottomLeft" visible={visible}>
<span id="down-btn">
<span>
<span className="color-grey-9 mr3">{search ==="branch"?"分支":"标签"}:</span>
<a className="ant-dropdown-link">
{branch}
</a>
</span>
<i className="showtag iconfont icon-xiajiantou font-14 color-grey-9" />
</span>
</Dropdown>
</div>
)
}
}
export default SelectBranch;

View File

@ -0,0 +1,19 @@
import React from 'react';
import './Component.scss';
export default (({img , title, desc , rightBtn})=>{
return(
<div className="cards">
<div className="img"><img src={img} alt=""/></div>
<div className="content">
<p className="titles">
<span>{title}</span>
{rightBtn}
</p>
<div className="desc">
{desc}
</div>
</div>
</div>
)
})

View File

@ -1,10 +1,122 @@
ul.ant-menu{
border-right: none;
ul.ant-menu{
border-right: none;
}
ul.ant-menu li:last-child{
border-bottom: none;
}
li.ant-menu-item{
margin:0px!important;
border-bottom: 1px solid #eee;
}
// Cards
.cards{
display: flex;
align-items: center;
padding:20px 34px;
background-color: #fff;
margin-bottom:18px;
.img{
margin-right: 20px;
width: 190px;
height: 90px;
border:1px solid rgba(238,238,238,1);
display: flex;
justify-content: center;
align-items: center;
img{
max-width: 100%;
}
}
ul.ant-menu li:last-child{
border-bottom: none;
.content{
flex:1;
width: 0;
.titles{
display: flex;
justify-content: space-between;
margin-bottom: 10px!important;
align-items: center;
&>span{
font-size:18px ;
color: #333;
}
}
.desc{
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
}
li.ant-menu-item{
margin:0px!important;
border-bottom: 1px solid #eee;
}
}
// Tabs
.tabsStyle{
.ant-tabs-bar.ant-tabs-top-bar{
padding-left: 35px;
margin-bottom: 0px;
}
.ant-tabs-nav .ant-tabs-tab{
padding:19px 0px;
margin-right: 40px;
}
.ant-tabs-ink-bar{
width:25px!important;
bottom: 10px;
}
}
.statusColor{
display: inline-block;
padding:0px 10px;
height:20px;
line-height: 20px;
border-radius:11px;
color: #fff;
margin-left: 5px;
&.running{
background:#5091FF;
color: #F1F8FF;
}
&.Preparing{
background:rgba(255,110,33,1);
color:rgba(255,248,244,1);
}
&.pass{
background:#28BD6C;
color: #EEFDF5;
}
&.failed{
background:#F73030;
color:#FCEEEE ;
}
}
.handleBox{
position: fixed;
top:45%;
right:240px;
z-index: 10000;
}
@media screen and (max-width: 1800px){
.handleBox{
right:190px;
}
}
@media screen and (max-width: 1700px){
.handleBox{
right:140px;
}
}
@media screen and (max-width: 1600px){
.handleBox{
right:90px;
}
}
@media screen and (max-width: 1450px){
.handleBox{
right:10px;
}
}
@media screen and (max-width: 1380px){
.handleBox{
right:0px;
}
}

View File

@ -0,0 +1,66 @@
import React from 'react';
import { Select } from 'antd';
const Option = Select.Option;
const LANGUAGE = [
"apex",
"azcli",
"bat",
"clojure",
"coffee",
"cpp",
"csharp",
"csp",
"css",
"dockerfile",
"fsharp",
"go",
"handlebars",
"html",
"ini",
"java",
"javascript",
"json",
"less",
"lua",
"markdown",
"msdax",
"mysql",
"objective",
"perl",
"pgsql",
"php",
"postiats",
"powerquery",
"powershell",
"pug",
"python",
"r",
"razor",
"redis",
"redshift",
"ruby",
"rust",
"sb",
"scheme",
"scss",
"shell",
"solidity",
"sql",
"st",
"swift",
"typescript",
"vb",
"xml",
"yaml",
];
export default (({ language , select_language })=>{
return(
<Select showSearch={true} placeholder={"请选择文本语言"} style={{ width: 200 }} value={language} onChange={select_language}>
<Option value={undefined}>请选择文本语言</Option>
{LANGUAGE.map((item, key) => {
return <Option value={item}>{item}</Option>;
})}
</Select>
)
})

View File

@ -0,0 +1,13 @@
import React from 'react';
import Handbook from '../Images/handbook.png';
import './Component.scss';
export default (()=>{
return(
<div className="handleBox">
<a href="https://www.trustie.net/forums/82/memos/3075" target="_blank" >
<img src={Handbook} alt=""/>
</a>
</div>
)
})

View File

@ -0,0 +1,41 @@
import React from 'react';
import styled from 'styled-components';
export default (({fork,parise})=>{
const DivStyle = styled.div`{
display:flex;
align-item:center;
}`;
const SpanStylefork = styled.span`{
display:flex;
align-item:center;
margin-left:30px;
padding:0px 12px;
border-radius:13px;
background-color:#EBF4FE;
height:24px;
line-height:24px;
font-size:12px;
}`;
const SpanStyleparise = styled.span`{
display:flex;
align-item:center;
margin-left:30px;
padding:0px 12px;
border-radius:13px;
background-color:#FFF3DC;
height:24px;
line-height:24px;
font-size:12px;
}`;
return(
<DivStyle>
{
fork || fork ===0 ? <SpanStylefork><i className="iconfont icon-fork font-15 mr3" style={{color:"#1B8FFF"}}></i>fork({fork})</SpanStylefork>:""
}
{
parise || parise ===0?<SpanStyleparise><i className="iconfont icon-guanzhu font-14 mr3" style={{color:"#FFA802"}}></i>点赞({parise})</SpanStyleparise>:""
}
</DivStyle>
)
})

View File

@ -0,0 +1,74 @@
import React from 'react';
import './Component.scss';
import styled from 'styled-components';
const Img = styled.img`{
border-radius:50%;
width:50px;
height:50px;
margin-right:14px;
}`
const Name = styled.div`{
color:#5091FF;
font-size:16px;
height:22px;
line-height:22px;
margin-bottom:7px;
}`
const Time = styled.div`{
color:#888;
font-size:12px;
height:16px;
line-height:16px;
margin-bottom:9px;
display:flex;
align-item:center;
}`
const I = styled.i`{
font-size:13px!important;
color:#60B25E;
margin-right:2px;
}`
const FocusBtn = styled.a`{
display:inline-block;
height:30px;
line-height:26px;
padding:0px 12px;
background-color:#fafafa;
border:1px solid #eee;
border-radius:2px;
color:#888!important;
}`
const Ifocused = styled.i`{
font-size:16px!important;
color:#FFA802;
margin-right:4px;
}`
const Ifocus = styled.i`{
font-size:16px!important;
color:#BBBBBB;
margin-right:4px;
}`
const Div = styled.div`{
margin-bottom: 18px;
padding:20px 16px;
display: flex;
align-items: center;
border:1px solid #eee;
}`
export default (({img,name,time, focusStatus})=>{
return(
<Div>
<Img src={img}/>
<div className="m-infos">
<Name>{name}</Name>
<Time><I className="iconfont icon-shijian"></I>加入时间:{time}</Time>
{
focusStatus ?
<FocusBtn><Ifocused className="iconfont icon-shixing"></Ifocused>已关注</FocusBtn> :
<FocusBtn><Ifocus className="iconfont icon-kongxing"></Ifocus>关注</FocusBtn>
}
</div>
</Div>
)
})

View File

@ -0,0 +1,44 @@
import React from 'react';
import './Component.scss';
export const Tags = (status)=>{
switch(status){
case 1:
return(
<span className="statusColor running">运行中</span>
);
case 2:
return (
<span className="statusColor failed">未通过</span>
);
case 3:
return (
<span className="statusColor pass">已通过</span>
);
default:
return (
<span className="statusColor Preparing">准备中</span>
);
}
}
export const TagsLine = (status)=>{
switch(status){
case 1:
return(
<span className="statuslineColor running">运行中</span>
);
case 2:
return (
<span className="statuslineColor failed">未通过</span>
);
case 3:
return (
<span className="statuslineColor pass">已通过</span>
);
default:
return (
<span className="statuslineColor Preparing">准备中</span>
);
}
}

View File

@ -0,0 +1,70 @@
import React , { useState , useEffect } from 'react';
import { AutoComplete } from 'antd';
import { getImageUrl } from "educoder";
import axios from 'axios';
const Option = AutoComplete.Option;
export default ({ getUser })=>{
const [ searchKey , setSearchKey ] = useState(undefined);
const [ userDataSource , setUserDataSource ] = useState(undefined);
function getUserList(e){
const url = `/users/list.json`;
axios.get(url, {
params: {
search: e,
},
})
.then((result) => {
if (result) {
setUserDataSource(result.data.users);
}
})
.catch((error) => {
console.log(error);
});
};
function changeInputUser(value){
setSearchKey(value);
getUserList(value);
}
function selectInputUser(id, option){
setSearchKey(option.props.searchValue);
getUserList(option.props.searchValue);
getUser && getUser(id);
}
const source =
userDataSource && userDataSource.map((item, key) => {
return (
<Option
key={key}
value={`${item.user_id}`}
searchValue={`${item.username}`}
>
<img
className="user_img radius"
width="28"
height="28"
src={getImageUrl(`images/${item && item.image_url}`)}
alt=""
/>
<span className="ml10" style={{ "vertical-align": "middle" }}>
{item.username}
<span className="color-grey ml10">({item.login})</span>
</span>
</Option>
);
});
return(
<AutoComplete
dataSource={source}
value={searchKey}
style={{ width: 300 }}
onChange={changeInputUser}
onSelect={selectInputUser}
placeholder="搜索需要添加的用户..."
/>
)
}

View File

@ -0,0 +1,27 @@
import React from 'react';
import { Link } from 'react-router-dom';
/**
* nav:{list:[],active:0} */
export default(({ header , nav })=>{
return(
<ul className="list-l-Menu">
{header}
{
nav && nav.list && nav.list.length>0 ?
nav.list.map((item,key)=>{
return(
<li key={key} className={nav.active === key?"active":''}>
<p>
<Link to={item.href}>
<i className={`iconfont ${item.icon || 'icon-huabanfuben'} font-18 mr10`}></i>{item.name}
</Link>
</p>
</li>
)
})
:""
}
</ul>
)
})

View File

@ -0,0 +1,20 @@
import React from 'react';
import { Tabs } from 'antd';
import './Component.scss';
const { TabPane } = Tabs;
export default (({ nav, index , onChange , children })=>{
return(
nav && nav.length > 0 ?
<Tabs className="tabsStyle" animated={false} activeKey={index} onChange={onChange}>
{
nav.map((item,key)=>{
return(
<TabPane tab={item} key={`${key}`}>{children}</TabPane>
)
})
}
</Tabs>:""
)
})

View File

@ -0,0 +1,19 @@
import React from 'react';
import styled from 'styled-components';
const Nav = styled.div`{
background-color:#fff;
padding:20px 30px;
border-bottom:1px solid #eee;
font-size:16px;
color:#333;
display:flex;
justify-content: space-between;
align-items:center;
}`
export default (({children})=>{
return(
<Nav>{children}</Nav>
)
})

View File

@ -0,0 +1,156 @@
import styled from 'styled-components';
export const Banner = styled.div`{
padding:20px 25px;
color:#333;
font-size:18px;
border-bottom:1px solid #eee;
background-color:#fff;
border-radius:5px 5px 0px 0px;
}`
export const AlignCenterBetween = styled.div`{
display:flex;
align-items: center;
padding: 14px 14px 14px 20px;
justify-content: space-between;
border-bottom:1px solid #eee;
}`
export const FlexAJ = styled.div`{
display:flex;
align-items: center;
justify-content: space-between;
}`
export const AlignCenter = styled.div`{
display:flex;
align-items: center;
}`
//
export const Box = styled.div`{
display:flex;
align-item:flex-start;
}`
export const Long = styled.div`{
width:72%;
border-radius:5px;
margin-bottom:30px;
}`
export const Short = styled.div`{
width:28%;
border-radius:5px;
margin-bottom:30px;
}`
export const Gap = styled.div`{
padding-left:20px;
box-sizing:border-box;
}`
export const WhiteBack = styled.div`{
background-color:#fff;
border-radius:5px;
}`
export const Blueline = styled.a`{
height:30px;
line-height:28px;
border-radius:2px;
border:1px solid rgba(80,145,255,1);
color:rgba(80,145,255,1);
padding:0px 12px;
display:inline-block;
}`
export const Redline = styled.a`{
height:30px;
line-height:28px;
border-radius:2px;
border:1px solid #F73030;
color:#F73030;
padding:0px 12px;
display:inline-block;
min-width:80px;
text-align:center;
}`
export const Greenline = styled.a`{
height:30px;
line-height:28px;
border-radius:2px;
border:1px solid #28BD6C;
color:#28BD6C;
padding:0px 12px;
display:inline-block;
min-width:80px;
text-align:center;
}`
export const Greenback = styled.a`{
height:30px;
line-height:30px;
border-radius:2px;
background-color:#28BD6C;
color:#fff;
padding:0px 12px;
display:inline-block;
min-width:80px;
text-align:center;
}`
export const Blueback = styled.a`{
height:30px;
line-height:30px;
border-radius:2px;
background-color:rgba(80,145,255,1);
color:#fff;
padding:0px 12px;
display:inline-block;
min-width:80px;
text-align:center;
}`
export const Redback = styled.a`{
height:30px;
line-height:30px;
border-radius:2px;
background-color:#F73030;
color:#fff;
padding:0px 12px;
display:inline-block;
min-width:80px;
text-align:center;
}`
export const NumUl = styled.ul`{
padding-left: 20px;
& > li{
list-style-type: decimal;
color:#888;
height:24px;
line-height:24px;
}
}`
export const GreenUnder = styled.a`{
color:#28BD6C!important;
position:relative;
&:after{
position:absolute;
bottom:-2px;
left:0px;
width:100%;
height:1px;
content:'';
background:#28BD6C;
}
}`
export const Cancel = styled.a`{
height:32px;
line-height:32px;
border-radius:2px;
background-color:#BBBBBB;
color:#fff;
padding:0px 12px;
display:inline-block;
min-width:64px;
text-align:center;
letter-spacing: 4px;
}`
export const Content = styled.div`{
width:1200px;
margin:20px auto;
text-align:center;
display:flex;
align-Items:center;
background-color:#fff;
justify-content: center;
}`

View File

@ -0,0 +1,78 @@
import React , { forwardRef , useCallback } from 'react';
import activate from '../Images/activate.png';
import { Blueback } from '../Component/layout';
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import { Form , Input } from 'antd';
import axios from 'axios';
const P = styled.p`{
width:200px;
line-height:30px;
font-size:16px;
color:#333;
text-align:center;
margin-top:30px;
margin-bottom:30px!important;
}`;
function About( props , ref){
const { form: { getFieldDecorator , validateFields } } = props;
const helper = useCallback(
(label, name, rules, widget, isRequired) => (
<React.Fragment>
<span className={isRequired?"required":""}>{label}</span>
<Form.Item>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
</Form.Item>
</React.Fragment>
),
[]
);
function startActive(){
console.log(props);
validateFields((error,values)=>{
if(!error){
const url = `/dev_ops/cloud_accounts.json`;
axios.post(url,{
...values,
}).then(result=>{
if(result){
}
}).catch(error=>{
console.log(error);
})
}
})
}
return(
<div className="activatePanel">
<img src={activate} alt="" width="250px"/>
<P>定义DevOps工作流帮助您检测bug发布代码</P>
<Link to={""} style={{color:"#5091FF",marginBottom:"20px"}}>了解什么是DevOps</Link>
<Form>
{helper(
"服务器IP地址",
"ip_num",
[{ required: true, message: "请输入服务器IP地址" }],
<Input placeholder="请输入服务器IP地址" style={{width:"368px"}} size="large" />,true
)}
{helper(
"服务器用户名:",
"account",
[{ required: true, message: "请输入服务器用户名" }],
<Input placeholder="请输入服务器用户名" size="large" />,true
)}
{helper(
"服务器密码:",
"secret",
[{ required: true, message: "请输入服务器密码" }],
<Input.Password placeholder="请输入服务器密码" size="large" />,true
)}
</Form>
<Blueback onClick={startActive}>开始激活</Blueback>
</div>
)
}
export default Form.create()(forwardRef(About));

View File

@ -0,0 +1,91 @@
import React , { forwardRef , useCallback , useState } from 'react';
import { Form , AutoComplete } from 'antd';
import { Blueback } from '../Component/layout';
import Editor from "react-monaco-editor";
import Modals from './DisposeModal';
import FileLanguage from '../Component/FileLanguage';
import docker from '../Images/docker.png';
import gradle from '../Images/gradle.png';
import java from '../Images/java.png';
import js from '../Images/js.png';
import php from '../Images/php.png';
import python from '../Images/python.png';
const Option = AutoComplete.Option;
export default Form.create()(
forwardRef(({ form })=>{
const [ visible , setVisible ] = useState(false);
const [ ymlValue , setYmlValue ] = useState("class Main 1111");
const [ fileLanguage , setFileLanguage ] = useState(undefined);
const { getFieldDecorator , validateFields } = form;
const helper = useCallback(
(label, name, rules, widget, isRequired = false) => (
<React.Fragment>
<span required={isRequired}>{label}</span>
<Form.Item>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
</Form.Item>
</React.Fragment>
),
[]
)
//
function changeEditor(value){
setYmlValue(value);
}
//
function select_language(value){
setFileLanguage(value);
}
//
function submit(){
validateFields((error,value)=>{
if(!error){
console.log(value);
}
})
}
return(
<React.Fragment>
<Modals visible={visible} closeFunc={(flag)=>setVisible(flag)}></Modals>
<Form>
<p>编程语言</p>
<ul className="language">
<li><img alt="" src={docker} /></li>
<li><img alt="" src={gradle} /></li>
<li><img alt="" src={java} /></li>
<li><img alt="" src={js} /></li>
<li><img alt="" src={php} /></li>
<li><img alt="" src={python} /></li>
</ul>
<div className="mt20 mb20">
<FileLanguage language={fileLanguage} select_language={select_language}/>
</div>
<p>配置脚本</p>
<div className="editorBody">
<p className="editorHead">
<span>.trustie-pipeline.yml</span>
<a><i className="iconfont icon-bianji6 font-14"></i></a>
</p>
<Editor
height="300px"
language={"java"}
theme={"vs-grey"}
defaultValue="请输入内容"
value={ymlValue}
options={"editor_options"}
onChange={changeEditor}
></Editor>
</div>
<Blueback onClick={submit}>确定提交</Blueback>
</Form>
</React.Fragment>
)
})
)

View File

@ -0,0 +1,28 @@
import React from 'react';
import styled from 'styled-components';
import { Modal ,Button } from 'antd';
const Div = styled.div`{
height:130px;
line-height:130px;
text-align:center;
color:#333;
}`
export default (({visible , closeFunc})=>{
return(
<Modal
title="提示"
visible={visible}
closable={true}
footer={
<div>
<Button onClick={()=>closeFunc(false)}>取消</Button>
<Button type={"primary"} onClick={()=>closeFunc(false)} style={{marginLeft:"20px"}}>确定</Button>
</div>
}
onCancel={()=>closeFunc(false)}
>
<Div>工作流配置完成您的DevOps之旅即刻开启</Div>
</Modal>
)
})

View File

@ -0,0 +1,39 @@
import React from 'react';
import { WhiteBack } from '../Component/layout';
import './ops.scss';
import { Route, Switch } from 'react-router-dom';
import Loadable from 'react-loadable';
import Loading from '../../Loading';
const About = Loadable({
loader: () => import('./About'),
loading: Loading,
})
const Infos = Loadable({
loader: () => import('./Infos'),
loading: Loading,
})
export default ((props)=>{
return(
<WhiteBack className="opsPanel">
<Switch {...props}>
<Route path="/projects/:projectsId/ops/dispose"
render={
() => (<Infos {...props} />)
}
></Route>
<Route path="/projects/:projectsId/ops/list"
render={
() => (<Infos {...props} />)
}
></Route>
<Route path="/projects/:projectsId/ops"
render={
() => (<About {...props} />)
}
></Route>
</Switch>
</WhiteBack>
)
})

View File

@ -0,0 +1,42 @@
import React , { useEffect , useState } from 'react';
import { Banner } from '../Component/layout';
import { Link } from 'react-router-dom';
import Dispost from './Dispose';
import Structure from './Structure';
import styled from 'styled-components';
const Div = styled.div`{
padding:24px 30px;
}`;
export default ((props)=>{
const [ menu , setMenu ] = useState(false);
const path = props.location.pathname;
useEffect(()=>{
console.log(props.match.params.projectsId)
if(path === `/projects/${props.match.params.projectsId}/ops/list`){
setMenu(true);
}else{
setMenu(false);
}
},[path])
return(
<div className="disposePanel">
<Banner>
<Link to={`/projects/${props.match.params.projectsId}/ops/dispose`}>工作流配置</Link>
{ menu ? <Link to={`/projects/${props.match.params.projectsId}/ops/list`} style={{ marginLeft:"66px",color:"#5091FF" }}>构建列表</Link>:""}
</Banner>
<Div>
{
menu ?
<Structure {...props}/>
:
<Dispost {...props}/>
}
</Div>
</div>
)
})

View File

@ -0,0 +1,42 @@
import React from 'react';
import { FlexAJ , Blueline , AlignCenter } from '../Component/layout';
import styled from 'styled-components';
import { Menu } from 'antd';
import { TagsLine } from '../Component/OpsStatus';
const SubMenu = Menu.SubMenu;
const Img = styled.img`{
width:25px;
height:25px;
border-radius:50%;
margin-right:10px;
}`
export default (()=>{
return(
<div>
<FlexAJ className="leftheader">
<AlignCenter>
<Img src="https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2091711702,2468700162&fm=111&gp=0.jpg"/>
<span className="nest">开始时间<span>2020.07.10 15:30</span></span>
<span className="nest">运行时间<span>20s</span></span>
</AlignCenter>
<Blueline>重新创建</Blueline>
</FlexAJ>
<div className="leftMainContent">
<AlignCenter className="contentBranch">
<i className="iconfont icon-fenzhi1"></i>
<span>分支</span>
<span className="branchname">master</span>
<span className="branchsha">8b3476f5</span>
</AlignCenter>
</div>
<Menu mode='inline' className="leftMenu">
<SubMenu title={<div><i className="iconfont icon-gongzuoliu font-14 mr4"></i><span>CI</span></div>}>
<Menu.Item>
<FlexAJ><span>Build setup 01 {TagsLine(1)}</span><span>20s</span></FlexAJ>
</Menu.Item>
</SubMenu>
</Menu>
</div>
)
})

View File

@ -0,0 +1,21 @@
import React from 'react';
import { FlexAJ , AlignCenter } from '../Component/layout';
export default (()=>{
return(
<div className="rightMainContent">
<div>
<FlexAJ className="items">
<span>Build setup 01</span>
<AlignCenter>20<i className="iconfont icon-triangle"></i></AlignCenter>
</FlexAJ>
</div>
<div>
<FlexAJ className="items"></FlexAJ>
</div>
<div>
<FlexAJ className="items"></FlexAJ>
</div>
</div>
)
})

View File

@ -0,0 +1,204 @@
import React , { useState } from 'react';
import { FlexAJ , Blueback } from '../Component/layout';
import { Table , Pagination } from 'antd';
import styled from 'styled-components';
const STATUS = [
{name:"所有",value:"1"},
{name:"准备中",value:"2"},
{name:"运行中",value:"3"},
{name:"已完成",value:"4"}
]
const LIMIT = 15;
const datasource = [
{
status:2,
author:"caishi",
message:{
branch:"master",
sha:"8b3476f5",
image:"https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2034740944,4251903193&fm=26&gp=0.jpg",
message:"将分支“ 221063-improve-buy-ci-minutes-link”"
},
begin:"2020-07-08",
run:"20s"
},
{
status:1,
author:"caishi",
message:{
branch:"master",
sha:"8b3476f5",
image:"https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2034740944,4251903193&fm=26&gp=0.jpg",
message:"将分支“ 221063-improve-buy-ci-minutes-link”"
},
begin:"2020-07-08",
run:""
}
];
const Img = styled.img`{
border-radius:50%;
margin-rigth:10px;
width:25px;
height:25px;
}`
export default (()=>{
const [ status ,setStatus ] = useState("1");
const [ page ,setPage ] = useState(1);
const [ total ,setTotal ] = useState(10);
function ChangeStatus(value){
setStatus(value)
}
//
function ChangePage(page){
setPage(page)
}
function renderStatus() {
return(
<ul className="listNav">
{
STATUS.map((item,key)=>{
return <li onClick={()=>ChangeStatus(item.value)} className={ status === item.value ? "active":""}>{item.name}</li>
})
}
</ul>
)
}
function renderStatusBtn(status){
if(status >1 && status <=3){
return(
<a className="color-blue">重新构建</a>
)
}else{
return(
<a className="color-red">撤销构建</a>
)
}
}
function renderTableStatus (status){
switch (status){
case 1:
return(
<span className="statusTag running"><i className="iconfont icon-yunhangzhong"></i>运行中</span>
);
case 2:
return (
<span className="statusTag failed"><i className="iconfont icon-weitongguo"></i>未通过</span>
);
case 3:
return (
<span className="statusTag pass"><i className="iconfont icon-yitongguo"></i>已通过</span>
);
default:
return (
<span className="statusTag Preparing"><i className="iconfont icon-zhunbeizhong"></i>准备中</span>
);
}
}
const column = [
{
title:'序号',
dataIndex:"No",
key:"No",
width:"8%",
render:(item,value,key)=>{
return(
<span>#{key+1}</span>
)
}
},
{
title:'状态',
dataIndex:"status",
key:"status",
width:"12%",
render:(value,item,key)=>{
return(renderTableStatus(value))
}
},
{
title:'构建人',
dataIndex:"author",
key:"author",
width:"12%",
align:"center"
},
{
title:'提交信息',
dataIndex:"message",
key:"message",
width:"30%",
render:(value,item,key)=>{
let meg = item.message;
return (
<React.Fragment>
<div>
{ meg.branch && <span className="mr10 color-grey-8"><i className="iconfont icon-fenzhi1 font-16 mr5"></i>分支{meg.branch}</span>}
{ meg.sha && <span className="color-orange">{meg.sha}</span>}
</div>
<FlexAJ>
<Img src={meg.image} />
<div className="task-hide" style={{maxWidth:"300px"}}>{meg.message}</div>
</FlexAJ>
</React.Fragment>
)
}
},
{
title:'开始时间',
dataIndex:"begin",
key:"begin",
width:"15%",
render:(value,item,key)=>{
return (
<span>{value || "--"}</span>
)
}
},
{
title:'运行时间',
dataIndex:"run",
key:"run",
width:"15%",
render:(value,item,key)=>{
return (
<span>{value || "--"}</span>
)
}
},
{
title:'操作',
dataIndex:"operation",
key:"operation",
render:(value,item,key)=>{
return(renderStatusBtn(item.status));
}
}
]
return(
<div className="listPart">
<FlexAJ>
{renderStatus()}
<span>
<Blueback className="mr30">手动创建</Blueback>
<span className="mr30"><i className="iconfont icon-fenzhi1 font-16 mr5 color-blue"></i>分支</span>
<span><i className="iconfont icon-biaoqian3 font-16 mr5 color-blue"></i>标签</span>
</span>
</FlexAJ>
<Table
columns={column}
className="normalTable"
dataSource={datasource}
pagination={false}
></Table>
{
total > LIMIT ?
<div style={{textAlign:'center',margin:"30px 50px"}}>
<Pagination showQuickJumper defaultCurrent={page} total={total} pageSize={LIMIT} onChange={ChangePage}></Pagination>
</div>:""
}
</div>
)
})

267
src/forge/DevOps/ops.scss Normal file
View File

@ -0,0 +1,267 @@
.opsPanel
{
margin:20px auto;
width: 1200px;
// 开始激活页面
.activatePanel{
display: flex;
flex-direction: column;
align-items: center;
padding:60px 0px;
}
.disposePanel{
.language{
display: flex;
li{
margin-right: 20px;
}
}
.editorBody{
border:1px solid #ddd;
margin:20px 0px;
.editorHead{
background-color: #F1F8FF;
height: 48px;
line-height: 48px;
display: flex;
justify-content: space-between;
padding:0px 20px;
border-bottom: 1px solid #ddd;
}
.monaco-editor{
width:1138px!important;
}
}
.ant-modal-close{
top:7px;
}
.listPart{
.listNav{
display: flex;
li{
background-color: #fafafa;
border:1px solid #eee;
border-radius: 5px;
height: 38px;
line-height:38px;
padding:0px 20px;
color: #333;
margin-right: 20px;
cursor: pointer;
&:last-child{
margin-right: 0px;
}
&.active{
border:1px solid #5091FF;
color: #5091FF;
background-color: #fff;
}
}
}
.normalTable{
margin-top: 20px;
.ant-table-thead > tr > th, .ant-table-tbody > tr > td{
padding:10px 5px;
color:#333;
}
.ant-table-thead{
border:1px solid rgba(238,238,238,1)
}
}
}
}
// 列表
.listPart{
.statusTag{
display: flex;
padding:0px 16px;
height: 32px;
line-height: 32px;
border-radius:20px;
float: left;
i{
font-size: 20px!important;
margin-right: 7px;
}
&.running{
background:#F1F8FF;
border:1px solid #5091FF;
color: #5091FF;
}
&.Preparing{
background:rgba(255,248,244,1);
border:1px solid rgba(255,110,33,1);
color:rgba(255,110,33,1) ;
}
&.pass{
background:#EEFDF5;
border:1px solid #28BD6C;
color:#28BD6C ;
}
&.failed{
background:#FCEEEE;
border:1px solid #F73030;
color:#F73030 ;
}
}
}
}
// ops详情
.opsDetailPanel{
height: 100vh;
background-color: #114879;
.opsInfos{
height: 60px;
background-color: #114879;
color:#fff;
padding:0px 20px;
}
.opsSection{
height:calc( 100% - 60px );
background-color: #fff;
display: flex;
section{
height: 100%;
float: left;
&.leftSection{
width:100%;
.leftheader{
background-color: #F1F8FF;
padding:10px 20px;
.nest{
color: #888888;
margin-right: 18px;
&>span{
color: #333;
}
}
}
.leftMainContent{
padding:14px 20px;
.contentBranch{
border:1px solid #eee;
background-color: #fafafa;
padding:0px 18px;
height: 40px;
border-radius: 3px;
color:#888;
i{
font-size: 16px;
color:#BBB;
margin-right: 10px;
}
.branchname{
color:#333;
margin-right: 15px;
}
.branchsha{
color:#FF6E21;
}
}
}
.leftMenu{
li.ant-menu-item,.ant-menu-submenu{
padding:0px 13px 0px 20px!important;
position: relative;
color: #333;
}
.ant-menu-submenu-title{
margin:0px;
padding:0px 0px 0px 20px!important
}
.ant-menu-submenu-arrow{
position: absolute;
left: 2px;
}
.ant-menu.ant-menu-sub{
.ant-menu-item:hover{
background-color: #F1F8FF;
}
}
}
.statuslineColor{
display: inline-block;
height: 20px;
line-height: 20px;
padding:0px 10px;
border-radius: 11px;
font-size: 12px;
margin-left: 6px;
&.pass{
border:1px solid rgba(40,189,108,1);
color:rgba(40,189,108,1);
}
&.failed{
border:1px solid #F73030;
color:#F73030;
}
&.running{
border:1px solid #5091FF;
color:#5091FF;
}
&.Preparing{
border:1px solid rgba(255,110,33,1);
color:rgba(255,110,33,1);
}
}
}
&.rightSection{
width:100%;
background-color: #081930;
.rightMainContent{
padding:24px 30px;
& > div{
margin-bottom: 12px;
.items{
height: 45px;
line-height: 45px;
padding:0px 24px;
background:rgba(24,41,62,1);
border-radius:5px;
color:#fff;
cursor: pointer;
i{
font-size: 13px;
margin-left: 10px;
}
}
}
}
}
}
.Resizer.vertical{
position: relative;
}
.Resizer.vertical:hover:before{
background: #eee;
}
.Resizer.vertical:before {
content: "";
border-radius: 50%;
background: hsla(0,0%,92.2%,.3);
width: 24px;
height: 24px;
position: absolute;
z-index: 999;
top: 50%;
margin-top: -12px;
right: -12px;
}
.Resizer.vertical::after{
position: absolute;
content: "\e712";
font-family: iconfont;
font-size: 10px;
transform: scale(.8);
top: 50%;
margin-top: -10px;
color: #666;
right: -12px;
opacity: .3;
z-index: 1000;
cursor: col-resize;
}
}
}

View File

@ -0,0 +1,33 @@
import React from 'react';
import './ops.scss';
import { FlexAJ, AlignCenter } from '../Component/layout';
import { Tags } from '../Component/OpsStatus';
import SplitPane from 'react-split-pane';
import LeftPanel from './OpsDetailLeftpanel';
import RightPanel from './OpsDetailRightpanel';
export default (()=>{
return(
<div className="opsDetailPanel">
<FlexAJ className="opsInfos">
<AlignCenter>
<span>#1</span>
<span className="ml10">将分支221063-improve-buy-ci-minutes-link合并到221063-improve-buy-ci-minutes-link"</span>
{Tags(1)}
</AlignCenter>
<a style={{color:"#ddd"}}><i className="iconfont icon-yiguanbi font-15 mr5"></i>退出</a>
</FlexAJ>
<div className="opsSection">
<SplitPane className="outer-split-pane" split="vertical" minSize={468} maxSize={-350} defaultSize="40%">
<section className="leftSection">
<LeftPanel />
</section>
<section className="rightSection">
<RightPanel />
</section>
</SplitPane>
</div>
</div>
)
});

View File

@ -1,9 +1,13 @@
import axios from 'axios';
//
export const getBranch = async (id)=>{
return (await axios.get(`/projects/${id}/branches.json`)).data;
}
//
export const getTag = async (id)=>{
return (await axios.get(`/repositories/${id}/tags.json`)).data;
}
// hooks-web
export const getHooks = async (id,params)=>{
return (await axios.get(`/projects/${id}/hooks.json`,{params})).data;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
src/forge/Images/docker.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
src/forge/Images/gradle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
src/forge/Images/java.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
src/forge/Images/js.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
src/forge/Images/php.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
src/forge/Images/python.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -6,15 +6,15 @@ import { withRouter } from "react-router";
import { SnackbarHOC } from "educoder";
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
import "./css/index.css";
import Handbook from './Component/Handbook';
import "./css/index.scss";
import Loadable from "react-loadable";
import Loading from "../Loading";
import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC";
const ProjectNew = Loadable({
loader: () => import("./New/Index"),
loader: () => import("./New/Index"),
loading: Loading,
});
const ProjectIndex = Loadable({
@ -27,42 +27,47 @@ const ProjectDetail = Loadable({
loading: Loading,
});
const Infos = Loadable({
loader: () => import("./users/Infos"),
loading: Loading,
});
class Index extends Component {
render() {
return (
<div className="newMain clearfix">
<Handbook />
<Switch {...this.props}>
<Route
path="/projects/:projectsType/new"
render={(props) => (
<ProjectNew {...this.props} {...props} {...this.state} />
<ProjectNew {...this.props} {...props} />
)}
></Route>
<Route
path="/projects/:projectsId"
render={(props) => (
<ProjectDetail {...this.props} {...props} {...this.state} />
<ProjectDetail {...this.props} {...props} />
)}
></Route>
<Route
exact
path="/projects"
render={(props) => (
<ProjectIndex {...this.props} {...props} {...this.state} />
<ProjectIndex {...this.props} {...props} />
)}
></Route>
<Route
exact
path="/"
render={(props) => (
<ProjectIndex
{...this.props}
{...props}
{...this.state}
></ProjectIndex>
this.props.current_user && this.props.current_user.login ?
<Infos {...this.props} {...props} />
:
<ProjectIndex {...this.props} {...props} />
)}
/>
></Route>
</Switch>
</div>
);

View File

@ -1,8 +1,9 @@
import React , { Component } from 'react';
import { Spin } from 'antd';
import { Spin , Pagination } from 'antd';
import { getImageUrl } from 'educoder';
import { truncateCommitId } from '../common/util'
import SelectBranch from '../Branch/Select';
import Nodata from '../Nodata';
import axios from 'axios';
import {Link} from "react-router-dom";
@ -12,23 +13,26 @@ class CoderRootCommit extends Component{
super(props)
this.state={
branch:"master",
data:undefined,
commitDatas:undefined,
dataCount:undefined,
limit:50,
limit:20,
page:1,
isSpin:false
isSpining:false
}
}
componentDidMount=()=>{
const { branch , page , limit } = this.state;
this.setState({
isSpin:true
isSpining:true
})
this.getCommitList( branch , page , limit );
}
getCommitList=(branch , page , limit)=>{
this.setState({
isSpining:true
})
const { projectsId } = this.props.match.params;
const url = `/repositories/${projectsId}/commits.json`;
axios.get(url,{
@ -38,9 +42,12 @@ class CoderRootCommit extends Component{
limit
}
}).then((result)=>{
if(result){
if(result && result.data){
this.setState({
isSpining:false
})
const array = [];
result.data && result.data.commits.length > 0 && result.data.commits.map((item,key)=>{
result.data.commits && result.data.commits.length > 0 && result.data.commits.map((item,key)=>{
array.push({
name:item.author && item.author.name,
login: item.author && item.author.login,
@ -51,9 +58,9 @@ class CoderRootCommit extends Component{
})
})
this.setState({
data:array,
commitDatas:array,
dataCount:result.data.total_count,
isSpin:false
isSpining:false
})
}
}).catch((error)=>{console.log(error)})
@ -62,42 +69,28 @@ class CoderRootCommit extends Component{
// 切换分支 search:tag为根据标签搜索
changeBranch=(value)=>{
const { page , limit } = this.state;
const { getTopCount } = this.props;
this.setState({
isSpin:true,
isSpining:true,
branch:value,
})
this.getCommitList(value , page , limit);
getTopCount && getTopCount(value);
}
ChangePage=(page)=>{
const { branch , limit } = this.state;
this.getCommitList(branch , page , limit);
}
render(){
const { branch , data , dataCount , limit , page , isSpin } = this.state;
const { branchs , projectDetail } = this.props;
const { branch , commitDatas , dataCount , limit , page , isSpining } = this.state;
const { branchs , projectDetail, commit_class } = this.props;
const { projectsId } = this.props.match.params;
const title =()=>{
return(
<div className="f-wrap-between" style={{alignItems:"center"}}>
<span className="font-16">{dataCount}次提交代码({branch})</span>
</div>
)
}
const Pagination =()=> {
if(dataCount > limit){
return(
<div className="edu-txt-center pt30 mb30">
<Pagination simple defaultCurrent={page} total={dataCount} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div>
)
}
}
return(
<React.Fragment>
<div className="main">
<div className={commit_class}>
<div className="f-wrap-between">
<SelectBranch
repo_id={projectDetail && projectDetail.repo_id}
@ -106,34 +99,41 @@ class CoderRootCommit extends Component{
changeBranch={this.changeBranch}
></SelectBranch>
</div>
<Spin spinning={isSpin}>
<Spin spinning={isSpining}>
<div className="commonBox">
<div className="commonBox-title">
{title()}
<div className="f-wrap-between" style={{alignItems:"center"}}>
<span className="font-16">{dataCount}次提交代码({branch})</span>
</div>
</div>
<div className="commitList">
{
data && data.length > 0 && data.map((item,key)=>{
commitDatas && commitDatas.length > 0 ? commitDatas.map((item,k)=>{
return(
<div>
<p className="df">
<div key={k}>
<p className="f-wrap-alignCenter">
<span className="commitKey" style={{marginLeft:0}}>{truncateCommitId(`${item.sha}`)}</span>
<span className="flex1 ml20 font-16 color-grey-3">{item.message}</span>
{/* <Link to={''} className="color-blue">浏览代码</Link> */}
</p>
<p className="f-wrap-alignCenter mt15">
<Link to={`/users/${item.login}`} className="show-user-link">
{item.image_url?<img src={getImageUrl(`images/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
<label className="font-14 color-grey-6" style={{'verticalAlign':'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
</Link>
</p>
</p>
</div>
)
})
}):<Nodata _html="暂无数据"/>
}
</div>
</div>
{ Pagination() }
{
dataCount > limit ?
<div className="edu-txt-center pt30 mb30">
<Pagination simple defaultCurrent={page} total={dataCount} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div>
:""
}
</Spin>
</div>
</React.Fragment>

View File

@ -42,7 +42,9 @@ class CoderRootDirectory extends Component {
readOnly: true,
zip_url:undefined,
tar_url:undefined,
chooseType:undefined
chooseType:undefined,
md:false
}
}
changeAddress = (address) => {
@ -90,6 +92,9 @@ class CoderRootDirectory extends Component {
// 页面地址返回到主目录
returnMain = (branch) => {
const { projectsId } = this.props.match.params;
this.setState({
readOnly:true
})
this.props.history.push(`/projects/${projectsId}/coders`);
this.getProjectRoot(branch);
};
@ -114,11 +119,9 @@ class CoderRootDirectory extends Component {
isSpin: false,
branchLastCommit: last_commit && last_commit.commit,
lastCommitAuthor:
last_commit &&
(last_commit.author ||
(last_commit.commit && last_commit.commit.author)),
last_commit && (last_commit.author || (last_commit.commit && last_commit.commit.author)),
zip_url: result.data.zip_url,
tar_url: result.data.tar_url,
tar_url: result.data.tar_url
});
if (entries && entries.length > 0) {
this.renderData(entries);
@ -138,6 +141,7 @@ class CoderRootDirectory extends Component {
this.props.history.push(`/projects/${projectsId}/coders?url=${arr.path}`);
this.setState({
readOnly: readOnly,
chooseType:"file"
});
};
@ -231,7 +235,7 @@ class CoderRootDirectory extends Component {
message: item.commit && item.commit.message,
...item,
});
if (item.name === "README.md") {
if (item.is_readme_file) {
readMeContent.push({ ...item });
readMeFile.push({ ...item });
}
@ -244,12 +248,21 @@ class CoderRootDirectory extends Component {
};
// 点击跳转到子目录
goToSubRoot=(path,type)=>{
goToSubRoot=(path,type,filename)=>{
this.setState({
chooseType:type
})
const { projectsId } = this.props.match.params;
this.props.history.push(`/projects/${projectsId}/coders?url=${path}`);
if(filename.substring(filename.length - 3) === ".md"){
this.setState({
md:true
})
}else{
this.setState({
md:false
})
}
};
// readme文件内容
@ -263,7 +276,7 @@ class CoderRootDirectory extends Component {
<div className="commonBox">
<div className="commonBox-title">
<span className="mr10">
<i className="iconfont icon-xinjianjianliwodejianli font-20 color-grey-9 fl mt3"></i>
<i className="iconfont icon-wenjian1 font-16 color-grey-9 fl mt3"></i>
</span>
<span className="commonBox-title-read">
{readMeContent[0].name}
@ -273,7 +286,7 @@ class CoderRootDirectory extends Component {
onClick={() => this.ChangeFile(readMeFile[0], false)}
className="ml20 pull-right"
>
<i className="iconfont icon-bianji2 font-20 color-blue"></i>
<i className="iconfont icon-bianji6 font-16 color-blue"></i>
</a>
) : (
""
@ -299,7 +312,11 @@ class CoderRootDirectory extends Component {
this.setState({
branch: value,
isSpin: true,
readOnly:true
});
const { getTopCount } = this.props;
getTopCount && getTopCount(value);
let { search } = this.props.history.location;
if (search && search.indexOf("?url=") > -1) {
let url = search.split("?url=")[1];
@ -315,101 +332,21 @@ class CoderRootDirectory extends Component {
// 子目录路径返回链接
returnUlr=(url)=>{
this.setState({
chooseType:"dir"
chooseType:"dir",
readOnly:true
})
const { projectsId } = this.props.match.params;
this.props.history.push(`/projects/${projectsId}/coders?url=${url}`);
}
render(){
const { branchLastCommit , lastCommitAuthor , rootList , branch ,filePath , fileDetail , subFileType , readMeContent, isSpin , zip_url , tar_url} = this.state;
const { isManager , isDeveloper , projectDetail } = this.props;
const { projectsId } = this.props.match.params;
const columns = [
{
dataIndex: 'name',
width:"30%",
render: (text,item) => (
<a onClick={()=>this.goToSubRoot(item.path,item.type)} className="ml12">
<i className={ item.type === "file" ? "iconfont icon-wenjia font-15 color-green-file mr5":"iconfont icon-wenjianjia1 color-green-file font-15 mr5"}></i>{text}
</a>
),
},
{
dataIndex: "commit",
width: "60%",
render: (text, item) =>
item.commit && item.commit.message ? (
<span
className="task-hide"
style={{ display: "block", maxWidth: "670px" }}
>
{item.commit.message}
</span>
) : (
""
),
},
{
dataIndex: "commit",
width: "10%",
className: "edu-txt-right",
render: (text, item) =>
item.commit && item.commit.time_from_now ? (
<a
title={item.commit.created_at}
className="mr12"
style={{ cursor: "default", color: "#888" }}
>
{item.commit.time_from_now}
</a>
) : (
""
),
},
];
const title = () => {
if (branchLastCommit) {
return (
<div className="f-wrap-alignCenter">
{lastCommitAuthor ? (
<React.Fragment>
{lastCommitAuthor.login ? (
<Link
to={`/users/${lastCommitAuthor.login}/projects`}
className="show-user-link"
>
<img
src={getImageUrl(`images/${lastCommitAuthor.image_url}`)}
className="radius mr10"
width="32"
height="32"
alt=""
/>
<span className="mr15">{lastCommitAuthor.name}</span>
</Link>
) : (
<span className="mr15">{lastCommitAuthor.name}</span>
)}
</React.Fragment>
) : (
""
)}
<span className="color-blue flex-1 hide-1">
{branchLastCommit.message}
</span>
<span>{branchLastCommit.time_from_now}</span>
<span className="commitKey">
{truncateCommitId(branchLastCommit.sha)}
</span>
</div>
);
} else {
return undefined;
}
};
onEdit=(readOnly)=>{
this.setState({
readOnly
})
}
const downloadUrl = () => (
downloadUrl = (zip_url,tar_url) => {
return(
<Menu>
{zip_url && (
<Menu.Item>
@ -422,7 +359,88 @@ class CoderRootDirectory extends Component {
</Menu.Item>
)}
</Menu>
);
)
}
title = (branchLastCommit,lastCommitAuthor) => {
console.log(branchLastCommit)
if (branchLastCommit) {
return (
<div className="f-wrap-alignCenter">
{lastCommitAuthor ? (
<React.Fragment>
{lastCommitAuthor.login ? (
<Link
to={`/users/${lastCommitAuthor.login}/projects`}
className="show-user-link"
>
<img
src={getImageUrl(`images/${lastCommitAuthor.image_url}`)}
className="radius mr10"
width="32"
height="32"
alt=""
/>
<span className="mr15">{lastCommitAuthor.name}</span>
</Link>
) : (
<span className="mr15">{lastCommitAuthor.name}</span>
)}
</React.Fragment>
) : (
""
)}
<span className="color-blue flex-1 hide-1">
{branchLastCommit.message}
</span>
<span>{branchLastCommit.time_from_now}</span>
<span className="commitKey">
{truncateCommitId(branchLastCommit.sha)}
</span>
</div>
);
}else{
return false;
}
}
render(){
const { branchLastCommit , lastCommitAuthor , rootList , branch ,filePath , fileDetail , subFileType , readMeContent, isSpin , zip_url , tar_url} = this.state;
const { isManager , isDeveloper , projectDetail } = this.props;
const { projectsId } = this.props.match.params;
const columns = [
{
dataIndex: 'name',
width:"30%",
render: (text,item) => (
<a onClick={()=>this.goToSubRoot(item.path,item.type,text)} className="ml12 task-hide" style={{ display: "block", maxWidth: "345px" }}>
<i className={ item.type === "file" ? "iconfont icon-wenjia font-15 color-green-file mr5":"iconfont icon-wenjianjia1 color-green-file font-15 mr5"}></i>{text}
</a>
),
},
{
dataIndex: "commit",
width: "60%",
render: (text, item) =>
item.commit && item.commit.message ?
<span className="task-hide" style={{ display: "block", maxWidth: "670px" }} >
{item.commit.message}
</span>
: ""
},
{
dataIndex: "commit",
width: "10%",
className: "edu-txt-right",
render: (text, item) =>
item.commit && item.commit.time_from_now ?
<a title={item.commit.created_at} className="mr12" style={{ cursor: "default", color: "#888" }} >
{item.commit.time_from_now}
</a>
:""
},
];
const urlRoot = filePath === undefined ? "" : `/${filePath}`;
let array = filePath && filePath.split("/");
@ -431,11 +449,11 @@ class CoderRootDirectory extends Component {
<div className="main">
<div className="f-wrap-between mb20">
<div className="f-wrap-alignCenter">
<SelectBranch
repo_id={projectDetail && projectDetail.repo_id}
projectsId={projectsId}
<SelectBranch
repo_id={projectDetail && projectDetail.repo_id}
projectsId={projectsId}
branch={branch}
changeBranch={this.changeBranch}
changeBranch={this.changeBranch}
></SelectBranch>
{filePath && (
@ -463,7 +481,7 @@ class CoderRootDirectory extends Component {
)}
</div>
<div className="f-wrap-alignCenter">
{subFileType && (isManager || isDeveloper) && (
{subFileType && (projectDetail && parseInt(projectDetail.type)) !== 2 && (isManager || isDeveloper) && (
<div>
<span>
<Link
@ -484,7 +502,7 @@ class CoderRootDirectory extends Component {
{projectDetail && projectDetail.clone_url && (
<CloneAddress
http_url={projectDetail.clone_url}
downloadUrl={downloadUrl}
downloadUrl={this.downloadUrl(zip_url,tar_url)}
showNotification={this.props.showNotification}
></CloneAddress>
)}
@ -495,7 +513,7 @@ class CoderRootDirectory extends Component {
<RootTable
columns={columns}
data={rootList}
title={() => title()}
title={() => this.title(branchLastCommit,lastCommitAuthor)}
></RootTable>
)}
{/* 子目录列表、文件 */}
@ -505,6 +523,7 @@ class CoderRootDirectory extends Component {
{...this.props}
{...this.state}
readOnly={this.state.readOnly}
onEdit={this.onEdit}
></CoderRootFileDetail>
)}
{/* readme.txt (isManager || isDeveloper)*/}

View File

@ -1,8 +1,11 @@
import React, { Component } from "react";
import { Popconfirm, Select } from "antd";
import { Popconfirm, Select } from "antd";
import "./list.css";
import axios from "axios";
import Meditor from "../Newfile/m_editor";
import MDEditor from "../../modules/tpm/challengesnew/tpm-md-editor";
import RenderHtml from "../../components/render-html";
function bytesToSize(bytes) {
if (bytes === 0) return "0 B";
@ -15,34 +18,98 @@ class CoderRootFileDetail extends Component {
constructor(props) {
super(props);
this.state = {
readOnly: true,
value: undefined,
language: undefined
language: undefined,
languages: undefined,
description:props.detail.content
};
}
componentDidMount = () => {
const { detail, readOnly } = this.props;
const { detail } = this.props;
this.setState({
value: detail.content,
readOnly: readOnly,
});
this.languages_total();
};
languages_total = () => {
const { detail } = this.props;
const file_name = detail.path.split("/").pop().split(".").pop();
let languages = [];
let default_language = "javascript";
let all_languages = {
apex: ["apex", "apxc"],
azcli: ["azcli"],
bat: ["bat"],
clojure: ["clj"],
coffee: ["coffee"],
cpp: ["cpp"],
csharp: ["cs"],
csp: ["csp"],
css: ["css"],
dockerfile: ["dockerfile", "docker", "yml"],
fsharp: ["fs"],
go: ["go"],
html: ["html", "htm", "erb"],
ini: ["ini"],
java: ["java", "class"],
javascript: ["js"],
json: ["json"],
less: ["less"],
lua: ["lua"],
markdown: ["markdown", "md", "rmd"],
msdax: ["dax"],
mysql: ["sql"],
objective: ["m", "mm", "o", "out"],
perl: ["perl"],
pgsql: ["sql"],
php: ["php"],
postiats: ["postiats"],
powerquery: [""],
powershell: ["ps1"],
pug: ["pug"],
python: ["py"],
r: ["r"],
razor: ["cshtml"],
redis: ["rdb"],
ruby: ["rb"],
rust: ["rs"],
sb: ["sb"],
scheme: ["scm", "ss"],
scss: ["scss"],
shell: ["sh"],
solidity: ["sol"],
sql: ["sql"],
st: ["st"],
swift: ["swift"],
typescript: ["ts"],
vb: ["vbp", "frm", "frx", "bas", "cls"],
xml: ["xml"],
yaml: ["yml"],
};
for (var item in all_languages) {
languages.push(item);
let item_values = all_languages[item];
if (item_values.indexOf(file_name) !== -1) {
default_language = item;
}
}
this.state.languages = languages;
this.state.language = default_language;
};
select_language = (e) => {
this.setState({
language: e,
});
};
EditFile = () => {
this.setState({
readOnly: false,
});
};
CancelEdit = () => {
this.setState({
readOnly: true,
});
EditFile = (flag) => {
const { onEdit } = this.props;
onEdit && onEdit(flag);
// this.setState({
// readOnly: false,
// });
};
// 编辑文件
@ -77,81 +144,44 @@ class CoderRootFileDetail extends Component {
});
};
updateCode = (value) => {
this.setState({
value,
});
};
onContentChange = (value) => {
this.setState({
description: value,
});
};
render() {
const { detail, current_user, isManager, isDeveloper } = this.props;
const { readOnly, language } = this.state;
const {
readOnly,
detail,
current_user,
isManager,
isDeveloper,
md
} = this.props;
const { language, languages , description } = this.state;
let flag = current_user && current_user.login && (isManager || isDeveloper);
const Option = Select.Option;
const languages = [
"apex",
"azcli",
"bat",
"clojure",
"coffee",
"cpp",
"csharp",
"csp",
"css",
"dockerfile",
"fsharp",
"go",
"handlebars",
"html",
"ini",
"java",
"javascript",
"json",
"less",
"lua",
"markdown",
"msdax",
"mysql",
"objective",
"perl",
"pgsql",
"php",
"postiats",
"powerquery",
"powershell",
"pug",
"python",
"r",
"razor",
"redis",
"redshift",
"ruby",
"rust",
"sb",
"scheme",
"scss",
"shell",
"solidity",
"sql",
"st",
"swift",
"typescript",
"vb",
"xml",
"yaml",
];
return (
<div className="mb20">
<div className="grid-item branchTitle">
<div className="grid-item">
<span className="ml20 color-grey-6 font-16">{bytesToSize(detail && detail.size)}</span>
<span className="ml20 color-grey-6 font-16">
{bytesToSize(detail && detail.size)}
</span>
</div>
<p className="text-right">
{flag && (
<div>
{readOnly ? (
<a onClick={this.EditFile} className="ml20">
<a onClick={() => this.EditFile(false)} className="ml20">
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
</a>
) : (
@ -164,14 +194,19 @@ class CoderRootFileDetail extends Component {
onChange={this.select_language}
>
<Option value={undefined}>请选择文本语言</Option>
{languages.map((item, key) => {
return <Option value={item}>{item}</Option>;
})}
{languages &&
languages.map((item, key) => {
return (
<Option value={item} key={key}>
{item}
</Option>
);
})}
</Select>
<button
type="button"
className="ant-btn ant-btn-sm ml20"
onClick={this.CancelEdit}
onClick={() => this.EditFile(true)}
>
<span> </span>
</button>
@ -191,22 +226,29 @@ class CoderRootFileDetail extends Component {
</Popconfirm>
</div>
)}
{
detail.image_type && detail.direct_download ?
<div className="ml20">
<a href={detail.download_url} className="color-blue font-15">
下载原始文件
</a>
</div>:""
}
</p>
</div>
<div>
{detail.image_type && detail.direct_download ? (
{detail.image_type ? (
<div className="edu-txt-center pt20 pb20">
<img alt="" src={detail.download_url} style={{maxWidth:"80%"}}/>
<img
alt=""
src={detail.download_url}
style={{ maxWidth: "80%" }}
/>
</div>
) : detail.direct_download ? (
<div className="mt20 text-center">
<a href={detail.download_url} className="color-blue font-15">
下载原始文件
</a>
</div>
) : (
md && readOnly ?
<div className="files-md">
<RenderHtml className="file-md" value={description} />
</div>
:
<Meditor
{...this.props}
{...this.state}

View File

@ -1,11 +1,18 @@
import React , { Component } from 'react';
import { Route , Switch } from 'react-router-dom';
import Top from './DetailTop';
import Loadable from 'react-loadable';
import Loading from '../../Loading';
import Top from './DetailTop';
import axios from 'axios';
const FileNew = Loadable({
loader: () => import('../Newfile/Index'),
loading: Loading,
})
const UploadFile = Loadable({
loader: () => import('../Newfile/upload_file'),
loading: Loading,
})
const CoderRootDirectory = Loadable({
loader: () => import('./CoderRootDirectory'),
loading: Loading,
@ -40,58 +47,102 @@ const Diff = Loadable({
})
class CoderRootIndex extends Component{
constructor(props){
super(props);
this.state={
coderCount:undefined
}
}
componentDidMount=()=>{
let { search } = this.props.history.location;
let branchName = undefined;
if (search && search.indexOf("?branch=") > -1) {
branchName = search.split("?branch=")[1];
}
this.getTopCount(branchName);
}
getTopCount=(branch)=>{
const { projectsId } = this.props.match.params;
const url = `/repositories/${projectsId}/top_counts.json`;
axios.get(url,{params:{
ref:branch
}}).then(result=>{
if(result){
this.setState({
coderCount:result.data
})
}
}).catch(error=>{console.log(error);})
}
render(){
return(
<div>
<Top {...this.props} {...this.state}/>
<Switch {...this.props}>
{/* 新建文件 */}
<Route path="/projects/:projectsId/coders/:branch/newfile/:path"
render={
(props) => (<FileNew {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/coders/:branch/uploadfile"
render={
(props) => (<UploadFile {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/coders/:branch/newfile"
render={
(props) => (<FileNew {...this.props} {...props} {...this.state} getTopCount={this.getTopCount} />)
}
></Route>
<Route path="/projects/:projectsId/coders/commit"
render={
(props) => (<CoderRootCommit {...this.props} {...props} {...this.state} />)
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
}
></Route>
{/* diff */}
<Route path="/projects/:projectsId/diff/:sha"
render={
(props) => (<Diff {...this.props} {...props} {...this.state}/>)
() => (<Diff {...this.props} {...this.state}/>)
}
></Route>
<Route path="/projects/:projectsId/coders/version/new"
render={
(props) => (<CoderRootVersionNew {...this.props} {...props} {...this.state} />)
() => (<CoderRootVersionNew {...this.props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/coders/version/:versionId/update"
render={
(props) => (<CoderRootVersionUpdate {...this.props} {...props} {...this.state} />)
() => (<CoderRootVersionUpdate {...this.props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/coders/version"
render={
(props) => (<CoderRootVersion {...this.props} {...props} {...this.state} />)
() => (<CoderRootVersion {...this.props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/coders/tag"
render={
(props) => (<CoderRootTag {...this.props} {...props} {...this.state} />)
() => (<CoderRootTag {...this.props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/coders/branch"
render={
(props) => (<CoderRootBranch {...this.props} {...props} {...this.state} />)
() => (<CoderRootBranch {...this.props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/coders"
render={
(props) => (<CoderRootDirectory {...this.props} {...props} {...this.state} />)
() => (<CoderRootDirectory {...this.props} {...this.state} getTopCount={this.getTopCount} />)
}
></Route>
<Route path="/projects/:projectsId"
render={
(props) => (<CoderRootDirectory {...this.props} {...props} {...this.state} />)
() => (<CoderRootDirectory {...this.props} {...this.state} getTopCount={this.getTopCount} />)
}
></Route>
</Switch>
@ -99,4 +150,4 @@ class CoderRootIndex extends Component{
)
}
}
export default CoderRootIndex;
export default CoderRootIndex;

View File

@ -35,7 +35,6 @@ export default ({
<ul className="ul_thead">
<li>
<span className="flex1">标签名</span>
{/* <span>描述</span> */}
<span>提交信息</span>
<span className="ul_tbody_forth">下载</span>
</li>
@ -49,10 +48,8 @@ export default ({
<i className="iconfont icon-biaoqian3 font-16 mr5 color-grey-8"></i>
<span className="font-16">{item.name}</span>
</span>
{/* <span className="font-16 task-hide">坎坎坷坷死二无一额坎坎坷坷死二无一额坎坎坷坷死二无一额</span> */}
<span className="ul_tbody_third">
<span className="commitKey" style={{ "marginLeft": 0 }}>{truncateCommitId(`${item.id}`)}</span>
{/* <span>2020-05-18 16:30</span> */}
</span>
<span className="ul_tbody_forth">
<a href={item.tarball_url} style={{ color: "#4CC1DA" }} className="mr30"><i className="iconfont icon-TAR font-18 mr5"></i>TAR</a>

View File

@ -1,8 +1,8 @@
import React, { Component } from 'react';
import { Spin, Tooltip } from 'antd';
import { Link, Route, Switch, withRouter } from 'react-router-dom';
import '../css/index.css'
import { Link, Route, Switch } from 'react-router-dom';
import { Content } from '../Component/layout';
import '../css/index.scss'
import './list.css';
import Loadable from 'react-loadable';
@ -21,14 +21,6 @@ import img_parised from '../Images/parised.png';
import img_focused from '../Images/focused.png';
import img_fork from '../Images/fork.png';
import img_milepost from '../Images/milepost.png';
const FileNew = Loadable({
loader: () => import('../Newfile/Index'),
loading: Loading,
})
const UploadFile = Loadable({
loader: () => import('../Newfile/upload_file'),
loading: Loading,
})
const Setting = Loadable({
loader: () => import('../Settings/Index'),
loading: Loading,
@ -94,21 +86,26 @@ const MessageCount = Loadable({
loading: Loading,
})
const UpdateMerge = Loadable({
loader: () => import('../Merge/UpdateMerge'),
loading: Loading,
})
const MilepostDetail = Loadable({
loader: () => import('../Order/MilepostDetail'),
loading: Loading,
})
const WatchUsers = Loadable({
loader: () => import('../UsersList/watch_users'),
loading: Loading,
loader: () => import('../UsersList/watch_users'),
loading: Loading,
})
const PraiseUsers = Loadable({
loader: () => import('../UsersList/praise_users'),
loading: Loading,
loader: () => import('../UsersList/praise_users'),
loading: Loading,
})
const ForkUsers = Loadable({
loader: () => import('../UsersList/fork_users'),
loading: Loading,
loader: () => import('../UsersList/fork_users'),
loading: Loading,
})
@ -117,6 +114,10 @@ const TrendsIndex = Loadable({
loading: Loading,
})
const DevIndex = Loadable({
loader: () => import('../DevOps/Index'),
loading: Loading,
})
/**
* permissionManager:管理员Reporter报告人员(只有读取权限)Developer开发人员除不能设置仓库信息外
*/
@ -125,7 +126,6 @@ class Detail extends Component {
constructor(props) {
super(props);
this.state = {
isSpin: true,
projectDetail: undefined,
isManager: false,
isReporter: false,
@ -140,19 +140,78 @@ class Detail extends Component {
author: undefined,
branchs: undefined,
branchList: undefined,
project: null,
firstSync:false,
secondSync:false,
}
}
componentDidMount = () => {
this.getDetail();
this.getProject();
}
componentDidUpdate = (prevState) => {
if ((prevState.match.params.projectsId !== this.props.match.params.projectsId)) {
this.getDetail();
this.getProject();
}
}
getProject = (num) => {
const { projectsId } = this.props.match.params;
const url = `/projects/${projectsId}/simple.json`;
axios.get(url).then((result) => {
if (result && result.data) {
this.setState({
project: result.data
})
if (result.data.type !== 0 && result.data.mirror_status === 1) {
console.log("--------start channel --------");
// 是镜像项目,且未完成迁移
this.canvasChannel();
if(num){
this.setState({
secondSync:true,
firsrtSync:false
})
}else{
this.setState({
firstSync:true,
secondSync:false
})
}
}else{
this.getDetail();
this.setState({
firsrtSync:false,
secondSync:false
})
}
}
})
}
canvasChannel = () => {
const name = window.location.hostname === "localhost" ? "testforgeplus.trustie.net" : window.location.hostname;
const actioncable = require("actioncable");
var project = this.state.project;
var cable = actioncable.createConsumer(`wss://${name}/cable`);
this.canvasChannel1 = cable.subscriptions.create({
channel: `MirrorProjectChannel`,
id: project && project.identifier
}, {
connected: () => {
console.log("###### channel connected! ######");
},
disconnected: () => { },
received: data => {
console.log(`###### ---received data--- ######`);
console.log(data);
if (data) {
this.getDetail();
cable.subscriptions.consumer.disconnect();
}
}
})
}
getDetail = () => {
const { projectsId } = this.props.match.params;
@ -172,7 +231,6 @@ class Detail extends Component {
watchers_count: result.data.watchers_count,
praises_count: result.data.praises_count,
forked_count: result.data.forked_count,
isSpin:false
})
}
}).catch((error) => { })
@ -181,23 +239,23 @@ class Detail extends Component {
// 关注和取消关注
focusFunc = (flag) => {
const { project_id } = this.state;
axios({
method: flag? 'delete' : 'post',
url: `/watchers/${flag? 'unfollow' : 'follow'}.json`,
axios({
method: flag ? 'delete' : 'post',
url: `/watchers/${flag ? 'unfollow' : 'follow'}.json`,
params: {
target_type: "project",
id: project_id
}
})
.then(result => {
if(result && result.data.status === 0){
this.setWatchersCount(result.data.watchers_count, result.data.watched);
}
})
.catch(error => {
console.log(error);
});
})
.then(result => {
if (result && result.data.status === 0) {
this.setWatchersCount(result.data.watchers_count, result.data.watched);
}
})
.catch(error => {
console.log(error);
});
}
// 点赞和取消点赞
@ -233,13 +291,6 @@ class Detail extends Component {
// fork项目
forkFunc = () => {
// if (!checkIfLogin) {
// this.props.showLoginDialog();
// return;
// }
this.setState({
isSpin: true
})
const { project_id } = this.state;
const url = `/projects/${project_id}/forks.json`;
axios.post(url).then(result => {
@ -247,61 +298,29 @@ class Detail extends Component {
this.props.history.push(`/projects/${result.data.id}/coders`);
this.props.showNotification(result.data.message);
}
this.setState({
isSpin: false
})
}).catch(error => {
this.setState({
isSpin: false
})
console.log(error);
})
}
// 获取分支列表
getBranch = (id) => {
const url = `/projects/${id}/branches.json`;
axios.get(url).then((result) => {
if (result && result.data.length > 0) {
const branchs = [];
result.data.map((item, key) => {
branchs.push({
index: key,
name: item.name
})
})
this.setState({
branchList: result.data,
branchs,
})
}
}).catch((error) => { })
}
// 同步镜像
synchronismMirror=()=>{
synchronismMirror = () => {
const { repo_id } = this.state.projectDetail;
this.setState({
isSpin:true
})
const url = `/repositories/${repo_id}/sync_mirror.json`;
axios.post(url).then(result=>{
if(result && result.data && result.data.status === 0){
this.props.showNotification("镜像同步成功!");
this.getDetail();
}else{
const url = `/repositories/${repo_id}/sync_mirror.json`;
axios.post(url).then(result => {
if (result && result.data && result.data.status === 0) {
this.getProject(2);
} else {
this.props.showNotification("镜像同步失败!");
this.setState({
isSpin:false
})
}
}).catch(error=>{
}).catch(error => {
console.log(error);
})
}
render() {
const { projectDetail, watchers_count, praises_count, forked_count, isSpin, isManager, watched, praised } = this.state;
const { projectDetail, watchers_count, praises_count, forked_count, firstSync , secondSync , isManager, watched, praised, project } = this.state;
const url = this.props.history.location.pathname;
const urlArr = url.split("/");
const urlFlag = (urlArr.length === 3);
@ -321,58 +340,58 @@ class Detail extends Component {
</React.Fragment> : ""
);
const mirror = (
<React.Fragment>
<span>镜像自 </span>
<a href={projectDetail && projectDetail.mirror_url} target="_blank" style={{color:"#fff"}}>{projectDetail && projectDetail.mirror_url}</a>
</React.Fragment>
)
const common ={
getDetail:this.getDetail
const common = {
getDetail: this.getDetail
}
return (
<div>
<Spin spinning={isSpin}>
<div className="detailHeader-wrapper">
<div className="normal">
<div className="f-wrap-between mb15" style={{ position: "relative" }}>
<p className="font-18 color-white df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
{projectDetail && projectDetail.author &&
<Link to={`/users/${projectDetail.author.login}`} className="show-user-link color-white">
{projectDetail.author.name}
</Link>
<div className="detailHeader-wrapper">
<div className="normal">
<div className="f-wrap-between pb15" style={{ position: "relative" }}>
<p className="font-22 color-white df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
{project && project.author &&
<Link to={`/users/${project.author.login}`} className="show-user-link color-white">
{project.author.name}
</Link>
}
<span className="ml5 mr5">/</span>
<span className="hide-1 flex-1 df">
<Link to={`/projects/${projectsId}/coders`} className="color-white font-22">{project && project.name}</Link>
{
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
<Tooltip placement={'right'} title={text}>
<Link to={`/projects/${projectDetail.forked_from_project_id}/coders`}
className="ml10" >
<i className="iconfont icon-fork font-18 fl mt6" style={{ color: "#8D90E3" }}></i>
</Link>
</Tooltip> : ""
}
<span className="ml5 mr5">/</span>
<span className="hide-1 flex-1 df">
<Link to={`/projects/${projectsId}/coders`} className="color-white font-22">{projectDetail && projectDetail.name}</Link>
{
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
<Tooltip placement={'right'} title={text}>
<Link to={`/projects/${projectDetail.forked_from_project_id}/coders`}
className="ml10" >
<i className="iconfont icon-fork font-18 fl mt6" style={{ color: "#8D90E3" }}></i>
</Link>
</Tooltip> : ""
}
{
projectDetail && checkLogin && projectDetail.type && projectDetail.type === 2 ?
<Tooltip placement={'right'} title={mirror}>
<i className="iconfont icon-jingxiang font-18 fl mt6 ml10" style={{ color: "#8D90E3" }}></i>
</Tooltip>:""
}
</span>
</p>
{
projectDetail && projectDetail.type && projectDetail.type !== 0 ?
projectDetail.type === 2 ?
<Tooltip title={"镜像自: " + projectDetail.mirror_url} className="ml5" placement={'right'}>
<i className="iconfont icon-banbenku font-18 mt6" style={{ color: "#8D90E3" }}/>
</Tooltip>:
<Tooltip title={"镜像自: " + projectDetail.mirror_url} className="ml5" placement={'right'}>
<i className="iconfont icon-jingxiang font-18 color-green mt6" />
</Tooltip>
:""
}
</span>
</p>
{
firstSync ? "":
<span className="df mt25">
{
projectDetail && projectDetail.type && projectDetail.type === 2 ?
<a className="synchronism ml30" onClick={this.synchronismMirror}>同步镜像</a>:""
<a className="synchronism ml30" onClick={this.synchronismMirror}>同步镜像</a> : ""
}
<span className="detail_tag_btn">
<a className="detail_tag_btn_name" onClick={() => this.focusFunc(watched)}>
<img src={watched ? img_focused : img_focus} alt="" width="14px" />
{watched ? '取消关注' : '关注'}
</a>
<Link className="detail_tag_btn_count" to={{pathname:`/projects/${projectsId}/watch_users`, state}}>
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${projectsId}/watch_users`, state }}>
{watchers_count}
</Link>
</span>
@ -381,228 +400,225 @@ class Detail extends Component {
<img src={praised ? img_parised : img_parise} width="13px" alt="" />
{praised ? '取消点赞' : '点赞'}
</a>
<Link className="detail_tag_btn_count" to={{pathname:`/projects/${projectsId}/praise_users`,state}}>
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${projectsId}/praise_users`, state }}>
{praises_count}
</Link>
</Link>
</span>
<span className="detail_tag_btn">
<a className="detail_tag_btn_name" onClick={this.forkFunc}>
<img src={img_fork} alt="" width="10px"/>Fork</a>
<Link className="detail_tag_btn_count" to={{pathname:`/projects/${projectsId}/fork_users`,state}}>
<img src={img_fork} alt="" width="10px" />Fork</a>
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${projectsId}/fork_users`, state }}>
{forked_count}
</Link>
</Link>
</span>
</span>
</div>
<div className="f-wrap-between">
}
</div>
{
firstSync ? "" :
<div className="f-wrap-between pb20">
<ul className="headerMenu-wrapper">
<li className={(url.indexOf("coders") > -1 || urlFlag) ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/coders`, state }}>
<img alt="" src={img_1} width="18" />代码库
{ projectDetail && projectDetail.commits_count ? <span>{projectDetail.commits_count}</span>:""}
</Link>
</Link>
</li>
<li className={(url.indexOf("orders") > -1 && !(url.indexOf("Milepost") > 0 || url.indexOf("meilpost") > 0 || url.indexOf("tags") > 0)) ? "active" : ""}>
<li className={(url.indexOf("/orders") > -1 && !(url.indexOf("Milepost") > 0 || url.indexOf("meilpost") > 0 || url.indexOf("tags") > 0)) ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/orders`, state }}>
<img alt="" src={img_2} width="12" />任务
{ projectDetail && projectDetail.issues_count ? <span>{projectDetail.issues_count}</span> :""}
</Link>
</li>
<li className={url.indexOf("merge") > -1 ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/merge`, state }}>
<img alt="" src={img_3} width="13" />合并请求
{ projectDetail && projectDetail.pull_requests_count ? <span>{projectDetail.issues_count}</span> : "" }
</Link>
</li>
<li className={(url.indexOf("Milepost") > -1 || url.indexOf("meilpost") > -1) ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/orders/Milepost`, state }}>
<img alt="" src={img_milepost} width="16" />里程碑
{projectDetail && projectDetail.version_count && <span>{projectDetail.version_count}</span>}
</Link>
</li>
<li className={url.indexOf("trends") > -1 ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/trends`, state }}>
<img alt="" src={img_6} width="16" />动态
{projectDetail && projectDetail.issues_count ? <span>{projectDetail.issues_count}</span> : ""}
</Link>
</li>
{
projectDetail && parseInt(projectDetail.type) !== 2 &&
<li className={url.indexOf("merge") > -1 ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/merge`, state }}>
<img alt="" src={img_3} width="13" />合并请求
{projectDetail && projectDetail.pull_requests_count ? <span>{projectDetail.pull_requests_count}</span> : ""}
</Link>
</li>
}
{/* <li className={url.indexOf("/ops") > -1 ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/ops`, state }}>
<i className="iconfont icon-gongzuoliu font-13 mr8"></i>
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
</Link>
</li> */}
<li className={(url.indexOf("/Milepost") > -1 || url.indexOf("meilpost") > -1) ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/orders/Milepost`, state }}>
<img alt="" src={img_milepost} width="16" />里程碑
{projectDetail && projectDetail.versions_count ? <span>{projectDetail.versions_count}</span> :""}
</Link>
</li>
<li className={url.indexOf("/trends") > -1 ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/trends`, state }}>
<img alt="" src={img_6} width="16" />动态
</Link>
</li>
{
isManager &&
<li className={url.indexOf("setting") > 0 ? "active" : ""}><Link to={`/projects/${projectsId}/setting`}><img alt="" src={img_7} width="19" />仓库设置</Link></li>
<li className={url.indexOf("/setting") > 0 ? "active" : ""}><Link to={`/projects/${projectsId}/setting`}><img alt="" src={img_7} width="19" />仓库设置</Link></li>
}
</ul>
</div>
</div>
}
</div>
</div>
{
firstSync ?
<Content className="spincontent">
<Spin className="spinstyle" tip={project && `正在从 ${project.mirror_url} 迁移`} size="large">
</Spin>
</Content>
:
<Spin spinning={secondSync} className="spinstyle" tip="正在同步镜像" size="large">
<Switch {...this.props}>
{/* 工作流 */}
<Route path="/projects/:projectsId/ops"
render={
() => (<DevIndex {...this.props} {...this.state} {...common} />)
}
></Route>
{/* 标签列表 */}
<Route path="/projects/:projectsId/orders/tags"
render={
(props) => (<TagList {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 仓库设置 */}
<Route path="/projects/:projectsId/setting"
render={
(props) => (<Setting {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 任务详情 */}
<Route path="/projects/:projectsId/orders/:orderId/detail"
render={
(props) => (<OrderDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 里程碑 */}
<Route path="/projects/:projectsId/orders/Milepost"
render={
(props) => (<OrderMilepost {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 新建里程碑 */}
<Route path="/projects/:projectsId/orders/meilpost"
render={
(props) => (<OrdernewMilepost {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/*里程碑详情*/}
<Route path="/projects/:projectsId/orders/:meilid/MilepostDetail"
render={
(props) => (<MilepostDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/*修改里程碑*/}
<Route path="/projects/:projectsId/orders/:meilid/meilpost"
render={
(props) => (<OrderupdateMilepost {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 里程碑页面新建任务 */}
<Route path="/projects/:projectsId/orders/:milepostId/new"
render={
(props) => (<OrderNew {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 新建任务 */}
<Route path="/projects/:projectsId/orders/new"
render={
(props) => (<OrderNew {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 修改详情 */}
<Route path="/projects/:projectsId/orders/:orderId/updatedetail"
render={
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 复制详情 */}
<Route path="/projects/:projectsId/orders/:orderId/copyetail"
render={
(props) => (<OrdercopyDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 动态 */}
<Route path="/projects/:projectsId/trends"
render={
(props) => (<TrendsIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 代码Index */}
<Route path="/projects/:projectsId/orders"
render={
(props) => (<OrderIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/merge/new"
render={
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
}
></Route>
<Route path="/projects/:projectsId/merge/:mergeId/UpdateMerge"
render={
(props) => (<UpdateMerge {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/merge/:mergeId/Messagecount"
render={
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/merge/:mergeId/MergeSubmit"
render={
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Switch {...this.props}>
{/* 新建文件 */}
<Route path="/projects/:projectsId/coders/:branch/newfile/:path"
render={
(props) => (<FileNew {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:projectsId/coders/:branch/uploadfile"
render={
(props) => (<UploadFile {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:projectsId/coders/:branch/newfile"
render={
(props) => (<FileNew {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
{/* 标签列表 */}
<Route path="/projects/:projectsId/orders/tags"
render={
(props) => (<TagList {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
{/* 仓库设置 */}
<Route path="/projects/:projectsId/setting"
render={
(props) => (<Setting {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 任务详情 */}
<Route path="/projects/:projectsId/orders/:orderId/detail"
render={
(props) => (<OrderDetail {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
{/* 里程碑 */}
<Route path="/projects/:projectsId/orders/Milepost"
render={
(props) => (<OrderMilepost {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
{/* 新建里程碑 */}
<Route path="/projects/:projectsId/orders/meilpost"
render={
(props) => (<OrdernewMilepost {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
{/*里程碑详情*/}
<Route path="/projects/:projectsId/orders/:meilid/MilepostDetail"
render={
(props) => (<MilepostDetail {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
{/*修改里程碑*/}
<Route path="/projects/:projectsId/orders/:meilid/meilpost"
render={
(props) => (<OrderupdateMilepost {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
{/* 里程碑页面新建任务 */}
<Route path="/projects/:projectsId/orders/:milepostId/new"
render={
(props) => (<OrderNew {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
{/* 新建任务 */}
<Route path="/projects/:projectsId/orders/new"
render={
(props) => (<OrderNew {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
{/* 修改详情 */}
<Route path="/projects/:projectsId/orders/:orderId/updatedetail"
render={
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
{/* 复制详情 */}
<Route path="/projects/:projectsId/orders/:orderId/copyetail"
render={
(props) => (<OrdercopyDetail {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
{/* 动态 */}
<Route path="/projects/:projectsId/trends"
render={
(props) => (<TrendsIndex {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
{/* 代码Index */}
<Route path="/projects/:projectsId/orders"
render={
(props) => (<OrderIndex {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:projectsId/merge/new"
render={
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:projectsId/merge/:mergeId/UpdateMerge"
render={
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:projectsId/merge/:mergeId/Messagecount"
render={
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:projectsId/merge/:mergeId/MergeSubmit"
render={
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:projectsId/merge"
render={
(props) => (<MergeIndexDetail {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:projectsId/coders/filesurl"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:projectsId/coders"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:projectsId/watch_users"
render={
(props) => (<WatchUsers {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:projectsId/praise_users"
render={
(props) => (<PraiseUsers {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:projectsId/fork_users"
render={
(props) => (<ForkUsers {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:projectsId"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
</Switch>
</Spin>
<Route path="/projects/:projectsId/merge"
render={
(props) => (<MergeIndexDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/coders/filesurl"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/coders"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/watch_users"
render={
(props) => (<WatchUsers {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/praise_users"
render={
(props) => (<PraiseUsers {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/fork_users"
render={
(props) => (<ForkUsers {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
</Switch>
</Spin>
}
</div>
)
}
}
export default withRouter(Detail);
export default Detail;

View File

@ -3,34 +3,30 @@ import { Link } from 'react-router-dom';
class DetailTop extends Component {
render() {
const { projectDetail } = this.props;
const { coderCount } = this.props;
const { projectsId } = this.props.match.params;
const { pathname } = this.props.location;
return (
<p className="branch-wrapper">
<Link to={`/projects/${projectsId}/coders/commit`} className={pathname.indexOf("/coders/commit") > 0 ? "active" : ""}>
<i className="iconfont icon-tijiaojilu font-20 mr3 font-bd"></i>
<span>{projectDetail && projectDetail.commits_count}</span>
<span>{(coderCount && coderCount.commits_count) || 0}</span>
</Link>
<Link to={`/projects/${projectsId}/coders/branch`} className={pathname.indexOf("/coders/branch") > 0 ? "active" : ""}>
<i className="iconfont icon-fenzhi1 font-18 mr3"></i>
<span>{projectDetail && projectDetail.branches_count}</span>
<span>{(coderCount && coderCount.branches_count) || 0}</span>
</Link>
<Link to={`/projects/${projectsId}/coders/tag`} className={pathname.indexOf("/coders/tag") > 0 ? "active" : ""}>
<i className="iconfont icon-biaoqian3 font-18 mr3"></i>
<span>{projectDetail && projectDetail.issue_tags_count}</span>
<span>{(coderCount && coderCount.tags_count) || 0}</span>
</Link>
<Link to={`/projects/${projectsId}/coders/version`} className={pathname.indexOf("/coders/version") > 0 ? "active" : ""}>
<i className="iconfont icon-fahangban font-18 mr3"></i>
<span>{projectDetail && projectDetail.version_releasesed_count}</span>
<span>{(coderCount && coderCount.version_releasesed_count) || 0}</span>
</Link>
{/* <Link to={`/projects/${projectsId}/coders/contributor`} className={pathname.indexOf("/coders/contributor") > 0 ? "active" : ""}>
<i className="iconfont icon-gongxianzhe font-18 mr3"></i>
<span>{projectDetail && projectDetail.contributor_users_count}</span>
</Link> */}
<a href="javscript:void(0)" style={{cursor:"default"}}>
<i className="iconfont icon-cangku font-18 mr3"></i>
仓库 <span className="ml3">{projectDetail && projectDetail.size}</span>
仓库 <span className="ml3">{(coderCount && coderCount.size) || 0}</span>
</a>
</p>
)

View File

@ -50,7 +50,7 @@ const DetailP = styled.p`
`;
export default ({ projectDetail, match }) => {
const [data, setData] = useState(undefined);
const [data, setData] = useState({undefined});
const [commit, setCommit] = useState(undefined);
const [files, setFiles] = useState(undefined);
const [parents, setParents] = useState(undefined);

View File

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Menu, Input , Spin, Pagination , Popover } from 'antd';
import '../css/index.css'
import '../css/index.scss'
import './list.css';
import ListItem from './IndexItem'
import axios from 'axios';
@ -196,7 +196,7 @@ class Index extends Component {
const pagination = (
total && total > limit ?
<div className="edu-txt-center pt30 mb30">
<div className="edu-txt-center pt30 mb30 border-top-grey">
<Pagination simple defaultCurrent={page} total={total} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div> : ""
)

View File

@ -2,7 +2,7 @@ import React, { Component } from 'react';
import { Tooltip } from 'antd';
import { getImageUrl } from 'educoder';
import { Link } from 'react-router-dom';
import '../css/index.css'
import '../css/index.scss'
import './list.css';
import img_parise from '../Images/parise.png';
@ -34,8 +34,8 @@ class IndexItem extends Component {
: ""
}
{
item.type && item.type !==0 ?
item.type ==2?
item.type && item.type !== 0 ?
item.type === 2 ?
<Tooltip title="该项目是一个镜像" className="ml5">
<i className="iconfont icon-banbenku font-18 color-green" />
</Tooltip>:
@ -44,16 +44,12 @@ class IndexItem extends Component {
</span>:""
}
</Link>
{
item.is_public ? "" :
<span className="p-r-tags"><span>私有</span></span>
}
<span className="p-r-tags">
<span className="pariseTag"><img src={img_parise} alt="" className="pariseImg" /> ({item.praises_count})</span>
<span><i className="iconfont icon-fork mr3 font-16" style={{ color: "#1B8FFF" }} />fork ({item.forked_count})</span>
</span>
</div>
<p className="break_word task-hide-2 mt10" style={{ maxHeight: "40px" }}>{item.description}</p>
<p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p>
<div className="p-r-about">
<span className="p-r-detail">
@ -69,7 +65,7 @@ class IndexItem extends Component {
}) : ""
)
return (
<div className="project-list">
<div className="project-list minH-670">
{renderList}
</div>
)

View File

@ -11,7 +11,7 @@ class RootTable extends Component{
showHeader={false}
size="small"
pagination={false}
title={() => title()}
title={title}
/>
)
}

View File

@ -23,61 +23,7 @@
background: #fff;
padding:10px;
}
.list-l-Menu{
margin-bottom: 12px;
border-radius:2px;
border:1px solid rgba(221,221,221,1);
background-color: #fff;
}
.list-l-Menu>li{
font-size: 1rem;
padding:0px 0px 0px 20px;
box-sizing: border-box;
color: #333;
position: relative;
}
.list-l-Menu>li > p{
height: 62px;
line-height: 62px;
width: 100%;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
cursor: pointer;
padding-right: 20px;
}
.list-l-Menu>li:last-child > p{
border-bottom: none;
}
.list-l-Menu li p span:last-child{
color: #999;
}
.list-l-Menu .MenuTitle{
font-size: 16px;
background-size: 100% 100%;
color: #333!important;
height: 62px;
line-height: 62px;
border-bottom: 1px solid #E0E0E0;
font-weight: 400;
}
.list-l-Menu > li:not(.MenuTitle):hover{
background-color: #fafafa;
}
/* 左侧menu */
.list-l-Menu .ant-menu-inline{
border:none;
}
.list-l-Menu .ant-menu-inline .ant-menu-item{
width:100%!important;
}
.list-l-Menu .ant-menu-item-group-title{
padding:0px;
}
.list-l-Menu li.active{
background-color: #fafafa;
}
/* 首页列表的新建和排序的下拉列表 */
.ant-menu-inline, .ant-menu-vertical, .ant-menu-vertical-left{
@ -95,16 +41,6 @@
}
.list-l-Menu li.active::before{
position: absolute;
left: 0px;
top: 10px;
width: 6px;
content: '';
height: 33px;
background: #4CACFF;
}
.list-r-operation{
display: flex;
justify-content: space-between;
@ -137,6 +73,12 @@
.project-list{
padding:0px 30px;
}
.border-top-grey{
border-top: 1px solid rgba(238,238,238,1);
}
.p-r-Item:last-child{
border-bottom: none !important;
}
.p-r-Item{
display: flex;
border-bottom:1px solid rgba(238,238,238,1);
@ -256,10 +198,15 @@
margin-top: 8px;
color: #666;
}
.spincontent{
height:400px;
}
.spinstyle .ant-spin-text{
margin-top:30px;
color: #888;
}
/* -----------详情------------ */
.detailHeader-wrapper{
height: 125px;
background:linear-gradient(82deg,rgba(82,91,215,1) 0%,rgba(34,24,171,1) 100%);
}
.headerMenu-wrapper{
@ -305,6 +252,9 @@
align-items: center;
margin-left: 30px
}
.ant-tooltip {
max-width: fit-content!important;
}
.detail_tag_btn_name{
padding:0px 10px;
display: flex;
@ -325,6 +275,10 @@
/* color: #1C91FF !important; */
background: rgba(255,255,255,0.5);
}
.files-md{
border:1px solid #eee;
padding:20px;
}
/* 详情-代码 */
.branch-wrapper{
border:1px solid #eee;
@ -378,6 +332,7 @@
border:1px solid #eee;
background: #fff;
margin-left: 20px;
position: relative;
}
.gitAddressClone > span{
display: flex;
@ -387,6 +342,53 @@
cursor: pointer;
align-items: center;
}
.addressTips{
position: absolute;
font-size: 12px;
color: #FF6E21;
top:-34px;
left: 30px;
background-color: #fff;
border:1px solid #FE881D;
padding:0px 5px;
height: 28px;
line-height: 28px;
}
.addressTips>span{position: relative;display: block;}
.addressTips>span::before{
box-sizing: content-box;
width: 0px;
height: 0px;
position: absolute;
top: 25px;
left:50%;
margin-left: -4px;
padding:0;
border-top:8px solid #FFFFFF;
border-bottom:8px solid transparent;
border-left:8px solid transparent;
border-right:8px solid transparent;
display: block;
content:'';
z-index: 12;
}
.addressTips>span::after{
box-sizing: content-box;
width: 0px;
height: 0px;
position: absolute;
top: 26px;
left:50%;
margin-left: -4px;
padding:0;
border-top:8px solid #FE881D;
border-bottom:8px solid transparent;
border-left:8px solid transparent;
border-right:8px solid transparent;
display: block;
content:'';
z-index: 11;
}
.gitAddressClone > span.addressType{
color: #4CACFF;
}

View File

@ -1,6 +1,8 @@
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { Popconfirm } from "antd";
import { Popconfirm, Tag } from "antd";
import { getImageUrl } from "educoder";
import "./merge.css";
class MergeItem extends Component {
constructor(props) {
@ -29,7 +31,7 @@ class MergeItem extends Component {
if (issue_tags && issue_tags.length > 0) {
return issue_tags.map((item, key) => {
return (
<span className="issue-tag-show" style={{ background: item.color }}>
<span className="issue-tag-show" style={{ color: item.color }}>
{item.name}
</span>
);
@ -40,7 +42,7 @@ class MergeItem extends Component {
};
render() {
const { issues, search_count, page, limit } = this.props;
const { issues, project_name, project_author_name } = this.props;
const { projectsId } = this.props.match.params;
const { current_user } = this.props;
const renderList = () => {
@ -49,34 +51,82 @@ class MergeItem extends Component {
return (
<div className="issueItem">
<div className="flex-1">
<p className="mb15 df">
<span
className={
item.issue_status === "关闭"
? "issueNo"
: "issueNo issueOpen"
}
>
# {search_count - (key + (page - 1) * limit)}
</span>
<p className="mb15 df" style={{ alignItems: "center" }}>
<Link
to={`/projects/${projectsId}/merge/${item.pull_request_id}/Messagecount`}
className="flex-1 hide-1 font-16 color-grey-3 lineh-30"
className="hide-1 font-15 color-grey-3 fwb lineh-30 mr10"
style={{ maxWidth: "300px" }}
>
{item.name}
</Link>
<Tag className={`pr_tags_${item.pull_request_staus}`}>
{item.pull_request_staus === "merged"
? "已合并"
: item.pull_request_staus === "closed"
? "已拒绝"
: "开启的"}
</Tag>
</p>
<p className="color-grey-6 font-12">
<span>{item.format_time}</span>
<span className="ml5">发布</span>
{item.updated_at === item.format_time ? (
""
) : (
<span className="ml20">
<span>{item.updated_at}</span>
<span className="ml5">更新</span>
<p className="grid-item font-13">
<Link
to={`/users/${item && item.author_login}`}
className="show-user-link"
>
<img
className="radius"
src={getImageUrl(`images/${item && item.avatar_url}`)}
alt=""
width="24"
height="24"
/>
</Link>
<span>
<Link
to={`/users/${item && item.author_login}`}
className="show-user-link color-grey-8 ml5"
>
{item && item.author_name}
</Link>
<span className="ml15 color-grey-8">
{item.pull_request_staus === "open"
? "创建于"
: item.pull_request_staus === "merged"
? "合并于"
: "更新于"}
</span>
)}
<span className="color-grey-8">{item.pr_time}</span>
<span className="ml15">
<Tag className="pr-branch-tag">
<Link
to={`/projects/${
item.is_original ? item.fork_project_id : projectsId
}/coders?branch=${item.pull_request_head}`}
className="maxW200px hide-1 ver-middle"
>
{item.is_original
? item.fork_project_user
: project_author_name}
:{item.pull_request_head}
</Link>
</Tag>
<span className="mr8 ver-middle">
<i
className={
"iconfont icon-youjiang color-grey-c font-16"
}
></i>
</span>
<Tag className="pr-branch-tag">
<Link
to={`/projects/${projectsId}/coders?branch=${item.pull_request_base}`}
className="maxW200px hide-1 ver-middle"
>
{/* {item.is_fork ? item.pull_request_base : `${item.author_name}:${item.pull_request_base}`} */}
{project_author_name}:{item.pull_request_base}
</Link>
</Tag>
</span>
</span>
</p>
</div>
<ul
@ -84,9 +134,8 @@ class MergeItem extends Component {
onMouseMove={() => this.onMouseMove(item.id)}
onMouseOut={() => this.onMouseOut()}
>
<li>{item.priority}</li>
<li>{this.set_issue_tags(item.issue_tags)}</li>
{/*<li>{item.issue_type || "--"}</li>*/}
<li>{item.version || "--"}</li>
<li>
{item.assign_user_name ? (
<Link
@ -99,14 +148,19 @@ class MergeItem extends Component {
"--"
)}
</li>
<li>{item.version || "--"}</li>
<li>
<div className="flex1 df" style={{justifyContent:"center"}}>
<div
className="flex1 df"
style={{ justifyContent: "center" }}
>
{item.journals_count ? (
<Link
className="mr5"
className="mr5 color-grey-8"
to={`/projects/${projectsId}/merge/${item.pull_request_id}/Messagecount`}
>
<i className="iconfont icon-pinglun1 mr3 font-16"></i>
<i className="iconfont icon-huifu1 font-15 mr5 ver-middle"></i>
{item.journals_count}
</Link>
) : (

File diff suppressed because it is too large Load Diff

View File

@ -1,431 +1,292 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Radio, Form, Menu, Dropdown, Input, Select, Table, Spin } from 'antd';
import axios from 'axios';
import UploadComponent from '../Upload/Index';
import { getImageUrl } from 'educoder';
import '../Order/order.css';
import MDEditor from '../../modules/tpm/challengesnew/tpm-md-editor';
const { Button } = Radio;
import React, { Component } from "react";
import { Input, Select, Button, Spin, Alert } from "antd";
import axios from "axios";
import "../Order/order.css";
import "./merge.css";
import MergeForm from "./merge_form";
import MergeFooter from "./merge_footer";
const Option = Select.Option;
const options = [
['bold', 'italic', 'underline'],
[{ header: [1, 2, 3, false] }],
['blockquote', 'code-block'],
['link', 'image'],
['formula']
];
class NewMerge extends Component {
constructor(props) {
super(props);
this.state = {
data: undefined,
//合并 拉取
merge: undefined,
pull: undefined,
//判断 是否显示创建合并请求的页面
desc: undefined,
iscreatemerge: 'none',
issue_tag_ids: "",
fixed_version_id: "",
assigned_to_id: "",
titledata: undefined,
dataCount: undefined,
limit: 50,
page: 1,
branches: undefined,
merge_branches: undefined,
merge_projects: undefined,
merge: "master",
pull: "master",
is_fork: false,
projects_names: undefined,
isSpin: false,
mergedata: undefined,
}
show_message: true,
merge_head: false, // 是否向fork后的源项目发起合并请求
default_message: "必须选择不同的分支",
project_id: undefined, // 当前项目的id也即开始发送合并请求的源项目id
merge_project_user: undefined
};
}
componentDidMount = () => {
this.getmergelist();
this.InitData();
}
InitData = () => {
this.props.form.setFieldsValue({
...this.state
});
}
onPanelChange = (time, mode) => {
this.setState({
value: time
});
}
onSelect = (time) => {
this.setState({
value: time,
selectedValue: time,
});
}
getOption = (name, id) => {
if (id === 'branches') {
this.ischeckmerge(name, this.state.pull)
this.setState({
merge: name
})
} else {
if (this.state.iscreatemerge === 'block') {
if (this.state.merge === name) {
} else {
const { page, limit } = this.state;
this.getCommitList(name, page, limit);
}
} else {
}
this.ischeckmerge(this.state.merge, name)
this.setState({
pull: name
})
}
}
ismerge = () => {
this.setState({
iscreatemerge: 'block'
})
const { page, limit } = this.state;
this.getCommitList(this.state.pull, page, limit);
}
const { projectsId } = this.props.match.params;
this.getmergelist(projectsId);
};
//获取新建分枝数据
getmergelist = () => {
const { projectsId } = this.props.match.params;
getmergelist = (projectsId) => {
this.setState({isSpin: true})
const url = `/projects/${projectsId}/pull_requests/new.json`;
axios.get(url).then((result) => {
if (result) {
this.setState({
data: result.data,
merge: result.data.branches[0],
pull: result.data.branches[0],
})
}
}).catch((error) => {
console.log(error);
})
}
renderMenu = (array, id) => {
return (
<Menu>
{
array && array.length > 0 && array.map((item, key) => {
return (
<Menu.Item key={item} onClick={() => this.getOption(item, id)}>{item}</Menu.Item>
)
})
axios
.get(url)
.then((result) => {
if (result) {
this.setState({
is_fork: result.data.is_fork,
projects_names: result.data.projects_names,
merge_projects: result.data.merge_projects,
branches: result.data.branches,
merge_branches: result.data.branches,
project_id: result.data.project_id,
});
this.set_default_pull()
this.set_default_merge()
}
</Menu>
)
}
this.setState({isSpin: false})
})
.catch((error) => {
this.setState({isSpin: false})
console.log(error);
});
};
renderSelect = (list) => {
if (list && list.length > 0) {
return (
list.map((item, key) => {
return (
<Option key={key + 1} value={item.id + ''}>{item.name}</Option>
)
})
)
set_default_pull = () => {
const {branches} = this.state;
let default_pull = branches.filter((e) => e.name === "master")
if (default_pull.length > 0){
this.state.pull = default_pull[0].name
}else{
this.state.pull = "master"
}
}
//创建合并请求
set_default_merge = () => {
const {merge_branches} = this.state;
let default_merge = merge_branches.filter((e) => e.name === "master")
if (default_merge.length > 0){
this.state.merge = default_merge[0].name
}else{
this.state.merge = "master"
}
this.ischeckmerge();
}
submit = () => {
this.setState({
isSpin: true
})
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
const { projectsId } = this.props.match.params;
const url = `/projects/${projectsId}/pull_requests.json`;
if (values.issue_tag_ids.length > 0) {
values.issue_tag_ids = [parseInt(values.issue_tag_ids)]
} else {
values.issue_tag_ids = []
}
const { desc } = this.state;
axios.post(url, {
...values,
body: JSON.stringify(desc),
project_id: projectsId,
head: this.state.merge,
base: this.state.pull,
}).then(result => {
if (result) {
this.setState({
isSpin: false
})
this.props.history.push(`/projects/${projectsId}/merge`);
const { getDetail } = this.props;
getDetail && getDetail();
}
}).catch(error => {
newMergelist = (projectsId) => {
this.setState({isSpin: true})
const url = `/projects/${projectsId}/pull_requests/get_branches.json`;
axios
.get(url)
.then((result) => {
if (result) {
this.setState({
isSpin: false
merge_branches: result.data
})
console.log(error);
})
} else {
this.setState({
isSpin: false
})
this.set_default_merge()
}
this.setState({isSpin: false})
})
.catch((error) => {
this.setState({isSpin: false})
console.log(error);
});
};
selectBrach = (type, value) => {
this.state[type] = value;
this.ischeckmerge();
};
selectProjectName = (value) => {
const { project_id, projects_names } = this.state;
let is_fork_id = parseInt(value) !== parseInt(project_id)
this.setState({
isSpin: true,
merge_head: is_fork_id,
data: {
is_original: is_fork_id,
fork_project_id: is_fork_id ? project_id : "",
merge_user_login: is_fork_id ? projects_names[0].project_user_login : undefined
}
})
}
//获取提交列表
getCommitList = (branch, page, limit) => {
const { projectsId } = this.props.match.params;
const url = `/repositories/${projectsId}/commits.json`;
axios.get(url, {
params: {
sha: branch,
page,
limit
}
}).then((result) => {
if (result) {
const array = [];
result.data && result.data.commits.length > 0 && result.data.commits.map((item, key) => {
array.push({
name: item.author && item.author.name,
login: item.author && item.author.login,
image_url: item.author && item.author.image_url,
sha: item.sha,
time_from_now: item.time_from_now,
message: item.message
})
})
this.setState({
titledata: array,
dataCount: result.data.total_count,
isSpin: false
})
}
}).catch((error) => { console.log(error) })
}
this.props.history.push(`/projects/${value}/merge/new`);
this.newMergelist(value);
};
//判断2分支是否可以合并
ischeckmerge = (head, base) => {
ischeckmerge = () => {
this.setState({ isSpin: true });
const { projectsId } = this.props.match.params;
const { pull, merge, project_id, merge_head } = this.state;
const url = `/projects/${projectsId}/pull_requests/check_can_merge.json`;
axios.post(url, {
project_id: projectsId,
head: head,
base: base,
}).then(result => {
if (result) {
this.setState({
mergedata: result.data
})
}
}).catch(error => {
console.log(error);
})
}
onContentChange = (value) => {
this.setState({
desc: value
})
}
axios
.post(url, {
head: pull,
base: merge,
is_original: merge_head,
fork_project_id: merge_head ? project_id : undefined
})
.then((result) => {
if (result) {
if (result.data.status === 0) {
this.setState({
isSpin: false,
show_message: false,
});
} else {
this.setState({
isSpin: false,
show_message: true,
default_message: result.data.message,
});
}
} else {
this.setState({
isSpin: false,
show_message: true,
default_message: "出现错误了",
});
}
})
.catch((error) => {
this.setState({ isSpin: false, show_message: true });
console.log(error);
});
};
render() {
const { getFieldDecorator } = this.props.form;
const {
data,
branches,
merge_branches,
merge_projects,
pull,
merge,
isSpin,
show_message,
default_message,
merge_head,
projects_names,
} = this.state;
const { projectsId } = this.props.match.params;
const { current_user } = this.props;
const { issue_tag_ids, fixed_version_id, assigned_to_id, data, titledata, desc, isSpin } = this.state;
const columns = [{
title: "作者",
dataIndex: 'name',
width: "10%",
render: (text, item) => (
<span className="f-wrap-alignCenter">
<Link to={`/users/${item.login}`} className="show-user-link">
<img src={getImageUrl(`images/${item.image_url}`)} alt="" width="28px" height="28px" className="mr3 radius" />
<label className="hide-1" style={{ maxWidth: "75px", 'vertical-align': 'middle' }}>{text}</label>
</Link>
</span>
),
}, {
title: "SHA",
dataIndex: 'sha',
render: (text) => (
<span className="commitKey">{text}</span>
)
}, {
title: "备注",
dataIndex: 'message',
render: (text) => (
<span>{text}</span>
)
}, {
title: "提交时间",
className: "edu-txt-right",
dataIndex: 'time_from_now',
render: (text) => (
<span>{text}</span>
)
}]
const title = () => {
return (
<div className="f-wrap-between" style={{ alignItems: "center" }}>
<span className="font-16">提交列表</span>
</div>
)
}
const pull = () => {
if (this.state.mergedata && this.state.mergedata.status === -2) {
return (
<div>
在这些分支直接合并请求已经存在<Link to={`/projects/${projectsId}/merge/${this.state.mergedata && this.state.mergedata.pull_request_id}/Messagecount`} style={{ color: 'blue' }}>{this.state.mergedata && this.state.mergedata.pull_request_name}</Link>
</div>
)
} else {
return (
<div>
{this.state.mergedata && this.state.mergedata.status === 0 ? <Button className="topWrapper_btn" onClick={() => this.ismerge()}>创建合并请求</Button> : ""}
</div>
)
const renderBrances = (list, type) => {
if (list && list.length > 0) {
return list.map((item, key) => {
return (
<Option
key={key + 1}
value={item.name}
>
{item.name}
</Option>
);
});
}
}
};
const renderProjectNames = (list) => {
if (list && list.length > 0) {
return list.map((item, key) => {
return (
<Option key={key + 1} value={item.project_id}>
{item.project_name}
</Option>
);
});
}
};
const withHtml = (html) => {
return <div dangerouslySetInnerHTML={{ __html: html }}></div>;
};
return (
<div className="main">
<h1 className="mb10">创建合并请求</h1>
<h5 className="mb10">选择合并的目标分支和源分支</h5>
<div style={{ display: 'flex' }}>
<div className="mergediv">
<div>
<Dropdown className="topWrapperSelect" overlay={this.renderMenu(this.state.data && this.state.data.branches, 'branches')} trigger={['click']} placement="bottomCenter">
<Button>合并到{this.state.merge}</Button>
</Dropdown>
...
<Dropdown overlay={this.renderMenu(this.state.data && this.state.data.branches, 'pull')} trigger={['click']} placement="bottomCenter">
<Button>拉取从{this.state.pull}</Button>
</Dropdown>
</div>
</div>
</div>
<div style={{ display: this.state.iscreatemerge === 'none' ? 'block' : 'none' }}>
<div className="mergediv" style={{ marginTop: 15 }} >
{pull()}
</div>
</div>
<div style={{ display: this.state.iscreatemerge === 'none' ? 'none' : 'block' }}>
<Form>
<div className="f-wrap-between mt20" style={{ alignItems: "flex-start" }}>
<div className="list-right df" style={{ padding: "0px", paddingTop: "10px" }}>
<Link to={`/users/${current_user && current_user.login}`} className="show-user-link">
<img className="user_img" src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt="" />
</Link>
<div className="new_context">
<Form.Item>
{getFieldDecorator('title', {
rules: [{
required: true, message: '请填写请求标题'
}],
})(
<Input placeholder="标题" />
)}
</Form.Item>
<MDEditor placeholder={'请输入合并请求的描述...'} height={350}
mdID={'merge-new-description'} initValue={desc} onChange={this.onContentChange} ></MDEditor>
<UploadComponent load={this.UploadFunc} isComplete={true} ></UploadComponent>
<p className="clearfix mt15">
<Spin spinning={isSpin}>
<a className="topWrapper_btn fr" type="submit" onClick={this.submit}>创建合并请求</a>
</Spin>
</p>
</div>
<div>
<div className="main">
<Spin spinning={isSpin}>
<div className="merge-header width100 inline-block">
<div className="width45 pull-left">
<div className="color-grey-3 mb10 fwb">源分支:</div>
<Input.Group compact className="display-flex">
<Select
defaultValue={parseInt(projectsId)}
class=" maxW50 hide-1 task-hide"
disabled
>
{renderProjectNames(projects_names)}
</Select>
<Select
defaultValue={pull}
onSelect={(e) => this.selectBrach("pull", e)}
showSearch
className="minW50 merge-flex1"
>
{renderBrances(branches, false)}
</Select>
</Input.Group>
</div>
<div className="list-left" style={{ paddingRight: "0px", paddingLeft: "15px", paddingTop: "10px" }}>
<div className="list-l-panel">
<Form.Item
label="标签"
>
{getFieldDecorator('issue_tag_ids', {
rules: [],
})(
<Select value={issue_tag_ids}>
<Option value="">{data && data.issue_tags.length > 0 ? '未选择标签' : '请在仓库设置里添加标签'}</Option>
{this.renderSelect(data && data.issue_tags)}
</Select>
)}
</Form.Item>
<Form.Item
label="里程碑"
>
{getFieldDecorator('fixed_version_id', {
rules: [],
})(
<Select value={fixed_version_id}>
<Option value="">{data && data.issue_versions.length > 0 ? '未选择里程碑' : '请添加里程碑'}</Option>
{this.renderSelect(data && data.issue_versions)}
</Select>
)}
</Form.Item>
<Form.Item
label="指派成员"
>
{getFieldDecorator('assigned_to_id', {
})(
<Select value={assigned_to_id}>
<Option value="">未指派成员</Option>
{this.renderSelect(data && data.members)}
</Select>
)}
</Form.Item>
<div className="width10 pull-left text-center mt25">
<i
className={"iconfont icon-youjiang color-grey-c font-32"}
></i>
</div>
<div className="width45 pull-left">
<div>
<div className="color-grey-3 mb10 fwb">目标分支:</div>
<Input.Group compact className="display-flex">
<Select
defaultValue={parseInt(projectsId)}
class=" maxW50 hide-1 task-hide"
onSelect={(e) => this.selectProjectName(e)}
>
{renderProjectNames(merge_projects)}
</Select>
<Select
defaultValue={merge}
value={merge}
onSelect={(e) => this.selectBrach("merge", e)}
showSearch
className="minW50 merge-flex1"
>
{renderBrances(merge_branches, merge_head)}
</Select>
</Input.Group>
</div>
</div>
</div>
</Form>
</div>
<div style={{ display: this.state.iscreatemerge === 'none' ? 'none' : 'block' }}>
<Table
className="mt20 wrap-commit-table"
columns={columns}
dataSource={titledata}
showHeader={false}
size="small"
pagination={false}
title={() => title()}
/>
{show_message ? (
<div className="mb20">
<Alert description={withHtml(default_message)} type="error" />
</div>
) : (
<MergeForm
{...this.props}
merge_type="new"
data={data}
merge={merge}
pull={pull}
></MergeForm>
)}
</Spin>
</div>
{/* <div className=" main">
<MergeFooter footer_type="new" {...this.props}></MergeFooter>
</div> */}
</div>
)
);
}
}
const WrappedNewMerge = Form.create({ name: 'NewMergeFrom' })(NewMerge);
export default WrappedNewMerge;
export default NewMerge;

View File

@ -1,275 +1,115 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import UploadComponent from '../Upload/Index';
import { getImageUrl } from 'educoder';
import { Modal, Form, Input, Select, Spin } from 'antd'
import MDEditor from '../../modules/tpm/challengesnew/tpm-md-editor';
import Attachments from '../Upload/attachment'
import React, { Component } from "react";
import { Input, Select, Button, Spin, Empty } from "antd";
import axios from "axios";
import "../Order/order.css";
import "./merge.css";
import MergeForm from "./merge_form";
import MergeFooter from "./merge_footer";
const Option = Select.Option;
class UpdateMerge extends Component {
constructor(props) {
super(props);
this.state = {
data: undefined,
isShow: false,
imgsrc: '',
journalsdata: undefined,
//图片区域是否显示 none 隐藏 block 显示
display: 'none',
titledisplay: 'none',
subject: '',
branch_name: "",
issue_tag_ids: "",
fixed_version_id: "",
tracker_id: 0,
issue_type: 0,
status_id: 0,
assigned_to_id: "",
priority_id: 0,
done_ratio: 0,
textcount: "",
fileList: undefined,
get_attachments: undefined,
desc: undefined,
isSpin: false
}
merge: undefined,
pull: undefined,
isSpin: false,
};
}
componentDidMount = () => {
this.getDetail();
}
this.getmergelist();
};
getDetail = () => {
//获取新建分枝数据
getmergelist = () => {
this.setState({ isSpin: true });
const { projectsId, mergeId } = this.props.match.params;
const url = `/projects/${projectsId}/pull_requests/${mergeId}/edit.json`;
axios.get(url).then((result) => {
if (result) {
this.setState({
data: result.data,
subject: result.data.issue.subject,
issue_chosen: result.data.issue.issue_chosen,
branches: result.data.issue.branches,
tracker_id: result.data.issue.tracker_id,
issue_type: result.data.issue.issue_type,
status_id: result.data.issue.status_id,
priority_id: result.data.issue.priority_id,
done_ratio: result.data.issue.done_ratio,
textcount: result.data.issue.description,
branch_name: result.data.issue.branch_name,
get_attachments: result.data.issue.attachments,
fileList: undefined,
issue_tag_ids: result.data.issue.issue_tags && result.data.issue.issue_tags[0].id,
fixed_version_id: result.data.issue.fixed_version_id,
assigned_to_id: result.data.issue.assigned_to_id
})
// this.getjournalslist();
}
}).catch((error) => {
console.log(error);
})
}
handleok = () => {
this.setState({
isShow: false
});
};
handleCancel = () => {
this.setState({
isShow: false
});
}
imgshow = () => {
this.setState({
isShow: true
});
};
onContentChange = (value) => {
this.setState({
textcount: value
})
}
changmodelname = (e) => {
this.setState({
subject: e.target.value
})
}
stringJson = (value) => {
let _value = null;
try {
_value = JSON.parse(value);
} catch (e) {
_value = value;
}
return _value
}
renderSelect = (list) => {
if (list && list.length > 0) {
return (
list.map((item, key) => {
return (
<Option key={key + 1} value={item.id}>{item.name}</Option>
)
})
)
}
}
// 获取上传后的文件id数组
UploadFunc = (fileList) => {
this.setState({
fileList
})
}
handleSubmit = () => {
const { fileList } = this.state;
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
const { projectsId, mergeId } = this.props.match.params;
const { data, textcount } = this.state;
const url = `/projects/${projectsId}/pull_requests/${mergeId}.json`;
if (values.issue_tag_ids === '') {
values.issue_tag_ids = []
axios
.get(url)
.then((result) => {
if (result) {
this.setState({
isSpin: false,
data: result.data,
pull: result.data.head,
merge: result.data.base,
});
} else {
this.setState({ isSpin: false });
}
if (values.assigned_to_id === 0) {
values.assigned_to_id = ""
}
axios.put(url, {
project_id: projectsId,
id: data.issue.id,
attachment_ids: fileList,
body: textcount,
...values
}).then(result => {
if (result) {
this.props.history.push(`/projects/${projectsId}/merge`);
this.setState({
textcount: ''
})
}
}).catch(error => {
console.log(error);
})
}
})
}
})
.catch((error) => {
this.setState({ isSpin: false });
console.log(error);
});
};
render() {
const { projectsId, mergeId } = this.props.match.params;
const { getFieldDecorator } = this.props.form;
const { current_user } = this.props;
const { issue_tag_ids, fixed_version_id, assigned_to_id, issue_chosen, subject, textcount, get_attachments, isSpin } = this.state;
const { data, isSpin, pull, merge } = this.state;
return (
<div className="main">
<div>
<Form>
<div className="f-wrap-between mt20" style={{ alignItems: "flex-start" }}>
<div className="list-right df" >
<Link to={`/users/${current_user && current_user.login}`} className="show-user-link">
<img className="user_img" src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt="" />
</Link>
<div className="new_context">
<Form.Item>
{getFieldDecorator('title', {
rules: [{
required: true, message: '请填写任务标题'
}],
initialValue: subject
})(
<Input placeholder="标题" onChange={this.changmodelname} />
)}
</Form.Item>
<MDEditor placeholder={'请输入合并请求的描述...'} height={350}
mdID={`orderdetail-add-description`} initValue={textcount} onChange={this.onContentChange} ></MDEditor>
<UploadComponent load={this.UploadFunc} showNotification={this.props.showNotification} isComplete={true} ></UploadComponent>
{
get_attachments ?
<Attachments attachments={get_attachments} showNotification={this.props.showNotification} canDelete={true} />
:
""
}
<p className="clearfix mt15 text-right">
<Spin spinning={isSpin}>
<a className="topWrapper_btn fr" type="submit" style={{ marginLeft: 5 }} onClick={this.handleSubmit}>保存</a>
<Link to={`/projects/${projectsId}/merge/${mergeId}/Messagecount`} className="a_btn cancel_btn fr">取消</Link>
</Spin>
</p>
<div>
<div className="main">
<Spin spinning={isSpin}>
{data ? (
<div>
<div className="merge-header width100 inline-block">
<div className="width45 pull-left">
<div className="color-grey-3 mb10 fwb">源分支:</div>
<Input.Group compact className="display-flex">
<Button className="merge-header-button maxW50 hide-1 task-hide">
{data.is_original ? `${data.fork_project_user_name}/${data.fork_project_identifier}` : `${data.project_author}/${data.project_name}`}
</Button>
<Select
defaultValue={data.is_original ? `${data.fork_project_user}:${pull}` : `${pull}`}
className="minW50 merge-flex1"
disabled
></Select>
</Input.Group>
</div>
<div className="width10 pull-left text-center mt25">
<i
className={"iconfont icon-youjiang color-grey-c font-32"}
></i>
</div>
<div className="width45 pull-left">
<div>
<div className="color-grey-3 mb10 fwb">目标分支:</div>
<Input.Group compact className="display-flex">
<Button className="merge-header-button maxW50 hide-1 task-hide">
{`${data.project_author}/${data.project_name}`}
</Button>
<Select
defaultValue={data.is_original ? `${data.project_login}:${merge}` : `${merge}`}
className="minW50 merge-flex1"
disabled
></Select>
</Input.Group>
</div>
</div>
</div>
<MergeForm
{...this.props}
merge_type="edit"
data={data}
merge={merge}
pull={pull}
></MergeForm>
</div>
<div className="list-left" style={{ paddingRight: "0px", paddingLeft: "15px", paddingTop: "10px" }}>
<div className="list-l-panel">
<Form.Item
label="标签"
>
{getFieldDecorator('issue_tag_ids', {
initialValue: issue_tag_ids ? [issue_tag_ids] : '',
rules: [],
})(
<Select>
<Option value={''}>{issue_chosen && issue_chosen.issue_tag.length > 0 ? '未选择标签' : '请在仓库设置里添加标签'}</Option>
{this.renderSelect(issue_chosen && issue_chosen.issue_tag)}
</Select>
)}
</Form.Item>
<Form.Item
label="里程碑"
>
{getFieldDecorator('fixed_version_id', {
initialValue: fixed_version_id ? fixed_version_id : "",
rules: [],
})(
<Select>
<Option value={''}>{issue_chosen && issue_chosen.issue_version.length > 0 ? '未选择里程碑' : '请添加里程碑'}</Option>
{this.renderSelect(issue_chosen && issue_chosen.issue_version)}
</Select>
)}
</Form.Item>
<Form.Item
label="指派成员"
>
{getFieldDecorator('assigned_to_id', {
initialValue: assigned_to_id ? assigned_to_id : "",
})(
<Select>
<Option value={''}>未指派成员</Option>
{this.renderSelect(issue_chosen && issue_chosen.assign_user)}
</Select>
)}
</Form.Item>
</div>
</div>
</div>
</Form>
) : (
""
)}
</Spin>
</div>
<Modal
onCancel={this.handleCancel}
visible={this.state.isShow}
width="400px"
footer={
[]
}
bodyStyle={{ textAlign: 'center' }}
>
<img class="list_img" src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1608431072,669449145&fm=27&gp=0.jpg" alt="" />
</Modal>
{/* <div className=" main">
<MergeFooter footer_type="new" {...this.props}></MergeFooter>
</div> */}
</div>
)
);
}
}
const UpdateMergeForm = Form.create({ name: 'UpdateMergeForm' })(UpdateMerge);
export default UpdateMergeForm;
export default UpdateMerge;

View File

@ -37,4 +37,7 @@
}
form .ant-cascader-picker, form .ant-select {
width: 100%;
}
.merge-header-button{
background:rgba(241,248,255,1);
}

View File

@ -1,12 +1,12 @@
import React, { Component } from "react";
import { Input, Dropdown, Menu, Icon, Pagination, Spin } from 'antd';
import './merge.css';
import '../Order/order.css';
import NoneData from '../Nodata';
import OrderItem from './MergeItem';
import { Input, Dropdown, Menu, Icon, Pagination, Spin } from "antd";
import "./merge.css";
import "../Order/order.css";
import "../Order/index.scss";
import NoneData from "./no_data";
import OrderItem from "./MergeItem";
import axios from 'axios';
import axios from "axios";
const Search = Input.Search;
/**
@ -37,68 +37,75 @@ class merge extends Component {
// page: 1,
search_count: undefined,
issue_type: undefined,
status_type: '1',
status_type: undefined,
//设置选择高亮
openselect: 1,
closeselect: undefined,
issue_tag_ids: '标签',
fixed_version_ids: '里程碑',
assigned_to_ids: '指派人',
paix: '排序',
issue_tag_ids: "标签",
fixed_version_ids: "里程碑",
assigned_to_ids: "审查人员",
paix: "排序",
priority_ids: "优先级",
select_params: {
status_type: "1", //开启中和关闭中,默认为开启中的
status_type: undefined, //开启中和关闭中,默认为开启中的
assigned_to_id: undefined, // 指派人
fixed_version_id: undefined,
priority_id: undefined,
order_name: undefined,
order_type: undefined,
search: undefined,
page: 1,
limit: 15,
},
}
};
}
componentDidMount = () => {
this.getSelectList();
this.getIssueList();
}
};
getSelectList = () => {
const { projectsId } = this.props.match.params;
const url = `/projects/${projectsId}/issues/index_chosen.json`;
axios.get(url).then((result) => {
if (result) {
this.setState({
issue_chosen: result.data.issue_chosen
})
}
}).catch((error) => {
console.log(error);
})
}
axios
.get(url)
.then((result) => {
if (result) {
this.setState({
issue_chosen: result.data.issue_chosen,
});
}
})
.catch((error) => {
console.log(error);
});
};
// 获取列表数据
getIssueList = () => {
const { select_params } = this.state;
const { projectsId } = this.props.match.params;
const url = `/projects/${projectsId}/pull_requests.json`;
axios.get(url, {
params: select_params,
}).then((result) => {
if (result) {
this.setState({
data: result.data,
issues: result.data.issues,
search_count: result.data.search_count,
isSpin: false
})
}
}).catch((error) => {
console.log(error);
})
}
axios
.get(url, {
params: select_params,
})
.then((result) => {
if (result) {
this.setState({
data: result.data,
issues: result.data.issues,
search_count: result.data.search_count,
isSpin: false,
});
}
})
.catch((error) => {
console.log(error);
});
};
getMenu = (e, id, name) => {
this.setState({
@ -145,22 +152,29 @@ class merge extends Component {
this.state.select_params.page = 1;
this.state[`${id}s`] = name;
this.getIssueList();
}
};
renderMenu = (array, name, id) => {
return (
<Menu>
<Menu.Item key={"all"} onClick={(e) => this.getOption(e, id, name)}>{name}</Menu.Item>
{
array && array.length > 0 && array.map((item, key) => {
<Menu.Item key={"all"} onClick={(e) => this.getOption(e, id, name)}>
{name}
</Menu.Item>
{array &&
array.length > 0 &&
array.map((item, key) => {
return (
<Menu.Item key={item.id} onClick={(e) => this.getOption(e, id, item.name)}>{item.name}</Menu.Item>
)
})
}
<Menu.Item
key={item.id}
onClick={(e) => this.getOption(e, id, item.name)}
>
{item.name}
</Menu.Item>
);
})}
</Menu>
)
}
);
};
// 翻页
ChangePage = (page) => {
@ -169,7 +183,7 @@ class merge extends Component {
});
this.state.select_params.page = page;
this.getIssueList();
}
};
// 搜索
searchFunc = (value) => {
@ -180,69 +194,51 @@ class merge extends Component {
this.state.select_params.search = value;
this.state.select_params.page = 1;
this.getIssueList();
}
};
openorder = (type) => {
// if (type) {
// if (type === 1) {
// this.setState({
// status_type: '1',
// closeselect: undefined,
// openselect: '123',
// issue_tag_ids: '标签',
// fixed_version_ids: '里程碑',
// assigned_to_ids: '指派人',
// paix: '排序'
// })
// this.getIssueList("", "", "", "", "", 1, "");
// } else {
// this.setState({
// status_type: '2',
// openselect: undefined,
// closeselect: '123',
// issue_tag_ids: '标签',
// fixed_version_ids: '里程碑',
// assigned_to_ids: '指派人',
// paix: '排序'
// })
// this.getIssueList("", "", "", "", "", 2, "");
// }
// }
this.setState({
isSpin: true,
});
if (type) {
this.setState({
status_type: type,
issue_tag_ids: '标签',
fixed_version_ids: '里程碑',
assigned_to_ids: '指派人',
paix: '排序'
});
this.state.select_params = {
status_type: type,
search: undefined,
page: 1,
limit: 15,
};
this.getIssueList();
}}
this.setState({
status_type: type,
issue_tag_ids: "标签",
fixed_version_ids: "里程碑",
assigned_to_ids: "审查人员",
paix: "排序",
priority_ids: "优先级",
});
this.state.select_params = {
status_type: type,
search: undefined,
page: 1,
limit: 15,
};
this.getIssueList();
};
islogin() {
const { projectsId } = this.props.match.params;
if (this.props.checkIfLogin() === false) {
this.props.showLoginDialog()
return
this.props.showLoginDialog();
return;
} else {
this.props.history.push(`/projects/${projectsId}/merge/new`);
}
}
render() {
const { issue_chosen, issues, limit, page, search_count, data, isSpin, status_type, select_params } = this.state;
const { projectsId } = this.props.match.params;
const {
issue_chosen,
issues,
limit,
page,
search_count,
data,
isSpin,
status_type,
select_params,
} = this.state;
const menu = (
<Menu onClick={(e) => this.getMenu(e)}>
<Menu.Item key={"created_on-desc"} value="desc">
@ -262,17 +258,176 @@ class merge extends Component {
const Paginations = (
<React.Fragment>
{
search_count > limit ?
<div className="mt30 mb50 edu-txt-center">
<Pagination simple defaultCurrent={page} total={search_count} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div> : ""
}
{search_count > limit ? (
<div className="mt30 mb50 edu-txt-center">
<Pagination
simple
defaultCurrent={page}
total={search_count}
pageSize={limit}
onChange={this.ChangePage}
></Pagination>
</div>
) : (
""
)}
</React.Fragment>
)
);
return (
<div className="main">
<div className="topWrapper" style={{ borderBottom: "none" }}>
<div className="topWrapper">
<div className="target-detail-search">
<Search
placeholder="输入关键字搜索合并请求"
enterButton
onSearch={this.searchFunc}
style={{ width: 300 }}
/>
</div>
<a className="topWrapper_btn ml10" onClick={() => this.islogin()}>
+&nbsp;新建合并请求
</a>
</div>
<div className="f-wrap-between screenWrap">
<div className="df">
<ul className="searchBanner">
<li
className={!status_type ? "active" : ""}
onClick={() => this.openorder(undefined)}
>
<label>搜索结果</label>
<span>{data && data.search_count}</span>
</li>
<li
className={status_type === "1" ? "active" : ""}
onClick={() => this.openorder("1")}
>
<label>开启的</label>
<span>{data && data.open_count}</span>
</li>
<li
className={status_type === "11" ? "active" : ""}
onClick={() => this.openorder("11")}
>
<label>已合并</label>
<span>{data && data.merged_issues_size}</span>
</li>
<li
className={status_type === "2" ? "active" : ""}
onClick={() => this.openorder("2")}
>
<label>已拒绝</label>
<span>{data && data.close_count}</span>
</li>
</ul>
</div>
<ul className="topWrapper_select">
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.priority,
"优先级",
"priority_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.priority_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.issue_tag,
"标签",
"issue_tag_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.issue_tag_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.assign_user,
"审查人员",
"assigned_to_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.assigned_to_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.issue_version,
"里程碑",
"fixed_version_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.fixed_version_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={menu}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.paix}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
</ul>
</div>
{data && data.search_count && data.search_count > 0 ? (
<div style={{minHeight:"400px"}}>
<Spin spinning={isSpin}>
<OrderItem
issues={issues}
search_count={search_count}
page={select_params.page}
limit={select_params.limit}
project_name={data.project_name}
project_author_name={data.project_author_name}
{...this.props}
{...this.state}
></OrderItem>
{Paginations}
</Spin>
</div>
) : (
<NoneData _html="暂时还没有相关数据哦!" projectsId={projectsId} />
)}
{/* <div className="topWrapper" style={{ borderBottom: "none" }}>
<p className="topWrapper_type_infos">
<li className={status_type === "1" ? "active" : ""} onClick={() => this.openorder("1")}>{data && data.open_count ? data.open_count : 0}个开启中</li>
<li className={status_type === "2" ? "active" : ""} onClick={() => this.openorder("2")}>{data && data.close_count ? data.close_count : 0}个已关闭</li>
@ -326,11 +481,9 @@ class merge extends Component {
</div>
:
<NoneData _html="暂时还没有相关数据哦!" />
}
} */}
</div>
)
);
}
}
export default merge;

View File

@ -0,0 +1,47 @@
import React, { Component } from "react";
import { Tabs, Empty } from "antd";
import "../Order/order.css";
import "./merge.css";
import CodesCommit from "../Main/CoderRootCommit";
import Comments from "../comments/comments";
const { TabPane } = Tabs;
class MergeFooter extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
const { footer_type, order_id } = this.props;
return (
<div>
<Tabs
defaultActiveKey={footer_type === "show" ? "1" : "2"}
className="custom-commit-tabs"
>
{
footer_type === "show" &&
<TabPane tab={<span className="ml-3 font-16">评论</span>} key="1">
<Comments
order_id={order_id}
showNotification={this.props.showNotification}
only_show_content={true}
{...this.props}
/>
</TabPane>
}
{/* <TabPane tab={<span className="ml-3 font-16"></span>} key="2">
<CodesCommit {...this.props} main_class="pd10"></CodesCommit>
</TabPane> */}
{/* <TabPane tab={<span className="ml-3 font-16"></span>} key="3">
<Empty />
</TabPane> */}
</Tabs>
</div>
);
}
}
export default MergeFooter;

View File

@ -0,0 +1,371 @@
import React, { Component } from "react";
import { Button, Form, Menu, Input, Select, Tag, Checkbox, Spin } from "antd";
import axios from "axios";
import "../Order/order.css";
import "./merge.css";
import MDEditor from "../../modules/tpm/challengesnew/tpm-md-editor";
const Option = Select.Option;
class MergeForm extends Component {
constructor(props) {
super(props);
this.state = {
desc: undefined,
issue_tag_ids: undefined,
fixed_version_id: undefined,
assigned_to_id: undefined,
titledata: undefined,
isSpin: false,
mergedata: undefined,
priority_id: undefined,
title: undefined,
members: undefined,
issue_tags: undefined,
issue_versions: undefined,
issue_priories: undefined,
};
}
componentDidMount = () => {
// this.check_is_login();
this.get_default_selects();
this.set_defatul();
};
componentDidUpdate=(prevPros)=>{
if(prevPros && this.props && !this.props.checkIfLogin()){
this.props.history.push("/403")
return
}
}
// check_is_login =() =>{
// if(!this.props.checkIfLogin()){
// this.props.history.push("/403")
// return
// }
// };
get_default_selects = () => {
const { projectsId } = this.props.match.params;
this.setState({ isSpin: true });
axios
.get(`/projects/${projectsId}/pull_requests/create_merge_infos.json`)
.then((result) => {
if (result) {
this.setState({
members: result.data.members,
issue_tags: result.data.issue_tags,
issue_versions: result.data.issue_versions,
issue_priories: result.data.issue_priories,
});
}
this.setState({ isSpin: false });
})
.catch((error) => {
this.setState({ isSpin: false });
console.log(error);
});
};
set_defatul = () => {
const { data, merge_type } = this.props;
if (data && merge_type === "edit") {
this.setState({
desc: data.body,
issue_tag_ids: data.issue_tag_ids ? data.issue_tag_ids[0] : undefined,
fixed_version_id: data.fixed_version_id ? String(data.fixed_version_id) : undefined,
assigned_to_id: data.assigned_to_id ? String(data.assigned_to_id) : undefined,
priority_id: data.priority_id ? String(data.priority_id) :undefined,
title: data.title,
});
}
this.InitData();
};
InitData = () => {
setTimeout(() => {
this.props.form.setFieldsValue({
...this.state,
});
}, 100);
};
onPanelChange = (time, mode) => {
this.setState({
value: time,
});
};
onSelect = (time) => {
this.setState({
value: time,
selectedValue: time,
});
};
renderMenu = (array, id) => {
return (
<Menu>
{array &&
array.length > 0 &&
array.map((item, key) => {
return (
<Menu.Item key={item} onClick={() => this.getOption(item, id)}>
{item}
</Menu.Item>
);
})}
</Menu>
);
};
renderSelect = (list) => {
if (list && list.length > 0) {
return list.map((item, key) => {
return (
<Option key={key + 1} value={item.id + ""}>
{item.name}
</Option>
);
});
}
};
//创建合并请求
handleSubmit = () => {
this.setState({
isSpin: true,
});
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
const { projectsId, mergeId } = this.props.match.params;
const { merge, pull, merge_type, data } = this.props;
if (values.issue_tag_ids && values.issue_tag_ids.length > 0) {
values.issue_tag_ids = [parseInt(values.issue_tag_ids)];
} else {
values.issue_tag_ids = [];
}
const { desc } = this.state;
if (merge_type === "new") {
let url = `/projects/${projectsId}/pull_requests.json`;
axios
.post(url, {
...values,
body: desc,
head: pull,
base: merge,
is_original: data && data.is_original,
fork_project_id: data && data.fork_project_id,
merge_user_login: data && data.merge_user_login
})
.then((result) => {
if (result) {
this.setState({
isSpin: false,
});
this.props.history.push(`/projects/${projectsId}/merge`);
const { getDetail } = this.props;
getDetail && getDetail();
} else {
this.setState({
isSpin: false,
});
}
})
.catch((error) => {
this.setState({
isSpin: false,
});
console.log(error);
});
} else {
let url = `/projects/${projectsId}/pull_requests/${mergeId}.json`;
axios
.put(url, {
...values,
body: desc,
head: pull,
base: merge,
})
.then((result) => {
if (result) {
this.setState({
isSpin: false,
});
this.props.history.push(
`/projects/${projectsId}/merge/${mergeId}/Messagecount`
);
} else {
this.setState({
isSpin: false,
});
}
})
.catch((error) => {
this.setState({
isSpin: false,
});
console.log(error);
});
}
} else {
this.setState({
isSpin: false,
});
}
});
};
onContentChange = (value) => {
this.setState({
desc: value,
});
};
render() {
const { merge_type, data } = this.props;
const { getFieldDecorator } = this.props.form;
const { projectsId, mergeId } = this.props.match.params;
const {
issue_tag_ids,
fixed_version_id,
assigned_to_id,
priority_id,
desc,
isSpin,
title,
members,
issue_tags,
issue_versions,
issue_priories,
} = this.state;
return (
<div>
<Spin spinning={isSpin}>
<div className="mb20">
<span className="font-16 fwb mr10 ver-middle">
{merge_type === "new" ? "新建" : "编辑"}合并请求:
</span>
<Tag color="#28BD6C" className="ver-middle">
可合并的
</Tag>
</div>
<Form>
<div className="width100 inline-block">
<div className="width70 pull-left">
<Form.Item>
{getFieldDecorator("title", {
rules: [
{
required: true,
message: "请填写请求标题",
},
],
initialValue: title,
})(<Input placeholder="标题" />)}
</Form.Item>
<MDEditor
placeholder={"请输入合并请求的描述..."}
height={350}
mdID={"merge-new-description"}
initValue={desc}
onChange={this.onContentChange}
></MDEditor>
<p className="clearfix mt20">
<Button
type="primary"
loading={isSpin}
onClick={this.handleSubmit}
>
<span className="plr10">
{merge_type === "new" ? "创建" : "提交"}
</span>
</Button>
<Button
type="default"
className="ml30"
href={
merge_type === "new"
? `/projects/${projectsId}/merge`
: `/projects/${projectsId}/merge/${mergeId}/detail`
}
>
<span className="plr10">取消</span>
</Button>
</p>
</div>
<div className="width30 pull-left">
<div className="pl30">
<Form.Item>
{getFieldDecorator("assigned_to_id", {
initialValue: assigned_to_id,
})(
<Select placeholder="审查人员" showSearch>
{this.renderSelect(members)}
</Select>
)}
</Form.Item>
<Form.Item>
{getFieldDecorator("fixed_version_id", {
initialValue: fixed_version_id,
})(
<Select
placeholder={
issue_versions && issue_versions.length > 0
? "未选择里程碑"
: "请添加里程碑"
}
showSearch
>
{this.renderSelect(issue_versions)}
</Select>
)}
</Form.Item>
<Form.Item>
{getFieldDecorator("issue_tag_ids", {
initialValue: issue_tag_ids,
})(
<Select
placeholder={
issue_tags && issue_tags.length > 0
? "未选择标签"
: "请在仓库设置里添加标签"
}
showSearch
>
{this.renderSelect(issue_tags)}
</Select>
)}
</Form.Item>
<Form.Item>
{getFieldDecorator("priority_id", {
initialValue: priority_id,
})(
<Select placeholder="优先级" showSearch>
{this.renderSelect(issue_priories)}
</Select>
)}
</Form.Item>
<Form.Item name="checkbox-group" label="其他">
<Checkbox.Group>
<div>
<Checkbox value="A">必须审查代码</Checkbox>
</div>
<div>
<Checkbox value="B">合并后删除提交分支</Checkbox>
</div>
<div>
<Checkbox value="C">合并后关闭提到的任务</Checkbox>
</div>
</Checkbox.Group>
</Form.Item>
</div>
</div>
</div>
</Form>
</Spin>
</div>
);
}
}
const WrappedNewMerge = Form.create({ name: "NewMergeForm" })(MergeForm);
export default WrappedNewMerge;

View File

@ -0,0 +1,22 @@
import React , { Component } from 'react';
import { Link } from "react-router-dom";
class Nodata extends Component{
render(){
const { _html, projectsId } = this.props;
return(
<div className="none_panels">
<div>
<div className="mb15">
<i className="iconfont icon-hebingqingqiu font-80 ver-middle color-grey-b"></i>
</div>
<h3>欢迎使用合并请求</h3>
<div className="color-grey-8">
合并请求可以帮助您与他人协作编写代码在使用之前请先创建一个 <Link className="color-blue" to={`/projects/${projectsId}/merge/new`}>合并请求</Link>
</div>
</div>
</div>
)
}
}
export default Nodata;

View File

@ -1,13 +1,13 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Input, Form, Select, Checkbox, Button, Divider, Spin, AutoComplete } from 'antd';
import { Input , Form , Select , Checkbox , Button , Spin , AutoComplete } from 'antd';
import { Base64 } from 'js-base64';
import '../css/index.css';
import '../css/index.scss';
import './new.css'
import axios from 'axios';
const Option = Select.Option
const Option = Select.Option;
class Index extends Component {
constructor(props) {
super(props);
@ -41,21 +41,7 @@ class Index extends Component {
ignore_name: undefined
}
}
getUserInfo = () => {
const url = `/users/me.json`;
axios.get(url).then(result => {
if (result && result.data.login) {
this.setState({
current_user: result.data
})
this.getDetail();
}
}).catch(error => {
console.log(error)
})
}
componentDidMount = () => {
// this.getUserInfo();
// 获取项目类别
this.getCategory();
// 获取项目语言
@ -64,6 +50,13 @@ class Index extends Component {
this.getGitignore();
// 获取开源许可证
this.getLicenses();
}
componentDidUpdate=(prevPros)=>{
if(prevPros && this.props && !this.props.checkIfLogin()){
this.props.history.push("/403")
return
}
}
getCategory = () => {
const url = `/project_categories.json`
@ -216,10 +209,26 @@ class Index extends Component {
})
}
ChangeAddr=(e)=>{
let value = e.target.value;
if(value.indexOf("/") > -1){
let arr = value.split("/");
let first = arr[arr.length-1];
if(first.indexOf(".git") > -1){
let second = first.split('.')[0];
if(!second)return;
this.props.form.setFieldsValue({
repository_name:second
})
}
}
}
render() {
const { getFieldDecorator } = this.props.form;
// 项目类型deposit-托管项目mirror-镜像项目
const { projectsType } = this.props.match.params;
const {
preType,
languageValue,
@ -262,7 +271,7 @@ class Index extends Component {
required: true, message: '请填写镜像版本库地址'
}],
})(
<Input placeholder="输入需要同步到本项目的镜像版本库地址" />
<Input placeholder="输入需要同步到本项目的镜像版本库地址" onChange={this.ChangeAddr} />
)}
</Form.Item>
<p className="formTip color-orange">示例https://github.com/facebook/reack.git</p>
@ -394,7 +403,6 @@ class Index extends Component {
className="plateAutoComplete"
onBlur={(value) => this.blurCategory(value, GitignoreList, "ignore")}
>
{/* {this.setOptionsList(GitignoreList,ignore_name)} */}
{ignore_list}
</AutoComplete>
)}
@ -415,7 +423,6 @@ class Index extends Component {
className="plateAutoComplete"
onBlur={(value) => this.blurCategory(value, LicensesList, "license")}
>
{/* {this.setOptionsList(LicensesList,license_name)} */}
{license_list}
</AutoComplete>
)}

View File

@ -1,8 +1,8 @@
import React, { Component } from "react";
import Meditor from "./m_editor";
import Top from "../Main/DetailTop";
import "./index.css";
import { Input, Select } from "antd";
import { Input } from "antd";
import FileLanguage from '../Component/FileLanguage';
class Index extends Component {
constructor(props) {
@ -39,62 +39,9 @@ class Index extends Component {
const urlroot = pathname.split("newfile")[1];
const file_path = `${urlroot}/${filename}`;
const { projectDetail } = this.props;
const Option = Select.Option;
const languages = [
"apex",
"azcli",
"bat",
"clojure",
"coffee",
"cpp",
"csharp",
"csp",
"css",
"dockerfile",
"fsharp",
"go",
"handlebars",
"html",
"ini",
"java",
"javascript",
"json",
"less",
"lua",
"markdown",
"msdax",
"mysql",
"objective",
"perl",
"pgsql",
"php",
"postiats",
"powerquery",
"powershell",
"pug",
"python",
"r",
"razor",
"redis",
"redshift",
"ruby",
"rust",
"sb",
"scheme",
"scss",
"shell",
"solidity",
"sql",
"st",
"swift",
"typescript",
"vb",
"xml",
"yaml",
];
return (
<React.Fragment>
<Top {...this.props} {...this.state} />
<div className="main">
<p className="pb15 bor-bottom-greyE font-16 color-grey-3 mb20">
新建文件
@ -117,12 +64,7 @@ class Index extends Component {
</a>
</div>
<div className="text-right">
<Select showSearch={true} placeholder={"请选择文本语言"} style={{ width: 200 }} value={language} onChange={this.select_language}>
<Option value={undefined}>请选择文本语言</Option>
{languages.map((item, key) => {
return <Option value={item}>{item}</Option>;
})}
</Select>
<FileLanguage language={language} select_language={this.select_language}></FileLanguage>
</div>
</div>
<Meditor

View File

@ -12,7 +12,7 @@ class UserSubmitComponent extends Component {
this.state = {
submitType: "0",
filename: "",
isSpin: false
isSpin: false,
};
}
@ -22,19 +22,19 @@ class UserSubmitComponent extends Component {
});
};
// 命名文件
changeFileName = (e) => {
this.setState({
filename: e.target.value,
});
};
// 命名文件
changeFileName = (e) => {
this.setState({
filename: e.target.value,
});
};
// 提交变更
subMitFrom = () => {
const { filepath, content,editor_type } = this.props;
const { filepath, content, editor_type } = this.props;
const { branch, projectsId } = this.props.match.params;
const { submitType, filename } = this.state;
this.setState({isSpin: true})
this.setState({ isSpin: true });
let path = editor_type === "upload" ? filepath : filepath.substr(1);
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
@ -48,28 +48,32 @@ class UserSubmitComponent extends Component {
message: values.desc,
})
.then((result) => {
this.setState({isSpin: false})
this.setState({ isSpin: false });
if (result.data && result.data.name) {
let url = values.branchname
? `/projects/${projectsId}/coders?branch=${values.branchname}`
: `/projects/${projectsId}/coders`;
this.props.history.push(url);
this.props.showNotification("文件新建成功!");
if(submitType === "1"){
const { getTopCount } = this.props;
getTopCount && getTopCount(values.branchname);
}
let url = values.branchname
? `/projects/${projectsId}/coders?branch=${values.branchname}`
: `/projects/${projectsId}/coders`;
this.props.history.push(url);
}
})
.catch((error) => {
this.setState({isSpin: false})
this.setState({ isSpin: false });
console.log(error);
});
}else{
this.setState({isSpin: false})
} else {
this.setState({ isSpin: false });
}
});
};
// 确认修改文件
UpdateFile = () => {
this.setState({isSpin: true})
this.setState({ isSpin: true });
const { branch, detail, content, filepath } = this.props;
const { projectsId } = this.props.match.params;
const { submitType } = this.state;
@ -86,28 +90,28 @@ class UserSubmitComponent extends Component {
message: values.desc,
})
.then((result) => {
this.setState({isSpin: false})
this.setState({ isSpin: false });
if (result.data && result.data.status === 1) {
let url = values.branchname
? `/projects/${projectsId}/coders?branch=${values.branchname}`
: `/projects/${projectsId}/coders`;
this.props.history.push(url);
this.props.showNotification("修改成功!");
}
})
.catch((error) => {
this.setState({isSpin: false})
this.setState({ isSpin: false });
console.log(error);
});
}else{
this.setState({isSpin: false})
} else {
this.setState({ isSpin: false });
}
});
};
render() {
const { submitType,filename, isSpin } = this.state;
const { submitType, filename, isSpin } = this.state;
const { getFieldDecorator } = this.props.form;
const { branch, projectsId } = this.props.match.params;
@ -115,29 +119,6 @@ class UserSubmitComponent extends Component {
const { current_user, filepath, projectDetail } = this.props;
const { editor_type } = this.props;
const changeSubmitBranch = () => {
if (submitType === "1") {
return (
<div className="mt15">
<Form.Item style={{ paddingLeft: "24px" }}>
{getFieldDecorator("branchname", {
rules: [
{
required: true,
message: "请输入分支名称",
},
],
})(
<Input
placeholder={`请输入分支名称`}
style={{ width: "220px" }}
/>
)}
</Form.Item>
</div>
);
}
};
return (
<div>
<span className="df mt30" style={{ alignItems: "center" }}>
@ -160,81 +141,102 @@ class UserSubmitComponent extends Component {
<span className="color-grey-8">提交变更</span>
</span>
<Spin spinning={isSpin}>
<div className="userScrew">
<div className="screwPanel">
<Form>
<Form.Item style={{display: editor_type === "upload" ? "block" : "none"}}>
{getFieldDecorator("path", {
rules: [],
})(
// <Input
// placeholder={`/${
// projectDetail && projectDetail.identifier
// }${filepath}`}
// readOnly
// />
<div className="setInputAddon">
<Input
addonBefore={`/${
projectDetail && projectDetail.identifier
}/`}
value={filename ? filename: filepath}
onChange={this.changeFileName}
placeholder="文件路径..."
/>
</div>
)}
</Form.Item>
<Form.Item>
{getFieldDecorator("desc", {
rules: [
{
required: true,
message: "请添加描述信息",
},
],
})(
<TextArea
placeholder={`必填,描述主要修改类型和内容`}
authSize={{ minRows: 3, maxRows: 5 }}
/>
)}
</Form.Item>
<Radio.Group value={submitType} onChange={this.changeSubmittype}>
<Radio value="0" className="mb10">
<i className="iconfont icon-banbenku font-16 mr5"></i>
直接提交至<span className="color-orange">{branch}</span>
</Radio>
<Radio value="1">
<Icon type="pull-request" className="mr5" />
为此提交创建一个<span className="font-bd">新的分支</span>
并发起合并请求
</Radio>
</Radio.Group>
{changeSubmitBranch()}
</Form>
<div className="userScrew">
<div className="screwPanel">
<Form>
<Form.Item
style={{
display: editor_type === "upload" ? "block" : "none",
}}
>
{getFieldDecorator("path", {
rules: [],
})(
<div className="setInputAddon">
<Input
addonBefore={`/${
projectDetail && projectDetail.identifier
}/`}
value={filename ? filename : filepath}
onChange={this.changeFileName}
placeholder="文件路径..."
/>
</div>
)}
</Form.Item>
<Form.Item>
{getFieldDecorator("desc", {
rules: [
{
required: true,
message: "请添加描述信息",
},
],
})(
<TextArea
placeholder={`必填,描述主要修改类型和内容`}
authSize={{ minRows: 3, maxRows: 5 }}
/>
)}
</Form.Item>
<Radio.Group
value={submitType}
onChange={this.changeSubmittype}
>
<Radio value="0" className="mb10">
<i className="iconfont icon-banbenku font-16 mr5"></i>
直接提交至<span className="color-orange">{branch}</span>
</Radio>
<Radio value="1">
<Icon type="pull-request" className="mr5" />
为此提交创建一个<span className="font-bd">新的分支</span>
并发起合并请求
</Radio>
</Radio.Group>
{
submitType === "1" ?
<div className="mt15">
<Form.Item style={{ paddingLeft: "24px" }}>
{getFieldDecorator("branchname", {
rules: [
{
required: true,
message: "请输入分支名称",
},
],
})(
<Input
placeholder={`请输入分支名称`}
style={{ width: "220px" }}
/>
)}
</Form.Item>
</div>:""
}
</Form>
</div>
</div>
<div className="mt20">
<Button
type="primary"
onClick={
editor_type === "update" ? this.UpdateFile : this.subMitFrom
}
className="mr30"
>
提交变更
</Button>
<Button
type="primary grey"
onClick={() => {
this.props.history.push(`/projects/${projectsId}/coders`);
}}
className="mr20"
>
取消
</Button>
</div>
</div>
<div className="mt20">
<Button
type="primary"
onClick={editor_type === "update" ? this.UpdateFile : this.subMitFrom}
className="mr30"
>
提交变更
</Button>
<Button
type="primary grey"
onClick={() => {
this.props.history.push(`/projects/${projectsId}/coders`);
}}
className="mr20"
>
取消
</Button>
</div>
</Spin>
</div>
);
}

View File

@ -5,7 +5,7 @@
.setInputAddon .ant-input-group-addon{
height: 30px;
line-height: 30px;
border-left: 1px solid #d9d9d9!important;
border: 1px solid #d9d9d9!important;
border-right: none!important;
}

View File

@ -24,6 +24,7 @@ class m_editor extends Component {
const { readOnly, editorType, language } = this.props;
const editor_options = {
lineNumbers: "on",
wordWrap: true, //强制换行
selectOnLineNumbers: true,
lineHeight: 24,
renderLineHighlight: "line",

View File

@ -1,8 +1,5 @@
import React, { Component } from "react";
// import Meditor from "./m_editor";
import Top from "../Main/DetailTop";
import "./index.css";
// import { Input, Select } from "antd";
import UserSubmitComponent from "./UserSubmitComponent";
import Upload from "../Upload/read";
import UploadImg from "../Images/upload.png";
@ -34,7 +31,6 @@ class UploadFile extends Component {
return (
<React.Fragment>
<Top {...this.props} {...this.state} />
<div className="main">
<p className="pb15 bor-bottom-greyE font-16 color-grey-3 mb20">
上传文件

View File

@ -2,15 +2,10 @@
import React, { Component } from "react";
import OrderItem from './order_form'
class CopyDetail extends Component {
constructor(props) {
super(props);
}
render() {
return (
<OrderItem form_type="copy" {...this.props}></OrderItem>
)
}
}
export default CopyDetail;

View File

@ -3,13 +3,11 @@ import { Link } from "react-router-dom";
import axios from "axios";
import { getImageUrl } from "educoder";
import { Modal, Form, Tooltip, Popconfirm, Pagination, Spin, Tag } from "antd";
import { Form , Popconfirm , Tag , Spin } from "antd";
import Attachments from "../Upload/attachment";
// import MDEditor from "../../modules/tpm/challengesnew/tpm-md-editor";
import RenderHtml from "../../components/render-html";
import Comments from "../comments/comments";
import "./order.css";
// import AmplifyImg from "./AmplifyImg";
class Detail extends Component {
constructor(props) {
@ -29,7 +27,7 @@ class Detail extends Component {
limit: 10,
page: 1,
search_count: undefined,
isSpin: false,
isSpins: true,
showFiles: true,
quillValue: "",
quillFlag: false,
@ -54,8 +52,8 @@ class Detail extends Component {
if (result) {
this.setState({
data: result.data,
isSpins:false
});
// this.getjournalslist();
}
})
.catch((error) => {
@ -147,7 +145,7 @@ class Detail extends Component {
ChangePage = (page) => {
this.setState({
page,
isSpin: true,
isSpins: true,
});
const { limit } = this.state;
this.getjournalslist(page, limit);
@ -189,7 +187,7 @@ class Detail extends Component {
render() {
const { projectsId, orderId } = this.props.match.params;
const { data } = this.state;
const { data , isSpins } = this.state;
const get_color = (type) => {
if (type === "高") {
return "#e67e22";
@ -203,111 +201,112 @@ class Detail extends Component {
};
return (
<div className="ProjectListIndex">
<div className="item-list-right">
<div className="background-f boder-4">
<div className="grid-item border-1f pd20 ">
<Link
to={`/users/${data && data.author_login}`}
className="show-user-link"
>
<img
className="user_img"
src={getImageUrl(`images/${data && data.author_picture}`)}
alt=""
width="50"
height="50"
/>
</Link>
<div className="ml10">
<div className="ver-middle">
<span className="mr10 ver-middle">
<span className="font-16">
{data && data.issue_classify === "issue"
? data.tracker
<Spin spinning={isSpins}>
<div className="ProjectListIndex">
<div className="item-list-right">
<div className="background-f boder-4">
<div className="grid-item border-1f pd20 ">
<Link
to={`/users/${data && data.author_login}`}
className="show-user-link"
>
<img
className="user_img"
src={getImageUrl(`images/${data && data.author_picture}`)}
alt=""
width="50"
height="50"
/>
</Link>
<div className="ml10">
<div className="ver-middle">
<span className="mr10 ver-middle">
<span className="font-16">
{data && data.issue_classify === "issue"
? data.tracker
: "缺陷"
: "合并请求"}
? data.tracker
: "缺陷"
: "合并请求"}
</span>
<span className="font-16 fwb">{data && data.subject}</span>
</span>
<span className="font-16 fwb">{data && data.subject}</span>
</span>
{data && data.priority && (
<Tag color={get_color(data.priority)}>{data.priority}</Tag>
)}
</div>
<div className="mt10">
<span className="color-grey-9 mr5"></span>
<Link
to={`/users/${data && data.author_login}`}
className="show-user-link color-blue"
>
{data && data.author_name}
</Link>
<span className="color-grey-9 ml5">
添加于 {data && data.created_at}
</span>
{data && data.user_permission ? (
<span className="pull-right">
<a className="color-blue fr" onClick={this.copydetail}>
复制
</a>
<Popconfirm
placement="bottom"
title={"您确定要删除吗"}
okText="是"
cancelText="否"
onConfirm={() => this.deletedetail(orderId)}
>
<a
className="color-blue fr"
style={{ marginLeft: 20, marginRight: 20 }}
>
删除
{data && data.priority && (
<Tag color={get_color(data.priority)}>{data.priority}</Tag>
)}
</div>
<div className="mt10">
<span className="color-grey-9 mr5"></span>
<Link
to={`/users/${data && data.author_login}`}
className="show-user-link color-blue"
>
{data && data.author_name}
</Link>
<span className="color-grey-9 ml5">
添加于 {data && data.created_at}
</span>
{data && data.user_permission ? (
<span className="pull-right">
<a className="color-blue fr" onClick={this.copydetail}>
复制
</a>
</Popconfirm>
<Popconfirm
placement="bottom"
title={"您确定要删除吗"}
okText="是"
cancelText="否"
onConfirm={() => this.deletedetail(orderId)}
>
<a
className="color-blue fr"
style={{ marginLeft: 20, marginRight: 20 }}
>
删除
</a>
</Popconfirm>
<Link
to={`/projects/${projectsId}/orders/${orderId}/updatedetail`}
className="color-blue fr"
>
编辑
</Link>
</span>
) : (
""
)}
<Link
to={`/projects/${projectsId}/orders/${orderId}/updatedetail`}
className="color-blue fr"
>
编辑
</Link>
</span>
) : (
""
)}
</div>
</div>
</div>
</div>
<div className="pd20">
<div className="detail_p">
{data && data.description && data.description.length > 0 ? (
this.commentCtx(data.description)
<div className="pd20">
<div className="detail_p">
{data && data.description && data.description.length > 0 ? (
this.commentCtx(data.description)
) : (
<span className="color-grey-9 ml3 mr3">没有描述</span>
)}
</div>
{data && data.attachments && data.attachments.length > 0 ? (
<Attachments
attachments={data.attachments}
showNotification={this.props.showNotification}
/>
) : (
<span className="color-grey-9 ml3 mr3">没有描述</span>
""
)}
</div>
{data && data.attachments && data.attachments.length > 0 ? (
<Attachments
attachments={data.attachments}
showNotification={this.props.showNotification}
/>
) : (
""
)}
</div>
</div>
<Comments
order_id={orderId}
showNotification={this.props.showNotification}
{...this.props}
/>
</div>
<div className="list-left list-left-padding">
<Comments
order_id={orderId}
showNotification={this.props.showNotification}
{...this.props}
/>
</div>
<div className="list-left list-left-padding">
<div className="list-right-item-padding background-f boder-4">
<p className="grid-item-left pb15">
<span className="issue_detail_info">分支:</span>
@ -324,7 +323,6 @@ class Detail extends Component {
<span>{data && data.token ? data.token : "--"}</span>
</p>
} */}
<p className="grid-item-left pb15">
<span className="issue_detail_info">标签:</span>
<span>
@ -378,7 +376,8 @@ class Detail extends Component {
</p>
</div>
</div>
</div>
</div>
</Spin>
);
}
}

View File

@ -1,9 +1,9 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Dropdown, Icon, Menu, Pagination, Typography, Popconfirm } from 'antd';
import Nav from './Nav';
import { Dropdown, Icon, Menu, Pagination, Typography, Popconfirm, Spin } from 'antd';
import NoneData from '../Nodata';
import axios from 'axios';
import './order.css';
const { Text } = Typography;
@ -20,7 +20,9 @@ class Milepost extends Component {
status: 'open',
openselect: 1,
closeselect: undefined,
order_name: undefined
order_name: undefined,
spinings: true
}
}
@ -28,9 +30,6 @@ class Milepost extends Component {
this.getList(1, this.state.status, 'desc');
}
getList = (page, status, order_type, order_name) => {
const { projectsId } = this.props.match.params;
const { limit } = this.state;
@ -41,9 +40,9 @@ class Milepost extends Component {
}
}).then((result) => {
if (result) {
this.setState({
data: result.data
data: result.data,
spinings: false
})
}
}).catch((error) => {
@ -59,7 +58,8 @@ class Milepost extends Component {
this.setState({
status: 'open',
openselect: current_user.user_id,
closeselect: undefined
closeselect: undefined,
})
this.getList(1, 'open', 'desc', order_name);
} else {
@ -147,7 +147,7 @@ class Milepost extends Component {
render() {
const { data, limit, page, openselect, closeselect } = this.state;
const { data, limit, page, openselect, closeselect, spinings } = this.state;
const { projectsId } = this.props.match.params;
const menu = (
<Menu onClick={this.arrayList}>
@ -160,111 +160,10 @@ class Milepost extends Component {
</Menu>
)
const Paginations = (
<React.Fragment>
{
data && data.issue_tags_count > limit ?
<div className="mt30 mb50 edu-txt-center">
<Pagination simple defaultCurrent={page} total={data && data.issue_tags_count} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div> : ""
}
</React.Fragment>
)
const renderList = () => {
if (data && data.versions && data.versions.length > 0) {
return (
<div>
<div className="tagList">
{
data.versions.length === 0 ? <NoneData></NoneData> : data.versions.map((item, key) => {
return (
<div style={{ display: 'block' }}>
<div className="milepostdiv">
<div className="milepostwidth">
<div className="grid-item width100">
<i className="iconfont icon-lubiaosignpost3 font-12 mr3"></i>
<Link to={`/projects/${projectsId}/orders/${item.id}/MilepostDetail`} className="font-16">{item.name}</Link>
</div>
</div>
</div>
<div className="milepostdiv" style={{ marginTop: 5 }}>
<div className="milepostrighe">
<div className="grid-item mr10">
<i className="iconfont icon-rili font-14 mr5">
</i>
{
item.effective_date ?
<span className="color-red">{item.effective_date}</span>
:
<span className="color-grey-c">暂无截止时间</span>
}
</div>
<div className="grid-item mr10 color-grey-9">
<i className="iconfont icon-issue font-14 mr5"></i>
<span>
{item.open_issues_count}个开启
</span>
</div>
<div className="grid-item mr10 color-grey-9">
<i className="iconfont icon-shanchudiao font-14 mr5"></i>
<span>
{item.close_issues_count}个关闭
</span>
</div>
</div>
{
data && data.user_admin_or_member ?
<div className="milepostleft">
<div className="grid-item mr15 color-grey-9">
<i className="iconfont icon-bianji3 font-14 mr5"></i>
<Link to={`/projects/${projectsId}/orders/${item.id}/meilpost`} className="color-grey-9">编辑</Link>
</div>
<div className="grid-item mr15 color-grey-9">
<i className="iconfont icon-yiguanbi1 font-14 mr5"></i>
<a onClick={() => this.updatestatusemile(this.state.status === "closed" ? "open" : "closed", item)} className="color-grey-9">{this.state.status === "closed" ? "开启" : "关闭"}</a>
</div>
<div className="grid-item mr15 color-grey-9">
<i className="iconfont icon-lajitong font-14 mr5" ></i>
<Popconfirm placement="bottom" title={'是否删除里程碑?'} okText="是" cancelText="否" onConfirm={() => this.closemile(item)}>
<a className="color-grey-9">删除</a>
</Popconfirm>
</div>
</div>
: ''
}
</div>
<div className="milepostdiv" style={{ marginTop: 5 }}>
<div className="textwidth">
<Text
type="secondary"
ellipsis={{ rows: 30, expandable: false, onExpand: Function }}
>
{item.description}</Text>
</div>
</div>
</div>
)
})
}
</div>
</div>
)
} else {
return (
<NoneData _html="暂时还没有相关数据哦!" />
)
}
}
return (
<div className="main">
<div>
<Spin spinning={spinings}>
<div className="main">
<div style={{ display: this.state.display }}>
<div className="tagdiv" >
<span>里程碑{data && data.issue_tags_count}已创建</span>
@ -290,10 +189,78 @@ class Milepost extends Component {
}
</div>
</div>
{renderList()}
{Paginations}
{
data && data.versions && data.versions.length > 0
?
<div className="tagList">
{
data.versions.length === 0 ? <NoneData></NoneData> : data.versions.map((item, key) => {
return (
<div style={{ display: 'block' }} key={key}>
<div className="milepostdiv">
<div className="milepostwidth">
<div className="grid-item width100">
<i className="iconfont icon-lubiaosignpost3 font-12 mr3"></i>
<Link to={`/projects/${projectsId}/orders/${item.id}/MilepostDetail`} className="font-16">{item.name}</Link>
</div>
</div>
</div>
<div className="milepostdiv" style={{ marginTop: 5 }}>
<div className="milepostrighe">
<div className="grid-item mr10">
<i className="iconfont icon-rili font-14 mr5"></i>
<span className={item.effective_date ? "color-red" : "color-grey-c"}>{item.effective_date || "暂无截止时间"}</span>
</div>
<div className="grid-item mr10 color-grey-9">
<i className="iconfont icon-issue font-14 mr5"></i>
<span>{item.open_issues_count}个开启</span>
</div>
<div className="grid-item mr10 color-grey-9">
<i className="iconfont icon-shanchudiao font-14 mr5"></i>
<span>{item.close_issues_count}个关闭</span>
</div>
</div>
{
data && data.user_admin_or_member ?
<div className="milepostleft">
<div className="grid-item mr15 color-grey-9">
<i className="iconfont icon-bianji3 font-14 mr5"></i>
<Link to={`/projects/${projectsId}/orders/${item.id}/meilpost`} className="color-grey-9">编辑</Link>
</div>
<div className="grid-item mr15 color-grey-9">
<i className="iconfont icon-yiguanbi1 font-14 mr5"></i>
<a onClick={() => this.updatestatusemile(this.state.status === "closed" ? "open" : "closed", item)} className="color-grey-9">{this.state.status === "closed" ? "开启" : "关闭"}</a>
</div>
<div className="grid-item mr15 color-grey-9">
<i className="iconfont icon-lajitong font-14 mr5" ></i>
<Popconfirm placement="bottom" title={'是否删除里程碑?'} okText="是" cancelText="否" onConfirm={() => this.closemile(item)}>
<a className="color-grey-9">删除</a>
</Popconfirm>
</div>
</div>
: ''
}
</div>
<div className="milepostdiv" style={{ marginTop: 5 }}>
<div className="textwidth">
<Text type="secondary" ellipsis={{ rows: 30, expandable: false, onExpand: Function }} >{item.description}</Text>
</div>
</div>
</div>
)
})
}
</div>
: <NoneData _html="暂时还没有相关数据哦!" />
}
{
data && data.versions_count > limit ?
<div className="mt30 mb50 edu-txt-center">
<Pagination simple defaultCurrent={page} total={data && data.versions_count} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div> : ""
}
</div>
</div>
</Spin>
)
}
}

View File

@ -6,7 +6,6 @@ import './order.css';
import NoneData from '../Nodata';
import OrderItem from './OrderItem';
import axios from 'axios';
/**
@ -30,7 +29,7 @@ class MilepostDetail extends Component {
issue_chosen: undefined,
data: undefined,
issues: undefined,
isSpin: false,
isSpin: true,
search: undefined,
author_id: undefined,
assigned_to_id: undefined,
@ -249,7 +248,13 @@ class MilepostDetail extends Component {
}
}
Paginations = (search_count) => {
const { limit, page } = this.state;
if(search_count > limit)
return <div className="mt30 mb50 edu-txt-center">
<Pagination simple defaultCurrent={page} total={search_count} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div>;
};
render() {
@ -265,22 +270,11 @@ class MilepostDetail extends Component {
<Menu.Item key={'updated_on'} value="asc">最早更新</Menu.Item>
</Menu>
)
const Paginations = (
<React.Fragment>
{
search_count > limit ?
<div className="mt30 mb50 edu-txt-center">
<Pagination simple defaultCurrent={page} total={search_count} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div> : ""
}
</React.Fragment>
)
return (
<div className="main">
<div className="miledetail mb20">
<div className="topmilepost">
<p>{data && data.name}</p>
<p className="font-18">{data && data.name}</p>
<div className="milepostdiv">
<Link to={`/projects/${projectsId}/orders/${meilid}/meilpost`} className="topWrapper_btn" style={{ marginRight: 15 }} >编辑里程碑</Link>
<Link to={`/projects/${projectsId}/orders/${meilid}/new`} className="topWrapper_btn">创建任务</Link>
@ -353,11 +347,11 @@ class MilepostDetail extends Component {
:
issues && issues.length>0 && issues.map((item,key)=>{
return(
<OrderItem item={item} mile search_count={search_count} page={page} limit={limit} {...this.props} {...this.state}></OrderItem>
<OrderItem key={key} item={item} mile search_count={search_count} page={page} limit={limit} {...this.props} {...this.state}></OrderItem>
)
})
}
{Paginations}
{this.Paginations(search_count)}
</Spin>
</div>

View File

@ -21,84 +21,80 @@ class OrderItem extends Component {
const { data } = this.props;
const { projectsId } = this.props.match.params;
const renderList = () => {
data.versions.map((item, key) => {
return (
<div style={{ display: 'block' }}>
<div className="milepostdiv">
<div className="milepostwidth">
<div className="grid-item width100">
<i className="iconfont icon-lubiaosignpost3 font-12 mr3"></i>
<Link to={`/projects/${projectsId}/orders/${item.id}/MilepostDetail`} className="font-16">{item.name}</Link>
</div>
</div>
</div>
<div className="milepostdiv" style={{ marginTop: 5 }}>
<div className="milepostrighe">
<div className="grid-item mr10">
<i className="iconfont icon-rili font-14 mr5">
</i>
{
item.effective_date ?
<span className="color-red">{item.effective_date}</span>
:
<span className="color-grey-c">暂无截止时间</span>
}
</div>
<div className="grid-item mr10 color-grey-9">
<i className="iconfont icon-issue font-14 mr5"></i>
<span>
{item.open_issues_count}个开启
</span>
</div>
<div className="grid-item mr10 color-grey-9">
<i className="iconfont icon-shanchudiao font-14 mr5"></i>
<span>
{item.close_issues_count}个关闭
</span>
</div>
</div>
{
data && data.user_admin_or_member ?
<div className="milepostleft">
<div className="grid-item mr15 color-grey-9">
<i className="iconfont icon-bianji3 font-14 mr5"></i>
<Link to={`/projects/${projectsId}/orders/${item.id}/meilpost`} className="color-grey-9">编辑</Link>
</div>
<div className="grid-item mr15 color-grey-9">
<i className="iconfont icon-yiguanbi1 font-14 mr5"></i>
<a onClick={() => this.updatestatusemile(this.state.status === "closed" ? "open" : "closed", item)} className="color-grey-9">{this.state.status === "closed" ? "开启" : "关闭"}</a>
</div>
<div className="grid-item mr15 color-grey-9">
<i className="iconfont icon-lajitong font-14 mr5" ></i>
<Popconfirm placement="bottom" title={'是否删除里程碑?'} okText="是" cancelText="否" onConfirm={() => this.closemile(item)}>
<a className="color-grey-9">删除</a>
</Popconfirm>
</div>
</div>
: ''
}
</div>
<div className="milepostdiv" style={{ marginTop: 5 }}>
<div className="textwidth">
<Text
type="secondary"
ellipsis={{ rows: 30, expandable: false, onExpand: Function }}
>
{item.description}</Text>
</div>
</div>
</div>
)
})
}
return (
<div>
{renderList()}
{
data && data.versions && data.versions.length > 0 && data.versions.map((item, key) => {
return (
<div style={{ display: 'block' }}>
<div className="milepostdiv">
<div className="milepostwidth">
<div className="grid-item width100">
<i className="iconfont icon-lubiaosignpost3 font-12 mr3"></i>
<Link to={`/projects/${projectsId}/orders/${item.id}/MilepostDetail`} className="font-16">{item.name}</Link>
</div>
</div>
</div>
<div className="milepostdiv" style={{ marginTop: 5 }}>
<div className="milepostrighe">
<div className="grid-item mr10">
<i className="iconfont icon-rili font-14 mr5">
</i>
{
item.effective_date ?
<span className="color-red">{item.effective_date}</span>
:
<span className="color-grey-c">暂无截止时间</span>
}
</div>
<div className="grid-item mr10 color-grey-9">
<i className="iconfont icon-issue font-14 mr5"></i>
<span>
{item.open_issues_count}个开启
</span>
</div>
<div className="grid-item mr10 color-grey-9">
<i className="iconfont icon-shanchudiao font-14 mr5"></i>
<span>
{item.close_issues_count}个关闭
</span>
</div>
</div>
{
data.user_admin_or_member ?
<div className="milepostleft">
<div className="grid-item mr15 color-grey-9">
<i className="iconfont icon-bianji3 font-14 mr5"></i>
<Link to={`/projects/${projectsId}/orders/${item.id}/meilpost`} className="color-grey-9">编辑</Link>
</div>
<div className="grid-item mr15 color-grey-9">
<i className="iconfont icon-yiguanbi1 font-14 mr5"></i>
<a onClick={() => this.updatestatusemile(this.state.status === "closed" ? "open" : "closed", item)} className="color-grey-9">{this.state.status === "closed" ? "开启" : "关闭"}</a>
</div>
<div className="grid-item mr15 color-grey-9">
<i className="iconfont icon-lajitong font-14 mr5" ></i>
<Popconfirm placement="bottom" title={'是否删除里程碑?'} okText="是" cancelText="否" onConfirm={() => this.closemile(item)}>
<a className="color-grey-9">删除</a>
</Popconfirm>
</div>
</div>
: ''
}
</div>
<div className="milepostdiv" style={{ marginTop: 5 }}>
<div className="textwidth">
<Text
type="secondary"
ellipsis={{ rows: 30, expandable: false, onExpand: Function }}
>
{item.description}</Text>
</div>
</div>
</div>
)
})
}
</div>
)
}

View File

@ -2,13 +2,7 @@ import React , { Component } from "react";
import { NavLink } from 'react-router-dom';
import './order.css'
class Nav extends Component{
constructor(props){
super(props);
this.state={
projectTag: undefined
}
}
render(){
const { projectsId } = this.props.match.params;
return(

View File

@ -1,17 +1,11 @@
import React, { Component } from "react";
import OrderItem from './order_form'
import OrderForm from './order_form'
class New extends Component {
constructor(props) {
super(props);
}
render() {
return (
<OrderItem form_type="new" {...this.props}></OrderItem>
<OrderForm form_type="new" {...this.props}></OrderForm>
)
}
}
export default New;

View File

@ -18,7 +18,7 @@ class OrderItem extends Component {
return (
issue_tags.map((item, key) => {
return (
<Tag color={item.color} className="mlr10" key={key}>{item.name}</Tag>
<span className="mr10" key={key}>{item.name}</span>
)
})
)
@ -44,78 +44,72 @@ class OrderItem extends Component {
})
}
render() {
const { item, key, checkbox , mile } = this.props;
const { item , checkbox , mile } = this.props;
const { projectsId } = this.props.match.params;
const { current_user } = this.props
const renderList = () => {
if (item) {
return (
<div className="issueItem" key={key}>
{current_user && current_user.login && checkbox}
<div className="flex-1">
<p className="mb15 df" style={{alignItems:"center"}}>
<Link to={`/projects/${projectsId}/orders/${item.id}/detail`} className="hide-1 font-16 color-grey-3 lineh-30 mr10" style={{maxWidth:"300px"}}>{item.name}</Link>
{TagInfo(item.priority,"mr10")}
</p>
<p className="color-grey-6 font-12">
<span>{item.format_time}</span><span className="ml5"></span>
{
item.updated_at === item.format_time ? "" :
<span className="ml20"><span>{item.updated_at}</span><span className="ml5"></span></span>
}
</p>
</div>
<ul className="topWrapper_select no-cursor" onMouseMove={() => this.onMouseMove(item.id)} onMouseOut={() => this.onMouseOut()} >
<li>{this.set_issue_tags(item.issue_tags)}</li>
<li>
{
item.author_name ?
<Link to={`/users/${item.author_login}`} className="show-user-link">
{item.author_name}
</Link>
: "--"
}
</li>
<li>
{
item.assign_user_name ?
<Link to={`/users/${item.assign_user_login}`} className="show-user-link">
{item.assign_user_name}
</Link>
: "--"
}
</li>
<li>{item.tracker || "--"}</li>
{ !mile ?<li>{item.version || "--"}</li>:""}
<li>{item.issue_status || "--"}</li>
<li style={{color:`${item.done_ratio === "100%"?"#28BD6C":"#F73030"}`}}>{item.done_ratio || "--"}</li>
<li>
<div className="milepostleft">
<Link to={`/projects/${projectsId}/orders/${item.id}/detail`}><i className="iconfont icon-pinglun1 mr3 font-16"></i>{item.journals_count}</Link>
{
current_user && current_user.login ?
<div style={{ display: this.state.orderid === item.id && this.state.isdisplay ? 'flex' : 'none' }}>
<div className="mr8 ml8 color-grey-9">
<Link to={`/projects/${projectsId}/orders/${item.id}/updatedetail`} className="color-grey-9"><i className="iconfont icon-bianji3 font-14 mr5"></i></Link>
</div>
<div className="color-grey-9">
<Popconfirm placement="bottom" title={'您确定要删除吗'} okText="是" cancelText="否" onConfirm={() => this.deletedetail(item.id)}>
<i className="iconfont icon-yiguanbi1 font-14"></i>
</Popconfirm>
</div>
</div>
: ""
}
</div>
</li>
</ul>
</div>
)
}
}
return (
renderList()
item &&
<div className="issueItem">
{current_user && current_user.login && checkbox}
<div className="flex-1">
<p className="mb15 df" style={{alignItems:"center"}}>
<Link to={`/projects/${projectsId}/orders/${item.id}/detail`} target="_blank" title={item.name} className="hide-1 font-16 color-grey-3 lineh-30 mr10" style={{maxWidth:"300px"}}>{item.name}</Link>
{TagInfo(item.priority,"mr10")}
</p>
<p className="color-grey-6 font-12">
<span>{item.format_time}</span><span className="ml5"></span>
{
item.updated_at === item.format_time ? "" :
<span className="ml20"><span>{item.updated_at}</span><span className="ml5"></span></span>
}
</p>
</div>
<ul className="topWrapper_select no-cursor" onMouseMove={() => this.onMouseMove(item.id)} onMouseOut={() => this.onMouseOut()} >
<li>{this.set_issue_tags(item.issue_tags)}</li>
<li>
{
item.author_name ?
<Link to={`/users/${item.author_login}`} className="show-user-link">
{item.author_name}
</Link>
: "--"
}
</li>
<li>
{
item.assign_user_name ?
<Link to={`/users/${item.assign_user_login}`} className="show-user-link">
{item.assign_user_name}
</Link>
: "--"
}
</li>
<li>{item.tracker || "--"}</li>
{ !mile ?<li>{item.version || "--"}</li>:""}
<li>{item.issue_status || "--"}</li>
<li style={{color:`${item.done_ratio === "100%"?"#28BD6C":"#F73030"}`}}>{item.done_ratio || "--"}</li>
<li>
<div className="milepostleft">
<Link to={`/projects/${projectsId}/orders/${item.id}/detail`}><i className="iconfont icon-pinglun1 mr3 font-16"></i>{item.journals_count}</Link>
{
current_user && current_user.login ?
<div style={{ display: this.state.orderid === item.id && this.state.isdisplay ? 'flex' : 'none' }}>
<div className="mr8 ml8 color-grey-9">
<Link to={`/projects/${projectsId}/orders/${item.id}/updatedetail`} className="color-grey-9"><i className="iconfont icon-bianji3 font-14 mr5"></i></Link>
</div>
<div className="color-grey-9">
<Popconfirm placement="bottom" title={'您确定要删除吗'} okText="是" cancelText="否" onConfirm={() => this.deletedetail(item.id)}>
<i className="iconfont icon-yiguanbi1 font-14"></i>
</Popconfirm>
</div>
</div>
: ""
}
</div>
</li>
</ul>
</div>
)
}
}

View File

@ -5,6 +5,46 @@ import NoneData from '../Nodata';
import { SketchPicker } from 'react-color'
import reactCSS from 'reactcss'
import axios from 'axios';
const styles = reactCSS({
'default': {
color: {
width: '20px',
height: '20px',
borderRadius: '2px',
background: `rgba(${this.state.color.r}, ${this.state.color.g}, ${this.state.color.b}, ${this.state.color.a})`,
},
swatch: {
padding: '5px',
background: '#fff',
borderRadius: '1px',
width: '100px',
marginTop: '5px',
height: '28px',
boxShadow: '0 0 0 1px rgba(0,0,0,.1)',
display: 'flex',
cursor: 'pointer',
},
popover: {
position: 'absolute',
zIndex: '2',
},
cover: {
position: 'fixed',
top: '0px',
right: '0px',
bottom: '0px',
left: '0px',
},
modalcolor: {
width: '20px',
height: '20px',
borderRadius: '2px',
background: this.state.newcolor,
}
},
});
class Tags extends Component {
constructor(props) {
super(props);
@ -210,120 +250,18 @@ class Tags extends Component {
id: arr.id
});
};
menu =()=> (
<Menu onClick={this.arrayList}>
<Menu.Item key={'created_at'} value="desc">按创建时间降序排序</Menu.Item>
<Menu.Item key={'created_at'} value="asc">按创建时间升序排序</Menu.Item>
<Menu.Item key={'issues_count'} value="desc">按issue个数降序排序</Menu.Item>
<Menu.Item key={'issues_count'} value="asc">按issue个数升序排序</Menu.Item>
</Menu>
)
render() {
const { data, limit, page } = this.state;
const { getFieldDecorator } = this.props.form;
const menu = (
<Menu onClick={this.arrayList}>
<Menu.Item key={'created_at'} value="desc">按创建时间降序排序</Menu.Item>
<Menu.Item key={'created_at'} value="asc">按创建时间升序排序</Menu.Item>
<Menu.Item key={'issues_count'} value="desc">按issue个数降序排序</Menu.Item>
<Menu.Item key={'issues_count'} value="asc">按issue个数升序排序</Menu.Item>
</Menu>
)
const styles = reactCSS({
'default': {
color: {
width: '20px',
height: '20px',
borderRadius: '2px',
background: `rgba(${this.state.color.r}, ${this.state.color.g}, ${this.state.color.b}, ${this.state.color.a})`,
},
swatch: {
padding: '5px',
background: '#fff',
borderRadius: '1px',
width: '100px',
marginTop: '5px',
height: '28px',
boxShadow: '0 0 0 1px rgba(0,0,0,.1)',
display: 'flex',
cursor: 'pointer',
},
popover: {
position: 'absolute',
zIndex: '2',
},
cover: {
position: 'fixed',
top: '0px',
right: '0px',
bottom: '0px',
left: '0px',
},
modalcolor: {
width: '20px',
height: '20px',
borderRadius: '2px',
background: this.state.newcolor,
}
},
});
const Paginations = (
<React.Fragment>
{
data && data.issue_tags_count > limit ?
<div className="mt30 mb50 edu-txt-center">
<Pagination simple defaultCurrent={page} total={data && data.issue_tags_count} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div> : ""
}
</React.Fragment>
)
const renderList = () => {
if (data && data.issue_tags && data.issue_tags.length > 0) {
return (
<div>
<div className="topWrapper">
<span>{data && data.issue_tags_count}个标签</span>
<ul className="topWrapper_select">
<li>
<Dropdown className="topWrapperSelect" overlay={menu} trigger={['click']} placement="bottomCenter">
<span>标签<Icon type="caret-down" className="ml5" /></span>
</Dropdown>
</li>
</ul>
</div>
<div className="tagList">
{
data.issue_tags.map((item, key) => {
return (
<div key={key}>
<span className="width20 mr10">
<span style={{ backgroundColor: `${item.color}` }} className="tagColor"></span>
{item.name}
</span>
<span className="hide-1 width50 mr10">{item.description}</span>
<span className="width15 mr10">{item.issues_count}个开启的任务</span>
{
data && data.user_admin_or_member ?
<div className="width15 text-right">
<a onClick={() => this.editshow(item)} className="topWrapper_btn fr" >编辑</a>
<Popconfirm placement="bottom" title={'删除标签会将其从所有引用中删除。继续?'} okText="是" cancelText="否" onConfirm={() => this.deletetag(item.id)}>
<a className="a_btn delete_btn fr" >删除</a>
</Popconfirm>
</div>
: ''
}
</div>
)
})
}
</div>
</div>
)
} else {
return (
<NoneData _html="暂时还没有相关数据哦!" />
)
}
}
return (
<div className="main">
<div>
@ -363,7 +301,6 @@ class Tags extends Component {
)}
</Form.Item>
<div>
<div style={styles.swatch} onClick={this.handleClick}>
<div style={styles.color}>
@ -383,8 +320,56 @@ class Tags extends Component {
</div>
</Form>
</div>
{renderList()}
{Paginations}
{
data && data.issue_tags && data.issue_tags.length > 0 ?
<div>
<div className="topWrapper">
<span>{data && data.issue_tags_count}个标签</span>
<ul className="topWrapper_select">
<li>
<Dropdown className="topWrapperSelect" overlay={this.menu()} trigger={['click']} placement="bottomCenter">
<span>标签<Icon type="caret-down" className="ml5" /></span>
</Dropdown>
</li>
</ul>
</div>
<div className="tagList">
{
data.issue_tags.map((item, key) => {
return (
<div key={key}>
<span className="width20 mr10">
<span style={{ backgroundColor: `${item.color}` }} className="tagColor"></span>
{item.name}
</span>
<span className="hide-1 width50 mr10">{item.description}</span>
<span className="width15 mr10">{item.issues_count}个开启的任务</span>
{
data && data.user_admin_or_member ?
<div className="width15 text-right">
<a onClick={() => this.editshow(item)} className="topWrapper_btn fr" >编辑</a>
<Popconfirm placement="bottom" title={'删除标签会将其从所有引用中删除。继续?'} okText="是" cancelText="否" onConfirm={() => this.deletetag(item.id)}>
<a className="a_btn delete_btn fr" >删除</a>
</Popconfirm>
</div>
: ''
}
</div>
)
})
}
</div>
</div>
:
<NoneData _html="暂时还没有相关数据哦!" />
}
{
data && data.issue_tags_count > limit ?
<div className="mt30 mb50 edu-txt-center">
<Pagination simple defaultCurrent={page} total={data && data.issue_tags_count} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div>:""
}
</div>
<Modal
title="编辑标签"

View File

@ -1,17 +1,11 @@
import React, { Component } from "react";
import OrderItem from './order_form'
import OrderForm from './order_form'
class UpdateDetail extends Component {
constructor(props) {
super(props);
}
render() {
return (
<OrderItem form_type="edit" {...this.props}></OrderItem>
<OrderForm form_type="edit" {...this.props}></OrderForm>
)
}
}
export default UpdateDetail;

View File

@ -58,9 +58,6 @@ class UpdateMilepost extends Component {
}).catch((error) => {
console.log(error);
})
}
submit = () => {

View File

@ -2,6 +2,7 @@
background:rgba(250,250,250,1);
border:1px solid rgba(221,221,221,1);
padding-left: 20px;
box-sizing: border-box;
}
.searchBanner{
@ -9,7 +10,7 @@
height: 50px;
line-height: 50px;
li{
margin-right: 30px;
margin-right: 15px;
display: flex;
align-items: center;
}

View File

@ -16,6 +16,21 @@ class NewMilepost extends Component {
isSpin: false
}
}
componentDidUpdate=(prevPros)=>{
if(prevPros && this.props && !this.props.checkIfLogin()){
this.props.history.push("/403")
return
}
}
// componentDidMount = () => {
// this.check_is_login();
// };
// check_is_login =() =>{
// if(!this.props.checkIfLogin()){
// this.props.history.push("/403")
// return
// }
// };
onPanelChange = (time, mode) => {
this.setState({
@ -71,7 +86,6 @@ class NewMilepost extends Component {
render() {
const { getFieldDecorator } = this.props.form;
const { projectsId } = this.props.match.params;
const { isSpin } = this.state
return (
<div className="main">
@ -198,7 +212,6 @@ class NewMilepost extends Component {
<Spin spinning={isSpin}>
<a className="topWrapper_btn fr" >创建里程碑</a>
</Spin>
</div>
</Form>
</div>

View File

@ -27,7 +27,7 @@
}
.miledetail {
padding: 20px 0;
padding-bottom: 20px;
box-sizing: border-box;
justify-content: space-between;
border-bottom: 1px solid #eeeeee;
@ -38,19 +38,11 @@
}
.detail_p {
display: flex;
/*padding:10px;*/
/*width: 80%;*/
/*padding-left: 15px;*/
/*margin: auto;*/
}
.detail_right {
/*display: flex;*/
flex-grow: 1;
text-align: right;
/*width: 15%;*/
/*padding-left: 15px;*/
/*margin: auto; */
}
.commit_p {
font-size: 12px;
@ -201,7 +193,7 @@
text-align: center;
cursor: pointer;
color: #666;
width: 90px;
width: 86px;
text-align: center;
display: inline-block;
overflow: hidden;
@ -225,7 +217,7 @@
display: flex;
flex-wrap: wrap;
align-content: center;
border-bottom: 1px dashed #cecdcd;
border-bottom: 1px solid #eee;
padding: 16px 0px 16px 20px;
}
.issueNo {
@ -311,7 +303,6 @@
padding: 0px 12px;
text-align: center;
height: 32px;
/*width: 110px;*/
border-radius: 4px;
line-height: 32px;
}
@ -333,7 +324,6 @@
.topWrapper_detali {
display: flex;
/*height: 35px;*/
background-color: #eee;
align-items: center;
margin-bottom: 10px;
@ -360,9 +350,6 @@
border: 1px solid #f4f4f4;
margin-left: 15px;
padding: 10px;
/*padding-top: 0px;*/
/*padding-left: 0px;*/
/*margin-right: 15px;*/
position: relative;
background: #ffffff;
border-radius: 4px;
@ -414,12 +401,6 @@
.text-right {
text-align: right;
}
/*.tagList > div > span{*/
/*display: block*/
/*}*/
/*.tagList > div > span:nth-child(2){*/
/*width: 450px;*/
/*}*/
.tagColor {
display: inline-block;
width: 28px;
@ -524,14 +505,9 @@
border-radius: 6px;
}
.journal-list-item {
padding: 10px;
padding: 10px 0px;
}
/*.DetailRight > p >span:nth-child(1){*/
/*min-width: 90px;*/
/*margin-right: 15px;*/
/*text-align: right;*/
/*}*/
.span_title {
min-width: 40px;
margin-right: 15px;
@ -568,7 +544,6 @@ a.issue-type-button.active:hover {
}
.item-list-right {
width: 74%;
/* padding: 10px; */
}
.detail_edit_action {
padding: 10px;
@ -576,9 +551,6 @@ a.issue-type-button.active:hover {
cursor: pointer;
line-height: 40px;
}
.attachmentsList {
margin-left: 4px;
}
.paper-clip-color {
color: #29bd8b !important;
}
@ -653,8 +625,6 @@ a.issue-type-button.active:hover {
}
.issue_detail_info {
width: 65px;
/* margin-right: 15px;
text-align: right; */
color: #888888;
}
.list-left-padding {
@ -663,8 +633,7 @@ a.issue-type-button.active:hover {
.comment-background {
background: #fff;
border-radius: 4px;
padding: 0 15px 15px;
/* border: 1px solid #f4f4f4; */
padding: 0px 30px;
}
.border-bottom-comment {
border-bottom: 1px solid #eee;
@ -684,9 +653,9 @@ a.issue-type-button.active:hover {
border-radius: 9px;
}
.comment-background .ant-list-item {
padding: 16px;
padding-left: 20px;
box-sizing: border-box;
}
/* .comment-background .ant-list-split .ant-list-item:last-child{border-bottom: 1px solid #e8e8e8;} */
.border-top-e {
border-top: 1px solid #e8e8e8;
}
@ -725,4 +694,6 @@ a.issue-type-button.active:hover {
vertical-align: middle;
}
.boder-4{border-radius: 4px;}
.pbt20{padding: 20px 0;}
.pbt20{padding: 20px 0;}
.inline-block{display: inline-block;}
.pd10{padding: 10px;}

View File

@ -1,5 +1,6 @@
import React, { Component } from "react";
import { Input, Dropdown, Menu, Icon, Pagination, Spin, DatePicker, Checkbox } from "antd";
import { Link } from 'react-router-dom';
import "./order.css";
import './index.scss';
import moment from 'moment';
@ -46,16 +47,15 @@ class order extends Component {
status_ids: "状态",
done_ratios: "完成度",
paix: "排序",
update_author_ids:"更换负责人",
update_fixed_version_ids:'更换里程碑',
update_status_ids:"修改状态",
update_author_ids: "更换负责人",
update_fixed_version_ids: '更换里程碑',
update_status_ids: "修改状态",
begin: '',
end: '',
checkedValue: [],
allValue: [],
all: false,
select_params: {
status_type: "1", //开启中和关闭中,全部,默认为全部
assigned_to_id: undefined, // 负责人
author_id: undefined, // 发布人
issue_tag_id: undefined, // 标签
@ -66,9 +66,9 @@ class order extends Component {
order_name: undefined,
order_type: undefined,
search: undefined,
update_author_id:undefined,
update_fixed_version_id:undefined,
update_status_id:undefined,
update_author_id: undefined,
update_fixed_version_id: undefined,
update_status_id: undefined,
page: 1,
limit: 15,
},
@ -77,7 +77,7 @@ class order extends Component {
componentDidMount = () => {
this.getSelectList();
this.getIssueList();
this.getIssueList('1');
};
getSelectList = () => {
@ -101,7 +101,7 @@ class order extends Component {
};
// 获取列表数据
getIssueList = (begin, end) => {
getIssueList = (status_type, begin, end) => {
this.setState({
isSpin: true
})
@ -113,7 +113,8 @@ class order extends Component {
params: {
...select_params,
start_date: begin,
due_date: end
due_date: end,
status_type
}
})
.then((result) => {
@ -165,10 +166,11 @@ class order extends Component {
this.state.select_params.order_name = key_name[0];
this.state.select_params.order_type = e.item.props.value;
this.state.select_params.page = 1;
this.getIssueList();
const { status_type } = this.state;
this.getIssueList(status_type);
};
getOption = (e, id, name,toGet) => {
getOption = (e, id, name, toGet) => {
const { current_user } = this.props;
let option_id = e.key === "all" ? undefined : e.key;
@ -181,25 +183,26 @@ class order extends Component {
if (current_user) {
author_id = (select_params.author_id && select_params.author_id === current_user.user_id) ? current_user.user_id : undefined;
assigned_to_id = (select_params.assigned_to_id && select_params.assigned_to_id === current_user.user_id) ? current_user.user_id : undefined;
}
this.setState({
[`${id}s`] : name,
[`${id}s`]: name,
select_params,
author_id,
assigned_to_id
});
if(!toGet){
this.getIssueList();
if (!toGet) {
const { status_type } = this.state;
this.getIssueList(status_type);
}
};
renderMenu = (array, name, id,toGet) => {
renderMenu = (array, name, id, toGet) => {
return (
<Menu>
<Menu.Item key={"all"} onClick={(e) => this.getOption(e, id, name,toGet)}>
<Menu.Item key={"all"} onClick={(e) => this.getOption(e, id, name, toGet)}>
{name}
</Menu.Item>
{array &&
@ -208,7 +211,7 @@ class order extends Component {
return (
<Menu.Item
key={item.id}
onClick={(e) => this.getOption(e, id, item.name,toGet)}
onClick={(e) => this.getOption(e, id, item.name, toGet)}
>
{item.name}
</Menu.Item>
@ -225,8 +228,10 @@ class order extends Component {
checkedValue: [],
all: false
});
const { status_type } = this.state;
this.state.select_params.page = page;
this.getIssueList();
this.getIssueList(status_type);
};
// 搜索
@ -235,9 +240,11 @@ class order extends Component {
search: value,
isSpin: true,
});
const { status_type } = this.state;
this.state.select_params.search = value;
this.state.select_params.page = 1;
this.getIssueList();
this.getIssueList(status_type);
};
openorder = (type) => {
@ -254,12 +261,11 @@ class order extends Component {
paix: "排序",
});
this.state.select_params = {
status_type: type,
search: undefined,
page: 1,
limit: 15,
};
this.getIssueList();
this.getIssueList(type);
};
// 筛选:全部、指派给我、由我创建
@ -269,7 +275,7 @@ class order extends Component {
isSpin: true,
});
if (type) {
if (current_user === undefined) {
if (!current_user) {
this.setState({
isSpin: false,
});
@ -304,8 +310,9 @@ class order extends Component {
this.state.select_params.assigned_to_id = undefined;
this.state.select_params.author_id = undefined;
}
const { status_type } = this.state;
this.getIssueList();
this.getIssueList(status_type);
};
deletedetail = (id) => {
@ -319,7 +326,9 @@ class order extends Component {
})
.then((result) => {
if (result) {
this.getIssueList();
const { status_type } = this.state;
this.getIssueList(status_type);
}
})
.catch((error) => {
@ -328,27 +337,39 @@ class order extends Component {
};
islogin() {
this.props.showLoginDialog();
}
renderNew =()=>{
const { projectsId } = this.props.match.params;
if (this.props.checkIfLogin() === false) {
this.props.showLoginDialog();
return;
} else {
this.props.history.push(`/projects/${projectsId}/orders/new`);
if (this.props.checkIfLogin()) {
return(
<Link className="topWrapper_btn ml10" target="_blank" to={`/projects/${projectsId}/orders/new`}>
+&nbsp;创建任务
</Link>
)
}else{
return(
<a className="topWrapper_btn ml10" onClick={this.islogin}>
+&nbsp;创建任务
</a>
)
}
}
// 修改开始时间
changeBeginTime = (data, value) => {
const { status_type } = this.state;
this.setState({
begin: value
})
this.getIssueList(value, this.state.end);
this.getIssueList(status_type, value, this.state.end);
}
changeEndTime = (data, value) => {
const { status_type } = this.state;
this.setState({
end: value
})
this.getIssueList(this.state.begin, value);
this.getIssueList(status_type, this.state.begin, value);
}
// 选择列表里面的checkbox
@ -361,15 +382,15 @@ class order extends Component {
all: allValue && value && value.length === allValue.length,
})
// 不勾选数据时清除右上角选择的项
if(value.length === 0){
if (value.length === 0) {
this.setState({
update_author_ids:"更换负责人",
update_fixed_version_ids:"更换里程碑",
update_status_ids:"修改状态",
select_params:{
update_author_id:undefined,
update_fixed_version_id:undefined,
update_status_id:undefined
update_author_ids: "更换负责人",
update_fixed_version_ids: "更换里程碑",
update_status_ids: "修改状态",
select_params: {
update_author_id: undefined,
update_fixed_version_id: undefined,
update_status_id: undefined
}
})
}
@ -392,69 +413,94 @@ class order extends Component {
}
// 批量修改
updateIssues=()=>{
const {checkedValue , select_params} = this.state;
updateIssues = () => {
const { checkedValue, select_params } = this.state;
const { projectsId } = this.props.match.params;
if (!select_params.update_author_id && !select_params.update_fixed_version_id && !select_params.update_status_id) {
this.resetSelectParams();
return;
}
this.setState({
isSpin:true
isSpin: true
})
const url = `/projects/${projectsId}/issues/series_update.json`;
axios.post(url,{
ids:checkedValue,
assigned_to_id:select_params.update_author_id,
fixed_version_id:select_params.update_fixed_version_id,
status_id:select_params.update_status_id
}).then(result=>{
if(result){
axios.post(url, {
ids: checkedValue,
assigned_to_id: select_params.update_author_id,
fixed_version_id: select_params.update_fixed_version_id,
status_id: select_params.update_status_id
}).then(result => {
if (result) {
this.props.showNotification("修改成功!");
this.successFunc();
}
}).catch(error=>{
}).catch(error => {
console.log(error);
})
}
successFunc=()=>{
successFunc = () => {
this.resetSelectParams();
const { status_type } = this.state;
this.getIssueList(status_type);
}
resetSelectParams = () => {
let select_params = this.state.select_params;
select_params.update_author_id = undefined;
select_params.update_fixed_version_id = undefined;
select_params.update_status_id = undefined;
this.setState({
all:false,
checkedValue:[],
update_author_ids:"更换负责人",
update_fixed_version_ids:"更换里程碑",
update_status_ids:"修改状态",
all: false,
checkedValue: [],
update_author_ids: "更换负责人",
update_fixed_version_ids: "更换里程碑",
update_status_ids: "修改状态",
select_params
})
this.getIssueList();
}
// 批量删除
deleteIssues=()=>{
deleteIssues = () => {
this.props.confirm({
content: "是否确认删除所有选中的任务?",
onOk:()=>{
onOk: () => {
this.setState({
isSpin:true
isSpin: true
})
const { checkedValue } = this.state;
const { projectsId } = this.props.match.params;
const url = `/projects/${projectsId}/issues/clean.json`;
axios.post(url,{
ids:checkedValue
}).then(result=>{
if(result){
axios.post(url, {
ids: checkedValue
}).then(result => {
if (result) {
this.props.showNotification("删除成功!");
this.successFunc();
}
}).catch(error=>{
}).catch(error => {
console.log(error);
})
}
})
}
menu =()=> (
<Menu onClick={(e) => this.getMenu(e)}>
<Menu.Item key={"created_on-desc"} value="desc">
最新创建
</Menu.Item>
<Menu.Item key={"created_on-asc"} value="asc">
最早创建
</Menu.Item>
<Menu.Item key={"updated_on-desc"} value="desc">
最新更新
</Menu.Item>
<Menu.Item key={"updated_on-asc"} value="asc">
最早更新
</Menu.Item>
</Menu>
);
render() {
const { current_user } = this.props;
@ -470,40 +516,7 @@ class order extends Component {
select_params,
begin, end, checkedValue, all
} = this.state;
const menu = (
<Menu onClick={(e) => this.getMenu(e)}>
<Menu.Item key={"created_on-desc"} value="desc">
最新创建
</Menu.Item>
<Menu.Item key={"created_on-asc"} value="asc">
最早创建
</Menu.Item>
<Menu.Item key={"updated_on-desc"} value="desc">
最新更新
</Menu.Item>
<Menu.Item key={"updated_on-asc"} value="asc">
最早更新
</Menu.Item>
</Menu>
);
const Paginations = (
<React.Fragment>
{search_count > select_params.limit ? (
<div className="mt30 mb50 edu-txt-center">
<Pagination
simple
defaultCurrent={select_params.page}
total={search_count}
pageSize={select_params.limit}
onChange={this.ChangePage}
></Pagination>
</div>
) : (
""
)}
</React.Fragment>
);
return (
<div className="main">
<div className="topWrapper" style={{ paddingTop: "10px" }}>
@ -528,9 +541,7 @@ class order extends Component {
onClick={() => this.openorder("2")}>{data && data.close_count}</span>
</li>
</ul>
<a className="topWrapper_btn ml10" onClick={() => this.islogin()}>
+&nbsp;创建任务
</a>
{this.renderNew()}
</div>
<div className="topWrapper">
<div className="target-detail-search">
@ -557,7 +568,7 @@ class order extends Component {
{
current_user && current_user.login ?
<Checkbox value="0" style={{ lineHeight: "50px", marginRight: "15px" }} checked={all} onChange={this.changeAll}></Checkbox>
:""
: ""
}
{checkedValue && checkedValue.length > 0 ?
<span style={{ lineHeight: "50px" }}>选中{checkedValue.length}个issue</span>
@ -596,199 +607,199 @@ class order extends Component {
}
</div>
{
checkedValue && checkedValue.length>0 ?
<ul className="topWrapper_select">
<li className="mr20">
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.assign_user,
"更换负责人",
"update_author_id",true
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.update_author_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li className="mr20">
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.issue_version,
"更换里程碑",
"update_fixed_version_id",true
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.update_fixed_version_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li className="mr20">
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.issue_status,
"修改状态",
"update_status_id",true
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.update_status_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<a onClick={this.updateIssues} className="updateBtn blue mr20">确定</a>
<a onClick={this.deleteIssues} className="updateBtn red mr20">删除</a>
</ul>
:
<ul className="topWrapper_select">
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.issue_tag,
"标签",
"issue_tag_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.issue_tag_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.assign_user,
"发布人",
"author_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.author_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.assign_user,
"负责人",
"assigned_to_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.assigned_to_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.tracker,
"类型",
"tracker_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.tracker_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.issue_version,
"里程碑",
"fixed_version_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.fixed_version_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.issue_status,
"状态",
"status_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.status_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.done_ratio,
"完成度",
"done_ratio"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.done_ratios}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={menu}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.paix}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
</ul>
checkedValue && checkedValue.length > 0 ?
<ul className="topWrapper_select">
<li className="mr20">
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.assign_user,
"更换负责人",
"update_author_id", true
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.update_author_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li className="mr20">
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.issue_version,
"更换里程碑",
"update_fixed_version_id", true
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.update_fixed_version_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li className="mr20">
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.issue_status,
"修改状态",
"update_status_id", true
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.update_status_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<a onClick={this.updateIssues} className="updateBtn blue mr20">确定</a>
<a onClick={this.deleteIssues} className="updateBtn red mr20">删除</a>
</ul>
:
<ul className="topWrapper_select">
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.issue_tag,
"标签",
"issue_tag_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.issue_tag_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.assign_user,
"发布人",
"author_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.author_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.assign_user,
"负责人",
"assigned_to_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.assigned_to_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.tracker,
"类型",
"tracker_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.tracker_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.issue_version,
"里程碑",
"fixed_version_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.fixed_version_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.issue_status,
"状态",
"status_id"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.status_ids}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.renderMenu(
issue_chosen && issue_chosen.done_ratio,
"完成度",
"done_ratio"
)}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.done_ratios}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
<li>
<Dropdown
className="topWrapperSelect"
overlay={this.menu()}
trigger={["click"]}
placement="bottomCenter"
>
<span>
{this.state.paix}
<Icon type="caret-down" className="ml5" />
</span>
</Dropdown>
</li>
</ul>
}
</div>
{search_count === 0 ? (
<NoneData _html="暂时还没有相关数据哦!" />
@ -800,7 +811,7 @@ class order extends Component {
<OrderItem
key={key}
item={item}
checkbox={current_user ? <Checkbox value={item.id} key={item.id} style={{ margin: '4px 15px 0px 0px' }}></Checkbox>:""}
checkbox={current_user ? <Checkbox value={item.id} key={item.id} style={{ margin: '4px 15px 0px 0px' }}></Checkbox> : ""}
search_count={search_count}
page={select_params.page}
limit={select_params.limit}
@ -813,7 +824,20 @@ class order extends Component {
</Checkbox.Group>
</div>
)}
{Paginations}
{
search_count > select_params.limit ?
<div className="mt30 mb50 edu-txt-center">
<Pagination
simple
defaultCurrent={select_params.page}
total={search_count}
pageSize={select_params.limit}
onChange={this.ChangePage}
></Pagination>
</div>
:
""
}
</Spin>
</div>
);

View File

@ -1,5 +1,5 @@
import React, { Component } from "react";
import { Form, Input, Select, Button, DatePicker, Switch } from "antd";
import { Form, Input, Select, Button, DatePicker ,Spin } from "antd";
import Upload from "../Upload/Index";
import UploadImg from "../Images/upload.png";
import MDEditor from "../../modules/tpm/challengesnew/tpm-md-editor";
@ -17,17 +17,17 @@ class order_form extends Component {
branch_name: "",
issue_tag_ids: "",
fixed_version_id: "",
tracker_id: "缺陷",
tracker_id: "1",
issue_type: "1",
status_id: "新增",
status_id: "1",
assigned_to_id: "",
priority_id: "正常",
priority_id: "1",
done_ratio: "0%",
issue_chosen: undefined,
branches: undefined,
fileList: undefined,
description: undefined,
isSpin: false,
isSpin: true,
token: undefined,
start_date: "",
due_date: "",
@ -36,77 +36,56 @@ class order_form extends Component {
show_token: false,
};
}
componentDidUpdate=(prevPros)=>{
if(prevPros && this.props && this.props.checkIfLogin()===false){
this.props.history.push("/403")
return
}
}
componentDidMount = () => {
this.getSelectList();
this.get_detail();
};
get_detail = () => {
const { form_type } = this.props;
if (form_type === "new") {
this.InitData();
this.getSelectList();
} else {
this.state.isSpin = true;
const { projectsId, orderId } = this.props.match.params;
const url = `/projects/${projectsId}/issues/${orderId}/edit.json`;
axios
.get(url)
.then((result) => {
if (result) {
this.setState(
{
branch_name: result.data.branch_name,
issue_tag_ids: [
result.data.issue_tags && result.data.issue_tags[0].id
? String(
result.data.issue_tags && result.data.issue_tags[0].id
)
: "",
],
fixed_version_id: result.data.fixed_version_id
? String(result.data.fixed_version_id)
: "",
tracker_id: result.data.tracker_id
? String(result.data.tracker_id)
: "",
issue_type: result.data.issue_type,
status_id: result.data.status_id
? String(result.data.status_id)
: "",
assigned_to_id: result.data.assigned_to_id
? String(result.data.assigned_to_id)
: "",
priority_id: result.data.priority_id
? String(result.data.priority_id)
: "",
done_ratio: result.data.done_ratio,
fileList: undefined,
description: result.data.description,
isSpin: false,
token: result.data.token,
get_attachments: result.data.attachments,
start_date: result.data.start_date,
due_date: result.data.due_date,
subject: result.data.subject,
},
() => this.InitData()
);
}
})
.catch((error) => {
this.state.isSpin = false;
console.log(error);
});
}
this.setState({
isSpin:true
})
const { projectsId, orderId } = this.props.match.params;
const url = `/projects/${projectsId}/issues/${orderId}/edit.json`;
axios.get(url).then((result) => {
if (result) {
let data ={
branch_name: result.data.branch_name,
issue_tag_ids: [
result.data.issue_tags && result.data.issue_tags[0].id ?
String(result.data.issue_tags[0].id) : "",
],
fixed_version_id: result.data.fixed_version_id ? String(result.data.fixed_version_id) : "",
tracker_id: result.data.tracker_id ? String(result.data.tracker_id) : "",
issue_type: result.data.issue_type,
status_id: result.data.status_id ? String(result.data.status_id) : "",
assigned_to_id: result.data.assigned_to_id ? String(result.data.assigned_to_id) : "",
priority_id: result.data.priority_id ? String(result.data.priority_id) : "",
done_ratio: result.data.done_ratio,
fileList: undefined,
description: result.data.description,
isSpin: false,
token: result.data.token,
get_attachments: result.data.attachments,
start_date: result.data.start_date,
due_date: result.data.due_date,
subject: result.data.subject,
}
this.props.form.setFieldsValue({ ...data });
this.setState({ ...data });
}
}).catch((error) => {
this.setState({
isSpin:false
})
console.log(error);
});
};
InitData = () => {
// this.props.form.setFieldsValue({
// ...this.state,
// });
};
getSelectList = () => {
let projectsId = "";
if (this.props.match.params.milepostId) {
@ -117,28 +96,32 @@ class order_form extends Component {
} else {
projectsId = this.props.match.params.projectsId;
}
const url = `/projects/${projectsId}/issues/new.json`;
axios
.get(url)
.then((result) => {
if (result) {
this.setState({
issue_chosen: result.data.issue_chosen,
branches: result.data.branches,
axios.get(url).then((result) => {
if (result) {
this.setState({
issue_chosen: result.data.issue_chosen,
branches: result.data.branches,
isSpin:false
});
if(this.props.form_type !== "new"){
this.get_detail();
}else{
this.props.form.setFieldsValue({
...this.state
});
}
})
.catch((error) => {
console.log(error);
});
}
}).catch((error) => {
console.log(error);
});
};
renderSelect = (list) => {
if (list && list.length > 0) {
return list.map((item, key) => {
return (
<Option key={key + 1} value={item.id + ""}>
<Option key={key + 1} value={String(item.id)}>
{item.name}
</Option>
);
@ -156,7 +139,6 @@ class order_form extends Component {
const { form_type } = this.props;
const { projectsId, orderId } = this.props.match.params;
// const { projectsId } = this.props.match.params;
const { fileList } = this.state;
if (values.status_id === "新增") {
@ -177,58 +159,54 @@ class order_form extends Component {
const { description, start_date, due_date, issue_type } = this.state;
if (form_type === "new") {
const url = `/projects/${projectsId}/issues.json`;
axios
.post(url, {
...values,
description: description,
attachment_ids: fileList,
start_date: start_date,
due_date: due_date,
issue_type: issue_type,
})
.then((result) => {
if (result) {
this.props.showNotification("任务创建成功!");
this.props.history.push(`/projects/${projectsId}/orders`);
this.setState({
description: "",
isSpin: false,
});
const { getDetail } = this.props;
getDetail && getDetail();
}
})
.catch((error) => {
axios.post(url, {
...values,
description: description,
attachment_ids: fileList,
start_date: start_date,
due_date: due_date,
issue_type: issue_type,
}).then((result) => {
if (result && result.data.id) {
this.props.showNotification("任务创建成功!");
this.props.history.push(`/projects/${projectsId}/orders/${result.data.id}/detail`);
this.setState({
description: "",
isSpin: false,
});
console.log(error);
const { getDetail } = this.props;
getDetail && getDetail();
}
})
.catch((error) => {
this.setState({
isSpin: false,
});
console.log(error);
});
} else {
const url = `/projects/${projectsId}/issues/${orderId}.json`;
axios
.put(url, {
description: description,
attachment_ids: fileList,
start_date: start_date,
due_date: due_date,
issue_type: issue_type,
...values,
})
.then((result) => {
if (result) {
this.props.history.push(
`/projects/${projectsId}/orders/${orderId}/detail`
);
this.props.showNotification("任务更新成功!");
}
})
.catch((error) => {
this.setState({
isSpin: false,
});
console.log(error);
axios.put(url, {
description: description,
attachment_ids: fileList,
start_date: start_date,
due_date: due_date,
issue_type: issue_type,
...values,
}).then((result) => {
if (result) {
this.props.history.push(
`/projects/${projectsId}/orders/${orderId}/detail`
);
this.props.showNotification("任务更新成功!");
}
})
.catch((error) => {
this.setState({
isSpin: false,
});
console.log(error);
});
}
}
this.setState({
@ -324,273 +302,224 @@ class order_form extends Component {
const projectsId = this.props.match.params.projectsId;
const { orderId } = this.props.match.params;
const { form_type } = this.props;
const {
issue_tag_ids,
fixed_version_id,
branch_name,
status_id,
tracker_id,
issue_type,
assigned_to_id,
priority_id,
done_ratio,
issue_chosen,
branches,
subject,
description,
get_attachments,
isSpin,
start_date,
due_date,
token,
show_token,
} = this.state;
const {issue_chosen,branches,description,get_attachments,isSpin,start_date,due_date} = this.state;
return (
<div className="ProjectListIndex issue-form-index">
<Form className="width100 display-in" size="small">
<div className="list-right">
<div className="pd20">
<h3 className="mb15">
{form_type === "new" ? "新建" :( form_type === "copy" ? "复制" : "编辑")}任务
</h3>
<Form.Item>
{getFieldDecorator("subject", {
rules: [
{
required: true,
message: "请填写任务标题",
},
],
initialValue: subject,
})(<Input placeholder="标题" size="large" />)}
</Form.Item>
<div className="quillContent">
<MDEditor
placeholder={"请输入描述信息"}
height={500}
mdID={"order-new-description"}
initValue={description}
onChange={this.onContentChange}
></MDEditor>
</div>
{get_attachments && get_attachments.length > 0 ? (
<div className="mt20">
<Attachments
attachments={get_attachments}
showNotification={this.props.showNotification}
canDelete={true}
/>
<Spin spinning={isSpin}>
<div className="ProjectListIndex issue-form-index">
<Form className="width100 display-in" size="small">
<div className="list-right">
<div className="pd20">
<h3 className="mb15">
{form_type === "new" ? "新建" :( form_type === "copy" ? "复制" : "编辑")}任务
</h3>
<Form.Item>
{getFieldDecorator("subject", {
rules: [
{
required: true,
message: "请填写任务标题",
},
]
})(<Input placeholder="标题" size="large" />)}
</Form.Item>
<div className="quillContent">
<MDEditor
placeholder={"请输入描述信息"}
height={500}
mdID={"order-new-description"}
initValue={description}
onChange={this.onContentChange}
></MDEditor>
</div>
) : (
""
)}
<Upload
className="commentStyle mt30"
isComplete={true}
load={this.UploadFunc}
icon={
<img
src={UploadImg}
width="58"
alt=""
style={{ marginBottom: 15 }}
/>
}
size={100}
showNotification={this.props.showNotification}
/>
<p className="clearfix mt20">
<Button
type="primary"
loading={isSpin}
onClick={this.handleSubmit}
>
<span className="plr10">
{form_type === "new" ? "创建" : "提交"}
</span>
</Button>
<Button
type="default"
className="ml30"
href={
form_type === "new"
? `/projects/${projectsId || orderId}/orders` : `/projects/${projectsId}/orders/${orderId}/detail`
{get_attachments && get_attachments.length > 0 ? (
<div className="mt20">
<Attachments
attachments={get_attachments}
showNotification={this.props.showNotification}
canDelete={true}
/>
</div>
) : (
""
)}
<Upload
className="commentStyle mt30"
isComplete={true}
load={this.UploadFunc}
icon={
<img
src={UploadImg}
width="58"
alt=""
style={{ marginBottom: 15 }}
/>
}
>
<span className="plr10">取消</span>
</Button>
</p>
size={100}
showNotification={this.props.showNotification}
/>
<p className="clearfix mt20">
<Button
type="primary"
onClick={this.handleSubmit}
>
<span className="plr10">
{form_type === "new" ? "创建" : "提交"}
</span>
</Button>
<Button
type="default"
className="ml30"
onClick={()=>
this.props.history.push(form_type === "new" ? `/projects/${projectsId || orderId}/orders` : `/projects/${projectsId}/orders/${orderId}/detail`)}
>
<span className="plr10">取消</span>
</Button>
</p>
</div>
</div>
</div>
<div className="list-left list-left-padding issue-edit-form-right">
<div className="pd20 background-f issue-form-right">
<Form.Item>
{getFieldDecorator("branch_name", {
rules: [],
initialValue: branch_name,
})(
<Select>
<Option value={""}>分支未指定</Option>
{branches &&
branches.length > 0 &&
branches.map((item, key) => {
<div className="list-left list-left-padding issue-edit-form-right">
<div className="pd20 background-f issue-form-right">
<Form.Item>
{getFieldDecorator("branch_name", {
rules: []
})(
<Select>
<Option value={""}>分支未指定</Option>
{branches && branches.length > 0 && branches.map((item, key) => {
return (
<Option value={item} key={key}>
{item}
</Option>
);
})}
</Select>
)}
</Form.Item>
<Form.Item label="状态">
{getFieldDecorator("status_id", {
rules: [
{
</Select>
)}
</Form.Item>
<Form.Item label="状态">
{getFieldDecorator("status_id", {
rules: [{
required: true,
message: "请选择完成状态",
},
],
initialValue: status_id,
})(
<Select onChange={this.changeStatus}>
{this.renderSelect(
issue_chosen && issue_chosen.issue_status
)}
</Select>
)}
</Form.Item>
<Form.Item label="类型">
{getFieldDecorator("tracker_id", {
rules: [
{
}]
})(
<Select onChange={this.changeStatus}>
{this.renderSelect( issue_chosen && issue_chosen.issue_status )}
</Select>
)}
</Form.Item>
<Form.Item label="类型">
{getFieldDecorator("tracker_id", {
rules: [{
required: true,
message: "请选择类型",
},
],
initialValue: tracker_id,
})(
<Select>
{this.renderSelect(issue_chosen && issue_chosen.tracker)}
</Select>
)}
</Form.Item>
}]
})(
<Select>
{this.renderSelect(issue_chosen && issue_chosen.tracker)}
</Select>
)}
</Form.Item>
<Form.Item label="优先度">
{getFieldDecorator("priority_id", {
rules: [
{
<Form.Item label="优先度">
{getFieldDecorator("priority_id", {
rules: [{
required: true,
message: "请选择优先度",
},
],
initialValue: priority_id,
})(
<Select>
{this.renderSelect(issue_chosen && issue_chosen.priority)}
</Select>
)}
</Form.Item>
<Form.Item label="里程碑">
{getFieldDecorator("fixed_version_id", {
rules: [],
initialValue: fixed_version_id,
})(
<Select>
<Option value={""}>
{issue_chosen && issue_chosen.issue_version.length > 0
? "未选择里程碑"
: "请添加里程碑"}
</Option>
{this.renderSelect(
issue_chosen && issue_chosen.issue_version
)}
</Select>
)}
</Form.Item>
<Form.Item label="标签">
{getFieldDecorator("issue_tag_ids", {
rules: [],
initialValue: issue_tag_ids,
})(
<Select>
<Option value={""}>
{issue_chosen && issue_chosen.issue_tag.length > 0
? "未选择标签"
: "请在仓库设置里添加标签"}
</Option>
{this.renderSelect(issue_chosen && issue_chosen.issue_tag)}
</Select>
)}
</Form.Item>
<Form.Item label="指派成员">
{getFieldDecorator("assigned_to_id", {
rules: [{}],
initialValue: assigned_to_id,
})(
<Select>
<Option value={""}>未指派成员</Option>
{this.renderSelect(
issue_chosen && issue_chosen.assign_user
)}
</Select>
)}
</Form.Item>
<Form.Item label="开始日期">
<DatePicker
value={start_date ? moment(start_date, "YYYY-MM-DD") : null}
style={{ width: "100%" }}
placeholder="请选择开始日期"
onChange={this.changeBeginTime}
/>
</Form.Item>
<Form.Item label="结束日期">
<DatePicker
value={due_date ? moment(due_date, "YYYY-MM-DD") : null}
style={{ width: "100%" }}
placeholder="请选择结束日期"
onChange={this.changeEndTime}
/>
</Form.Item>
<Form.Item label="完成度">
{getFieldDecorator("done_ratio", {
rules: [],
initialValue: done_ratio,
})(
<Select onChange={this.changeRatio}>
{this.renderSelect(issue_chosen && issue_chosen.done_ratio)}
</Select>
)}
</Form.Item>
{/* <Form.Item label="">
<Switch
checkedChildren="是"
unCheckedChildren="否"
defaultChecked={false}
checked={issue_type && issue_type === "2"}
onChange={this.change_issue_type}
/>
</Form.Item>
{(show_token || (issue_type && issue_type === "2")) && (
<Form.Item label="token">
{getFieldDecorator("token", {
rules: [
{
required: true,
message: "请填写token值",
},
],
initialValue: token,
})(<Input placeholder="请填写token值" />)}
}]
})(
<Select>
{this.renderSelect(issue_chosen && issue_chosen.priority)}
</Select>
)}
</Form.Item>
)} */}
<Form.Item label="里程碑">
{getFieldDecorator("fixed_version_id", {rules: []})(
<Select>
<Option value={""}>
{issue_chosen && issue_chosen.issue_version.length > 0
? "未选择里程碑"
: "请添加里程碑"}
</Option>
{this.renderSelect(
issue_chosen && issue_chosen.issue_version
)}
</Select>
)}
</Form.Item>
<Form.Item label="标签">
{getFieldDecorator("issue_tag_ids", {rules: []})(
<Select>
<Option value={""}>
{issue_chosen && issue_chosen.issue_tag.length > 0
? "未选择标签"
: "请在仓库设置里添加标签"}
</Option>
{this.renderSelect(issue_chosen && issue_chosen.issue_tag)}
</Select>
)}
</Form.Item>
<Form.Item label="指派成员">
{getFieldDecorator("assigned_to_id", {rules: []})(
<Select>
<Option value={""}>未指派成员</Option>
{this.renderSelect(
issue_chosen && issue_chosen.assign_user
)}
</Select>
)}
</Form.Item>
<Form.Item label="开始日期">
<DatePicker
value={start_date ? moment(start_date, "YYYY-MM-DD") : null}
style={{ width: "100%" }}
placeholder="请选择开始日期"
onChange={this.changeBeginTime}
/>
</Form.Item>
<Form.Item label="结束日期">
<DatePicker
value={due_date ? moment(due_date, "YYYY-MM-DD") : null}
style={{ width: "100%" }}
placeholder="请选择结束日期"
onChange={this.changeEndTime}
/>
</Form.Item>
<Form.Item label="完成度">
{getFieldDecorator("done_ratio", {rules: []})(
<Select onChange={this.changeRatio}>
{this.renderSelect(issue_chosen && issue_chosen.done_ratio)}
</Select>
)}
</Form.Item>
{/* <Form.Item label="">
<Switch
checkedChildren="是"
unCheckedChildren="否"
defaultChecked={false}
checked={issue_type && issue_type === "2"}
onChange={this.change_issue_type}
/>
</Form.Item>
{(show_token || (issue_type && issue_type === "2")) && (
<Form.Item label="token">
{getFieldDecorator("token", {
rules: [
{
required: true,
message: "请填写token值",
},
],
initialValue: token,
})(<Input placeholder="请填写token值" />)}
</Form.Item>
)} */}
</div>
</div>
</div>
</Form>
</div>
</Form>
</div>
</Spin>
);
}
}

View File

@ -1,42 +1,51 @@
import React , { useEffect , useState } from 'react';
import { Input , Select } from 'antd';
import { getBranch } from '../GetData/getData';
import React , { useState } from 'react';
import SelectBranch from '../Branch/Select';
import Title from '../Component/Title';
import styled from 'styled-components';
import { Blueline , FlexAJ , NumUl , GreenUnder , AlignCenter , WhiteBack } from '../Component/layout';
const Div = styled.div`{
padding:20px 30px;
min-height:500px;
}`
const { Option } = Select;
export default ((props)=>{
const [ branchList , setBranchList] = useState(undefined);
const [ branch , setBranch ] = useState("master");
const { projectsId } = props.match.params;
const projectDetail = props.projectDetail;
useEffect(()=>{
getBranchs(projectsId);
},[projectsId])
function resetSetting(){
async function getBranchs(id){
let result = await getBranch(id);
setBranchList(result);
}
const branchListRender = (
branchList && branchList.map((item,key)=>{
return(
<Option value={item.name}>{item.name}</Option>
)
})
)
return(
<div className="normalBox">
<div className="normalBox-title font-16">
分支列表
</div>
<p className="pl15 pt15">请选择一个默认的分支用于合并请求和提交</p>
<div className="addPanel">
<Select className="branchSelect">
{branchListRender}
</Select>
<a className="small_submitBtn ml20" onClick={this.resetSetting}>更新仓库设置</a>
</div>
</div>
<WhiteBack>
<Title>分支设置</Title>
<Div>
<div className="pb20" style={{borderBottom:"1px solid #eee"}}>
<p className="color-grey-3 mb10">默认分支</p>
<p className="mb10">默认分支被视作为代码库中的基本分支是所有克隆代码提交合并请求的目标分支</p>
<AlignCenter>
<SelectBranch
branch={branch}
repo_id={ projectDetail && projectDetail.repo_id}
projectsId={projectsId}
changeBranch={setBranch}
/>
<a className="color-blue ml20" onClick={resetSetting()}>设为默认分支</a>
</AlignCenter>
</div>
<div>
<FlexAJ className="pt20">
<span className="color-grey-3">保护分支规则</span>
<Blueline>+&nbsp;新建规则</Blueline>
</FlexAJ>
<NumUl>
<li>限制分支的推送合并强制推送相关请去<GreenUnder>仓库设置</GreenUnder></li>
<li>一个分支同时只能有一个保护分支规则生效越早创建的规则优先级越高</li>
<li>保护分支规则只影响状态是保护分支的分支常规分支只读分支都不影响</li>
</NumUl>
</div>
</Div>
</WhiteBack>
)
})

View File

@ -0,0 +1,60 @@
import React , { forwardRef , useCallback } from 'react';
import { Form , Input , Select , Button } from 'antd';
import Title from '../Component/Title';
import { WhiteBack , Cancel } from '../Component/layout';
import styled from 'styled-components';
const {Option} = Select;
const Div = styled.div`{
padding:20px 30px;
}`
export default Form.create()(
forwardRef(( { form })=>{
const { getFieldDecorator } = form;
const helper = useCallback(
(label, name, rules, widget , className , isRequired ) => (
<div className={className}>
<span className={isRequired?"required":""}>{label}</span>
<Form.Item>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
</Form.Item>
</div>
),
[]
);
return(
<WhiteBack>
<Title>新建保护分支规则</Title>
<Div>
{helper(
"设置分支/通配符",
"sign",
[{ required: true, message: "请输入分支/通配符" }],
<Input placeholder="请输入分支名称或通配符规则" />,'setStyleRule'
)}
<p className="color-grey-8 mb20">例如设置为master则对名称为master的分支生效设置为*-stable release*则对名称符合此通配符的所有保护分支生效</p>
{helper(
"可推送代码成员",
"psuhmember",
[],
<Select placeholder="请选择仓库成员" >
<Option value="0">请选择仓库成员</Option>
</Select>,'setSelectWidth'
)}
{helper(
"可合并Pull Request成员",
"pullmember",
[],
<Select placeholder="请选择仓库成员" >
<Option value="0">请选择仓库成员</Option>
</Select>,'setSelectWidth'
)}
<div className="df pb30">
<Button type="primary">保存</Button>
<Cancel className="ml30">取消</Cancel>
</div>
</Div>
</WhiteBack>
)
})
)

View File

@ -15,6 +15,8 @@ import {
import NoneData from "../Nodata";
import axios from "axios";
import { getImageUrl } from "educoder";
import {WhiteBack} from '../Component/layout';
const { Search } = Input;
const { Option } = AutoComplete;
@ -52,13 +54,26 @@ class Collaborator extends Component {
roleName: undefined,
};
}
componentDidUpdate=(prevPros)=>{
if(prevPros && this.props && !this.props.checkIfLogin()){
this.props.history.push("/403")
return
}
}
componentDidMount = () => {
// this.check_is_login()
if (this.props.project_id) {
this.getMember();
}
};
// check_is_login =() =>{
// if(!this.props.checkIfLogin()){
// this.props.history.push("/403")
// return
// }
// };
componentDidUpdate = (prevState) => {
if (
this.props.project_id &&
@ -425,9 +440,9 @@ class Collaborator extends Component {
);
});
return (
<div>
<WhiteBack>
<div className="flex-a-center baseForm bbr">
<span className="font-18 fwb text-black">协作者管理</span>
<span className="font-18 text-black">协作者管理</span>
<div className="addPanel">
<AutoComplete
dataSource={source}
@ -466,7 +481,7 @@ class Collaborator extends Component {
<Spin spinning={isSpin}>
<div className="collaboratorList baseForm">
{listData ? (
{listData && listData.length>0 ? (
<Table
pagination={false}
columns={columns}
@ -491,7 +506,7 @@ class Collaborator extends Component {
) : (
""
)}
</div>
</WhiteBack>
);
}
}

View File

@ -1,12 +1,17 @@
import React, { Component } from "react";
import { Link, Route, Switch } from "react-router-dom";
import "../css/index.css";
import "./setting.css";
import "../css/index.scss";
import "./setting.scss";
import Loadable from "react-loadable";
import Loading from "../../Loading";
import { Box, Long, Short, Gap } from '../Component/layout';
const BranchNew = Loadable({
loader: () => import("./BranchRule"),
loading: Loading,
});
const Branch = Loadable({
loader: () => import("./Branch"),
loading: Loading,
@ -23,6 +28,14 @@ const Tags = Loadable({
loader: () => import("./new_tags"),
loading: Loading,
});
const Manage = Loadable({
loader: () => import("./ManageWeb"),
loading: Loading,
});
const ManageNew = Loadable({
loader: () => import("./ManageWebNew"),
loading: Loading,
});
class Index extends Component {
render() {
const { projectsId } = this.props.match.params;
@ -30,14 +43,14 @@ class Index extends Component {
const flag = pathname === `/projects/${projectsId}/setting`;
return (
<div className="ProjectListIndex">
<div className="list-left">
<Box className="ProjectListIndex">
<Short>
<ul className="list-l-Menu">
<li className={flag ? "active" : ""}>
<p>
<Link to={`/projects/${projectsId}/setting`} className="w-100">
<i className="iconfont icon-huabanfuben font-18 mr10"></i>
<i className="iconfont icon-huabanfuben font-18 mr10"></i>
</Link>
</p>
</li>
@ -48,7 +61,7 @@ class Index extends Component {
>
<p>
<Link to={`/projects/${projectsId}/setting/collaborator`} className="w-100">
<i className="iconfont icon-chengyuan font-18 mr10"></i>
<i className="iconfont icon-chengyuan font-18 mr10"></i>
协作者管理
</Link>
</p>
@ -63,7 +76,6 @@ class Index extends Component {
<i className="iconfont icon-fenzhi font-20 mr10"></i>
分支设置
</Link>
</p>
</li> */}
<li
@ -71,7 +83,7 @@ class Index extends Component {
>
<p>
<Link to={`/projects/${projectsId}/setting/tags`} className="w-100">
<i className="iconfont icon-biaoqian3 font-18 mr10"></i>
<i className="iconfont icon-biaoqian3 font-18 mr10"></i>
项目标签
</Link>
</p>
@ -79,20 +91,20 @@ class Index extends Component {
{/* <li
className={
pathname.indexOf("setting/hooks") > -1 ? "active" : ""
pathname.indexOf("setting/manage") > -1 ? "active" : ""
}
>
<p>
<Link to={"javascript:void(0)"} className="w-100">
<Link to={""} className="w-100">
<i className="iconfont icon-zhongqingdianxinicon10 font-18 mr10"></i>
管理Web钩子
</Link>
</p>
</li> */}
</ul>
</div>
<div className="list-right">
<div>
</Short>
<Long>
<Gap>
<Switch {...this.props}>
{/* 协作者 */}
<Route
@ -108,6 +120,30 @@ class Index extends Component {
<Tags {...this.props} {...props} {...this.state} />
)}
></Route>
<Route
path="/projects/:projectsId/setting/branch/new"
render={(props) => (
<BranchNew {...this.props} {...props} {...this.state} />
)}
></Route>
<Route
path="/projects/:projectsId/setting/branch"
render={(props) => (
<Branch {...this.props} {...props} {...this.state} />
)}
></Route>
<Route
path="/projects/:projectsId/setting/manage/new"
render={(props) => (
<ManageNew {...this.props} {...props} {...this.state} />
)}
></Route>
<Route
path="/projects/:projectsId/setting/manage"
render={(props) => (
<Manage {...this.props} {...props} {...this.state} />
)}
></Route>
{/* 修改仓库信息 */}
<Route
path="/projects/:projectsId/setting"
@ -116,9 +152,9 @@ class Index extends Component {
)}
></Route>
</Switch>
</div>
</div>
</div>
</Gap>
</Long>
</Box>
);
}
}

Some files were not shown because too many files have changed in this diff Show More