forked from Gitlink/forgeplus-react
修改后的上线
This commit is contained in:
commit
ac39faceca
|
@ -30,6 +30,72 @@
|
|||
<div class="content unicode" style="display: block;">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">TAR</div>
|
||||
<div class="code-name">&#xe75e;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">ZIP</div>
|
||||
<div class="code-name">&#xe75d;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">文件夹</div>
|
||||
<div class="code-name">&#xe75c;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">文件</div>
|
||||
<div class="code-name">&#xe75b;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">下载</div>
|
||||
<div class="code-name">&#xe75a;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">复制</div>
|
||||
<div class="code-name">&#xe759;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">仓库</div>
|
||||
<div class="code-name">&#xe758;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">贡献者</div>
|
||||
<div class="code-name">&#xe757;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">发行版</div>
|
||||
<div class="code-name">&#xe755;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">标签</div>
|
||||
<div class="code-name">&#xe754;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">分支</div>
|
||||
<div class="code-name">&#xe753;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">项目类别</div>
|
||||
|
@ -2228,6 +2294,105 @@
|
|||
<div class="content font-class">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-TAR"></span>
|
||||
<div class="name">
|
||||
TAR
|
||||
</div>
|
||||
<div class="code-name">.icon-TAR
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-ZIP"></span>
|
||||
<div class="name">
|
||||
ZIP
|
||||
</div>
|
||||
<div class="code-name">.icon-ZIP
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-wenjianjia1"></span>
|
||||
<div class="name">
|
||||
文件夹
|
||||
</div>
|
||||
<div class="code-name">.icon-wenjianjia1
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-wenjia"></span>
|
||||
<div class="name">
|
||||
文件
|
||||
</div>
|
||||
<div class="code-name">.icon-wenjia
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-xiazai2"></span>
|
||||
<div class="name">
|
||||
下载
|
||||
</div>
|
||||
<div class="code-name">.icon-xiazai2
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-fuzhi5"></span>
|
||||
<div class="name">
|
||||
复制
|
||||
</div>
|
||||
<div class="code-name">.icon-fuzhi5
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-cangku"></span>
|
||||
<div class="name">
|
||||
仓库
|
||||
</div>
|
||||
<div class="code-name">.icon-cangku
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-gongxianzhe"></span>
|
||||
<div class="name">
|
||||
贡献者
|
||||
</div>
|
||||
<div class="code-name">.icon-gongxianzhe
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-fahangban"></span>
|
||||
<div class="name">
|
||||
发行版
|
||||
</div>
|
||||
<div class="code-name">.icon-fahangban
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-biaoqian3"></span>
|
||||
<div class="name">
|
||||
标签
|
||||
</div>
|
||||
<div class="code-name">.icon-biaoqian3
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-fenzhi1"></span>
|
||||
<div class="name">
|
||||
分支
|
||||
</div>
|
||||
<div class="code-name">.icon-fenzhi1
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-xiangmuleibie"></span>
|
||||
<div class="name">
|
||||
|
@ -5479,6 +5644,94 @@
|
|||
<div class="content symbol">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-TAR"></use>
|
||||
</svg>
|
||||
<div class="name">TAR</div>
|
||||
<div class="code-name">#icon-TAR</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-ZIP"></use>
|
||||
</svg>
|
||||
<div class="name">ZIP</div>
|
||||
<div class="code-name">#icon-ZIP</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-wenjianjia1"></use>
|
||||
</svg>
|
||||
<div class="name">文件夹</div>
|
||||
<div class="code-name">#icon-wenjianjia1</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-wenjia"></use>
|
||||
</svg>
|
||||
<div class="name">文件</div>
|
||||
<div class="code-name">#icon-wenjia</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-xiazai2"></use>
|
||||
</svg>
|
||||
<div class="name">下载</div>
|
||||
<div class="code-name">#icon-xiazai2</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-fuzhi5"></use>
|
||||
</svg>
|
||||
<div class="name">复制</div>
|
||||
<div class="code-name">#icon-fuzhi5</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-cangku"></use>
|
||||
</svg>
|
||||
<div class="name">仓库</div>
|
||||
<div class="code-name">#icon-cangku</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-gongxianzhe"></use>
|
||||
</svg>
|
||||
<div class="name">贡献者</div>
|
||||
<div class="code-name">#icon-gongxianzhe</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-fahangban"></use>
|
||||
</svg>
|
||||
<div class="name">发行版</div>
|
||||
<div class="code-name">#icon-fahangban</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-biaoqian3"></use>
|
||||
</svg>
|
||||
<div class="name">标签</div>
|
||||
<div class="code-name">#icon-biaoqian3</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-fenzhi1"></use>
|
||||
</svg>
|
||||
<div class="name">分支</div>
|
||||
<div class="code-name">#icon-fenzhi1</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-xiangmuleibie"></use>
|
||||
|
|
|
@ -2475,7 +2475,10 @@ a.color-grey-c:hover {
|
|||
.color-blue {
|
||||
color: #4CACFF !important;
|
||||
}
|
||||
|
||||
/* 绿色 */
|
||||
.color-green-file{
|
||||
color: #28BD6C;
|
||||
}
|
||||
/*主*/
|
||||
.color-blue_4C {
|
||||
color: #4CACFF !important;
|
||||
|
|
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
|
@ -5,6 +5,83 @@
|
|||
"css_prefix_text": "icon-",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "14776069",
|
||||
"name": "TAR",
|
||||
"font_class": "TAR",
|
||||
"unicode": "e75e",
|
||||
"unicode_decimal": 59230
|
||||
},
|
||||
{
|
||||
"icon_id": "14776044",
|
||||
"name": "ZIP",
|
||||
"font_class": "ZIP",
|
||||
"unicode": "e75d",
|
||||
"unicode_decimal": 59229
|
||||
},
|
||||
{
|
||||
"icon_id": "14706564",
|
||||
"name": "文件夹",
|
||||
"font_class": "wenjianjia1",
|
||||
"unicode": "e75c",
|
||||
"unicode_decimal": 59228
|
||||
},
|
||||
{
|
||||
"icon_id": "14706563",
|
||||
"name": "文件",
|
||||
"font_class": "wenjia",
|
||||
"unicode": "e75b",
|
||||
"unicode_decimal": 59227
|
||||
},
|
||||
{
|
||||
"icon_id": "14706484",
|
||||
"name": "下载",
|
||||
"font_class": "xiazai2",
|
||||
"unicode": "e75a",
|
||||
"unicode_decimal": 59226
|
||||
},
|
||||
{
|
||||
"icon_id": "14706480",
|
||||
"name": "复制",
|
||||
"font_class": "fuzhi5",
|
||||
"unicode": "e759",
|
||||
"unicode_decimal": 59225
|
||||
},
|
||||
{
|
||||
"icon_id": "14706430",
|
||||
"name": "仓库",
|
||||
"font_class": "cangku",
|
||||
"unicode": "e758",
|
||||
"unicode_decimal": 59224
|
||||
},
|
||||
{
|
||||
"icon_id": "14706421",
|
||||
"name": "贡献者",
|
||||
"font_class": "gongxianzhe",
|
||||
"unicode": "e757",
|
||||
"unicode_decimal": 59223
|
||||
},
|
||||
{
|
||||
"icon_id": "14706420",
|
||||
"name": "发行版",
|
||||
"font_class": "fahangban",
|
||||
"unicode": "e755",
|
||||
"unicode_decimal": 59221
|
||||
},
|
||||
{
|
||||
"icon_id": "14706416",
|
||||
"name": "标签",
|
||||
"font_class": "biaoqian3",
|
||||
"unicode": "e754",
|
||||
"unicode_decimal": 59220
|
||||
},
|
||||
{
|
||||
"icon_id": "14706413",
|
||||
"name": "分支",
|
||||
"font_class": "fenzhi1",
|
||||
"unicode": "e753",
|
||||
"unicode_decimal": 59219
|
||||
},
|
||||
{
|
||||
"icon_id": "14599181",
|
||||
"name": "项目类别",
|
||||
|
|
|
@ -20,6 +20,39 @@ Created by iconfont
|
|||
/>
|
||||
<missing-glyph />
|
||||
|
||||
<glyph glyph-name="TAR" unicode="" d="M916.945455-109.381818H139.636364c-69.818182 0-130.327273 55.854545-130.327273 130.327273V756.363636C9.309091 826.181818 65.163636 886.690909 139.636364 886.690909h572.509091l330.472727-302.545454v-563.2c0-69.818182-55.854545-130.327273-125.672727-130.327273zM139.636364 812.218182c-32.581818 0-55.854545-23.272727-55.854546-55.854546v-735.418181c0-32.581818 27.927273-55.854545 55.854546-55.854546h777.309091c32.581818 0 55.854545 27.927273 55.854545 55.854546V551.563636l-288.581818 260.654546H139.636364zM1010.036364 556.218182h-344.436364V849.454545h69.818182v-223.418181h274.618182zM386.327273 356.072727h-93.090909v-293.236363h-37.236364v293.236363h-93.090909v37.236364h228.072727v-37.236364zM660.945455 67.490909h-41.89091l-32.581818 93.090909h-139.636363l-32.581819-93.090909H372.363636l125.672728 325.818182h37.236363l125.672728-325.818182z m-88.436364 125.672727l-51.2 139.636364c0 4.654545-4.654545 13.963636-4.654546 23.272727 0-9.309091-4.654545-18.618182-4.654545-23.272727l-51.2-139.636364h111.709091zM940.218182 67.490909h-46.545455l-55.854545 93.090909c-4.654545 9.309091-9.309091 13.963636-13.963637 23.272727l-13.963636 13.963637c-4.654545 4.654545-9.309091 4.654545-13.963636 9.309091-4.654545 0-13.963636 4.654545-18.618182 4.654545H744.727273v-139.636363h-37.236364v325.818181h97.745455c13.963636 0 27.927273 0 37.236363-4.654545 13.963636-4.654545 23.272727-9.309091 32.581818-13.963636 9.309091-9.309091 13.963636-18.618182 18.618182-27.927273 4.654545-9.309091 9.309091-23.272727 9.309091-37.236364 0-9.309091 0-23.272727-4.654545-32.581818-4.654545-9.309091-9.309091-18.618182-13.963637-23.272727-4.654545-9.309091-13.963636-13.963636-23.272727-18.618182l-27.927273-13.963636c4.654545-4.654545 9.309091-4.654545 13.963637-9.309091 4.654545-4.654545 9.309091-4.654545 9.309091-9.309091s9.309091-9.309091 9.309091-13.963637c4.654545-4.654545 9.309091-9.309091 13.963636-18.618181l60.509091-107.054546zM744.727273 356.072727v-116.363636h51.2c9.309091 0 18.618182 0 27.927272 4.654545 9.309091 4.654545 13.963636 9.309091 23.272728 13.963637 4.654545 4.654545 9.309091 13.963636 13.963636 18.618182 4.654545 9.309091 4.654545 18.618182 4.654546 27.927272 0 18.618182-4.654545 32.581818-18.618182 41.890909-9.309091 9.309091-27.927273 13.963636-51.2 13.963637H744.727273z" horiz-adv-x="1070" />
|
||||
|
||||
|
||||
<glyph glyph-name="ZIP" unicode="" d="M916.945455-109.381818H139.636364c-69.818182 0-130.327273 55.854545-130.327273 130.327273V756.363636C9.309091 826.181818 65.163636 886.690909 139.636364 886.690909h572.509091l330.472727-302.545454v-563.2c0-69.818182-55.854545-130.327273-125.672727-130.327273zM139.636364 812.218182c-32.581818 0-55.854545-23.272727-55.854546-55.854546v-735.418181c0-32.581818 27.927273-55.854545 55.854546-55.854546h777.309091c32.581818 0 55.854545 27.927273 55.854545 55.854546V551.563636l-288.581818 260.654546H139.636364zM1010.036364 556.218182h-344.436364V849.454545h69.818182v-223.418181h274.618182zM456.145455 384l-190.836364-283.927273h186.181818v-32.581818H209.454545v9.309091l190.836364 279.272727H223.418182v37.236364h232.727273v-9.309091zM544.581818 67.490909h-37.236363v325.818182h37.236363v-325.818182zM670.254545 188.509091v-121.018182h-37.236363v325.818182h88.436363c32.581818 0 60.509091-9.309091 79.127273-23.272727 18.618182-18.618182 27.927273-41.890909 27.927273-69.818182s-9.309091-55.854545-32.581818-74.472727c-23.272727-18.618182-51.2-27.927273-88.436364-27.927273h-37.236364z m0 167.563636v-134.981818h41.89091c27.927273 0 46.545455 4.654545 60.50909 18.618182 13.963636 13.963636 18.618182 27.927273 18.618182 51.2 0 41.890909-23.272727 65.163636-74.472727 65.163636h-46.545455z" horiz-adv-x="1070" />
|
||||
|
||||
|
||||
<glyph glyph-name="wenjianjia1" unicode="" d="M529.709176 896a12.047059 12.047059 0 0 0 7.228236-2.409412l129.204706-97.219764h280.877176a120.470588 120.470588 0 0 0 120.470588-120.470589v-605.665882a120.470588 120.470588 0 0 0-120.470588-120.470588H120.470588a120.470588 120.470588 0 0 0-120.470588 120.470588V835.764706a60.235294 60.235294 0 0 0 60.235294 60.235294h469.473882z m357.376-197.150118H98.605176v-591.390117h788.48V698.849882zM0 600.244706h1084.235294v-599.582118a90.352941 90.352941 0 0 0-90.352941-90.352941h-903.529412a90.352941 90.352941 0 0 0-90.352941 90.352941V600.304941z" horiz-adv-x="1084" />
|
||||
|
||||
|
||||
<glyph glyph-name="wenjia" unicode="" d="M824.888889-128H199.111111c-62.577778 0-113.777778 51.2-113.777778 113.777778V782.222222C85.333333 844.8 136.533333 896 199.111111 896h506.311111L938.666667 651.377778V-14.222221999999988c0-62.577778-51.2-113.777778-113.777778-113.777778zM199.111111 810.666667c-17.066667 0-28.444444-11.377778-28.444444-28.444445v-796.444444c0-17.066667 11.377778-28.444444 28.444444-28.444445h625.777778c17.066667 0 28.444444 11.377778 28.444444 28.444445V617.2444439999999l-182.044444 193.422223H199.111111zM739.555556 99.55555600000002h-455.111112c-17.066667 0-28.444444 11.377778-28.444444 28.444444s11.377778 28.444444 28.444444 28.444444h455.111112c17.066667 0 28.444444-11.377778 28.444444-28.444444s-11.377778-28.444444-28.444444-28.444444zM625.777778 554.666667h-341.333334c-17.066667 0-28.444444 11.377778-28.444444 28.444444s11.377778 28.444444 28.444444 28.444445h341.333334c17.066667 0 28.444444-11.377778 28.444444-28.444445s-11.377778-28.444444-28.444444-28.444444zM739.555556 327.11111100000005h-455.111112c-17.066667 0-28.444444 11.377778-28.444444 28.444445s11.377778 28.444444 28.444444 28.444444h455.111112c17.066667 0 28.444444-11.377778 28.444444-28.444444s-11.377778-28.444444-28.444444-28.444445z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="xiazai2" unicode="" d="M602.352941 155.105882c-24.094118 0-48.188235 18.070588-48.188235 48.188236V835.764706c0 24.094118 18.070588 48.188235 48.188235 48.188235s48.188235-24.094118 48.188235-48.188235v-638.494118c0-24.094118-18.070588-42.164706-48.188235-42.164706zM602.352941 137.035294L222.870588 486.4c-18.070588 12.047059-18.070588 42.164706-6.023529 60.235294 18.070588 18.070588 48.188235 18.070588 66.258823 6.02353l319.247059-295.152942 325.270588 289.129412c18.070588 18.070588 48.188235 18.070588 66.258824-6.023529 18.070588-18.070588 18.070588-48.188235-6.023529-66.258824L602.352941 137.035294zM1017.976471-109.929412H180.705882c-90.352941 0-168.658824 72.282353-168.658823 168.658824v186.729412c0 24.094118 18.070588 48.188235 48.188235 48.188235s48.188235-18.070588 48.188235-48.188235v-186.729412c0-42.164706 36.141176-72.282353 72.282353-72.282353h837.270589c42.164706 0 72.282353 36.141176 72.282353 72.282353v186.729412c0 24.094118 18.070588 48.188235 48.188235 48.188235s48.188235-18.070588 48.188235-48.188235v-186.729412c0-90.352941-78.305882-168.658824-168.658823-168.658824z" horiz-adv-x="1204" />
|
||||
|
||||
|
||||
<glyph glyph-name="fuzhi5" unicode="" d="M939.670588 149.082353H481.882353c-90.352941 0-168.658824 72.282353-168.658824 168.658823V727.341176C313.223529 823.717647 391.529412 896 481.882353 896h457.788235c90.352941 0 168.658824-72.282353 168.658824-168.658824v-415.623529c-6.023529-90.352941-78.305882-162.635294-168.658824-162.635294zM481.882353 805.647059c-42.164706 0-72.282353-36.141176-72.282353-72.282353v-415.62353c0-42.164706 36.141176-72.282353 72.282353-72.282352h457.788235c42.164706 0 72.282353 36.141176 72.282353 72.282352V727.341176c0 42.164706-36.141176 72.282353-72.282353 72.282353H481.882353zM728.847059-91.858824h-602.352941c-60.235294 0-108.423529 42.164706-108.42353 102.4V649.035294c0 54.211765 48.188235 102.4 108.42353 102.4h108.423529V655.058824H126.494118c-12.047059 0-18.070588-6.023529-18.070589-6.02353v-638.494118c0-6.023529 6.023529-12.047059 18.070589-12.047058h602.352941c12.047059 0 18.070588 6.023529 18.070588 12.047058v90.352942h90.352941v-90.352942c0-54.211765-48.188235-102.4-108.423529-102.4z" horiz-adv-x="1144" />
|
||||
|
||||
|
||||
<glyph glyph-name="cangku" unicode="" d="M512-128C246.964706-128 36.141176-1.505882 36.141176 155.105882c0 42.164706 12.047059 78.305882 42.164706 120.470589l78.305883-60.235295c-12.047059-18.070588-24.094118-42.164706-24.094118-60.235294 0-90.352941 156.611765-186.729412 379.482353-186.729411 222.870588 0 379.482353 96.376471 379.482353 186.729411 0 18.070588-6.023529 36.141176-18.070588 54.211765l78.305882 54.211765c24.094118-36.141176 36.141176-66.258824 36.141177-108.42353 0-156.611765-210.823529-283.105882-475.858824-283.105882zM512 131.011765c-265.035294 0-475.858824 120.470588-475.858824 271.058823 0 48.188235 24.094118 96.376471 66.258824 138.541177L168.658824 474.352941c-24.094118-24.094118-36.141176-48.188235-36.141177-72.282353 0-84.329412 156.611765-174.682353 379.482353-174.682353 222.870588 0 379.482353 90.352941 379.482353 174.682353 0 36.141176-24.094118 60.235294-48.188235 78.305883l60.235294 72.282353c54.211765-42.164706 84.329412-96.376471 84.329412-156.611765 0-144.564706-210.823529-265.035294-475.858824-265.035294zM512 359.905882c-271.058824 0-481.882353 120.470588-481.882353 265.035294S240.941176 896 512 896s481.882353-120.470588 481.882353-265.035294-210.823529-271.058824-481.882353-271.058824z m0 439.717647c-228.894118 0-385.505882-90.352941-385.505882-168.658823S283.105882 456.282353 512 456.282353c228.894118 0 385.505882 90.352941 385.505882 168.658823S740.894118 799.623529 512 799.623529z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="gongxianzhe" unicode="" d="M498.346667 254.293333C341.333333 254.293333 211.626667 377.173333 211.626667 541.013333S341.333333 827.733333 498.346667 827.733333s286.72-129.706667 286.72-286.72-122.88-286.72-286.72-286.72z m0 464.213334c-95.573333 0-177.493333-81.92-177.493334-177.493334s81.92-177.493333 177.493334-177.493333S682.666667 438.613333 682.666667 541.013333 600.746667 718.506667 498.346667 718.506667zM885.282133 260.846933v109.226667c95.573333 0 177.493333 81.92 177.493334 177.493333s-81.92 177.493333-177.493334 177.493334v109.226666c157.013333 0 286.72-129.706667 286.72-286.72s-129.706667-286.72-286.72-286.72zM1212.962133 15.086933c-20.48 163.84-163.84 286.72-327.68 286.72v109.226667c218.453333 0 402.773333-163.84 436.906667-375.466667l-109.226667-20.48zM880.64-121.173333c-27.306667 211.626667-191.146667 368.64-375.466667 368.64s-348.16-157.013333-375.466666-368.64l-109.226667 13.653333c34.133333 259.413333 245.76 464.213333 484.693333 464.213333s450.56-197.973333 484.693334-464.213333l-109.226667-13.653333z" horiz-adv-x="1365" />
|
||||
|
||||
|
||||
<glyph glyph-name="fahangban" unicode="" d="M881.777778-93.866667l-318.577778 170.666667 45.511111 79.644444 199.111111-108.088888 68.266667 665.6L204.8 435.2l142.222222-113.777778-56.888889-73.955555L22.755556 463.644444 984.177778 850.488889zM466.488889-25.6H375.466667v261.688889l517.688889 574.577778 68.266666-56.888889-494.933333-551.822222z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="biaoqian3" unicode="" d="M597.333333-76.8c-34.133333 0-68.266667 11.377778-91.022222 34.133333L5.688889 418.133333 79.644444 878.933333h438.044445l426.666667-455.111111c45.511111-51.2 51.2-130.844444 0-182.044444l-244.622223-278.755556c-22.755556-22.755556-56.888889-39.822222-102.4-39.822222 5.688889 0 5.688889 0 0 0zM108.088889 457.955556L568.888889 25.6c11.377778-5.688889 17.066667-11.377778 34.133333-11.377778 11.377778 0 22.755556 5.688889 34.133334 17.066667l244.622222 278.755555c17.066667 17.066667 17.066667 45.511111 0 62.577778L483.555556 799.288889H159.288889l-51.2-341.333333zM398.222222 543.288889m-113.777778 0a113.777778 113.777778 0 1 1 227.555556 0 113.777778 113.777778 0 1 1-227.555556 0Z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="fenzhi1" unicode="" d="M267.377778 531.911111C164.977778 531.911111 85.333333 611.555556 85.333333 713.955556S164.977778 896 267.377778 896s182.044444-79.644444 182.044444-182.044444S369.777778 531.911111 267.377778 531.911111z m0 273.066667c-51.2 0-91.022222-39.822222-91.022222-91.022222s39.822222-91.022222 91.022222-91.022223 91.022222 39.822222 91.022222 91.022223-39.822222 91.022222-91.022222 91.022222zM267.377778-105.244444c-102.4 0-182.044444 79.644444-182.044445 182.044444s79.644444 182.044444 182.044445 182.044444 182.044444-79.644444 182.044444-182.044444-79.644444-182.044444-182.044444-182.044444z m0 273.066666c-51.2 0-91.022222-39.822222-91.022222-91.022222 0-51.2 39.822222-91.022222 91.022222-91.022222s91.022222 39.822222 91.022222 91.022222c0 51.2-39.822222 91.022222-91.022222 91.022222zM750.933333 213.333333C665.6 213.333333 597.333333 281.6 597.333333 366.933333c0 85.333333 68.266667 153.6 153.6 153.6 85.333333 0 153.6-68.266667 153.6-153.6 0-85.333333-68.266667-153.6-153.6-153.6z m0 216.177778c-34.133333 0-62.577778-28.444444-62.577777-62.577778 0-34.133333 28.444444-62.577778 62.577777-62.577777s62.577778 28.444444 62.577778 62.577777c0 34.133333-28.444444 62.577778-62.577778 62.577778zM194.446222 160.995556l5.802667 432.298666 91.022222-1.251555-5.802667-432.355556zM330.524444 590.734222l50.801778 75.548445 287.971556-193.649778-50.801778-75.548445z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="xiangmuleibie" unicode="" d="M542.117647 317.741176c-6.023529 0-12.047059 0-18.070588 6.02353l-481.882353 246.964706C24.094118 576.752941 12.047059 594.823529 12.047059 612.894118c0 18.070588 12.047059 30.117647 24.094117 42.164706L505.976471 877.929412c12.047059 6.023529 24.094118 6.023529 42.164705 0l493.929412-234.917647c18.070588-6.023529 24.094118-24.094118 24.094118-42.164706s-12.047059-30.117647-24.094118-42.164706L566.211765 323.764706c-6.023529-6.023529-18.070588-6.023529-24.094118-6.02353zM162.635294 612.894118L542.117647 414.117647l373.458824 186.729412-385.505883 186.729412-367.435294-174.682353zM542.117647 124.988235c-6.023529 0-12.047059 0-18.070588 6.02353L42.164706 353.882353C18.070588 365.929412 12.047059 390.023529 18.070588 414.117647s36.141176 30.117647 60.235294 24.094118l457.788236-216.847059 457.788235 240.941176c24.094118 12.047059 48.188235 6.023529 60.235294-18.070588 12.047059-24.094118 6.023529-48.188235-18.070588-60.235294l-481.882353-252.988235s-6.023529-6.023529-12.047059-6.02353zM542.117647-85.835294c-6.023529 0-12.047059 0-18.070588 6.023529l-481.882353 222.870589c-24.094118 12.047059-30.117647 36.141176-24.094118 60.235294 12.047059 24.094118 36.141176 30.117647 60.235294 24.094117l457.788236-216.847059 457.788235 240.941177c24.094118 12.047059 48.188235 6.023529 60.235294-18.070588 12.047059-24.094118 6.023529-48.188235-18.070588-60.235294l-481.882353-252.988236c0-6.023529-6.023529-6.023529-12.047059-6.023529z" horiz-adv-x="1084" />
|
||||
|
||||
|
||||
|
|
Before Width: | Height: | Size: 438 KiB After Width: | Height: | Size: 450 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -17573,7 +17573,7 @@ Copyright © 2018 Basecamp, LLC
|
|||
|
||||
var actualPadding = document.body.style.paddingRight;
|
||||
var calculatedPadding = $(document.body).css('padding-right');
|
||||
$(document.body).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px");
|
||||
// $(document.body).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px");
|
||||
}
|
||||
|
||||
$(document.body).addClass(ClassName.OPEN);
|
||||
|
@ -17597,9 +17597,9 @@ Copyright © 2018 Basecamp, LLC
|
|||
}
|
||||
}); // Restore body padding
|
||||
|
||||
var padding = $(document.body).data('padding-right');
|
||||
$(document.body).removeData('padding-right');
|
||||
document.body.style.paddingRight = padding ? padding : '';
|
||||
// var padding = $(document.body).data('padding-right');
|
||||
// $(document.body).removeData('padding-right');
|
||||
// document.body.style.paddingRight = padding ? padding : '';
|
||||
};
|
||||
|
||||
_proto._getScrollbarWidth = function _getScrollbarWidth() {
|
||||
|
|
|
@ -19,14 +19,14 @@ class CloneAddress extends Component {
|
|||
}
|
||||
<input type="text" id="copy_rep_content" value={http_url} />
|
||||
<Tooltip title="复制链接">
|
||||
<span onClick={() => this.jsCopy()}><i className="iconfont icon-fuzhi"></i></span>
|
||||
<span className="color-blue" onClick={() => this.jsCopy()}><i className="iconfont icon-fuzhi"></i></span>
|
||||
</Tooltip>
|
||||
{
|
||||
downloadUrl &&
|
||||
<span>
|
||||
<Dropdown overlay={downloadUrl} trigger={['click']} placement="bottomRight">
|
||||
<a className="ant-dropdown-link">
|
||||
<Icon type="cloud-download" className="font-18 fl" />
|
||||
<Icon type="cloud-download" className="font-18 fl color-blue" />
|
||||
</a>
|
||||
</Dropdown>
|
||||
</span>
|
||||
|
|
|
@ -63,7 +63,9 @@ class SelectBranch extends Component{
|
|||
let branchsFilter = value ? (branchs && branchs.length>0 && branchs.filter(item=>item.name.indexOf(value)>-1)):branchs;
|
||||
const menu = (
|
||||
<div className="branchOptions" id="m-btn" onClick={this.stopPropagations}>
|
||||
<Input placeholder="请输入分支名称进行搜索" autocomplete="off" id="input-btn" value={value} className="OptionsInput" onChange={this.changeValue} onClick={this.InputClick}/>
|
||||
<div className="padding10 bor-bottom-greyE">
|
||||
<Input placeholder="请输入分支名称进行搜索" autocomplete="off" id="input-btn" value={value} className="OptionsInput" onChange={this.changeValue} onClick={this.InputClick}/>
|
||||
</div>
|
||||
<ul className="OptionsUl" id="ul-btn">
|
||||
{
|
||||
branchsFilter && branchsFilter.map((item,key)=>{
|
||||
|
@ -79,10 +81,13 @@ class SelectBranch extends Component{
|
|||
<div className="branchDropdown f-wrap-alignCenter" onClick={()=>this.ChangeVisible(visible)}>
|
||||
<Dropdown overlay={menu} trigger={['click']} placement="bottomLeft" visible={visible}>
|
||||
<span>
|
||||
<span className="color-grey-9 mr3"><i className="iconfont icon-fenzhi font-20 color-grey-6 mr3"></i>分支:</span>
|
||||
<a className="ant-dropdown-link">
|
||||
{branch} <Icon type="down" />
|
||||
</a>
|
||||
<span>
|
||||
<span className="color-grey-9 mr3">分支:</span>
|
||||
<a className="ant-dropdown-link">
|
||||
{branch}
|
||||
</a>
|
||||
</span>
|
||||
<Icon type="down" />
|
||||
</span>
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
|
|
@ -3,37 +3,40 @@
|
|||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
min-width: 150px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
min-width: 220px;
|
||||
}
|
||||
.branchDropdown .ant-dropdown-trigger{
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding:0px 15px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.branchOptions{
|
||||
width: 200px;
|
||||
padding:10px;
|
||||
width: 220px;
|
||||
box-shadow: 0px 0px 1px 1px rgba(134, 134, 134, 0.1);
|
||||
border-radius: 3px;
|
||||
background: #fff;
|
||||
max-height: 300px;
|
||||
}
|
||||
.OptionsUl{
|
||||
max-height: 200px;
|
||||
max-height: 220px;
|
||||
overflow-y: auto;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.OptionsUl li{
|
||||
height: 30px;
|
||||
/*line-height: 22px;*/
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
cursor: pointer;
|
||||
padding:0px 10px;
|
||||
}
|
||||
.OptionsUl li:hover{
|
||||
background-color: #F0F0F0;
|
||||
}
|
||||
.OptionsUl li a{
|
||||
display: block;
|
||||
padding: 4px;
|
||||
/*padding-left: 2px;*/
|
||||
}
|
||||
.OptionsInput{
|
||||
height: 32px;
|
||||
|
|
|
@ -28,15 +28,15 @@ class CoderRootBranch extends Component {
|
|||
<li key={key}>
|
||||
<div>
|
||||
<Link to={`/projects/${projectsId}/coders?branch=${item.name}`} className="color-blue font-15" style={{"maxWidth":"100px"}}>{item.name}</Link>
|
||||
<p className="f-wrap-alignCenter">
|
||||
<span className="mr5 color-blue">{item.last_commit && truncateCommitId(item.last_commit.id)}</span>
|
||||
<span className="color-grey-9 hide-1 messages leftPoint">{item.last_commit && item.last_commit.message}</span>
|
||||
<span className="color-grey-6 leftPoint">最后更新于{item.last_commit && item.last_commit.time_from_now}</span>
|
||||
<p className="f-wrap-alignCenter mt15">
|
||||
<span className="mr5 commitKey" style={{marginLeft:0}}>{item.last_commit && truncateCommitId(item.last_commit.id)}</span>
|
||||
<span className="color-grey-3 hide-1 messages leftPoint">{item.last_commit && item.last_commit.message}</span>
|
||||
<span className="color-grey-8 ml30">最后更新于{item.last_commit && item.last_commit.time_from_now}</span>
|
||||
</p>
|
||||
</div>
|
||||
<span>
|
||||
<Link to={`/projects/${projectsId}/merge/new`} className="mr20 operationBtn">创建合并请求</Link>
|
||||
<Dropdown overlay={menu(item.zip_url,item.tar_url)} trigger={['click']} placement="bottomRight" className="operationBtn">
|
||||
<Link to={`/projects/${projectsId}/merge/new`} className="mr20 color-blue mr30">创建合并请求</Link>
|
||||
<Dropdown overlay={menu(item.zip_url,item.tar_url)} trigger={['click']} placement="bottomRight" className="color-green-file">
|
||||
<a className="ant-dropdown-link">
|
||||
<Tooltip title={`下载分支${item.name}`}><Icon type="cloud-download" className="font-18"/></Tooltip>
|
||||
</a>
|
||||
|
@ -58,13 +58,14 @@ class CoderRootBranch extends Component {
|
|||
</Menu>
|
||||
)
|
||||
return(
|
||||
<div>
|
||||
<Top { ...this.props } {...this.state} />
|
||||
<div className="branchTable">
|
||||
<p className="branchTitle">分支列表</p>
|
||||
{list()}
|
||||
<React.Fragment>
|
||||
<div className="main">
|
||||
<div className="branchTable">
|
||||
<p className="branchTitle bor-bottom-greyE">分支列表</p>
|
||||
{list()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -81,39 +81,7 @@ class CoderRootCommit extends Component{
|
|||
render(){
|
||||
const { branch , data , dataCount , limit , page , isSpin } = this.state;
|
||||
const { branchs } = this.props;
|
||||
const columns=[{
|
||||
title:"作者",
|
||||
dataIndex: 'name',
|
||||
width:"10%",
|
||||
render: (text,item) => (
|
||||
<span className="f-wrap-alignCenter">
|
||||
<Link to={`/users/${item.login}/projects`} 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",'verticalAlign':'middle'}}>{text}</label>
|
||||
</Link>
|
||||
</span>
|
||||
),
|
||||
},{
|
||||
title:"SHA",
|
||||
dataIndex: 'sha',
|
||||
render: (text) => (
|
||||
<span className="commitKey">{truncateCommitId(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"}}>
|
||||
|
@ -132,24 +100,42 @@ class CoderRootCommit extends Component{
|
|||
}
|
||||
}
|
||||
return(
|
||||
<div>
|
||||
<Top { ...this.props } {...this.state} />
|
||||
<div className="f-wrap-between mt20">
|
||||
<SelectBranch branch={branch} branchs={branchs} changeBranch={this.changeBranch}></SelectBranch>
|
||||
<React.Fragment>
|
||||
<div className="main">
|
||||
<div className="f-wrap-between">
|
||||
<SelectBranch branch={branch} branchs={branchs} changeBranch={this.changeBranch}></SelectBranch>
|
||||
</div>
|
||||
<Spin spinning={isSpin}>
|
||||
<div className="commonBox">
|
||||
<div className="commonBox-title">
|
||||
{title()}
|
||||
</div>
|
||||
<div className="commitList">
|
||||
{
|
||||
data && data.length > 0 && data.map((item,key)=>{
|
||||
return(
|
||||
<div>
|
||||
<p className="df">
|
||||
<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}/projects`} className="show-user-link">
|
||||
<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.time_from_now}</label>
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
{ Pagination() }
|
||||
</Spin>
|
||||
</div>
|
||||
<Spin spinning={isSpin}>
|
||||
<Table
|
||||
className="mt20 wrap-commit-table"
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
showHeader={false}
|
||||
size="small"
|
||||
pagination={false}
|
||||
title={() => title()}
|
||||
/>
|
||||
{ Pagination() }
|
||||
</Spin>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -230,11 +230,11 @@ class CoderRootDirectory extends Component{
|
|||
return(
|
||||
<div className="commonBox">
|
||||
<div className="commonBox-title">
|
||||
<span className="mr5"><img src={readme_img} alt="" width="16px"/></span>
|
||||
<span className="mr10"><i className="iconfont icon-xinjianjianliwodejianli font-20 color-grey-9 fl mt3"></i></span>
|
||||
<span className="commonBox-title-read">{readMeContent[0].name}</span>
|
||||
{
|
||||
permission ?
|
||||
<a onClick={()=>this.ChangeFile(readMeFile[0],false)} className="ml20 pull-right"><i className="iconfont icon-bianji font-15 color-grey-6"></i></a>
|
||||
<a onClick={()=>this.ChangeFile(readMeFile[0],false)} className="ml20 pull-right"><i className="iconfont icon-bianji2 font-20 color-blue"></i></a>
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
|
@ -286,7 +286,7 @@ class CoderRootDirectory extends Component{
|
|||
width:"100%",
|
||||
render: (text,item) => (
|
||||
<a onClick={()=>this.goToSubRoot(item.path)}>
|
||||
<i className={ item.type === "file" ? "iconfont icon-zuoye font-15 color-blue mr5":"iconfont icon-wenjian font-15 color-blue mr5"}></i>{text}
|
||||
<i className={ item.type === "file" ? "iconfont icon-wenjian1 font-15 color-green-file mr5":"iconfont color-green-file font-15 color-blue mr5"}></i>{text}
|
||||
</a>
|
||||
),
|
||||
}
|
||||
|
@ -307,8 +307,8 @@ class CoderRootDirectory extends Component{
|
|||
:""
|
||||
}
|
||||
<span className="color-blue flex-1 hide-1">{branchLastCommit.last_commit.message}</span>
|
||||
<span className="commitKey">{truncateCommitId(branchLastCommit.last_commit.id)}</span>
|
||||
<span>{branchLastCommit.last_commit.time_from_now}</span>
|
||||
<span className="commitKey">{truncateCommitId(branchLastCommit.last_commit.id)}</span>
|
||||
</div>
|
||||
)
|
||||
}else{
|
||||
|
@ -332,9 +332,8 @@ class CoderRootDirectory extends Component{
|
|||
let array = filePath && filePath.split("/");
|
||||
return(
|
||||
<Spin spinning={isSpin}>
|
||||
<div>
|
||||
<Top { ...this.props } {...this.state} />
|
||||
<div className="f-wrap-between mt20">
|
||||
<div className="main">
|
||||
<div className="f-wrap-between">
|
||||
<div className="f-wrap-alignCenter">
|
||||
<SelectBranch branch={branch} changeBranch={this.changeBranch} {...this.props} {...this.state}></SelectBranch>
|
||||
|
||||
|
@ -365,8 +364,8 @@ class CoderRootDirectory extends Component{
|
|||
<div className="f-wrap-alignCenter">
|
||||
{
|
||||
subFileType && (isManager || isDeveloper) &&
|
||||
<p className="addFile mr30">
|
||||
<Link to={`/projects/${projectsId}/coders/${branch}/newfile${urlRoot}`} >新建文件</Link>
|
||||
<p className="mr30">
|
||||
<Link className="color-blue" to={`/projects/${projectsId}/coders/${branch}/newfile${urlRoot}`} >新建文件</Link>
|
||||
</p>
|
||||
}
|
||||
{
|
||||
|
@ -378,7 +377,6 @@ class CoderRootDirectory extends Component{
|
|||
{
|
||||
rootList &&
|
||||
<RootTable columns = {columns} data={rootList} title={() => title()}></RootTable>
|
||||
|
||||
}
|
||||
{/* 子目录列表、文件 */}
|
||||
{
|
||||
|
|
|
@ -105,8 +105,8 @@ class CoderRootFileDetail extends Component{
|
|||
}
|
||||
|
||||
render(){
|
||||
const { detail , current_user , isManager , isReporter , isDeveloper } = this.props;
|
||||
const { readOnly ,value } = this.state;
|
||||
const { detail , current_user , isManager , isDeveloper } = this.props;
|
||||
const { readOnly } = this.state;
|
||||
let flag = current_user && current_user.login && (isManager || isDeveloper);
|
||||
var options = {
|
||||
lineNumbers: true,
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import React , { Component } from 'react';
|
||||
import { Route , Switch , Link} from 'react-router-dom';
|
||||
import { Route , Switch } from 'react-router-dom';
|
||||
|
||||
import Loadable from 'react-loadable';
|
||||
import Loading from '../../Loading';
|
||||
import Top from './DetailTop';
|
||||
|
||||
|
||||
const CoderRootDirectory = Loadable({
|
||||
|
@ -13,27 +14,61 @@ const CoderRootCommit = Loadable({
|
|||
loader: () => import('./CoderRootCommit'),
|
||||
loading: Loading,
|
||||
})
|
||||
const CoderRootFileDetail = Loadable({
|
||||
loader: () => import('./CoderRootFileDetail'),
|
||||
loading: Loading,
|
||||
})
|
||||
const CoderRootBranch = Loadable({
|
||||
loader: () => import('./CoderRootBranch'),
|
||||
loading: Loading,
|
||||
})
|
||||
const CoderRootTag = Loadable({
|
||||
loader: () => import('./CoderRootTag'),
|
||||
loading: Loading,
|
||||
})
|
||||
const CoderRootVersion = Loadable({
|
||||
loader: () => import('../Version/version'),
|
||||
loading: Loading,
|
||||
})
|
||||
const CoderRootVersionNew = Loadable({
|
||||
loader: () => import('../Version/NewVersion'),
|
||||
loading: Loading,
|
||||
})
|
||||
const CoderRootVersionUpdate = Loadable({
|
||||
loader: () => import('../Version/UpdateVersion'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
class CoderRootIndex extends Component{
|
||||
|
||||
render(){
|
||||
|
||||
return(
|
||||
<div className="main">
|
||||
<div>
|
||||
<Top {...this.props} {...this.state}/>
|
||||
<Switch {...this.props}>
|
||||
<Route path="/projects/:projectsId/coders/commit"
|
||||
render={
|
||||
(props) => (<CoderRootCommit {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/projects/:projectsId/coders/version/new"
|
||||
render={
|
||||
(props) => (<CoderRootVersionNew {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route path="/projects/:projectsId/coders/version/:versionId/update"
|
||||
render={
|
||||
(props) => (<CoderRootVersionUpdate {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route path="/projects/:projectsId/coders/version"
|
||||
render={
|
||||
(props) => (<CoderRootVersion {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/projects/:projectsId/coders/tag"
|
||||
render={
|
||||
(props) => (<CoderRootTag {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/projects/:projectsId/coders/branch"
|
||||
render={
|
||||
(props) => (<CoderRootBranch {...this.props} {...props} {...this.state} />)
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import React , { useState, useEffect } from 'react';
|
||||
import axios from 'axios';
|
||||
import { Spin } from 'antd';
|
||||
import { truncateCommitId } from '../common/util';
|
||||
|
||||
|
||||
export default ({
|
||||
projectDetail
|
||||
}) => {
|
||||
const [ isSpin , setSpin ] = useState(true);
|
||||
const [ data , setData ] = useState(undefined);
|
||||
|
||||
const repo_id = projectDetail && projectDetail.repo_id;
|
||||
useEffect(()=>{
|
||||
if(repo_id){
|
||||
const url = `/repositories/${repo_id}/tags.json`;
|
||||
axios.get(url).then((result)=>{
|
||||
if(result){
|
||||
setData(result.data);
|
||||
setSpin(false);
|
||||
}
|
||||
}).catch(error=>{
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
},[repo_id]);
|
||||
|
||||
return(
|
||||
<div className="main">
|
||||
<Spin spinning={isSpin}>
|
||||
<div className="div_table">
|
||||
<ul className="ul_thead">
|
||||
<li>
|
||||
<span className="flex1">标签名</span>
|
||||
{/* <span>描述</span> */}
|
||||
<span>提交信息</span>
|
||||
<span className="ul_tbody_forth">下载</span>
|
||||
</li>
|
||||
</ul>
|
||||
<ul className="ul_tbody">
|
||||
{
|
||||
data && data.length > 0 && data.map((item,key)=>{
|
||||
return(
|
||||
<li>
|
||||
<span className="flex1">
|
||||
<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>
|
||||
<a href={item.zipball_url} style={{color:"#28BD6C"}}><i className="iconfont icon-ZIP font-18 mr5"></i>ZIP</a>
|
||||
</span>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import React , { Component } from 'react';
|
||||
import { Spin , Tooltip } from 'antd';
|
||||
import { Link , Route , Switch,withRouter } from 'react-router-dom';
|
||||
import React, { Component } from 'react';
|
||||
import { Spin, Tooltip } from 'antd';
|
||||
import { Link, Route, Switch, withRouter } from 'react-router-dom';
|
||||
|
||||
import '../css/index.css'
|
||||
import './list.css';
|
||||
|
@ -13,7 +13,6 @@ import axios from 'axios';
|
|||
import img_1 from '../Images/1.png';
|
||||
import img_2 from '../Images/2.png';
|
||||
import img_3 from '../Images/3.png';
|
||||
import img_4 from '../Images/4.png';
|
||||
import img_6 from '../Images/6.png';
|
||||
import img_7 from '../Images/7.png';
|
||||
import img_parise from '../Images/parise.png';
|
||||
|
@ -23,99 +22,77 @@ 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,
|
||||
loader: () => import('../Newfile/Index'),
|
||||
loading: Loading,
|
||||
})
|
||||
const Setting = Loadable({
|
||||
loader: () => import('../Settings/Index'),
|
||||
loading: Loading,
|
||||
loader: () => import('../Settings/Index'),
|
||||
loading: Loading,
|
||||
})
|
||||
const TagList = Loadable({
|
||||
loader: () => import('../Order/Tags'),
|
||||
loading: Loading,
|
||||
loader: () => import('../Order/Tags'),
|
||||
loading: Loading,
|
||||
})
|
||||
const OrderNew = Loadable({
|
||||
loader: () => import('../Order/New'),
|
||||
loading: Loading,
|
||||
loader: () => import('../Order/New'),
|
||||
loading: Loading,
|
||||
})
|
||||
const OrderDetail = Loadable({
|
||||
loader: () => import('../Order/Detail'),
|
||||
loading: Loading,
|
||||
loader: () => import('../Order/Detail'),
|
||||
loading: Loading,
|
||||
})
|
||||
const OrderIndex = Loadable({
|
||||
loader: () => import('../Order/order'),
|
||||
loading: Loading,
|
||||
loader: () => import('../Order/order'),
|
||||
loading: Loading,
|
||||
})
|
||||
const CoderRootIndex = Loadable({
|
||||
loader: () => import('./CoderRootIndex'),
|
||||
loading: Loading,
|
||||
loader: () => import('./CoderRootIndex'),
|
||||
loading: Loading,
|
||||
})
|
||||
const OrderMilepost = Loadable({
|
||||
loader: () => import('../Order/Milepost'),
|
||||
loading: Loading,
|
||||
loader: () => import('../Order/Milepost'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
const OrdernewMilepost = Loadable({
|
||||
loader: () => import('../Order/newMilepost'),
|
||||
loading: Loading,
|
||||
loader: () => import('../Order/newMilepost'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
const OrderupdateMilepost = Loadable({
|
||||
loader: () => import('../Order/UpdateMilepost'),
|
||||
loading: Loading,
|
||||
loader: () => import('../Order/UpdateMilepost'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
const OrderupdateDetail = Loadable({
|
||||
loader: () => import('../Order/UpdateDetail'),
|
||||
loading: Loading,
|
||||
loader: () => import('../Order/UpdateDetail'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
const OrdercopyDetail = Loadable({
|
||||
loader: () => import('../Order/CopyDetail'),
|
||||
loading: Loading,
|
||||
loader: () => import('../Order/CopyDetail'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//合并请求
|
||||
const MergeIndexDetail = Loadable({
|
||||
loader: () => import('../Merge/merge'),
|
||||
loading: Loading,
|
||||
loader: () => import('../Merge/merge'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
const CreateMerge = Loadable({
|
||||
loader: () => import('../Merge/NewMerge'),
|
||||
loading: Loading,
|
||||
loader: () => import('../Merge/NewMerge'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
const MessageCount = Loadable({
|
||||
loader: () => import('../Merge/MessageCount'),
|
||||
loading: Loading,
|
||||
loader: () => import('../Merge/MessageCount'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
const MergeSubmit = Loadable({
|
||||
loader: () => import('../Merge/MergeSubmit'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
const UpdateMerge = Loadable({
|
||||
loader: () => import('../Merge/UpdateMerge'),
|
||||
loading: Loading,
|
||||
})
|
||||
//版本发布
|
||||
const VersionIndex = Loadable({
|
||||
loader: () => import('../Version/version'),
|
||||
loading: Loading,
|
||||
})
|
||||
const NewVersionIndex = Loadable({
|
||||
loader: () => import('../Version/NewVersion'),
|
||||
loading: Loading,
|
||||
})
|
||||
const UpVersionIndex = Loadable({
|
||||
loader: () => import('../Version/UpdateVersion'),
|
||||
loading: Loading,
|
||||
})
|
||||
const MilepostDetail = Loadable({
|
||||
loader: () => import('../Order/MilepostDetail'),
|
||||
loading: Loading,
|
||||
loader: () => import('../Order/MilepostDetail'),
|
||||
loading: Loading,
|
||||
})
|
||||
const WatchUsers = Loadable({
|
||||
loader: () => import('../UsersList/watch_users'),
|
||||
|
@ -132,85 +109,82 @@ const ForkUsers = Loadable({
|
|||
|
||||
|
||||
const TrendsIndex = Loadable({
|
||||
loader: () => import('../Activity/Activity'),
|
||||
loading: Loading,
|
||||
loader: () => import('../Activity/Activity'),
|
||||
loading: Loading,
|
||||
})
|
||||
/**
|
||||
* permission:Manager:管理员,Reporter:报告人员(只有读取权限),Developer:开发人员(除不能设置仓库信息外)
|
||||
*/
|
||||
|
||||
class Detail extends Component{
|
||||
constructor(props){
|
||||
class Detail extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state={
|
||||
isSpin:false,
|
||||
projectDetail:undefined,
|
||||
isManager:false,
|
||||
isReporter:false,
|
||||
isDeveloper:false,
|
||||
project_id:undefined,
|
||||
watchers_count:undefined ,
|
||||
praises_count:undefined ,
|
||||
forked_count:undefined,
|
||||
watched: false,
|
||||
praised: false,
|
||||
this.state = {
|
||||
isSpin: false,
|
||||
projectDetail: undefined,
|
||||
isManager: false,
|
||||
isReporter: false,
|
||||
isDeveloper: false,
|
||||
project_id: undefined,
|
||||
watchers_count: undefined,
|
||||
praises_count: undefined,
|
||||
forked_count: undefined,
|
||||
watched: false,
|
||||
praised: false,
|
||||
http_url: undefined,
|
||||
author:undefined,
|
||||
branchs:undefined,
|
||||
branchList:undefined,
|
||||
branchLastCommit:undefined,
|
||||
author: undefined,
|
||||
branchs: undefined,
|
||||
branchList: undefined,
|
||||
branchLastCommit: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount=()=>{
|
||||
componentDidMount = () => {
|
||||
this.getDetail();
|
||||
}
|
||||
|
||||
componentDidUpdate=(prevState)=>{
|
||||
if((prevState.match.params.projectsId !== this.props.match.params.projectsId)){
|
||||
componentDidUpdate = (prevState) => {
|
||||
if ((prevState.match.params.projectsId !== this.props.match.params.projectsId)) {
|
||||
this.getDetail();
|
||||
}
|
||||
|
||||
const { search } = this.props.location;
|
||||
const search_c = prevState.location && prevState.location.search;
|
||||
if( search && search!== search_c){
|
||||
// console.log("branches",this.props.location);
|
||||
// console.log("branches_p",prevState.location);
|
||||
// console.log("111",this.props.dataquerys);
|
||||
if (search && search !== search_c) {
|
||||
const { projectsId } = this.props.match.params;
|
||||
this.getBranch(projectsId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
getDetail=()=>{
|
||||
getDetail = () => {
|
||||
const { projectsId } = this.props.match.params;
|
||||
const url = `/repositories/${projectsId}.json`;
|
||||
axios.get(url).then((result)=>{
|
||||
if(result){
|
||||
axios.get(url).then((result) => {
|
||||
if (result) {
|
||||
this.setState({
|
||||
projectDetail:result.data,
|
||||
project_id:result.data.project_id,
|
||||
isManager:result.data.permission && result.data.permission === "Manager",
|
||||
isReporter:result.data.permission && result.data.permission === "Reporter",
|
||||
isDeveloper:result.data.permission && result.data.permission === "Developer",
|
||||
projectDetail: result.data,
|
||||
project_id: result.data.project_id,
|
||||
isManager: result.data.permission && result.data.permission === "Manager",
|
||||
isReporter: result.data.permission && result.data.permission === "Reporter",
|
||||
isDeveloper: result.data.permission && result.data.permission === "Developer",
|
||||
http_url: result.data.clone_url,
|
||||
author:result.data.author,
|
||||
praised: result.data.praised,
|
||||
watched: result.data.watched,
|
||||
watchers_count:result.data.watchers_count,
|
||||
praises_count:result.data.praises_count,
|
||||
forked_count:result.data.forked_count,
|
||||
author: result.data.author,
|
||||
praised: result.data.praised,
|
||||
watched: result.data.watched,
|
||||
watchers_count: result.data.watchers_count,
|
||||
praises_count: result.data.praises_count,
|
||||
forked_count: result.data.forked_count,
|
||||
})
|
||||
if(result.data.project_id){
|
||||
if (result.data.project_id) {
|
||||
this.getBranch(result.data.project_id);
|
||||
}
|
||||
}
|
||||
}).catch((error)=>{})
|
||||
}).catch((error) => { })
|
||||
}
|
||||
|
||||
// 关注和取消关注
|
||||
focusFunc =(flag)=>{
|
||||
focusFunc = (flag) => {
|
||||
const { project_id } = this.state;
|
||||
|
||||
axios({
|
||||
|
@ -232,153 +206,134 @@ class Detail extends Component{
|
|||
}
|
||||
|
||||
// 点赞和取消点赞
|
||||
pariseFunc=(flag)=>{
|
||||
pariseFunc = (flag) => {
|
||||
const { project_id } = this.state;
|
||||
axios({
|
||||
method: flag? 'delete' : 'post',
|
||||
url: `/projects/${project_id}/praise_tread/${flag? 'unlike' : 'like'}.json`
|
||||
})
|
||||
.then(result => {
|
||||
if(result && result.data.status === 0){
|
||||
this.setPraisesCount(result.data.praises_count, result.data.praised)
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
axios({
|
||||
method: flag ? 'delete' : 'post',
|
||||
url: `/projects/${project_id}/praise_tread/${flag ? 'unlike' : 'like'}.json`
|
||||
})
|
||||
.then(result => {
|
||||
if (result && result.data.status === 0) {
|
||||
this.setPraisesCount(result.data.praises_count, result.data.praised)
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
setWatchersCount = (count, is_watched) => {
|
||||
this.setState({
|
||||
watched: is_watched,
|
||||
watchers_count: count
|
||||
})
|
||||
}
|
||||
setWatchersCount = (count, is_watched) => {
|
||||
this.setState({
|
||||
watched: is_watched,
|
||||
watchers_count: count
|
||||
})
|
||||
}
|
||||
|
||||
setPraisesCount = (count, is_praised) => {
|
||||
this.setState({
|
||||
praised: is_praised,
|
||||
praises_count: count
|
||||
})
|
||||
}
|
||||
setPraisesCount = (count, is_praised) => {
|
||||
this.setState({
|
||||
praised: is_praised,
|
||||
praises_count: count
|
||||
})
|
||||
}
|
||||
|
||||
// fork项目
|
||||
forkFunc=()=>{
|
||||
forkFunc = () => {
|
||||
const { checkIfLogin } = this.props;
|
||||
if(!checkIfLogin){
|
||||
if (!checkIfLogin) {
|
||||
this.props.showLoginDialog();
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
isSpin:true
|
||||
isSpin: true
|
||||
})
|
||||
const { project_id } = this.state;
|
||||
const url = `/projects/${project_id}/forks.json`;
|
||||
axios.post(url).then(result=>{
|
||||
if (result && result.data.status === 0) {
|
||||
axios.post(url).then(result => {
|
||||
if (result && result.data.status === 0) {
|
||||
this.props.history.push(`/projects/${result.data.id}/coders`);
|
||||
this.props.showNotification(result.data.message);
|
||||
}
|
||||
this.setState({
|
||||
isSpin:false
|
||||
isSpin: false
|
||||
})
|
||||
}).catch(error=>{
|
||||
}).catch(error => {
|
||||
this.setState({
|
||||
isSpin:false
|
||||
isSpin: false
|
||||
})
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
// 获取分支列表
|
||||
getBranch=(id)=>{
|
||||
const url =`/projects/${id}/branches.json`;
|
||||
axios.get(url).then((result)=>{
|
||||
if(result && result.data.length>0){
|
||||
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)=>{
|
||||
result.data.map((item, key) => {
|
||||
branchs.push({
|
||||
index:key,
|
||||
name:item.name
|
||||
index: key,
|
||||
name: item.name
|
||||
})
|
||||
})
|
||||
this.setState({
|
||||
branchList:result.data,
|
||||
branchList: result.data,
|
||||
branchs,
|
||||
branchLastCommit:result.data[0],
|
||||
branchLastCommit: result.data[0],
|
||||
})
|
||||
}
|
||||
}).catch((error)=>{})
|
||||
}).catch((error) => { })
|
||||
}
|
||||
|
||||
render(){
|
||||
const { projectDetail , watchers_count , praises_count , forked_count , isSpin , isManager, watched, praised } = this.state;
|
||||
render() {
|
||||
const { projectDetail, watchers_count, praises_count, forked_count, isSpin, isManager, watched, praised } = this.state;
|
||||
const url = this.props.history.location.pathname;
|
||||
const urlArr= url.split("/");
|
||||
const urlArr = url.split("/");
|
||||
const urlFlag = (urlArr.length === 3);
|
||||
|
||||
const { projectsId } = this.props.match.params;
|
||||
|
||||
const { state } = this.props.history.location;
|
||||
|
||||
|
||||
const text = (
|
||||
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
|
||||
<React.Fragment>
|
||||
<span>forked from </span>
|
||||
<Link to={`/users/${projectDetail.fork_info.fork_project_user_login}/projects`} className="show-user-link color-grey-ccc">{projectDetail.fork_info.fork_project_user_name}</Link>
|
||||
<span> / </span>
|
||||
<Link to={`/projects/${projectDetail.forked_from_project_id}/coders`} className="color-grey-ccc">{ projectDetail.fork_info.fork_form_name }</Link>
|
||||
</React.Fragment>:""
|
||||
);
|
||||
return(
|
||||
<Link to={`/projects/${projectDetail.forked_from_project_id}/coders`} className="color-grey-ccc">{projectDetail.fork_info.fork_form_name}</Link>
|
||||
</React.Fragment> : ""
|
||||
);
|
||||
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"}}>
|
||||
|
||||
<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}/projects`} className="show-user-link color-white">
|
||||
{projectDetail.author.name}
|
||||
</Link>
|
||||
<Link to={`/users/${projectDetail.author.login}/projects`} className="show-user-link color-white">
|
||||
{projectDetail.author.name}
|
||||
</Link>
|
||||
}
|
||||
<span className="ml5 mr5">/</span>
|
||||
<span className="hide-1 flex-1 df">
|
||||
<Link to={`/projects/${projectsId}/coders`} className="color-white">{ projectDetail && projectDetail.name }</Link>
|
||||
<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="ml20" >
|
||||
<i className="iconfont icon-fork color-grey-74 font-20 fl"></i>
|
||||
</Link>
|
||||
</Tooltip>:""
|
||||
<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>
|
||||
</p>
|
||||
</div>
|
||||
<div className="f-wrap-between">
|
||||
<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" />代码库</Link>
|
||||
</li>
|
||||
<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===0?"":projectDetail&&projectDetail.issues_count===0?projectDetail.issues_count:""}</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===0?"":projectDetail&&projectDetail.pull_requests_count===0?projectDetail.pull_requests_count:""}</Link></li>
|
||||
<li className={url.indexOf("version")>-1 ? "active" : ""}><Link to={{pathname:`/projects/${projectsId}/version`,state}}><img alt="" src={img_4} width="16" />版本发布</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" />里程碑</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>
|
||||
}
|
||||
|
||||
</ul>
|
||||
<span className="df">
|
||||
<span className="df mt25">
|
||||
<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 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}}>
|
||||
{watchers_count}
|
||||
|
@ -386,9 +341,9 @@ class Detail extends Component{
|
|||
{/* <span className="detail_tag_btn_count">{watchers_count}</span> */}
|
||||
</span>
|
||||
<span className="detail_tag_btn">
|
||||
<a className="detail_tag_btn_name" onClick={()=>this.pariseFunc(praised)}>
|
||||
<img src={praised ? img_parised : img_parise} width="13px" alt=""/>
|
||||
{praised ? '取消点赞':'点赞'}
|
||||
<a className="detail_tag_btn_name" onClick={() => this.pariseFunc(praised)}>
|
||||
<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}}>
|
||||
{praises_count}
|
||||
|
@ -405,6 +360,51 @@ class Detail extends Component{
|
|||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="f-wrap-between">
|
||||
<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>
|
||||
</li>
|
||||
<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("version") > -1 ? "active" : ""}>
|
||||
<Link to={{ pathname: `/projects/${projectsId}/version`, state }}>
|
||||
<img alt="" src={img_4} width="16" />版本发布
|
||||
{projectDetail && projectDetail.version_releases_count && <span>{projectDetail.version_releases_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" />动态
|
||||
</Link>
|
||||
</li>
|
||||
{
|
||||
isManager &&
|
||||
<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>
|
||||
|
||||
|
@ -412,55 +412,55 @@ class Detail extends Component{
|
|||
{/* 新建文件 */}
|
||||
<Route path="/projects/:projectsId/coders/:branch/newfile/:path"
|
||||
render={
|
||||
(props) => (<FileNew {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<FileNew {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/projects/:projectsId/coders/:branch/newfile"
|
||||
render={
|
||||
(props) => (<FileNew {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<FileNew {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 标签列表 */}
|
||||
<Route path="/projects/:projectsId/orders/tags"
|
||||
render={
|
||||
(props) => (<TagList {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<TagList {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 仓库设置 */}
|
||||
<Route path="/projects/:projectsId/setting"
|
||||
render={
|
||||
(props) => (<Setting {...this.props} {...props} {...this.state} getDetail={this.getDetail}/>)
|
||||
(props) => (<Setting {...this.props} {...props} {...this.state} getDetail={this.getDetail} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 任务详情 */}
|
||||
<Route path="/projects/:projectsId/orders/:orderId/detail"
|
||||
render={
|
||||
(props) => (<OrderDetail {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<OrderDetail {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 里程碑 */}
|
||||
<Route path="/projects/:projectsId/orders/Milepost"
|
||||
<Route path="/projects/:projectsId/orders/Milepost"
|
||||
render={
|
||||
(props) => (<OrderMilepost {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<OrderMilepost {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 新建里程碑 */}
|
||||
<Route path="/projects/:projectsId/orders/meilpost"
|
||||
render={
|
||||
(props) => (<OrdernewMilepost {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<OrdernewMilepost {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/*里程碑详情*/ }
|
||||
{/*里程碑详情*/}
|
||||
<Route path="/projects/:projectsId/orders/:meilid/MilepostDetail"
|
||||
render={
|
||||
(props) => (<MilepostDetail {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<MilepostDetail {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/*修改里程碑*/}
|
||||
<Route path="/projects/:projectsId/orders/:meilid/meilpost"
|
||||
{/*修改里程碑*/}
|
||||
<Route path="/projects/:projectsId/orders/:meilid/meilpost"
|
||||
render={
|
||||
(props) => (<OrderupdateMilepost {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<OrderupdateMilepost {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
@ -468,34 +468,34 @@ class Detail extends Component{
|
|||
{/* 里程碑页面新建任务 */}
|
||||
<Route path="/projects/:projectsId/orders/:milepostId/new"
|
||||
render={
|
||||
(props) => (<OrderNew {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<OrderNew {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 新建任务 */}
|
||||
<Route path="/projects/:projectsId/orders/new"
|
||||
render={
|
||||
(props) => (<OrderNew {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<OrderNew {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 修改详情 */}
|
||||
<Route path="/projects/:projectsId/orders/:orderId/updatedetail"
|
||||
<Route path="/projects/:projectsId/orders/:orderId/updatedetail"
|
||||
render={
|
||||
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 复制详情 */}
|
||||
<Route path="/projects/:projectsId/orders/:orderId/copyetail"
|
||||
{/* 复制详情 */}
|
||||
<Route path="/projects/:projectsId/orders/:orderId/copyetail"
|
||||
render={
|
||||
(props) => (<OrdercopyDetail {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<OrdercopyDetail {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 动态 */}
|
||||
<Route path="/projects/:projectsId/trends"
|
||||
render={
|
||||
(props) => (<TrendsIndex {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<TrendsIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
@ -503,66 +503,48 @@ class Detail extends Component{
|
|||
{/* 代码Index */}
|
||||
<Route path="/projects/:projectsId/orders"
|
||||
render={
|
||||
(props) => (<OrderIndex {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<OrderIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route path="/projects/:projectsId/merge/new"
|
||||
render={
|
||||
(props) => (<CreateMerge {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<CreateMerge {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route path="/projects/:projectsId/merge/:mergeId/UpdateMerge"
|
||||
render={
|
||||
(props) => (<MessageCount {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<MessageCount {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route path="/projects/:projectsId/merge/:mergeId/Messagecount"
|
||||
render={
|
||||
(props) => (<MessageCount {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<MessageCount {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route path="/projects/:projectsId/merge/:mergeId/MergeSubmit"
|
||||
render={
|
||||
(props) => (<MessageCount {...this.props} {...props} {...this.state}/>)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/projects/:projectsId/version/new"
|
||||
render={
|
||||
(props) => (<NewVersionIndex {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<MessageCount {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
<Route path="/projects/:projectsId/version/:versionId/upversion"
|
||||
<Route path="/projects/:projectsId/merge"
|
||||
render={
|
||||
(props) => (<UpVersionIndex {...this.props} {...props} {...this.state}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
<Route path="/projects/:projectsId/version"
|
||||
render={
|
||||
(props) => (<VersionIndex {...this.props} {...props} {...this.state}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route path="/projects/:projectsId/merge"
|
||||
render={
|
||||
(props) => (<MergeIndexDetail {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<MergeIndexDetail {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/projects/:projectsId/coders/filesurl"
|
||||
render={
|
||||
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/projects/:projectsId/coders"
|
||||
render={
|
||||
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/projects/:projectsId/watch_users"
|
||||
|
@ -582,7 +564,7 @@ class Detail extends Component{
|
|||
></Route>
|
||||
<Route path="/projects/:projectsId"
|
||||
render={
|
||||
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
</Switch>
|
||||
|
|
|
@ -9,13 +9,29 @@ class DetailTop extends Component {
|
|||
return (
|
||||
<p className="branch-wrapper">
|
||||
<Link to={`/projects/${projectsId}/coders/commit`} className={pathname.indexOf("/coders/commit") > 0 ? "active" : ""}>
|
||||
<i className="iconfont icon-tijiaojilu font-18 mr3"></i>
|
||||
<span className="mr3">{projectDetail && projectDetail.commits_count}</span>提交
|
||||
<i className="iconfont icon-tijiaojilu font-20 mr3 font-bd"></i>
|
||||
<span>{projectDetail && projectDetail.commits_count}</span>个提交
|
||||
</Link>
|
||||
<Link to={`/projects/${projectsId}/coders/branch`} className={pathname.indexOf("/coders/branch") > 0 ? "active" : ""}>
|
||||
<i className="iconfont icon-fenzhi font-18 mr3"></i>
|
||||
<span className="mr3">{projectDetail && projectDetail.branches_count}</span>分支
|
||||
<i className="iconfont icon-fenzhi1 font-18 mr3"></i>
|
||||
<span>{projectDetail && projectDetail.branches_count}</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>个标签
|
||||
</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>个发行版
|
||||
</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>{projectDetail && projectDetail.size}</span>kb
|
||||
</a>
|
||||
</p>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -201,9 +201,9 @@ class Index extends Component {
|
|||
</div> : ""
|
||||
)
|
||||
return (
|
||||
<div style={{ background: "#EAEBEC" }}>
|
||||
<div>
|
||||
<p className="t_project_banner"></p>
|
||||
<div className="main ProjectListIndex">
|
||||
<div className="ProjectListIndex">
|
||||
<div className="list-left">
|
||||
<ul className="list-l-Menu">
|
||||
<li className="MenuTitle"><i className="iconfont icon-xiangmuleixing color-grey-9 font-15 mr5"></i>项目类型</li>
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
background-color: #050d34;
|
||||
}
|
||||
.ProjectListIndex{
|
||||
width: 1200px;
|
||||
margin:20px auto;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-wrap:wrap;
|
||||
|
@ -278,21 +280,27 @@
|
|||
align-items: center;
|
||||
}
|
||||
.headerMenu-wrapper li a > img{
|
||||
margin-right: 5px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.headerMenu-wrapper li a > span{
|
||||
background-color: #676AF1;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
border-radius: 10px;
|
||||
display: block;
|
||||
padding:0px 6px;
|
||||
margin-left: 5px;
|
||||
font-size: 11px;
|
||||
}
|
||||
.headerMenu-wrapper li.active{
|
||||
background:linear-gradient(180deg,rgba(58,194,255,1) 0%,rgba(27,143,255,1) 100%);
|
||||
border-radius: 15px;
|
||||
|
||||
}
|
||||
.headerMenu-wrapper li.active a {
|
||||
color: #fff !important;
|
||||
border:1px solid #71A6FF;
|
||||
}
|
||||
.detail_tag_btn{
|
||||
height:30px;
|
||||
line-height: 30px;
|
||||
border-radius:4px;
|
||||
border:1px solid rgba(28,145,255,1);
|
||||
height:26px;
|
||||
line-height: 26px;
|
||||
border-radius:5px;
|
||||
border:1px solid #71A6FF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 30px
|
||||
|
@ -304,13 +312,14 @@
|
|||
color: #fff;
|
||||
}
|
||||
.detail_tag_btn_name img{
|
||||
margin-right: 3px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.detail_tag_btn_count{
|
||||
padding:0px 10px;
|
||||
color: #fff !important;
|
||||
background: rgba(255,255,255,0.2);
|
||||
border-radius: 0px 4px 4px 0px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.detail_tag_btn_count:hover{
|
||||
/* color: #1C91FF !important; */
|
||||
|
@ -321,30 +330,47 @@
|
|||
border:1px solid #eee;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
padding:5px;
|
||||
align-items: center;
|
||||
height: 60px;
|
||||
padding:0px 30px;
|
||||
width: 1200px;
|
||||
margin:0px auto;
|
||||
background-color: #fff;
|
||||
margin-top: 20px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.branch-wrapper > a >i{
|
||||
color: #5091FF;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.branch-wrapper a{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
}
|
||||
.branch-wrapper a.active{
|
||||
background: #eee;
|
||||
.branch-wrapper a > span{
|
||||
position: relative;
|
||||
}
|
||||
.branch-wrapper a:hover{
|
||||
color: #4CACFF;
|
||||
.branch-wrapper a.active > span::after{
|
||||
position: absolute;
|
||||
content: '';
|
||||
bottom: -5px;
|
||||
width: 30px;
|
||||
height: 3px;
|
||||
left: 0px;
|
||||
background-color:#5091FF;
|
||||
}
|
||||
|
||||
|
||||
.gitAddressClone{
|
||||
display: flex;
|
||||
height: 32px;
|
||||
height: 40px;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
border:1px solid #eee;
|
||||
|
@ -353,14 +379,13 @@
|
|||
}
|
||||
.gitAddressClone > span{
|
||||
display: flex;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
line-height: 40px;
|
||||
height: 40px;
|
||||
padding:0px 12px;
|
||||
border-right: 1px solid #eee;
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
}
|
||||
.gitAddressClone > span.addressType.active{
|
||||
.gitAddressClone > span.addressType{
|
||||
color: #4CACFF;
|
||||
}
|
||||
.gitAddressClone > span:last-child{
|
||||
|
@ -370,47 +395,54 @@
|
|||
border:none;
|
||||
outline: none;
|
||||
padding:0px 8px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
border-radius: 0px;
|
||||
border-right: 1px solid #eee;
|
||||
border: 1px solid #eee;
|
||||
flex:1;
|
||||
}
|
||||
.wrap-commit-table .ant-table-small > .ant-table-content > .ant-table-body{
|
||||
margin:0px;
|
||||
}
|
||||
.wrap-commit-table .ant-table-title{
|
||||
background-color: rgba(241,248,255,1);
|
||||
padding: 13px 8px!important;
|
||||
}
|
||||
.commitKey{
|
||||
border:1px solid #dcdcdc;
|
||||
background-color:#f4f4f4;
|
||||
color: #666!important;
|
||||
padding:0px 5px;
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
margin-right:15px;
|
||||
border-radius: 4px;
|
||||
border:1px solid #FD7700;
|
||||
background-color:#FFF3DC;
|
||||
color: #FD7700!important;
|
||||
padding:0px 12px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin-left:15px;
|
||||
border-radius: 18px;
|
||||
max-width: 100%;
|
||||
}
|
||||
/* 分支 */
|
||||
.branchTable{
|
||||
border:1px solid #f7f7f7;
|
||||
background-color: #f7f7f7;
|
||||
border-radius: 4px;
|
||||
margin-top:20px;
|
||||
}
|
||||
.branchTitle{
|
||||
padding:12px 10px;
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
background: #EEEEEE;
|
||||
}
|
||||
.branchUl{
|
||||
padding:0px 30px;
|
||||
}
|
||||
.branchUl li{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
padding:8px 10px 10px 10px;
|
||||
padding:20px 0px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.branchUl li:nth-child(2n+1){
|
||||
background-color: #fff;
|
||||
.branchUl li:last-child{
|
||||
border-bottom: none;
|
||||
}
|
||||
.operationBtn{
|
||||
border:1px solid #f4f4f4;
|
||||
|
@ -511,16 +543,18 @@
|
|||
}
|
||||
}
|
||||
.commonBox{
|
||||
border:1px solid #f4f4f4;
|
||||
border-radius: 4px;
|
||||
border:1px solid #ddd;
|
||||
margin-top: 25px;
|
||||
}
|
||||
.commonBox .commonBox-title{
|
||||
padding:3px 15px;
|
||||
padding:0px 15px;
|
||||
box-sizing: border-box;
|
||||
font-size: 15px;
|
||||
background: #f0f0f0;
|
||||
font-size: 16px;
|
||||
background: #F1F8FF;
|
||||
font-weight: bold;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
.commonBox .commonBox-info{
|
||||
padding:20px 15px;
|
||||
|
@ -611,4 +645,63 @@ border: 1px solid #2185d0;
|
|||
a.color-grey-ccc:hover{
|
||||
color: #4cacff !important;
|
||||
}
|
||||
.pull-right{float: right;}
|
||||
.pull-right{float: right;}
|
||||
|
||||
.commitList{
|
||||
padding:0px 30px;
|
||||
}
|
||||
.commitList > div{
|
||||
border-bottom: 1px solid #EEEEEE;
|
||||
padding:16px 0px;
|
||||
}
|
||||
.commitList > div:last-child{
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
|
||||
/* 标签列表 */
|
||||
.div_table{
|
||||
border:1px solid #eee;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.ul_thead{
|
||||
padding:0px 30px;
|
||||
box-sizing: border-box;
|
||||
background: #FAFAFA;
|
||||
border-bottom: 1px solid #eee;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
}
|
||||
.ul_tbody{
|
||||
padding:0px 30px;
|
||||
}
|
||||
.ul_thead li, .ul_tbody li{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: left
|
||||
}
|
||||
.ul_tbody li{
|
||||
padding:18px 0px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.ul_tbody li:last-child{
|
||||
border-bottom: none;
|
||||
}
|
||||
.ul_thead li > span , .ul_tbody li > span{
|
||||
width: 20%;
|
||||
padding-right: 20px;
|
||||
}
|
||||
.ul_thead li > span:nth-child(2), .ul_tbody li > span:nth-child(2){
|
||||
flex:1;
|
||||
}
|
||||
.ul_tbody_third{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: left;
|
||||
}
|
||||
.ul_tbody_forth{
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
|
@ -193,6 +193,9 @@ class Index extends Component {
|
|||
|
||||
checkId = (rule, value, callback, list, title) => {
|
||||
let filter = list.filter(item => item.name === value);
|
||||
if(!value){
|
||||
callback();
|
||||
}
|
||||
if (filter && filter.length > 0) {
|
||||
callback();
|
||||
} else {
|
||||
|
@ -248,7 +251,7 @@ class Index extends Component {
|
|||
<Input placeholder="输入需要同步到本项目的镜像版本库地址" />
|
||||
)}
|
||||
</Form.Item>
|
||||
<p className="formTip">示例:https://github.com/facebook/reack.git</p>
|
||||
<p className="formTip color-orange">示例:https://github.com/facebook/reack.git</p>
|
||||
</React.Fragment>
|
||||
}
|
||||
<Form.Item
|
||||
|
@ -301,7 +304,6 @@ class Index extends Component {
|
|||
className="plateAutoComplete"
|
||||
onBlur={(value) => this.blurCategory(value, CategoryList, "project_category")}
|
||||
>
|
||||
{/* {this.setOptionsList(CategoryList,project_category_name)} */}
|
||||
{project_category_list}
|
||||
</AutoComplete>
|
||||
)}
|
||||
|
@ -322,14 +324,10 @@ class Index extends Component {
|
|||
className="plateAutoComplete"
|
||||
onBlur={(value) => this.blurCategory(value, LanguageList, "project_language")}
|
||||
>
|
||||
{/* {this.setOptionsList(LanguageList,project_language_name)} */}
|
||||
{project_language_list}
|
||||
</AutoComplete>
|
||||
)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
<Divider />
|
||||
<div className="newPanel_content">
|
||||
{
|
||||
projectsType === "deposit" &&
|
||||
<React.Fragment>
|
||||
|
@ -379,23 +377,17 @@ class Index extends Component {
|
|||
}
|
||||
<Form.Item
|
||||
label="可见性"
|
||||
style={{ marginBottom: "0px" }}
|
||||
style={{ margin: "0px" }}
|
||||
className="privatePart"
|
||||
>
|
||||
{getFieldDecorator('private')(
|
||||
<Checkbox value="limit">将项目设为私有<span className="ml15 font-13 color-grey-9">(只有项目所有人或拥有权限的项目成员才能看到)</span></Checkbox>
|
||||
)}
|
||||
</Form.Item >
|
||||
<div className="ant-row ant-form-item">
|
||||
<div className="ant-col ant-form-item-label">
|
||||
注:
|
||||
</div>
|
||||
<div className="ant-col ant-form-item-control-wrapper color-grey-9">
|
||||
<div className="ant-form-item-control">
|
||||
<span className="ant-form-item-required"></span> 为必填项,否则为选填
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
注:<span className="ant-form-item-required"></span> 为必填项,否则为选填
|
||||
</div>
|
||||
<Form.Item className="formTip">
|
||||
<Form.Item className="formTip mt20">
|
||||
<Button type="primary" onClick={this.subMitFrom} className="mr20">创建项目</Button>
|
||||
<Link to={'/projects'} className="btn_32">取消</Link>
|
||||
</Form.Item>
|
||||
|
|
|
@ -5,28 +5,14 @@
|
|||
.newPanel_title{
|
||||
height: 3rem;
|
||||
line-height: 3rem;
|
||||
background: #f0f0f0;
|
||||
background: #F1F8FF;
|
||||
text-align: center;
|
||||
border-radius: 4px 4px 0px 0px;
|
||||
font-size: 1.6em;
|
||||
border-bottom: 1px solid #f0f0f0
|
||||
}
|
||||
.newPanel_content{
|
||||
width: 600px;
|
||||
margin:1rem auto;
|
||||
}
|
||||
.newPanel_content .ant-row.ant-form-item{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.newPanel_content .ant-form-item-label{
|
||||
width: 135px;
|
||||
display: block;
|
||||
text-align: right;
|
||||
margin-right: 10px;
|
||||
height: 37px;
|
||||
line-height: 40px;
|
||||
padding:1rem 2rem;
|
||||
}
|
||||
.newPanel_content .ant-form-item-control-wrapper{
|
||||
flex: 1;
|
||||
|
@ -50,8 +36,13 @@
|
|||
.newContent_inline > .ant-form-item:nth-child(2){
|
||||
margin-left: 20px;
|
||||
}
|
||||
.formTip{
|
||||
margin:0px 0px 20px 146px;
|
||||
.newPanel_content .privatePart .ant-form-item-label{
|
||||
margin-left: 0px;
|
||||
}
|
||||
.newPanel_content .ant-form-item-label{
|
||||
line-height: 25px;
|
||||
height: 25px;
|
||||
margin-left: -0.8rem;
|
||||
}
|
||||
@media screen and (max-width: 750px){
|
||||
.newPanel_content{
|
||||
|
@ -60,13 +51,7 @@
|
|||
.newPanel_content .ant-row.ant-form-item{
|
||||
display: grid
|
||||
}
|
||||
.newPanel_content .ant-form-item-label{
|
||||
text-align: left;
|
||||
}
|
||||
.newContent_inline > .ant-form-item:nth-child(2){
|
||||
margin-left:0px
|
||||
}
|
||||
.formTip{
|
||||
margin:0px 0px 20px 0px;
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ import React , { Component } from "react";
|
|||
import Editor from "react-monaco-editor";
|
||||
|
||||
import UserSubmitComponent from './UserSubmitComponent';
|
||||
import Top from '../Main/DetailTop';
|
||||
import { Input } from 'antd';
|
||||
import './index.css';
|
||||
|
||||
|
@ -38,29 +39,32 @@ class Index extends Component{
|
|||
const { pathname } = this.props.location;
|
||||
const urlroot = pathname.split("newfile")[1];
|
||||
return(
|
||||
<div className="main">
|
||||
<div className="f-wrap-alignCenter">
|
||||
<div className="setInputAddon">
|
||||
<Input addonBefore={`/${projectDetail && projectDetail.identifier}${urlroot}/`} value={filename} onChange={this.changeFileName} placeholder="命名文件..."/>
|
||||
<React.Fragment>
|
||||
<Top {...this.props} {...this.state}/>
|
||||
<div className="main">
|
||||
<p className="pb15 bor-bottom-greyE font-16 color-grey-3 mb20">新建文件</p>
|
||||
<div className="f-wrap-alignCenter mb20">
|
||||
<div className="setInputAddon">
|
||||
<Input addonBefore={`/${projectDetail && projectDetail.identifier}${urlroot}/`} value={filename} onChange={this.changeFileName} placeholder="命名文件..."/>
|
||||
</div>
|
||||
<a onClick={this.CancelAddFile} className="color-blue">取消</a>
|
||||
</div>
|
||||
<a onClick={this.CancelAddFile} className="color-blue">取消</a>
|
||||
<div className="branchTable">
|
||||
<Editor
|
||||
height="320px"
|
||||
theme={"vs-grey"}
|
||||
value={editorValue}
|
||||
onChange={this.changeEditor}
|
||||
/>
|
||||
</div>
|
||||
<UserSubmitComponent
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
filepath={`${urlroot}/${filename}`}
|
||||
content={editorValue}
|
||||
></UserSubmitComponent>
|
||||
</div>
|
||||
<div className="branchTable">
|
||||
<p className="branchTitle">新建文件</p>
|
||||
<Editor
|
||||
height="320px"
|
||||
theme={"vs-dark"}
|
||||
value={editorValue}
|
||||
onChange={this.changeEditor}
|
||||
/>
|
||||
</div>
|
||||
<UserSubmitComponent
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
filepath={`${urlroot}/${filename}`}
|
||||
content={editorValue}
|
||||
></UserSubmitComponent>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,61 +50,63 @@ class UserSubmitComponent extends Component{
|
|||
const { submitType } = this.state;
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
|
||||
const { branch } = this.props.match.params;
|
||||
const { branch , projectsId } = this.props.match.params;
|
||||
|
||||
const { current_user , filepath , projectDetail } = this.props;
|
||||
|
||||
const changeSubmitBranch = ()=>{
|
||||
if(submitType==="1"){
|
||||
return(
|
||||
<div className="mt24">
|
||||
<Form.Item style={{paddingLeft:"24px"}}>
|
||||
{getFieldDecorator('desc', {
|
||||
rules: [{
|
||||
required:true,message:'请输入合并请求的描述内容'
|
||||
}],
|
||||
})(
|
||||
<TextArea placeholder={`请输入合并请求的描述,(必填)`} authSize={{minRows:3,maxRows:5}}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<div className="mt15">
|
||||
<Form.Item style={{paddingLeft:"24px"}}>
|
||||
{getFieldDecorator('branchname', {
|
||||
rules: [{
|
||||
required: true, message: '请输入分支名称'
|
||||
}],
|
||||
})(
|
||||
<Input placeholder={`请输入分支名称`}/>
|
||||
<Input placeholder={`请输入分支名称`} style={{width:"220px"}}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
return(
|
||||
<div className="userScrew">
|
||||
<img src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt="" className="screwImg"/>
|
||||
<div className="screwPanel">
|
||||
<Form>
|
||||
<Form.Item>
|
||||
{getFieldDecorator('path', {
|
||||
rules: [],
|
||||
})(
|
||||
<Input placeholder={`/${projectDetail && projectDetail.identifier}${filepath}`} readOnly/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<div>
|
||||
<span className="df mt20" style={{alignItems:"center"}}>
|
||||
<img src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt="" className="screwImg"/>
|
||||
<span className="color-grey-3">用户名:<span className="color-grey-8">{current_user && current_user.username}</span></span>
|
||||
</span>
|
||||
<div className="userScrew">
|
||||
<div className="screwPanel">
|
||||
<Form>
|
||||
<Form.Item>
|
||||
{getFieldDecorator('path', {
|
||||
rules: [],
|
||||
})(
|
||||
<Input placeholder={`/${projectDetail && projectDetail.identifier}${filepath}`} readOnly/>
|
||||
)}
|
||||
</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()}
|
||||
|
||||
<Radio.Group value={submitType} onChange={this.changeSubmittype}>
|
||||
<Radio value="0"><i className="iconfont icon-banbenku font-16 mr5"></i>直接提交至<span>{branch}</span>分支</Radio>
|
||||
<Radio value="1"><Icon type="pull-request" className="mr5" />为此提交创建一个<span className="font-bd">新的分支</span>并发起合并请求</Radio>
|
||||
</Radio.Group>
|
||||
{changeSubmitBranch()}
|
||||
|
||||
<Form.Item className="mt10" style={{marginBottom:"0px"}}>
|
||||
<Button type="primary" onClick={this.subMitFrom} className="mr20">提交变更</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
<Button type="primary" onClick={this.subMitFrom} className="mr20">提交变更</Button>
|
||||
<Button type="primary grey" onClick={()=>{this.props.history.push(`/projects/${projectsId}/coders`)}} className="mr20">取消</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -14,7 +14,39 @@
|
|||
border:1px solid #f4f4f4;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
padding:10px;
|
||||
padding:20px;
|
||||
position: relative;
|
||||
}
|
||||
.userScrew::before{
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 110px;
|
||||
top: -20px;
|
||||
border-bottom:10px solid #f4f4f4;
|
||||
border-top:10px solid transparent;
|
||||
border-left:10px solid transparent;
|
||||
border-right:10px solid transparent;
|
||||
}
|
||||
.userScrew::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
left:111px;
|
||||
top: -18px;
|
||||
border-bottom:9px solid #fff;
|
||||
border-top:9px solid transparent;
|
||||
border-left:9px solid transparent;
|
||||
border-right:9px solid transparent;
|
||||
z-index: 1;
|
||||
}
|
||||
.ant-input-group .ant-input:focus{
|
||||
border-right: 1px solid #d9d9d9!important;
|
||||
}
|
||||
.ant-btn-primary.grey{
|
||||
border:1px solid #BBBBBB;
|
||||
background-color: #BBBBBB;
|
||||
}
|
||||
.userScrew .ant-row{
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.screwImg{
|
||||
width: 34px;
|
||||
|
@ -29,6 +61,14 @@
|
|||
.screwPanel .ant-radio-wrapper{
|
||||
display: block;
|
||||
}
|
||||
.branchTable{
|
||||
border:1px solid #eaeaea;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.branchTable .margin-view-overlays{
|
||||
border-right: 1px solid #eaeaea;
|
||||
background-color: #fbfbfb;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 400px){
|
||||
.setInputAddon{
|
||||
|
|
|
@ -218,6 +218,8 @@ class order extends Component {
|
|||
});
|
||||
if (type) {
|
||||
this.setState({
|
||||
author_id: undefined,
|
||||
assigned_to_id: undefined,
|
||||
status_type: type,
|
||||
issue_tag_ids: "标签",
|
||||
tracker_ids: "所有分类",
|
||||
|
|
|
@ -1,56 +1,56 @@
|
|||
import React , { Component } from "react";
|
||||
import React, { Component } from "react";
|
||||
import { Upload, Button, Icon } from 'antd';
|
||||
import { getUploadActionUrl, appendFileSizeToUploadFileAll } from 'educoder';
|
||||
|
||||
import axios from 'axios';
|
||||
const { Dragger } = Upload;
|
||||
class Index extends Component{
|
||||
constructor(props){
|
||||
class Index extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state={
|
||||
fileList:undefined,
|
||||
this.state = {
|
||||
fileList: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
onAttachmentRemove = (file) => {
|
||||
if(!file.percent || file.percent === 100){
|
||||
// this.props.confirm({
|
||||
// content: '是否确认删除?',
|
||||
// onOk: () => {
|
||||
// this.deleteAttachment(file)
|
||||
// },
|
||||
// onCancel() {
|
||||
// console.log('Cancel');
|
||||
// },
|
||||
if (!file.percent || file.percent === 100) {
|
||||
// this.props.confirm({
|
||||
// content: '是否确认删除?',
|
||||
// onOk: () => {
|
||||
// this.deleteAttachment(file)
|
||||
// },
|
||||
// onCancel() {
|
||||
// console.log('Cancel');
|
||||
// },
|
||||
// });
|
||||
this.deleteAttachment(file)
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
deleteAttachment = (file) => {
|
||||
|
||||
|
||||
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
|
||||
axios.delete(url, {
|
||||
}).then((response) => {
|
||||
if (response.data) {
|
||||
if (response.data.status === 0) {
|
||||
this.setState((state) => {
|
||||
const index = state.fileList.indexOf(file);
|
||||
const newFileList = state.fileList.slice();
|
||||
newFileList.splice(index, 1);
|
||||
return {
|
||||
fileList: newFileList,
|
||||
};
|
||||
});
|
||||
this.fileIdList(this.state.fileList);
|
||||
}else{
|
||||
this.props.showNotification(response.data.message)
|
||||
}
|
||||
if (response.data) {
|
||||
if (response.data.status === 0) {
|
||||
this.setState((state) => {
|
||||
const index = state.fileList.indexOf(file);
|
||||
const newFileList = state.fileList.slice();
|
||||
newFileList.splice(index, 1);
|
||||
return {
|
||||
fileList: newFileList,
|
||||
};
|
||||
});
|
||||
this.fileIdList(this.state.fileList);
|
||||
} else {
|
||||
this.props.showNotification(response.data.message)
|
||||
}
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,36 +65,36 @@ class Index extends Component{
|
|||
}
|
||||
}
|
||||
|
||||
fileIdList=(fileList)=>{
|
||||
fileIdList = (fileList) => {
|
||||
let array = [];
|
||||
fileList && fileList.length>0 && fileList.map((item)=>{
|
||||
fileList && fileList.length > 0 && fileList.map((item) => {
|
||||
return array.push(item.response && item.response.id);
|
||||
})
|
||||
array && this.props.load && this.props.load(array);
|
||||
}
|
||||
|
||||
render(){
|
||||
render() {
|
||||
//判断是否已经提交,如已提交评论则上一条评论数据清除
|
||||
const { isComplete } = this.props;
|
||||
const { fileList } = this.state;
|
||||
|
||||
|
||||
let list = isComplete === true ? fileList : undefined;
|
||||
const upload = {
|
||||
name: 'file',
|
||||
fileList:list,
|
||||
fileList: list,
|
||||
action: `${getUploadActionUrl()}`,
|
||||
onChange:this.handleChange,
|
||||
onChange: this.handleChange,
|
||||
onRemove: this.onAttachmentRemove,
|
||||
};
|
||||
|
||||
return(
|
||||
return (
|
||||
<div>
|
||||
<Dragger {...upload} >
|
||||
<Icon type="inbox" />
|
||||
<p className="ant-upload-text">拖动文件或者点击此处上传</p>
|
||||
</Dragger>
|
||||
<Icon type="inbox" />
|
||||
<p className="ant-upload-text">拖动文件或者点击此处上传</p>
|
||||
</Dragger>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
export default Index;
|
|
@ -0,0 +1,52 @@
|
|||
import React , { useState, useEffect } from 'react';
|
||||
import { AutoComplete } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import './version.css';
|
||||
|
||||
export default ()=>{
|
||||
|
||||
const SelectDiv = styled.div`
|
||||
display:flex;
|
||||
align-item:center;
|
||||
margin-bottom:5px;
|
||||
& span{
|
||||
margin:0px 15px;
|
||||
color:#BBB;
|
||||
line-height:32px;
|
||||
}
|
||||
`;
|
||||
|
||||
useEffect(()=>{
|
||||
|
||||
})
|
||||
return(
|
||||
<div className="main df">
|
||||
<div className="versionForm">
|
||||
<p className="font-16 color-grey-3 mb15">创建发行版</p>
|
||||
<div>
|
||||
<SelectDiv>
|
||||
<AutoComplete placeholder="标记一个标签"></AutoComplete>
|
||||
<span>@</span>
|
||||
</SelectDiv>
|
||||
<p className="font-13 color-grey-8">选择一个已经存在的标签,或者在发布时新建一个标签</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="versionTips">
|
||||
<div className="infosTip">
|
||||
<p className="font-16 mb15">标签命名建议</p>
|
||||
<p className="mb15">通常的做法是在版本名称前加上字母 v 前缀, v1.0 或者 v2.3.4。</p>
|
||||
<p>如果标签不适合在生产环境下使用,请在版本名称后添加预发行版本。例如:v0.2-alpha 或者 v5.9-beta.3。</p>
|
||||
</div>
|
||||
<div className="infosTip">
|
||||
<p className="font-16 mb15">语义化版本</p>
|
||||
<p className="mb15">如果你是第一次发布版本,我们强烈建议你阅读语义化版本。</p>
|
||||
</div>
|
||||
<div className="infosTip">
|
||||
<p className="font-16 mb15">附件大小说明</p>
|
||||
<p className="mb15">单个附件不能超过 100M(GVP 项目200M),每个仓库总附件不可超过 1G(推荐项目不可超过 5G;GVP 项目不可超过 20G)。附件总容量统计包括仓库附件和发行版附件。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
import React , { Component } from "react";
|
||||
import { Form , Input , Select,Divider,Button,Checkbox,Dropdown,Menu, Spin} from 'antd';
|
||||
import {Link} from 'react-router-dom';
|
||||
import React, { Component } from "react";
|
||||
import { Form, Input, Select, Divider, Button, Checkbox, Dropdown, Menu, Spin } from 'antd';
|
||||
|
||||
import '../Order/order.css';
|
||||
import './version.css';
|
||||
|
@ -9,56 +8,56 @@ import axios from 'axios';
|
|||
|
||||
const Option = Select.Option;
|
||||
const TextArea = Input.TextArea;
|
||||
class NewVersion extends Component{
|
||||
constructor(props){
|
||||
class NewVersion extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state={
|
||||
branch_name:"",
|
||||
issue_tag_ids:"",
|
||||
fixed_version_id:"",
|
||||
issue_chosen:undefined,
|
||||
fileList:undefined,
|
||||
ischeck:undefined,
|
||||
branches:undefined,
|
||||
pull:undefined,
|
||||
tag_name:'',
|
||||
this.state = {
|
||||
branch_name: "",
|
||||
issue_tag_ids: "",
|
||||
fixed_version_id: "",
|
||||
issue_chosen: undefined,
|
||||
fileList: undefined,
|
||||
ischeck: undefined,
|
||||
branches: undefined,
|
||||
pull: undefined,
|
||||
tag_name: '',
|
||||
isSpin: false
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount=()=>{
|
||||
componentDidMount = () => {
|
||||
this.InitData();
|
||||
this.getSelectList();
|
||||
}
|
||||
|
||||
InitData=()=>{
|
||||
InitData = () => {
|
||||
this.props.form.setFieldsValue({
|
||||
...this.state
|
||||
});
|
||||
}
|
||||
|
||||
getSelectList=()=>{
|
||||
getSelectList = () => {
|
||||
const { projectsId } = this.props.match.params;
|
||||
const url = `/projects/${projectsId}/version_releases/new.json`;
|
||||
axios.get(url).then((result)=>{
|
||||
if(result){
|
||||
axios.get(url).then((result) => {
|
||||
if (result) {
|
||||
this.setState({
|
||||
branches:result.data.branches,
|
||||
pull:result.data.branches[0]
|
||||
branches: result.data.branches,
|
||||
pull: result.data.branches[0]
|
||||
})
|
||||
}
|
||||
}).catch((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+""}>{item.name}</Option>
|
||||
renderSelect = (list) => {
|
||||
if (list && list.length > 0) {
|
||||
return (
|
||||
list.map((item, key) => {
|
||||
return (
|
||||
<Option key={key + 1} value={item.id + ""}>{item.name}</Option>
|
||||
)
|
||||
})
|
||||
)
|
||||
|
@ -66,36 +65,36 @@ class NewVersion extends Component{
|
|||
}
|
||||
|
||||
// 创建
|
||||
handleSubmit=(draft)=>{
|
||||
handleSubmit = (draft) => {
|
||||
this.setState({
|
||||
isSpin: true
|
||||
})
|
||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||
if(!err){
|
||||
if (!err) {
|
||||
const { projectsId } = this.props.match.params;
|
||||
const { pull,tag_name,ischeck} = this.state;
|
||||
const { pull, tag_name, ischeck } = this.state;
|
||||
const url = `/projects/${projectsId}/version_releases.json`;
|
||||
// if(values.issue_type==="普通"){
|
||||
// values.issue_type="1"
|
||||
// }
|
||||
axios.post(url,{
|
||||
axios.post(url, {
|
||||
...values,
|
||||
tag_name:tag_name,
|
||||
draft:draft,
|
||||
prerelease:ischeck,
|
||||
target_commitish:pull,
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
tag_name: tag_name,
|
||||
draft: draft,
|
||||
prerelease: ischeck,
|
||||
target_commitish: pull,
|
||||
}).then(result => {
|
||||
if (result) {
|
||||
this.setState({
|
||||
isSpin: false
|
||||
})
|
||||
this.props.history.push(`/projects/${projectsId}/version`);
|
||||
}
|
||||
}).catch(error=>{
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
})
|
||||
|
||||
}else{
|
||||
} else {
|
||||
this.setState({
|
||||
isSpin: false
|
||||
})
|
||||
|
@ -104,27 +103,27 @@ class NewVersion extends Component{
|
|||
}
|
||||
|
||||
// 获取上传后的文件id数组
|
||||
UploadFunc=(fileList)=>{
|
||||
UploadFunc = (fileList) => {
|
||||
this.setState({
|
||||
fileList
|
||||
})
|
||||
}
|
||||
RedieonChange=(e)=>{
|
||||
this.setState({
|
||||
ischeck:e.target.checked
|
||||
})
|
||||
RedieonChange = (e) => {
|
||||
this.setState({
|
||||
ischeck: e.target.checked
|
||||
})
|
||||
}
|
||||
Preservation=()=>{
|
||||
alert(this.state.ischeck)
|
||||
Preservation = () => {
|
||||
alert(this.state.ischeck)
|
||||
}
|
||||
|
||||
renderMenu =(array,id)=>{
|
||||
return(
|
||||
renderMenu = (array, id) => {
|
||||
return (
|
||||
<Menu>
|
||||
{
|
||||
array && array.length > 0 && array.map((item,key)=>{
|
||||
return(
|
||||
<Menu.Item key={item} onClick={()=>this.getOption(item)}>{item}</Menu.Item>
|
||||
array && array.length > 0 && array.map((item, key) => {
|
||||
return (
|
||||
<Menu.Item key={item} onClick={() => this.getOption(item)}>{item}</Menu.Item>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
@ -132,78 +131,77 @@ class NewVersion extends Component{
|
|||
)
|
||||
}
|
||||
|
||||
getOption=(name)=>{
|
||||
this.setState({
|
||||
pull:name
|
||||
})
|
||||
|
||||
getOption = (name) => {
|
||||
this.setState({
|
||||
pull: name
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
changmodelname=(e)=>{
|
||||
changmodelname = (e) => {
|
||||
this.setState({
|
||||
tag_name:e.target.value
|
||||
tag_name: e.target.value
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const {branches,pull,tag_name, isSpin} = this.state;
|
||||
|
||||
return(
|
||||
<div className="main">
|
||||
<Form>
|
||||
<h1 style={{marginLeft:15,marginTop:20}}>发布新版</h1>
|
||||
<h5 style={{marginLeft:15}}>发布一个特定的打包好的项目版本</h5>
|
||||
<Divider/>
|
||||
<div style={{display:'flex'}}>
|
||||
<Input placeholder="标签名称" style={{width:180,marginLeft:15}} value={tag_name} onChange={this.changmodelname} />
|
||||
<div style={{marginLeft:20,marginRight:20,lineHeight: '32px'}}>@ </div>
|
||||
<Dropdown overlay={this.renderMenu(branches &&branches,'pull')} trigger={['click']} placement="bottomCenter">
|
||||
<Button style={{width:180}}>{pull}</Button>
|
||||
</Dropdown>
|
||||
const { branches, pull, tag_name, isSpin } = this.state;
|
||||
|
||||
return (
|
||||
<div className="main">
|
||||
<Form>
|
||||
<h1 style={{ marginLeft: 15, marginTop: 20 }}>发布新版</h1>
|
||||
<h5 style={{ marginLeft: 15 }}>发布一个特定的打包好的项目版本</h5>
|
||||
<Divider />
|
||||
<div style={{ display: 'flex' }}>
|
||||
<Input placeholder="标签名称" style={{ width: 180, marginLeft: 15 }} value={tag_name} onChange={this.changmodelname} />
|
||||
<div style={{ marginLeft: 20, marginRight: 20, lineHeight: '32px' }}>@ </div>
|
||||
<Dropdown overlay={this.renderMenu(branches && branches, 'pull')} trigger={['click']} placement="bottomCenter">
|
||||
<Button style={{ width: 180 }}>{pull}</Button>
|
||||
</Dropdown>
|
||||
</div>
|
||||
<div style={{display:'flex'}}>
|
||||
<div className="versionmilepostleft">
|
||||
<h1>标题</h1>
|
||||
<div>
|
||||
<Form.Item>
|
||||
<div style={{ display: 'flex' }}>
|
||||
<div className="versionmilepostleft">
|
||||
<h1>标题</h1>
|
||||
<div>
|
||||
<Form.Item>
|
||||
{getFieldDecorator('name', {
|
||||
rules: [{
|
||||
required: true, message: '请输入标题'
|
||||
}],
|
||||
})(
|
||||
<Input placeholder="标题" maxLength="32"/>
|
||||
<Input placeholder="标题" maxLength="32" />
|
||||
)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
<h1>内容</h1>
|
||||
<Form.Item>
|
||||
{getFieldDecorator('body', {
|
||||
rules: [{
|
||||
required: true, message: '请输入描述内容'
|
||||
}],
|
||||
})(
|
||||
<TextArea placeholder="添加描述内容..." style={{'min-height':"150px"}}/>
|
||||
|
||||
)}
|
||||
</Form.Item>
|
||||
{/* <UploadComponent load={this.UploadFunc} style={{width:80,marginLeft:15}}></UploadComponent> */}
|
||||
</div>
|
||||
<h1>内容</h1>
|
||||
<Form.Item>
|
||||
{getFieldDecorator('body', {
|
||||
rules: [{
|
||||
required: true, message: '请输入描述内容'
|
||||
}],
|
||||
})(
|
||||
<TextArea placeholder="添加描述内容..." style={{ 'min-height': "150px" }} />
|
||||
)}
|
||||
</Form.Item>
|
||||
{/* <UploadComponent load={this.UploadFunc} style={{width:80,marginLeft:15}}></UploadComponent> */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
<div className="fr mb15">
|
||||
<Checkbox onChange={this.RedieonChange}>标记为预行版<span className="ml15 color-grey-9 font-13">(此版本不适合生产使用)</span></Checkbox>
|
||||
</div>
|
||||
<div className="clearfix mt15" style={{ marginTop: 5 }} >
|
||||
<Spin spinning={isSpin}>
|
||||
<a className='topWrapper_btn_close fr' onClick={() => this.handleSubmit(true)} style={{ marginLeft: 15 }} >保存草稿</a>
|
||||
<a className='topWrapper_btn fr' onClick={() => this.handleSubmit(false)} style={{ marginRight: 15 }}>发布版本</a>
|
||||
</Spin>
|
||||
|
||||
</div>
|
||||
|
||||
<Divider/>
|
||||
<div className="fr mb15">
|
||||
<Checkbox onChange={this.RedieonChange}>标记为预行版<span className="ml15 color-grey-9 font-13">(此版本不适合生产使用)</span></Checkbox>
|
||||
</div>
|
||||
<div className="clearfix mt15" style={{marginTop:5}} >
|
||||
<Spin spinning={isSpin}>
|
||||
<a className='topWrapper_btn_close fr' onClick={()=>this.handleSubmit(true)} style={{marginLeft:15}} >保存草稿</a>
|
||||
<a className='topWrapper_btn fr' onClick={()=>this.handleSubmit(false)} style={{marginRight:15}}>发布版本</a>
|
||||
</Spin>
|
||||
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,16 +4,71 @@
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #EEEEEE;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
.topWrapper_btn {
|
||||
background: #21ba45;
|
||||
color: #FFFFFF!important;
|
||||
.topWrapper_btn_new {
|
||||
background: #fff;
|
||||
color: #5091FF!important;
|
||||
padding:0px 12px;
|
||||
text-align: center;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
border-radius: 4px;
|
||||
border:1px solid #5091FF;
|
||||
}
|
||||
.versionInfo{
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
.versionInfo_left{
|
||||
display: flex;
|
||||
width: 30%;
|
||||
padding-top: 20px;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
padding-right: 15px;
|
||||
}
|
||||
.versionInfo_right{
|
||||
flex: 1;
|
||||
padding: 20px 0px 20px 15px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
border-left: 1px solid #eee;
|
||||
}
|
||||
.versionTag{
|
||||
display: inline;
|
||||
border-radius: 2px;
|
||||
padding:2px 12px;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
}
|
||||
.versionTag.yellow{
|
||||
background-color: #FBBC06;
|
||||
}
|
||||
.versionTag.green{
|
||||
background-color: #20BA45;
|
||||
}
|
||||
.versionTag.orange{
|
||||
background-color: #F2711D;
|
||||
}
|
||||
.versionName{
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
position: relative;
|
||||
}
|
||||
.versionName::before{
|
||||
position: absolute;
|
||||
left: -19px;
|
||||
top:8px;
|
||||
content: '';
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: #5091FF;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
|
||||
|
@ -113,4 +168,21 @@
|
|||
}
|
||||
.ver-middle{
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.versionForm{
|
||||
flex:1;
|
||||
padding-right: 30px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.versionTips{
|
||||
width:30%;
|
||||
padding-right: 15px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.infosTip{
|
||||
padding:20px;
|
||||
background-color: #F1F8FF;
|
||||
margin-bottom: 22px;
|
||||
color: #333;
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
import React , { Component } from "react";
|
||||
import {Link} from 'react-router-dom';
|
||||
import { Input } from 'antd';
|
||||
import React, { Component } from "react";
|
||||
import { Link } from 'react-router-dom';
|
||||
import NoneData from '../Nodata';
|
||||
import './version.css';
|
||||
import { getImageUrl } from 'educoder';
|
||||
|
@ -11,160 +10,112 @@ import axios from 'axios';
|
|||
* data:列表接口返回的所有数据,
|
||||
* issues:列表数组,
|
||||
* isSpin:加载中,
|
||||
* search:搜索关键字,
|
||||
* author_id:发布者id,
|
||||
* assigned_to_id:指派给。。。的id,
|
||||
* limit:每页条数,
|
||||
* page:当前页,
|
||||
* search_count:列表总条数
|
||||
* issue_type:搜索条件
|
||||
*/
|
||||
class version extends Component{
|
||||
constructor(props){
|
||||
class version extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state={
|
||||
issue_chosen:undefined,
|
||||
data:undefined,
|
||||
issues:undefined,
|
||||
isSpin:false,
|
||||
search:undefined,
|
||||
author_id:undefined,
|
||||
assigned_to_id:undefined,
|
||||
limit:15,
|
||||
page:1,
|
||||
search_count:undefined,
|
||||
issue_type:undefined
|
||||
this.state = {
|
||||
issue_chosen: undefined,
|
||||
data: undefined,
|
||||
releases:undefined,
|
||||
issues: undefined,
|
||||
isSpin: false,
|
||||
search: undefined,
|
||||
search_count: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount=()=>{
|
||||
componentDidMount = () => {
|
||||
this.getIssueList();
|
||||
}
|
||||
// 获取列表数据
|
||||
getIssueList=(page,limit,search,author_id,assigned_to_id,id,value)=>{
|
||||
getIssueList = () => {
|
||||
const { projectsId } = this.props.match.params;
|
||||
const url = `/projects/${projectsId}/version_releases.json`;
|
||||
axios.get(url).then((result)=>{
|
||||
if(result){
|
||||
axios.get(url).then((result) => {
|
||||
if (result) {
|
||||
this.setState({
|
||||
data:result.data,
|
||||
issues:result.data.issues,
|
||||
search_count:result.data.search_count,
|
||||
isSpin:false
|
||||
data: result.data,
|
||||
releases:result.data.releases,
|
||||
issues: result.data.issues,
|
||||
isSpin: false
|
||||
})
|
||||
}
|
||||
}).catch((error)=>{
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
// 显示版本描述
|
||||
showBody=(key,flag)=>{
|
||||
let { releases } = this.state;
|
||||
releases[key].bodyshow = !flag;
|
||||
this.setState({
|
||||
releases
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
render(){
|
||||
render() {
|
||||
const { projectsId } = this.props.match.params;
|
||||
const{data}=this.state
|
||||
const renderList =()=>{
|
||||
if(data && data.releases && data.releases.length>0 ){
|
||||
return(
|
||||
<div>{
|
||||
data.releases.map((item,key)=>{
|
||||
return(
|
||||
<div key={key}>
|
||||
{
|
||||
item && item.id ?
|
||||
<div>
|
||||
<div style={{display:'flex'}}>
|
||||
<div className="versionleft">
|
||||
<div className="versionrighe"></div><span className={item&&item.draft==="稳定"?"opendversionetail":"closedversionetail"} style={{marginTop:5,margin:'auto',marginRight:15}}>{item.draft} </span>
|
||||
</div>
|
||||
<div className="version_line_one">
|
||||
<p className="versionrectangle"> </p>
|
||||
</div>
|
||||
<div className="versionrighe">
|
||||
<h1 style={{marginLeft:15,marginTop:5}}>{item.name}
|
||||
{
|
||||
data && data.user_permission ?
|
||||
<Link to={`/projects/${projectsId}/version/${item.version_id}/upversion`} style={{color:'blue',fontSize:10,marginLeft:5}}>(编辑)</Link>
|
||||
: ''
|
||||
}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div style={{display:'flex'}}>
|
||||
<div className="versionleft">
|
||||
<span style={{marginTop:5,margin:'auto',marginRight:15}}>{item.tag_name} </span>
|
||||
</div>
|
||||
<div className="version_line_one">
|
||||
<p style={{width:4}}> </p>
|
||||
|
||||
</div>
|
||||
<div className="versionrighe">
|
||||
<h5 style={{marginLeft:15,marginTop:10}}>{item.body} </h5>
|
||||
<div className="ml15">
|
||||
<Link to={`/users/${item && item.login}/projects`} className="show-user-link">
|
||||
<img src={getImageUrl(`images/${item.image_url}`)} alt="" width="28px" height="28px" className="mr5 radius"/>
|
||||
<span className="mr10 ver-middle">{item.user_name}</span>
|
||||
</Link>
|
||||
<span className="color-grey-9 ver-middle">发布于{item.created_at}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{display:'flex'}}>
|
||||
<div className="versionleft">
|
||||
<span style={{marginTop:5,marginRight:15}}></span>
|
||||
</div>
|
||||
<div className="version_line_tpw">
|
||||
<p style={{width:4}}> </p>
|
||||
</div>
|
||||
<div className="versionrighe">
|
||||
<h1 style={{marginLeft:15,marginTop:10}}>下载附件
|
||||
</h1>
|
||||
<a href={item.zipball_url} download="源代码(ZIP)" style={{color:'blue',marginLeft:15}}>源代码(ZIP)</a>
|
||||
<a href={item.tarball_url} download="源文件(TAR.GZ)" style={{color:'blue',marginLeft:15}}>源文件(TAR.GZ)</a>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{display:'flex'}}>
|
||||
<div className="versionleft">
|
||||
<span style={{marginTop:5,marginRight:15}}></span>
|
||||
</div>
|
||||
<div className="version_line_tpw">
|
||||
<p style={{width:4}}> </p>
|
||||
</div>
|
||||
<div className="versionrighe">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
""
|
||||
}
|
||||
const { data , releases } = this.state
|
||||
const renderList = () => {
|
||||
if (releases && releases.length > 0) {
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
releases.map((item, key) => {
|
||||
return (
|
||||
<div className="versionInfo" key={key}>
|
||||
<span className="versionInfo_left">
|
||||
<span className={`${item.draft === "稳定" ?"versionTag green":"versionTag yellow"}`}>{item.draft}</span>
|
||||
<span className="mt10">{item.created_at}</span>
|
||||
<span className="color-grey-8">
|
||||
<i className="iconfont icon-biaoqian3 mr3 font-14"></i>
|
||||
{item.tag_name}
|
||||
</span>
|
||||
</span>
|
||||
<div className="versionInfo_right">
|
||||
<span className="versionName">
|
||||
<span className="task-hide">{item.name}</span>
|
||||
<Link to={`/projects/${projectsId}/coders/version/${item.version_id}/update`} className="color-blue ml3 font-12">(编辑)</Link>
|
||||
</span>
|
||||
<span className="color-grey-3">
|
||||
<i className={`${item.bodyshow ? "iconfont icon-sanjiaoxing-down color-grey-8 mr3 font-14":"iconfont icon-triangle color-grey-8 mr3 font-14"}`} onClick={()=>this.showBody(key,item.bodyshow)}></i>
|
||||
{item.user_name}:<span className="color-grey-8">发布了这个版本,并在发布后提交给{item.target_commitish}</span>
|
||||
</span>
|
||||
{
|
||||
item.bodyshow && <p className="mt10">{item.body}</p>
|
||||
}
|
||||
<p className="mt10 pl3">
|
||||
{/* <span className="commitKey mr20">{item.commit_id}</span> */}
|
||||
<a href={item.tarball_url} style={{color:"#4CC1DA"}} className="mr30"><i className="iconfont icon-TAR font-18 mr5"></i>TAR</a>
|
||||
<a href={item.zipball_url} style={{color:"#28BD6C"}}><i className="iconfont icon-ZIP font-18 mr5"></i>ZIP</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}else{
|
||||
return(
|
||||
} else {
|
||||
return (
|
||||
<NoneData _html="暂时还没有相关数据哦!" />
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return(
|
||||
return (
|
||||
<div className="main">
|
||||
<div className="topWrapper">
|
||||
<h1>版本发布</h1>
|
||||
<span className="font-18 color-grey-3">版本发布</span>
|
||||
{
|
||||
data && data.user_permission ?
|
||||
<Link to={`/projects/${projectsId}/version/new`} className="topWrapper_btn">发布新版</Link>
|
||||
<Link to={`/projects/${projectsId}/coders/version/new`} className="topWrapper_btn_new">+ 发布新版</Link>
|
||||
: ''
|
||||
}
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<div className="releasesVersion">
|
||||
{renderList()}
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
ul,ol,dl{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
/* #EAEBEC */
|
||||
.newMain{
|
||||
background-color: #fff;
|
||||
background-color: #EAEBEC;
|
||||
}
|
||||
.main{
|
||||
width: 1200px;
|
||||
padding:20px 0px;
|
||||
margin:0px auto;
|
||||
padding:20px;
|
||||
margin:20px auto;
|
||||
background: #fff;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.radius-2{
|
||||
border-radius: 2px;
|
||||
|
|
|
@ -136,10 +136,6 @@ pre.prettyprint {
|
|||
color: #FF6545
|
||||
}
|
||||
|
||||
.color-orange {
|
||||
color: #ee4a1f !important;
|
||||
}
|
||||
|
||||
.color-orange02 {
|
||||
color: #f79f88 !important;
|
||||
}
|
||||
|
|
|
@ -12,43 +12,11 @@ const CommonWork = Loadable({
|
|||
loader: () => import('./busyWork/commonWork'),
|
||||
loading: Loading,
|
||||
})
|
||||
// 讨论
|
||||
const Boards = Loadable({
|
||||
loader: () => import('./boards'),
|
||||
loading: Loading,
|
||||
})
|
||||
//教师列表
|
||||
const TeacherList = Loadable({
|
||||
loader: () => import('./members/teacherList'),
|
||||
loading: Loading,
|
||||
})
|
||||
//主签到目录
|
||||
const Signinmain = Loadable({
|
||||
loader: () => import('./signin/mymain/Signinmain'),
|
||||
loading: Loading,
|
||||
});
|
||||
//学生列表
|
||||
const StudentsList = Loadable({
|
||||
loader: () => import('./members/studentsList'),
|
||||
loading: Loading,
|
||||
});
|
||||
//分班列表
|
||||
const CourseGroupList = Loadable({
|
||||
loader: () => import('./members/CourseGroupList'),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const Eduinforms = Loadable({
|
||||
loader: () => import('./gradinforms/Eduinforms'),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
//2019.10.29 统计
|
||||
const Statistics = Loadable({
|
||||
loader: () => import('./statistics/Statistics'),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const Elearning = Loadable({
|
||||
loader: () => import('./elearning/Elearning'),
|
||||
loading: Loading,
|
||||
|
@ -58,38 +26,13 @@ const Exercise = Loadable({
|
|||
loader: () => import('./exercise/Exercise'),
|
||||
loading: Loading,
|
||||
})
|
||||
//
|
||||
const Poll = Loadable({
|
||||
loader: () => import('./poll/Poll'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
// 资源
|
||||
const Resourcelist = Loadable({
|
||||
loader: () => import('./Resource/index'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
// 视频
|
||||
const CourseVideo = Loadable({
|
||||
loader: () => import('./Video/VideoIndex'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//实训作业
|
||||
const ShixunHomework = Loadable({
|
||||
loader: () => import('./shixunHomework/shixunHomework'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
const GraduationTopics = Loadable({
|
||||
loader: () => import('./graduation/topics'),
|
||||
loading: Loading,
|
||||
})
|
||||
const GraduationTasks = Loadable({
|
||||
loader: () => import('./graduation/tasks'),
|
||||
loading: Loading,
|
||||
})
|
||||
class ListPageIndex extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
@ -226,35 +169,6 @@ class ListPageIndex extends Component {
|
|||
(props) => (<CommonWork {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route exact path="/classrooms/:coursesId/boards/:boardId"
|
||||
render={
|
||||
(props) => (<Boards {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/*视频列表*/}
|
||||
<Route path="/classrooms/:coursesId/course_video/:videoId"
|
||||
render={
|
||||
(props) => (<CourseVideo {...this.props} {...props} {...this.state} homedirectory={this.state.homedirectory} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/classrooms/:coursesId/course_videos"
|
||||
render={
|
||||
(props) => (<CourseVideo {...this.props} {...props} {...this.state} homedirectory={this.state.homedirectory} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 教师列表*/}
|
||||
<Route path="/classrooms/:coursesId/teachers"
|
||||
render={
|
||||
(props) => (<TeacherList updatabanners={() => this.updatabanners()} {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 学生列表*/}
|
||||
<Route path="/classrooms/:coursesId/students"
|
||||
render={
|
||||
(props) => (<StudentsList {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 主签到 */}
|
||||
<Route path="/classrooms/:coursesId/attendances"
|
||||
render={
|
||||
|
@ -262,28 +176,12 @@ class ListPageIndex extends Component {
|
|||
}
|
||||
></Route>
|
||||
|
||||
<Route path="/classrooms/:coursesId/course_groups/:course_group_id"
|
||||
render={
|
||||
(props) => (<StudentsList {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/classrooms/:coursesId/course_groups"
|
||||
render={
|
||||
(props) => (<CourseGroupList {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route path="/classrooms/:coursesId/exercises/:Id"
|
||||
render={
|
||||
(props) => (<Exercise {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route path="/classrooms/:coursesId/polls/:Id"
|
||||
render={
|
||||
(props) => (<Poll {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 实训作业子页面*/}
|
||||
<Route path="/classrooms/:coursesId/shixun_homework/:category_id"
|
||||
render={
|
||||
|
@ -291,22 +189,6 @@ class ListPageIndex extends Component {
|
|||
}
|
||||
></Route>
|
||||
|
||||
{/*课堂统计列表2019.10.29 */}
|
||||
|
||||
<Route path="/classrooms/:coursesId/statistics"
|
||||
render={
|
||||
(props) => (<Statistics {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
{/*公告栏列表*/}
|
||||
|
||||
<Route path="/classrooms/:coursesId/informs"
|
||||
render={
|
||||
(props) => (<Eduinforms {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/*在线学习*/}
|
||||
<Route
|
||||
path="/classrooms/:coursesId/online_learning"
|
||||
|
@ -321,35 +203,6 @@ class ListPageIndex extends Component {
|
|||
(props) => (<ShixunHomework {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
<Route path="/classrooms/:coursesId/files/:main_id"
|
||||
render={
|
||||
(props) => (<Resourcelist {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/classrooms/:coursesId/file/:Id"
|
||||
render={
|
||||
(props) => (<Resourcelist {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route path="/classrooms/:coursesId/graduation_topics/:Id"
|
||||
render={
|
||||
(props) => (<GraduationTopics {...this.props} {...props} {...this.state} />)
|
||||
}></Route>
|
||||
<Route path="/classrooms/:coursesId/graduation_tasks/:Id"
|
||||
render={
|
||||
(props) => (<GraduationTasks {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 默认 */}
|
||||
<Route path="/classrooms/:coursesId"
|
||||
render={
|
||||
(props) => (<StudentsList {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,470 +0,0 @@
|
|||
import React, {Component} from "react";
|
||||
import {WordsBtn} from 'educoder';
|
||||
import {Tooltip, message} from 'antd';
|
||||
import {Link} from 'react-router-dom';
|
||||
import {getImageUrl} from 'educoder';
|
||||
import axios from 'axios'
|
||||
import {getUrl} from 'educoder';
|
||||
import moment from 'moment'
|
||||
import CoursesListType from '../coursesPublic/CoursesListType';
|
||||
import Showoldfiles from "../coursesPublic/Showoldfiles";
|
||||
import Modals from '../../modals/Modals';
|
||||
|
||||
class Fileslistitem extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {}
|
||||
}
|
||||
|
||||
settingList = (bools) => {
|
||||
let {discussMessage} = this.props
|
||||
console.log(discussMessage);
|
||||
this.setState({
|
||||
discussMessageid: discussMessage.id
|
||||
})
|
||||
if (bools === true) {
|
||||
this.props.Settingtypes(discussMessage.id)
|
||||
} else {
|
||||
this.props.Settingtypess(discussMessage.id,discussMessage.title,discussMessage.link)
|
||||
}
|
||||
|
||||
}
|
||||
//外链
|
||||
showfiless = (url,id) => {
|
||||
window.open(url)
|
||||
let urls=`/files/${id}/update_visits.json`;
|
||||
axios.post(urls,{
|
||||
}).then((result)=>{
|
||||
if(result.data.status===0){
|
||||
this.props.Updateresourcepage()
|
||||
}else{
|
||||
this.props.showNotification(result.data.message);
|
||||
}
|
||||
})
|
||||
}
|
||||
showfiles = (list) => {
|
||||
if (this.props.checkIfLogin() === false) {
|
||||
this.props.showLoginDialog()
|
||||
return
|
||||
}
|
||||
// if(this.props.checkIfProfileCompleted()===false){
|
||||
// this.setState({
|
||||
// AccountProfiletype:true
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
// if(this.props.checkIfProfessionalCertification()===false){
|
||||
// this.props.showProfileCompleteDialog()
|
||||
// return
|
||||
// }
|
||||
|
||||
if (list.is_history_file === false) {
|
||||
// this.props.DownloadFileA(list.title,list.url)
|
||||
//window.location.href=list.url;
|
||||
window.open(list.url, '_blank');
|
||||
} else {
|
||||
let {discussMessage, coursesId} = this.props
|
||||
let file_id = discussMessage.id
|
||||
let url = "/files/" + file_id + "/histories.json"
|
||||
axios.get(url, {
|
||||
params: {
|
||||
course_id: coursesId
|
||||
},
|
||||
}).then((result) => {
|
||||
|
||||
if (result.data.attachment_histories.length === 0) {
|
||||
// if(result.data.is_pdf===true){
|
||||
// this.props.ShowOnlinePdf(result.data.url)
|
||||
// //预览pdf
|
||||
// }else{
|
||||
//
|
||||
// }
|
||||
// this.props.DownloadFileA(result.data.title,result.data.url)
|
||||
window.open(list.url, '_blank');
|
||||
} else {
|
||||
this.setState({
|
||||
Showoldfiles: true,
|
||||
allfiles: result.data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
closaoldfilesprops = () => {
|
||||
this.setState({
|
||||
Showoldfiles: false,
|
||||
})
|
||||
}
|
||||
|
||||
onDelete = (id) => {
|
||||
|
||||
this.setState({
|
||||
Modalstype: true,
|
||||
Modalstopval: "是否确认删除?",
|
||||
ModalCancel: this.cancelmodel,
|
||||
ModalSave: () => this.savedelete(id),
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
cancelmodel = () => {
|
||||
|
||||
this.setState({
|
||||
Modalstype: false,
|
||||
Loadtype: false,
|
||||
Modalstopval: "",
|
||||
ModalCancel: "",
|
||||
ModalSave: "",
|
||||
checkBoxValues: [],
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
savedelete = (id) => {
|
||||
|
||||
this.setState({
|
||||
Modalstype: false,
|
||||
})
|
||||
|
||||
|
||||
const cid = this.props.match.params.coursesId
|
||||
const url = `/files/bulk_delete.json`;
|
||||
axios.delete(url, {
|
||||
data: {
|
||||
course_id: cid,
|
||||
ids: [id],
|
||||
}
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
//Modalstopval:response.data.message,
|
||||
|
||||
this.props.updatafiledfun()
|
||||
this.setState({
|
||||
// Modalstype:true,
|
||||
// Modalstopval:"删除成功",
|
||||
ModalsBottomval: "",
|
||||
// ModalSave:this.cancelmodel,
|
||||
// Loadtype:true,
|
||||
checkBoxValues: [],
|
||||
checkAllValue: false
|
||||
})
|
||||
|
||||
this.props.showNotification("删除成功");
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
eventStop = (event) => {
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const {
|
||||
checkBox,
|
||||
discussMessage, index
|
||||
} = this.props;
|
||||
|
||||
let bools = discussMessage.link && discussMessage.link ? false : true;
|
||||
return (
|
||||
<div className="graduateTopicList boardsList">
|
||||
|
||||
{/*提示*/}
|
||||
{this.state.Modalstype && this.state.Modalstype === true ? <Modals
|
||||
modalsType={this.state.Modalstype}
|
||||
modalsTopval={this.state.Modalstopval}
|
||||
modalCancel={this.state.ModalCancel}
|
||||
modalSave={this.state.ModalSave}
|
||||
modalsBottomval={this.state.ModalsBottomval}
|
||||
loadtype={this.state.Loadtype}
|
||||
/> : ""}
|
||||
<Showoldfiles
|
||||
{...this.props}
|
||||
visible={this.state.Showoldfiles}
|
||||
allfiles={this.state.allfiles}
|
||||
closaoldfilesprops={this.closaoldfilesprops}
|
||||
/>
|
||||
<style>{`
|
||||
.graduateTopicList .ant-checkbox-input {
|
||||
margin-right: 15px;
|
||||
}
|
||||
.graduateTopicList .ant-checkbox-wrapper {
|
||||
margin-top: 0px;
|
||||
}
|
||||
`}</style>
|
||||
|
||||
|
||||
<style>{`
|
||||
.boardsList .panel-list-img {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
`}</style>
|
||||
{/*<a href={"/users/"+this.props.user.login} alt="用户"*/}
|
||||
{/*style={{"width": "50px", "height": "50px", "display": "block", margin: "0 10px"}}>*/}
|
||||
{/*<img*/}
|
||||
{/*alt="1?1529221779" className="panel-list-img mr15" height="50"*/}
|
||||
{/*src={getImageUrl("images/"+discussMessage.author.image_url)} width="50"*/}
|
||||
{/*></img>*/}
|
||||
{/*</a>*/}
|
||||
|
||||
<style>{`
|
||||
.boardsList .contentSection{
|
||||
margin-left:0px;
|
||||
}
|
||||
.maxwidth580{
|
||||
max-width: 580px;
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space:nowrap
|
||||
}
|
||||
.mt2{
|
||||
margin-top:2px;
|
||||
}
|
||||
`}</style>
|
||||
<div className="clearfix ds pr contentSection" style={{cursor: this.props.isAdmin ? "pointer" : "default"}}
|
||||
onClick={() => window.$(`.sourceitem${index} input`).click()}>
|
||||
<h6 onClick={(event) => this.eventStop(event)}>
|
||||
<span className={`sourceitem${index} fl mr12 mt3`}>
|
||||
{checkBox}
|
||||
</span>
|
||||
{
|
||||
this.props.isAdmin ?
|
||||
(bools === true ?
|
||||
<a
|
||||
// href={"/classrooms/" + coursesId + "/graduation/graduation_tasks/" + categoryid + "/" + taskid + "/list"}
|
||||
onClick={() => this.showfiles(discussMessage)}
|
||||
title={discussMessage.title}
|
||||
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a>
|
||||
:
|
||||
<a
|
||||
// href={"/classrooms/" + coursesId + "/graduation/graduation_tasks/" + categoryid + "/" + taskid + "/list"}
|
||||
onClick={() => this.showfiless(discussMessage.link,discussMessage.id)}
|
||||
title={discussMessage.title}
|
||||
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a>
|
||||
)
|
||||
|
||||
: ""
|
||||
}
|
||||
{
|
||||
this.props.isStudent ?
|
||||
(bools === true ?
|
||||
<a
|
||||
onClick={() => this.showfiles(discussMessage)}
|
||||
title={discussMessage.title}
|
||||
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a>
|
||||
|
||||
:
|
||||
<a
|
||||
onClick={() => this.showfiless(discussMessage.link,discussMessage.id)}
|
||||
title={discussMessage.title}
|
||||
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a>
|
||||
|
||||
)
|
||||
|
||||
|
||||
: ""
|
||||
}
|
||||
|
||||
{
|
||||
this.props.isNotMember === true ?
|
||||
discussMessage.is_lock === true ?
|
||||
<span className="fl mt3 font-16 font-bd color-dark maxwidth580 pointer"
|
||||
title={"私有属性,非课堂成员不能访问"}>{discussMessage.title}</span>
|
||||
:
|
||||
(bools === true ?
|
||||
|
||||
<a
|
||||
onClick={() => this.showfiles(discussMessage)}
|
||||
title={discussMessage.title}
|
||||
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a> :
|
||||
|
||||
<a
|
||||
onClick={() =>this.showfiless(discussMessage.link,discussMessage.id)}
|
||||
title={discussMessage.title}
|
||||
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a>
|
||||
|
||||
)
|
||||
|
||||
|
||||
: ""
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
discussMessage.is_lock === true ?
|
||||
<Tooltip title={"私有属性,非课堂成员不能访问"} placement="bottom">
|
||||
<i className="iconfont icon-guansuo color-grey-c ml10 font-16 fl mt4"></i>
|
||||
</Tooltip>
|
||||
: ""
|
||||
}
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.fwlz{
|
||||
width:40px;
|
||||
height:20px;
|
||||
border-radius:2px;
|
||||
border:1px solid rgba(250,100,0,1);
|
||||
font-size:12px;
|
||||
font-family:MicrosoftYaHei;
|
||||
color:rgba(250,100,0,1);
|
||||
text-align: center;
|
||||
margin-left: 15px;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
{
|
||||
discussMessage.link && discussMessage.link ?
|
||||
<p className="fl mt3 fwlz " style={{
|
||||
cursor:"auto"
|
||||
}}>外链</p>
|
||||
:
|
||||
""
|
||||
}
|
||||
|
||||
{discussMessage.is_publish === false ? <CoursesListType typelist={["未发布"]} typesylename={""}/> : ""}
|
||||
|
||||
{this.props.isAdmin ?
|
||||
<span className={"fr mt2"} onClick={(event) => this.eventStop(event)}>
|
||||
<WordsBtn style="blue" className="colorblue font-16 ml20 fr">
|
||||
<a className="btn colorblue fontweight400"
|
||||
onClick={() => this.settingList(bools)}>设置</a>
|
||||
</WordsBtn>
|
||||
</span> : ""}
|
||||
|
||||
{this.props.isStudent === true && this.props.current_user.login === discussMessage.author.login ?
|
||||
<span className={"fr mt2"} onClick={(event) => this.eventStop(event)}>
|
||||
|
||||
<WordsBtn style="blue" className="colorblue font-16 ml20 fr">
|
||||
<a className="btn colorblue fontweight400"
|
||||
onClick={() => this.settingList(bools)}>设置</a>
|
||||
</WordsBtn>
|
||||
|
||||
<WordsBtn style="blue" className="colorblue font-16 ml20 fr">
|
||||
<a className="btn colorblue fontweight400"
|
||||
onClick={() => this.onDelete(discussMessage.id)}>删除</a>
|
||||
</WordsBtn>
|
||||
|
||||
</span> : ""}
|
||||
</h6>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.sttingbox{
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 20px;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.lightgreybox{
|
||||
min-width: 260px;
|
||||
}
|
||||
.mrf2{
|
||||
margin-top: -2px;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
{/*资源分班*/}
|
||||
{/*{discussMessage.course_groups.length===0?"":*/}
|
||||
{/*<p className="color-grey panel-lightgrey mt8 fl lightgreybox ml30" style={{width:'100%'}}>*/}
|
||||
{/*{discussMessage.course_groups.map((item,key)=>{*/}
|
||||
{/*return(*/}
|
||||
{/*<div className="mr50">*/}
|
||||
{/*<span className="mr15 color-dark">{item.course_group_name}</span>*/}
|
||||
{/*<span className="mr15 color-grey9 ">将发布于 { moment(item.course_group_publish_time).format('YYYY-MM-DD HH:mm')}</span>*/}
|
||||
{/*</div>*/}
|
||||
{/*)*/}
|
||||
{/*})}*/}
|
||||
|
||||
{/*</p>}*/}
|
||||
|
||||
<p
|
||||
className={this.props.isAdmin === true ? "color-grey panel-lightgrey mt8 fl ml30" : "color-grey panel-lightgrey mt8 fl ml13"}
|
||||
style={{width: '100%'}}>
|
||||
<span className="mr50">
|
||||
<span className="mr15 color-dark">{discussMessage.author.name}</span>
|
||||
{
|
||||
bools ?
|
||||
<span className="mr15 color-grey9">大小 {discussMessage.filesize}</span>
|
||||
|
||||
:
|
||||
""
|
||||
}
|
||||
|
||||
{
|
||||
bools ?
|
||||
<span className="mr15 color-grey9">下载 {discussMessage.downloads_count}</span>
|
||||
:
|
||||
<span className="mr15 color-grey9">点击次数:{discussMessage.downloads_count}</span>
|
||||
|
||||
}
|
||||
{/*<span className="mr15 color-grey9">引用 {discussMessage.quotes}</span>*/}
|
||||
<span className="mr15 color-grey-c">
|
||||
{/*{moment(discussMessage.publish_time).format('YYYY-MM-DD HH:mm:ss')}*/}
|
||||
{/*{moment(discussMessage.publish_time).fromNow()}*/}
|
||||
{discussMessage.publish_time === null ? "" :
|
||||
discussMessage.is_publish === true ? "" : "发布于"}
|
||||
{discussMessage.publish_time === null ? "" : discussMessage.is_publish === true ? moment(discussMessage.publish_time).fromNow() : moment(discussMessage.publish_time).format('YYYY-MM-DD HH:mm')}
|
||||
</span>
|
||||
</span>
|
||||
{discussMessage && discussMessage.category_name === undefined||discussMessage && discussMessage.category_name === null ? "" :
|
||||
<div className="color-grey9 task-hide fr mr30" title={discussMessage && discussMessage.category_name}
|
||||
style={{display:'flex',"max-width": "300px"}}>所属目录:<div style={{display:discussMessage && discussMessage.parent_category_name === null ? "none":'block',"max-width": "150px",overflow: 'hidden',textOverflow:'ellipsis',whiteSpace: 'nowrap'}}>{discussMessage && discussMessage. parent_category_name}</div><div style={{display:discussMessage && discussMessage.parent_category_name === null ? "none":'block'}}>/</div><div style={{"max-width": "150px",overflow: 'hidden',textOverflow:'ellipsis',whiteSpace: 'nowrap'}}>{discussMessage && discussMessage.category_name}</div>
|
||||
</div>}
|
||||
</p>
|
||||
|
||||
|
||||
<p
|
||||
className={this.props.isAdmin === true ? "color-grey panel-lightgrey mt8 fl ml30" : "color-grey panel-lightgrey mt8 fl ml13"}
|
||||
style={{width: '94%'}}>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.isspans{
|
||||
text-align: left;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
<span
|
||||
className="color-dark isspans">资源描述 :{discussMessage.description === null ? "暂无描述" : discussMessage.description}</span>
|
||||
{/*<span className="mr50">*/}
|
||||
{/*/!*<span className="mr15 color-dark"></span>*!/*/}
|
||||
{/*<span className="mr15 color-dark">*/}
|
||||
|
||||
{/*</span>*/}
|
||||
{/*/!*{this.props.isAdmin ?<span><i className="iconfont icon-bianjidaibeijing font-22 color-green" onClick={()=>this.settingList()}></i></span>:""}*!/*/}
|
||||
{/*</span>*/}
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Fileslistitem;
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +0,0 @@
|
|||
|
||||
.indexdiv {
|
||||
background:#ffffff;
|
||||
}
|
||||
.indexdiv:hover {
|
||||
background:#ccc;
|
||||
}
|
|
@ -582,8 +582,8 @@ span.CodeMirror-selectedtext {
|
|||
}
|
||||
|
||||
|
||||
#root {
|
||||
background: rgb(250, 250, 250);
|
||||
body #root {
|
||||
background: #EAEBEC;
|
||||
}
|
||||
|
||||
.newedu-class-leftnav {
|
||||
|
|
|
@ -1,549 +0,0 @@
|
|||
import React,{ Component } from "react";
|
||||
import { Input,Checkbox,Table, Pagination, Modal,Menu, Tooltip,Spin,Button,Form,Row, Col } from "antd";
|
||||
import { WordsBtn,on, off, trigger,markdownToHTML,getImageUrl} from 'educoder';
|
||||
import './myysleduinforms.css'
|
||||
import axios from 'axios';
|
||||
import TPMMDEditor from "../../tpm/challengesnew/TPMMDEditor";
|
||||
import moment from "../new/CoursesNew";
|
||||
import Fileslistitem from "../Resource/Fileslistitem";
|
||||
import Modals from "../../modals/Modals";
|
||||
// 公告栏
|
||||
class Bullsubdirectory extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.messageRef = React.createRef();
|
||||
|
||||
this.state={
|
||||
description:null,
|
||||
isSpinysl:false,
|
||||
whethertoeditysl:false,
|
||||
addonAfter:0,
|
||||
eduintits:"",
|
||||
informs:[],
|
||||
Modalstype:false,
|
||||
Modalstopval:"是否确认删除?",
|
||||
ModalCancel:"",
|
||||
ModalSave:"",
|
||||
index:0,
|
||||
|
||||
}
|
||||
//不能显示数据编辑的时候没有赋值
|
||||
//没加initialValue 输入不能赋值到from 上
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// console.log("获取到数据");
|
||||
// console.log(this.props);
|
||||
let{id,myname,mydescription,index,item} =this.props
|
||||
this.props.form.setFieldsValue({
|
||||
id:id,
|
||||
eduintits:item.name,
|
||||
description:item.description,
|
||||
});
|
||||
// this.contentMdRef.current.setValue(mydescription);
|
||||
this.setState({
|
||||
id:id,
|
||||
eduintits:item.name,
|
||||
description:item.description,
|
||||
index:index
|
||||
})
|
||||
if(myname!=undefined){
|
||||
this.setState({
|
||||
addonAfter:myname.length
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setModeltrue=()=>{
|
||||
this.setState({
|
||||
Modalstype:true,
|
||||
Modalstopval:"是否确认删除?",
|
||||
ModalCancel:this.cancelmodel,
|
||||
ModalSave:this.saveonOpen,
|
||||
})
|
||||
}
|
||||
|
||||
cancelmodel=()=>{
|
||||
//取消
|
||||
this.setState({
|
||||
Modalstype:false,
|
||||
Modalstopval:"是否确认删除?",
|
||||
ModalCancel:"",
|
||||
ModalSave:"",
|
||||
})
|
||||
}
|
||||
|
||||
saveonOpen=()=>{
|
||||
//确认
|
||||
// /
|
||||
// 删除公告
|
||||
var id=this.props.match.params.coursesId
|
||||
const url =`/courses/${id}/delete_informs.json`;
|
||||
axios.delete(url, { data: {
|
||||
inform_id: this.props.id
|
||||
}})
|
||||
.then((response) => {
|
||||
if(response){
|
||||
if(response.data){
|
||||
if(response.data.status===0){
|
||||
this.setState({
|
||||
Modalstype:false,
|
||||
Modalstopval:"是否确认删除?",
|
||||
ModalCancel:"",
|
||||
ModalSave:"",
|
||||
})
|
||||
this.props.showNotification(`删除成功`);
|
||||
this.props.getinputdata();
|
||||
}else{
|
||||
this.props.showNotification(`删除失败`);
|
||||
}
|
||||
}else{
|
||||
this.props.showNotification(`删除失败`);
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
this.props.showNotification(`删除失败`);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
bianji = (bians,i)=>{
|
||||
console.log("bianji");
|
||||
console.log(this.props.myname);
|
||||
console.log(this.props.mydescription);
|
||||
this.setState({
|
||||
whethertoeditysl:bians,
|
||||
eduintits:this.props.myname,
|
||||
description:this.props.mydescription,
|
||||
index:i
|
||||
});
|
||||
this.props.form.setFieldsValue({
|
||||
eduintits:this.props.myname,
|
||||
description:this.props.mydescription,
|
||||
});
|
||||
if(bians===true){
|
||||
this.props.getyslbooltrue();
|
||||
}else {
|
||||
this.props.getyslboolfalse();
|
||||
}
|
||||
};
|
||||
changeTopicName = (e) => {
|
||||
// console.log("调用了changeTopicName");
|
||||
let num = e.target.value.length;
|
||||
|
||||
if(num>60){
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
addonAfter: num < 0 ? 0 : num
|
||||
});
|
||||
if(num<=60){
|
||||
this.setState({
|
||||
eduintits: e.target.value
|
||||
})
|
||||
|
||||
this.props.form.setFieldsValue({
|
||||
eduintits: e.target.value,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
handleSubmit=(e) => {
|
||||
e.preventDefault();
|
||||
this.props.form.validateFields((err, values) => {
|
||||
|
||||
if (!err) {
|
||||
console.log(values.description);
|
||||
if(values.eduintits === undefined|| values.eduintits === "" || values.eduintits ===null){
|
||||
this.props.showNotification(`请输入标题`);
|
||||
return
|
||||
|
||||
}
|
||||
if(values.description === undefined|| values.description === "" || values.description ===null){
|
||||
this.props.showNotification(`请输入内容`);
|
||||
return
|
||||
|
||||
}
|
||||
var id=this.props.match.params.coursesId
|
||||
var titname="";
|
||||
try {
|
||||
if(values.eduintits.length>0){
|
||||
if( values.eduintits.length>60){
|
||||
var str=values.eduintits;
|
||||
titname=str.substring(0,60);
|
||||
}else {
|
||||
titname=values.eduintits;
|
||||
}
|
||||
}else {
|
||||
titname=values.eduintits;
|
||||
}
|
||||
}catch (e) {
|
||||
titname=values.eduintits;
|
||||
}
|
||||
var url = `/courses/${id}/update_informs.json`;
|
||||
axios.post(url,{
|
||||
inform_id:this.props.id,
|
||||
name:titname,
|
||||
description:values.description,
|
||||
}).then((result) => {
|
||||
if(result){
|
||||
if(result.data){
|
||||
if(result.data.status === 0){
|
||||
// this.props.form.setFieldsValue({
|
||||
// id:this.state.id,
|
||||
// eduintits:titname,
|
||||
// description:values.description,
|
||||
// });
|
||||
this.setState({
|
||||
whethertoeditysl:false,
|
||||
id:this.state.id,
|
||||
eduintits:titname,
|
||||
description:values.description,
|
||||
});
|
||||
this.props.getinputdata();
|
||||
this.props.getyslboolfalse();
|
||||
this.props.showNotification(result.data.message);
|
||||
}else {
|
||||
this.props.showNotification(result.data.message);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}else{
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
//上移
|
||||
Moveupward = (id) => {
|
||||
let url = `/courses/${this.props.match.params.coursesId}/inform_up.json`;
|
||||
axios.post(url, {
|
||||
inform_id: id
|
||||
}).then((response) => {
|
||||
if (response) {
|
||||
if (response.data) {
|
||||
if (response.data.status === 0) {
|
||||
this.props.showNotification(`上移成功`);
|
||||
this.props.getinputdata();
|
||||
} else {
|
||||
this.props.showNotification(`上移失败`);
|
||||
}
|
||||
} else {
|
||||
this.props.showNotification(`上移失败`);
|
||||
}
|
||||
} else {
|
||||
this.props.showNotification(`上移失败`);
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
});
|
||||
}
|
||||
//下移
|
||||
Movedown = (id) => {
|
||||
let url = `/courses/${this.props.match.params.coursesId}/inform_down.json`;
|
||||
axios.post(url, {
|
||||
inform_id: id
|
||||
}).then((response) => {
|
||||
if (response) {
|
||||
if (response.data) {
|
||||
if (response.data.status === 0) {
|
||||
this.props.showNotification(`下移成功`);
|
||||
this.props.getinputdata();
|
||||
} else {
|
||||
this.props.showNotification(`下移失败`);
|
||||
}
|
||||
} else {
|
||||
this.props.showNotification(`下移失败`);
|
||||
}
|
||||
} else {
|
||||
this.props.showNotification(`下移失败`);
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
render(){
|
||||
let{description,whethertoeditysl,addonAfter,eduintits,informs,isSpinysl,index} =this.state;
|
||||
let{myname,mydescription,id}=this.props;
|
||||
const {getFieldDecorator} = this.props.form;
|
||||
// console.log("Bullsubdirectory");
|
||||
// console.log(this.props.isAdmin());
|
||||
// console.log(this.props);
|
||||
// console.log(whethertoeditysl);
|
||||
// console.log(this.state.eduintits);
|
||||
// console.log(this.state.description);
|
||||
|
||||
return(
|
||||
<React.Fragment key={this.props.index} id={this.props.id}>
|
||||
<div key={this.props.index} id={this.props.id}>
|
||||
{this.state.Modalstype&&this.state.Modalstype===true?<Modals
|
||||
modalsType={this.state.Modalstype}
|
||||
modalsTopval={this.state.Modalstopval}
|
||||
modalCancel={this.state.ModalCancel}
|
||||
modalSave={this.state.ModalSave}
|
||||
/>:""}
|
||||
<Spin size="large" spinning={isSpinysl} >
|
||||
<div className="edu-back-white " id={
|
||||
index
|
||||
}>
|
||||
{
|
||||
whethertoeditysl === false?
|
||||
<div id={this.props.index}>
|
||||
<div className="fudonyingxiangysls">
|
||||
<div className="fudonyingxiangysl">
|
||||
<div style={{marginRight:"60px"}}>
|
||||
<span className="ysltitbt">{myname}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="fr yslbianji" style={{marginRight:"17px"}}>
|
||||
{
|
||||
this.props.isAdmin() === true ?
|
||||
(this.props.yslbool===false?
|
||||
<Tooltip placement="bottom" title={<div>
|
||||
编辑
|
||||
</div>}>
|
||||
<i className="iconfont icon-bianji1 newbianji1" onClick={()=>this.bianji(true,this.props.index)}></i>
|
||||
</Tooltip>
|
||||
:
|
||||
""
|
||||
)
|
||||
:""
|
||||
}
|
||||
</span>
|
||||
<span className="fr yslbianji" style={{marginRight:"22px"}}>
|
||||
{
|
||||
this.props.isAdmin() === true ?
|
||||
(this.props.yslbool===false?
|
||||
<Tooltip placement="bottom" title={<div>
|
||||
删除
|
||||
</div>}>
|
||||
<i className="iconfont icon-shanchu newbianji1" style={{ color: "#4CACFF"}} onClick={()=>this.setModeltrue(true)}></i>
|
||||
</Tooltip>
|
||||
:
|
||||
""
|
||||
)
|
||||
:""
|
||||
}
|
||||
</span>
|
||||
{
|
||||
this.props.length - 1 === this.props.index ? "" :
|
||||
this.props.isAdmin() === true ?
|
||||
(this.props.yslbool === false ?
|
||||
<a className="fr yslbianji mr30"
|
||||
style={{
|
||||
lineHeight: "31px",
|
||||
}}
|
||||
onClick={() => this.Movedown(this.props.id)}
|
||||
><Tooltip
|
||||
title="下移"><i
|
||||
style={{color: "#4CACFF"}}
|
||||
className=" font-18 iconfont icon-xiangxiayi"></i></Tooltip></a>
|
||||
:
|
||||
""
|
||||
)
|
||||
: ""
|
||||
}
|
||||
{
|
||||
this.props.index === 0 ? "" :
|
||||
this.props.isAdmin() === true ?
|
||||
(this.props.yslbool === false ?
|
||||
<a className="fr yslbianji mr30"
|
||||
style={{
|
||||
lineHeight: "31px",
|
||||
}}
|
||||
onClick={() => this.Moveupward(this.props.id)}
|
||||
><Tooltip
|
||||
title="上移"><i
|
||||
style={{color: "#4CACFF"}}
|
||||
className=" font-18 iconfont icon-xiangshangyi"></i></Tooltip></a>
|
||||
:
|
||||
""
|
||||
)
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
<div className="yslclear"></div>
|
||||
</div>
|
||||
<div id="MakedownHTML"className="markdown-body fonttext yslmtopcg yslminHeigth markdownysltext" dangerouslySetInnerHTML={{__html: markdownToHTML(mydescription).replace(/▁/g, "▁▁▁")}}/>
|
||||
</div>
|
||||
{parseInt(this.props&&this.props.informs.length)===parseInt(this.props&&this.props.index+1)?"":<div className="bor-bottom-greyE mr25 ml25"></div>}
|
||||
</div>
|
||||
:
|
||||
whethertoeditysl === true?
|
||||
<div className="edu-back-white " key={this.props.index} id={this.props.id}>
|
||||
<Form layout='vertical' onSubmit={this.handleSubmit} key={this.props.index}>
|
||||
<style>
|
||||
{
|
||||
`.ant-form-item{
|
||||
margin-bottom:0px !important;
|
||||
}
|
||||
.chooseDestwo .ant-form-item{
|
||||
margin-bottom:0px !important;
|
||||
}
|
||||
|
||||
.chooseDestwo .ant-form-item-control-wrapper .ant-form-item-control .ant-form-explain{
|
||||
padding-left: 25px !important;
|
||||
}
|
||||
.ant-form-vertical .ant-form-item {
|
||||
margin-bottom:0px !important;
|
||||
}
|
||||
`
|
||||
|
||||
}
|
||||
</style>
|
||||
<Form.Item
|
||||
style={{"borderBottom":'none'}}
|
||||
className="chooseDestwo "
|
||||
key={this.props.index}
|
||||
>
|
||||
{getFieldDecorator('eduintits', { initialValue: eduintits}, {
|
||||
rules: [{
|
||||
required: true, message: '请在此输入标题,最多60个字符',
|
||||
}],
|
||||
})(
|
||||
<div className="ysleduinwh">
|
||||
<div className="yslduinlefts">
|
||||
<span className="yslduincolorred">*</span>
|
||||
</div>
|
||||
<div className="yslduinleft">
|
||||
<style>{
|
||||
`
|
||||
.ant-input{
|
||||
border-right: none !important;
|
||||
height: 40px !important;
|
||||
}
|
||||
`
|
||||
}</style>
|
||||
<Input placeholder="请在此输入标题,最多60个字符" key={this.props.index} maxLength="60"
|
||||
style={{ textAlign: "left",width:"100%",}}
|
||||
onInput={this.changeTopicName}
|
||||
autoComplete="off"
|
||||
addonAfter={String(addonAfter)+"/60"}
|
||||
value={eduintits}
|
||||
className="searchViewAfter"></Input>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
|
||||
<div className="edu-back-white " key={this.props.index}>
|
||||
<div className={"yslmt16px"}>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.ant-form-item-children {
|
||||
position: unset;
|
||||
}
|
||||
|
||||
.chooseDes .ant-form-item{
|
||||
margin-bottom:0px !important;
|
||||
}
|
||||
.rememberTip{
|
||||
position:absolute;
|
||||
right:0px;
|
||||
bottom:-10px;
|
||||
}
|
||||
.chooseDes .ant-form-explain{
|
||||
position:absolute;
|
||||
bottom:-10px;
|
||||
left:0px;
|
||||
}
|
||||
.ant-form-vertical .ant-form-explain {
|
||||
margin-top: 0px !important;
|
||||
margin-bottom: 0px !important;
|
||||
padding-left: 0px !important;
|
||||
}
|
||||
.chooseDes .ant-form-item-with-help {
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
|
||||
.courseMessageMD .ant-form-item-with-help {
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
.chooseDes .editormd-toolbar {
|
||||
width: 100%;
|
||||
min-height: 37px;
|
||||
background: #fff;
|
||||
display: none;
|
||||
position: absolute !important;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
border-bottom: 1px solid #ddd;
|
||||
|
||||
}
|
||||
.yslmt16px .ant-form-item-with-help
|
||||
{
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
<Form.Item
|
||||
style={{"borderBottom":'none'}}
|
||||
className="chooseDes "
|
||||
key={this.props.index}
|
||||
>
|
||||
{getFieldDecorator('description', { initialValue: description},{
|
||||
rules: [{
|
||||
required: true, message: '请在此输入内容,最多5000个字符',
|
||||
}, {
|
||||
len: 5000, message: '最大限制为5000个字符',
|
||||
}],
|
||||
})(
|
||||
<TPMMDEditor ref={this.messageRef}
|
||||
key={this.props.index}
|
||||
placeholder={'请在此输入内容,最多5000个字符'}
|
||||
initValue={description}
|
||||
mdID={'courseMessageMD'}
|
||||
className="courseMessageMD "
|
||||
height={518}
|
||||
></TPMMDEditor>
|
||||
|
||||
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Form.Item>
|
||||
<div className="clearfix mt28 fr pb50 mr25">
|
||||
<a className="defalutCancelbtn fl mr20 " onClick={()=>this.bianji(false,this.props.index)}>取消</a>
|
||||
<Button htmlType="submit" className="ant-btn defalutSubmitbtn fl ant-btn-primary">
|
||||
<span>提 交</span></Button>
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<div className="bor-bottom-greyE mr25 ml25"></div>
|
||||
</div>
|
||||
:""
|
||||
}
|
||||
</div>
|
||||
</Spin>
|
||||
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
const Bullsubdirectorys = Form.create({ name: 'bullsubdirectorys' })(Bullsubdirectory);
|
||||
export default Bullsubdirectorys;
|
|
@ -1,531 +0,0 @@
|
|||
import React,{ Component } from "react";
|
||||
import { Input,Checkbox,Table, Pagination, Modal,Menu, Tooltip,Spin,Button,Form } from "antd";
|
||||
import { WordsBtn,on, off, trigger,markdownToHTML,getImageUrl} from 'educoder';
|
||||
import './myysleduinforms.css'
|
||||
import axios from 'axios';
|
||||
import TPMMDEditor from "../../tpm/challengesnew/TPMMDEditor";
|
||||
import Bullsubdirectory from "./Bullsubdirectory";
|
||||
import NoneData from '../../../modules/courses/coursesPublic/NoneData'
|
||||
|
||||
import moment from "../new/CoursesNew";
|
||||
import Fileslistitem from "../Resource/Fileslistitem";
|
||||
// 公告栏
|
||||
// var isOnComposition = false;
|
||||
// const isChrome = !!window.chrome && !!window.chrome.webstore
|
||||
class Eduinforms extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.messageRef = React.createRef();
|
||||
|
||||
this.state={
|
||||
description:null,
|
||||
isSpin:true,
|
||||
whethertoedit:false,
|
||||
addonAfter:0,
|
||||
eduintits:"",
|
||||
informs:[],
|
||||
yslbool:false,
|
||||
dataquerys:{},
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// console.log("Eduinformss");
|
||||
// console.log("获取到数据");
|
||||
// console.log(this.props);
|
||||
const query = this.props.location.search;
|
||||
// const type = query.split('?chinaoocTimestamp=');
|
||||
// console.log("Eduinforms12345");
|
||||
// console.log(this.foo(query));
|
||||
// console.log(JSON.stringify(this.foo(query)));
|
||||
var dataqueryss={}
|
||||
try {
|
||||
var foqus=this.foo(query);
|
||||
if(JSON.stringify(foqus) ==="{}"){
|
||||
this.setState({
|
||||
dataquerys:{},
|
||||
});
|
||||
}else {
|
||||
this.setState({
|
||||
dataquerys:foqus,
|
||||
});
|
||||
dataqueryss=foqus;
|
||||
}
|
||||
}catch (e) {
|
||||
this.setState({
|
||||
dataquerys:{},
|
||||
})
|
||||
}
|
||||
this.getinputdatas(dataqueryss);
|
||||
}
|
||||
//截取数据
|
||||
foo=(url)=> {
|
||||
var json = {};
|
||||
var regExp = /[\?\&](\w+)(=?)(\w*)/g;
|
||||
var arr;
|
||||
do {
|
||||
arr = regExp.exec(url);
|
||||
// console.log(arr); // arr = [完整的字符串, key, 等号或'', value或'']
|
||||
|
||||
if (arr) {
|
||||
var key = arr[1];
|
||||
var value = arr[3];
|
||||
// arr[2] === ''时, value = undefined
|
||||
if (!arr[2])
|
||||
value = undefined;
|
||||
|
||||
json[key] = value;
|
||||
}
|
||||
} while (arr);
|
||||
|
||||
return json;
|
||||
}
|
||||
getyslbooltrue(){
|
||||
console.log("调用了getyslbooltrue");
|
||||
this.setState({
|
||||
yslbool:true,
|
||||
});
|
||||
}
|
||||
|
||||
getyslboolfalse(){
|
||||
console.log("调用了getyslboolfalse");
|
||||
this.setState({
|
||||
yslbool:false,
|
||||
});
|
||||
}
|
||||
getinputdata=()=>{
|
||||
this.setState({
|
||||
isSpin:true,
|
||||
})
|
||||
let url = `/courses/${this.props.match.params.coursesId}/informs.json`;
|
||||
//
|
||||
axios.get(url,
|
||||
{params:this.state.dataquerys}
|
||||
).then((response) => {
|
||||
if(response){
|
||||
if(response.data){
|
||||
this.setState({
|
||||
informs:response.data.informs,
|
||||
isSpin:false,
|
||||
})
|
||||
}else {
|
||||
this.setState({
|
||||
informs:[],
|
||||
isSpin:false,
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
}else {
|
||||
this.setState({
|
||||
informs:[],
|
||||
isSpin:false,
|
||||
})
|
||||
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
this.setState({
|
||||
informs:[],
|
||||
isSpin:false,
|
||||
})
|
||||
});
|
||||
}
|
||||
getinputdatas=(yslwebobject)=>{
|
||||
this.setState({
|
||||
isSpin:true,
|
||||
})
|
||||
let url = `/courses/${this.props.match.params.coursesId}/informs.json`;
|
||||
//
|
||||
axios.get(url,
|
||||
{params:yslwebobject}
|
||||
).then((response) => {
|
||||
if(response){
|
||||
if(response.data){
|
||||
this.setState({
|
||||
informs:response.data.informs,
|
||||
isSpin:false,
|
||||
})
|
||||
}else {
|
||||
this.setState({
|
||||
informs:[],
|
||||
isSpin:false,
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
}else {
|
||||
this.setState({
|
||||
informs:[],
|
||||
isSpin:false,
|
||||
})
|
||||
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
this.setState({
|
||||
informs:[],
|
||||
isSpin:false,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
componentDidUpdate = (prevProps) => {
|
||||
|
||||
|
||||
|
||||
}
|
||||
bianji = (bians)=>{
|
||||
this.setState({
|
||||
whethertoedit:bians,
|
||||
description:"",
|
||||
eduintits:"",
|
||||
addonAfter:0,
|
||||
});
|
||||
this.props.form.setFieldsValue({
|
||||
description:"",
|
||||
eduintits:"",
|
||||
});
|
||||
if(bians===true){
|
||||
this.getyslbooltrue();
|
||||
|
||||
}else {
|
||||
this.getyslboolfalse();
|
||||
}
|
||||
};
|
||||
changeTopicName = (e) => {
|
||||
// console.log("调用了changeTopicName");
|
||||
let num = e.target.value.length;
|
||||
if(num>60){
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
addonAfter: num < 0 ? 0 : num
|
||||
});
|
||||
if(num<=60){
|
||||
this.setState({
|
||||
eduintits: e.target.value
|
||||
})
|
||||
|
||||
this.props.form.setFieldsValue({
|
||||
eduintits: e.target.value,
|
||||
});
|
||||
}
|
||||
};
|
||||
// handleComposition=(e)=>{
|
||||
// if (e.type === 'compositionend') {
|
||||
// // composition is end
|
||||
// isOnComposition = false
|
||||
//
|
||||
// if (!isOnComposition && isChrome) {
|
||||
// // fire onChange
|
||||
// console.log(!isOnComposition);
|
||||
// this.changeTopicName(e);
|
||||
// }
|
||||
// } else {
|
||||
// // in composition
|
||||
// isOnComposition = true
|
||||
// }
|
||||
// };
|
||||
// handleComposition = (e) => {
|
||||
// console.log(e.type + ": " + e.target.value);
|
||||
// if (e.type === 'compositionend') {
|
||||
// // composition is end
|
||||
// const value = e.target.value;
|
||||
// this.setState({ isOnComposition: false },()=>{
|
||||
// // this.handleFixedChange(value);
|
||||
// });
|
||||
// } else {
|
||||
// // in composition
|
||||
// this.setState({ isOnComposition: true });
|
||||
// }
|
||||
// }
|
||||
handleSubmit=(e) => {
|
||||
e.preventDefault();
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
console.log(values.description);
|
||||
if(values.eduintits === undefined|| values.eduintits === "" || values.eduintits ===null){
|
||||
this.props.showNotification(`请输入标题`);
|
||||
return
|
||||
|
||||
}
|
||||
if(values.description === undefined|| values.description === "" || values.description ===null){
|
||||
this.props.showNotification(`请输入内容`);
|
||||
return
|
||||
|
||||
}
|
||||
var id=this.props.match.params.coursesId
|
||||
var titname="";
|
||||
try {
|
||||
if(values.eduintits.length>0){
|
||||
if( values.eduintits.length>60){
|
||||
var str=values.eduintits;
|
||||
titname=str.substring(0,60);
|
||||
}else {
|
||||
titname=values.eduintits;
|
||||
}
|
||||
}else {
|
||||
titname=values.eduintits;
|
||||
}
|
||||
}catch (e) {
|
||||
titname=values.eduintits;
|
||||
}
|
||||
var url = `/courses/${id}/new_informs.json`;
|
||||
axios.post(url,{
|
||||
name:titname,
|
||||
description:values.description,
|
||||
}).then((result) => {
|
||||
if(result){
|
||||
if(result.data){
|
||||
if(result.data.status === 0){
|
||||
this.setState({
|
||||
whethertoedit:false,
|
||||
|
||||
});
|
||||
this.getinputdata();
|
||||
this.getyslboolfalse();
|
||||
this.props.showNotification(result.data.message);
|
||||
}else {
|
||||
this.props.showNotification(result.data.message);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}else{
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
render(){
|
||||
let{description,whethertoedit,addonAfter,eduintits,informs,yslbool} =this.state;
|
||||
const {getFieldDecorator} = this.props.form;
|
||||
|
||||
return(
|
||||
<React.Fragment >
|
||||
<div id={"zhudiv"}>
|
||||
<div className="edu-back-white">
|
||||
<p className="clearfix padding30 bor-bottom-greyE yslmaxheigth80" >
|
||||
<p style={{height: '20px'}}>
|
||||
<span className="font-18 fl color-dark-21">公告栏</span>
|
||||
{
|
||||
this.props.isAdmin()===true?
|
||||
(this.state.yslbool===false?
|
||||
<li className="btn colorblue font-16 fr bluebkbk pointer"
|
||||
onClick={() => this.bianji(true)}>
|
||||
发布公告
|
||||
</li>
|
||||
:"")
|
||||
|
||||
:""
|
||||
}
|
||||
|
||||
</p>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<Spin size="large" spinning={this.state.isSpin} id={"cdiv"}>
|
||||
|
||||
<div id={"cdiv1"}>
|
||||
{
|
||||
whethertoedit === false?""
|
||||
:
|
||||
<div className="edu-back-white ">
|
||||
|
||||
|
||||
<Form layout='vertical' onSubmit={this.handleSubmit} >
|
||||
<style>
|
||||
{
|
||||
`.ant-form-item{
|
||||
margin-bottom:0px !important;
|
||||
}
|
||||
.chooseDestwo .ant-form-item{
|
||||
margin-bottom:0px !important;
|
||||
}
|
||||
|
||||
.chooseDestwo .ant-form-item-control-wrapper .ant-form-item-control .ant-form-explain{
|
||||
padding-left: 25px !important;
|
||||
}
|
||||
.ant-form-vertical .ant-form-item {
|
||||
margin-bottom:0px !important;
|
||||
}
|
||||
`
|
||||
|
||||
}
|
||||
</style>
|
||||
<Form.Item
|
||||
style={{"borderBottom":'none'}}
|
||||
className="chooseDestwo "
|
||||
>
|
||||
{getFieldDecorator('eduintits', {
|
||||
rules: [{
|
||||
required: true, message: '请在此输入标题,最多60个字符',
|
||||
}],
|
||||
})(
|
||||
<div className="ysleduinwh">
|
||||
<div className="yslduinlefts">
|
||||
<span className="yslduincolorred">*</span>
|
||||
</div>
|
||||
<div className="yslduinleft">
|
||||
<style>{
|
||||
`
|
||||
.ant-input{
|
||||
border-right: none !important;
|
||||
height: 40px !important;
|
||||
}
|
||||
`
|
||||
}</style>
|
||||
<Input placeholder="请在此输入标题,最多60个字符" maxLength={60}
|
||||
style={{ textAlign: "left",width:"100%",}}
|
||||
onInput={this.changeTopicName}
|
||||
autoComplete="off"
|
||||
addonAfter={String(addonAfter)+"/60"}
|
||||
value={eduintits}
|
||||
className="searchViewAfter"></Input>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
|
||||
<div className="edu-back-white ">
|
||||
<div className={"yslmt16px"}>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.ant-form-item-children {
|
||||
position: unset;
|
||||
}
|
||||
|
||||
.chooseDes .ant-form-item{
|
||||
margin-bottom:0px !important;
|
||||
}
|
||||
.rememberTip{
|
||||
position:absolute;
|
||||
right:0px;
|
||||
bottom:-10px;
|
||||
}
|
||||
.chooseDes .ant-form-explain{
|
||||
position:absolute;
|
||||
bottom:-10px;
|
||||
left:0px;
|
||||
}
|
||||
.ant-form-vertical .ant-form-explain {
|
||||
margin-top: 0px !important;
|
||||
margin-bottom: 0px !important;
|
||||
padding-left: 0px !important;
|
||||
}
|
||||
.chooseDes .ant-form-item-with-help {
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
|
||||
.courseMessageMD .ant-form-item-with-help {
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
.chooseDes .editormd-toolbar {
|
||||
width: 100%;
|
||||
min-height: 37px;
|
||||
background: #fff;
|
||||
display: none;
|
||||
position: absolute !important;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
border-bottom: 1px solid #ddd;
|
||||
|
||||
}
|
||||
.yslmt16px .ant-form-item-with-help
|
||||
{
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
<Form.Item
|
||||
style={{"borderBottom":'none'}}
|
||||
className="chooseDes "
|
||||
>
|
||||
{getFieldDecorator('description', {
|
||||
rules: [{
|
||||
required: true, message: '请在此输入内容,最多5000个字符',
|
||||
}, {
|
||||
max: 5000, message: '最大限制为5000个字符',
|
||||
}],
|
||||
})(
|
||||
<TPMMDEditor ref={this.messageRef}
|
||||
placeholder={'请在此输入内容,最多5000个字符'}
|
||||
initValue={description}
|
||||
mdID={'courseMessageMD'}
|
||||
className="courseMessageMD "
|
||||
height={518}
|
||||
></TPMMDEditor>
|
||||
)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Form.Item>
|
||||
<div className="clearfix mt28 fr pb50 mr25" >
|
||||
<a className="defalutCancelbtn fl mr20 " onClick={()=>this.bianji(false)}>取消</a>
|
||||
<Button htmlType="submit" className="ant-btn defalutSubmitbtn fl ant-btn-primary">
|
||||
<span>提 交</span></Button>
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<div className="bor-bottom-greyE mr25 ml25"></div>
|
||||
</div>
|
||||
}
|
||||
<div>
|
||||
{
|
||||
informs === null || informs=== undefined ||informs.length === 0 ?
|
||||
this.state.yslbool===false?
|
||||
<NoneData></NoneData>
|
||||
:""
|
||||
:
|
||||
|
||||
<div className="edu-back-white ">
|
||||
{/*公告栏底部*/}
|
||||
{ informs&&informs.map((item, index) => {
|
||||
return (
|
||||
<Bullsubdirectory {...this.state} {...this.props} key={index} index={index}
|
||||
length={informs.length} yslbool={yslbool} id={item.id}
|
||||
myname={item.name} mydescription={item.description}
|
||||
item={item}
|
||||
getyslbooltrue={()=>this.getyslbooltrue()}
|
||||
getyslboolfalse={()=>this.getyslboolfalse()}
|
||||
getinputdata={()=>this.getinputdata()} ></Bullsubdirectory>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</Spin>
|
||||
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
const Eduinformss = Form.create({ name: 'eduinforms' })(Eduinforms);
|
||||
export default Eduinformss;
|
||||
{/*<div key={index} className="bor-bottom-greyE" >*/}
|
||||
{/* {item.name===""?"":item.name===undefined?"":item.name===null?"":<div className="ysltitbt"><span >{item.name}</span></div>}*/}
|
||||
{/* <div id="MakedownHTML" key={index} className={"markdown-body fonttext yslmtopcg yslminHeigth markdownysltext"} dangerouslySetInnerHTML={{__html: markdownToHTML(item.description).replace(/▁/g, "▁▁▁")}}/>*/}
|
||||
{/*</div>*/}
|
|
@ -1,93 +0,0 @@
|
|||
.yslmt16px{
|
||||
padding-top: 12px !important;
|
||||
padding-left: 25px !important;
|
||||
padding-right: 25px !important;
|
||||
padding-bottom: 1px !important;
|
||||
}
|
||||
|
||||
.yslmtopcg
|
||||
{
|
||||
padding: 25px !important;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.bluebkbk{
|
||||
border: 1px solid #4CADFF;
|
||||
width: 79px;
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.ysleduinwh{
|
||||
|
||||
padding-right: 25px;
|
||||
margin-top: 26px;
|
||||
display: flex;
|
||||
justify-content:flex-start;
|
||||
}
|
||||
.yslduincolorred{
|
||||
color: red;
|
||||
line-height: 40px;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
.yslduinleft{
|
||||
width: 100% ;
|
||||
}
|
||||
.yslduinlefts{
|
||||
width: 25px;
|
||||
line-height: 40px;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
.mtyslduin25{
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.newbianji1{
|
||||
font-size: 16px !important;
|
||||
margin-right: 10px;
|
||||
color: #4CACFF;
|
||||
margin-bottom: 3px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.ysltitbt{
|
||||
float: left;
|
||||
padding-top: 28px;
|
||||
padding-left: 25px;
|
||||
font-size: 21px;
|
||||
color: #05101a;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
max-width: 805px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
}
|
||||
.markdownysltext{
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
}
|
||||
.fudonyingxiangysl{
|
||||
width: 100%;
|
||||
}
|
||||
.fudonyingxiangysls{
|
||||
display: flex;
|
||||
flex-direction:column;
|
||||
}
|
||||
.yslbianji{
|
||||
padding-top: 31px;
|
||||
|
||||
}
|
||||
.yslmaxheigth80{
|
||||
max-height: 80px;
|
||||
}
|
||||
.ysldashed{
|
||||
border:1px dashed #EEE;
|
||||
}
|
||||
.yslclear{ clear: both;
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
import React, { useState, useEffect, memo } from 'react'
|
||||
import { trigger, WordsBtn } from 'educoder'
|
||||
import { Input, Checkbox, Popconfirm } from "antd";
|
||||
import axios from 'axios'
|
||||
|
||||
/**
|
||||
角色数组, CREATOR: 创建者, PROFESSOR: 教师, ASSISTANT_PROFESSOR: 助教, STUDENT: 学生
|
||||
*/
|
||||
function ChangeRolePop({ member_roles = [], record, courseId, onChangeRoleSuccess, showNotification, getUserId, fetchUser, style }) {
|
||||
const [checkBoxRoles, setCheckBoxRoles] = useState(member_roles)
|
||||
// useEffect(() => {
|
||||
// if (checkBoxRoles.length != member_roles.length) { // 死循环
|
||||
// setCheckBoxRoles(member_roles)
|
||||
// }
|
||||
// }, [member_roles])
|
||||
function onCheckBoxChange(val) {
|
||||
console.log(val)
|
||||
|
||||
const isTeacher = checkBoxRoles.indexOf('PROFESSOR')
|
||||
const isAssitant = checkBoxRoles.indexOf('ASSISTANT_PROFESSOR')
|
||||
const isTeacherNew = val.indexOf('PROFESSOR')
|
||||
const isAssitantNew = val.indexOf('ASSISTANT_PROFESSOR')
|
||||
if (isTeacherNew > -1 && isTeacher == -1 && isAssitantNew > -1) {
|
||||
val.splice(isAssitantNew, 1)
|
||||
}
|
||||
if (isAssitantNew > -1 && isAssitant == -1 && isTeacherNew > -1) {
|
||||
val.splice(isTeacherNew, 1)
|
||||
}
|
||||
|
||||
setCheckBoxRoles(val)
|
||||
}
|
||||
function onCancel() {
|
||||
setCheckBoxRoles(member_roles)
|
||||
}
|
||||
const onConfirm = async () => {
|
||||
if (checkBoxRoles && checkBoxRoles.length == 0) {
|
||||
showNotification('请至少选择一个角色');
|
||||
setCheckBoxRoles(member_roles);
|
||||
return;
|
||||
}
|
||||
const url = `/courses/${courseId}/change_member_role.json`
|
||||
const response = await axios.post(url, {
|
||||
roles: checkBoxRoles,
|
||||
user_id: record.user_id
|
||||
})
|
||||
if (response.data.status == 0) {
|
||||
showNotification('保存成功')
|
||||
onChangeRoleSuccess()
|
||||
|
||||
trigger('updatabanner')
|
||||
if (fetchUser && record.user_id == getUserId) {
|
||||
fetchUser()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
const isAdmin = checkBoxRoles.indexOf('CREATOR') != -1
|
||||
const isTeacher = checkBoxRoles.indexOf('PROFESSOR') != -1
|
||||
const isAssitant = checkBoxRoles.indexOf('ASSISTANT_PROFESSOR') != -1
|
||||
const isStudent = checkBoxRoles.indexOf('STUDENT') != -1
|
||||
return (
|
||||
<Popconfirm
|
||||
overlayClassName="changeRolePop"
|
||||
placement="bottom"
|
||||
icon={null}
|
||||
onConfirm={onConfirm}
|
||||
onCancel={onCancel}
|
||||
title={
|
||||
<Checkbox.Group style={{ width: '100%' }} onChange={onCheckBoxChange} value={checkBoxRoles}>
|
||||
{isAdmin && <Checkbox disabled={isAdmin} value="CREATOR">管理员</Checkbox>}
|
||||
{!isAdmin && <Checkbox value="PROFESSOR">教师</Checkbox>}
|
||||
<Checkbox disabled={isAdmin} value="ASSISTANT_PROFESSOR">助教</Checkbox>
|
||||
<Checkbox value="STUDENT">学生</Checkbox>
|
||||
</Checkbox.Group>
|
||||
}
|
||||
>
|
||||
<WordsBtn style={'blue'} style2={style}>修改角色</WordsBtn>
|
||||
</Popconfirm>
|
||||
)
|
||||
}
|
||||
export default memo(ChangeRolePop)
|
|
@ -1,98 +0,0 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import { trigger } from 'educoder'
|
||||
import { Input, Checkbox } from "antd";
|
||||
|
||||
/**
|
||||
arg_course_groups 选中的id数组
|
||||
joinCourseGroup 选中时触发 joinCourseGroup(checkedValues, item, index) 传入item:数据对象,index: 数据对象index
|
||||
checkAllValue 是否全选
|
||||
onCheckAllChange 全选 onCheckAllChange(e, item, index)
|
||||
course_groups 所有的group
|
||||
|
||||
*/
|
||||
function CourseGroupChooser({ course_groups, isAdminOrCreator = true, item, index, arg_course_groups, checkAllValue, alwaysShow
|
||||
, onCheckAllChange, joinCourseGroup }) {
|
||||
const [state, setState] = useState({ counter: 0 })
|
||||
const [search, setSearch] = useState('')
|
||||
// useEffect(() => {
|
||||
// console.log(' cdm')
|
||||
// return () => {
|
||||
// console.log(' cwum')
|
||||
// };
|
||||
// // , [state.counter] 加了这个后,onClick就消失了 加错位置了?
|
||||
// }, [state.counter] )
|
||||
// TODO 为什么每次onClick都会执行 cwum
|
||||
|
||||
// const add1ToCounter = () => {
|
||||
// const newCounterValue = state.counter + 1
|
||||
// setState({ counter: newCounterValue })
|
||||
// }
|
||||
|
||||
/**
|
||||
that.state.groupSearchValue
|
||||
that.setState({groupSearchValue: e.target.value})
|
||||
|
||||
that.onCheckAllChange(e, item, index) - onCheckAllChange(e, item, index)
|
||||
that.joinCourseGroup(checkedValues, item, index) - joinCourseGroup(checkedValues, item, index)
|
||||
|
||||
that.state.checkAllArray[index] - checkAllValue
|
||||
*/
|
||||
|
||||
// console.log('arg_course_groups', arg_course_groups)
|
||||
|
||||
|
||||
const urlStyle = { "left": "unset", minWidth: '262px' };
|
||||
if (alwaysShow == true) {
|
||||
urlStyle.display = 'block'
|
||||
}
|
||||
return (
|
||||
<ul className="drop_down_menu" style={urlStyle}>
|
||||
{
|
||||
course_groups && course_groups.length > 10 ?
|
||||
(<p className="drop_down_search">
|
||||
<Input placeholder="搜索" value={search} onChange={(e) => { setSearch(e.target.value) }} allowClear />
|
||||
</p>) :
|
||||
''
|
||||
}
|
||||
|
||||
<Checkbox.Group onChange={(checkedValues) => joinCourseGroup(checkedValues, item, index)}
|
||||
value={arg_course_groups.length && arg_course_groups[0].id ? arg_course_groups.map(item => item.id) : arg_course_groups}
|
||||
disabled={!isAdminOrCreator} className="mainGroup"
|
||||
>
|
||||
{course_groups && course_groups.length > 1 && <li key={'_all' + index} >
|
||||
{/* 防止被外面group包裹 */}
|
||||
<Checkbox.Group onChange={(e) => onCheckAllChange(e, item, index)} value={[checkAllValue]}>
|
||||
<Checkbox
|
||||
value={true}
|
||||
disabled={!isAdminOrCreator}
|
||||
style={{ marginRight: '6px' }} onClick={() => { }}
|
||||
>全选</Checkbox>
|
||||
</Checkbox.Group>
|
||||
</li>}
|
||||
{
|
||||
course_groups && course_groups.filter((item) => {
|
||||
return (!search || item.name.indexOf(search) != -1)
|
||||
}).map((item, key) => {
|
||||
return (
|
||||
<li key={item.id} value={item.id} >
|
||||
<Checkbox value={item.id}
|
||||
key={item.id}
|
||||
id={`check${item.id}`}
|
||||
style={{ marginRight: '6px' }}
|
||||
></Checkbox>
|
||||
<label for={`check${item.id}`}>{item.name}</label>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
</Checkbox.Group>
|
||||
<p className="drop_down_btn">
|
||||
<a className="color-grey-6"
|
||||
onClick={() => trigger('groupAdd')}
|
||||
>新建分班</a>
|
||||
</p>
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
export default CourseGroupChooser
|
|
@ -1,246 +0,0 @@
|
|||
// 分班列表 加入分班
|
||||
|
||||
import React, { useState, useEffect, useRef } from 'react'
|
||||
|
||||
import { Input,Checkbox,Table, Pagination, Modal,Menu ,Spin, Tooltip , Divider, Popconfirm } from "antd";
|
||||
import ClipboardJS from 'clipboard'
|
||||
import axios from 'axios'
|
||||
import _ from 'lodash'
|
||||
|
||||
import '../css/Courses.css'
|
||||
import '../css/members.css'
|
||||
|
||||
import CourseLayoutcomponent from '../common/CourseLayoutComponent'
|
||||
import Titlesearchsection from '../common/titleSearch/TitleSearchSection'
|
||||
import ColorCountText from '../common/titleSearch/ColorCountText'
|
||||
|
||||
import { WordsBtn, trigger, on, off, getUrl, downloadFile , getRandomcode, NoneData } from 'educoder'
|
||||
import Modals from "../../modals/Modals";
|
||||
|
||||
import DownloadMessageysl from "../../modals/DownloadMessageysl";
|
||||
import CreateGroupByImportModal from './modal/CreateGroupByImportModal'
|
||||
import ChangeRolePop from './ChangeRolePop'
|
||||
import CourseGroupListTable from './CourseGroupListTable'
|
||||
|
||||
import './studentsList.css'
|
||||
/**
|
||||
角色数组, CREATOR: 创建者, PROFESSOR: 教师, ASSISTANT_PROFESSOR: 助教, STUDENT: 学生
|
||||
*/
|
||||
function CourseGroupList(props) {
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const [valueFlag,setValueFlag] = useState(false);
|
||||
const [isSpin, setIsSpin] = useState(true)
|
||||
|
||||
const [DownloadType, setDownloadType] = useState()
|
||||
const [DownloadMessageval, setDownloadMessageval] = useState()
|
||||
|
||||
const [listRes, setListRes] = useState({})
|
||||
const createGroupModalEl = useRef(null);
|
||||
|
||||
const courseId = props.match.params.coursesId
|
||||
|
||||
useEffect(() => {
|
||||
fetchAll()
|
||||
on('updateNavSuccess', onOperationSuccess)
|
||||
return () => {
|
||||
off('updateNavSuccess', onOperationSuccess)
|
||||
}
|
||||
}, [valueFlag])
|
||||
function onOperationSuccess() {
|
||||
fetchAll()
|
||||
props.updataleftNavfun()
|
||||
}
|
||||
async function fetchAll() {
|
||||
const url = `/courses/${courseId}/course_groups.json`;
|
||||
setIsSpin(true);
|
||||
const response = await axios.get(url, { params: {
|
||||
search: searchValue
|
||||
}});
|
||||
|
||||
setIsSpin(false)
|
||||
if (response) {
|
||||
setListRes(response.data)
|
||||
}
|
||||
}
|
||||
const onConfirm = async () => {
|
||||
}
|
||||
|
||||
function createGroupImportSuccess() {
|
||||
|
||||
}
|
||||
function addDir() {
|
||||
trigger('groupAdd', props.coursesids)
|
||||
}
|
||||
function deleteDir() {
|
||||
|
||||
}
|
||||
function onPressEnter(value) {
|
||||
setSearchValue(value);
|
||||
setValueFlag(!valueFlag);
|
||||
// fetchAll();
|
||||
}
|
||||
function onInputSearchChange(e) {
|
||||
setSearchValue(e.target.value)
|
||||
}
|
||||
function Downloadcal() {
|
||||
|
||||
}
|
||||
const confirmysl = (url) => {
|
||||
axios.get(url + '&export=true').then((response) => {
|
||||
if(response === undefined){
|
||||
return
|
||||
}
|
||||
if(response.data.status&&response.data.status===-1){
|
||||
|
||||
}else if(response.data.status&&response.data.status===-2){
|
||||
if(response.data.message === "100"){
|
||||
// 已超出文件导出的上限数量(100 ),建议:
|
||||
setDownloadType(true)
|
||||
setDownloadMessageval(100)
|
||||
}else {
|
||||
//因附件资料超过500M
|
||||
setDownloadType(true)
|
||||
setDownloadMessageval(500)
|
||||
}
|
||||
}else {
|
||||
props.slowDownload(getRandomcode(url))
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
});
|
||||
}
|
||||
|
||||
const isAdmin = props.isAdmin();
|
||||
const isSuperAdmin = props.isSuperAdmin();
|
||||
const isParent = true;
|
||||
// const searchValue = '';
|
||||
const isCourseEnd= props.isCourseEnd();
|
||||
|
||||
const course_group_id= '';
|
||||
|
||||
|
||||
const total_count = listRes.group_count;
|
||||
const none_group_member_count = listRes.none_group_member_count;
|
||||
const course_groups = listRes.course_groups
|
||||
const current_group_id = listRes.current_group_id
|
||||
|
||||
let exportUrl = `/courses/${courseId}/export_member_scores_excel.xlsx`; //总成绩
|
||||
let exportUrltwo = `/courses/${courseId}/export_couser_info.xlsx`; //课堂信息
|
||||
let exportUrlthree = `/courses/${courseId}/export_member_act_score.xlsx`; //活跃度
|
||||
return (
|
||||
<React.Fragment>
|
||||
<DownloadMessageysl
|
||||
{...props}
|
||||
value={DownloadMessageval}
|
||||
modalCancel={Downloadcal}
|
||||
modalsType={DownloadType}
|
||||
/>
|
||||
<Titlesearchsection
|
||||
title={
|
||||
<ul className="course_publicNav">
|
||||
<li className="active">分班列表</li>
|
||||
<li onClick={() => {props.history.push(`/classrooms/${courseId}/course_groups/0`)}}>未分班</li>
|
||||
</ul>
|
||||
}
|
||||
searchValue={ searchValue }
|
||||
onInputSearchChange={onInputSearchChange}
|
||||
allowClearonChange={onInputSearchChange}
|
||||
showSearchInput={total_count >= 10}
|
||||
searchPlaceholder={ '请输入分班名称进行搜索' }
|
||||
firstRowRight={
|
||||
<React.Fragment>
|
||||
{ // pageType !== TYPE_STUDENTS &&
|
||||
isSuperAdmin && <React.Fragment>
|
||||
{/* ref="createGroupByImportModal" */}
|
||||
<CreateGroupByImportModal {...props}
|
||||
ref={createGroupModalEl}
|
||||
createGroupImportSuccess={createGroupImportSuccess}
|
||||
></CreateGroupByImportModal>
|
||||
{/* this.refs['createGroupByImportModal'].setVisible(true) */}
|
||||
<WordsBtn style="blue" className="mr30" onClick={()=> {createGroupModalEl.current.setVisible(true)}}>导入创建分班</WordsBtn>
|
||||
</React.Fragment> }
|
||||
{
|
||||
// pageType !== TYPE_STUDENTS &&
|
||||
!isCourseEnd && isAdmin && <WordsBtn style="blue" className="mr30" onClick={()=>addDir()}>新建分班</WordsBtn> }
|
||||
{/* {
|
||||
isAdmin && !isParent && course_group_id != 0 && <WordsBtn style="blue" className="mr30" onClick={()=>deleteDir()}>删除分班</WordsBtn> } */}
|
||||
{/* {
|
||||
isAdmin && !isParent && course_group_id != 0 && <WordsBtn style="blue" className="mr30" onClick={()=>this.renameDir()}>分班重命名</WordsBtn> } */}
|
||||
<style>{`
|
||||
.drop_down_menu li a {
|
||||
padding: 0px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.drop_down_menu {
|
||||
/*width: 93px;*/
|
||||
}
|
||||
.drop_down_menu li {
|
||||
width:100%;
|
||||
box-sizing:boder-box;
|
||||
float:unset;
|
||||
line-height:30px!important;
|
||||
flex: 0 0 30px;
|
||||
}
|
||||
.drop_down_menu, .drop_down_normal {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
.drop_down_menu .drop_down_btn{
|
||||
border-top:none;
|
||||
}
|
||||
.dividerStyle.ant-divider-horizontal{
|
||||
margin: 0px;
|
||||
}
|
||||
.courseGroupList .ant-table-tbody tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
`}</style>
|
||||
{ isAdmin &&
|
||||
<li className="li_line drop_down fr color-blue font-16">
|
||||
导出<i className="iconfont icon-xiajiantou font-12 ml2"></i>
|
||||
<ul className="drop_down_menu" style={{"right": "-20px", "left": "unset", "height": "auto"}}>
|
||||
<li><a
|
||||
onClick={(i) => confirmysl(exportUrltwo)}>课堂信息</a>
|
||||
</li>
|
||||
<li><a
|
||||
onClick={(i) => confirmysl(exportUrlthree)}>活跃度</a>
|
||||
</li>
|
||||
<li><a
|
||||
onClick={(i) => confirmysl(exportUrl)}>总成绩</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
}
|
||||
</React.Fragment>
|
||||
}
|
||||
secondRowLeft={
|
||||
total_count ? <ColorCountText count={total_count} name="个分班"></ColorCountText> : ''
|
||||
}
|
||||
onPressEnter={onPressEnter}
|
||||
></Titlesearchsection>
|
||||
|
||||
{/* {!!none_group_member_count && <div className="mt20 E9F8FF padding20-30 pointer" onClick={() => {props.history.push(`/classrooms/${courseId}/course_groups/0`)}}>
|
||||
<span>未分班:</span>
|
||||
<span style={{color: '#999999'}}>{none_group_member_count}个学生</span>
|
||||
|
||||
<WordsBtn style="blue" className="fr">查看</WordsBtn>
|
||||
</div>} */}
|
||||
|
||||
<Spin size="large" spinning={isSpin}>
|
||||
{course_groups && !!course_groups.length ?
|
||||
<div className="mt20 edu-back-white padding20 courseGroupList">
|
||||
|
||||
<CourseGroupListTable
|
||||
course_groups={course_groups}
|
||||
onOperationSuccess={onOperationSuccess}
|
||||
current_group_id={current_group_id}
|
||||
{...props}
|
||||
></CourseGroupListTable>
|
||||
|
||||
</div>:
|
||||
<NoneData></NoneData>}
|
||||
</Spin>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
export default CourseGroupList
|
|
@ -1,280 +0,0 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
|
||||
import { Input,Checkbox,Table, Pagination, Modal,Menu ,Spin, Tooltip , Badge, Popconfirm, Result } from "antd";
|
||||
import axios from 'axios'
|
||||
|
||||
import { WordsBtn, trigger, on, off, getUrl, downloadFile , sortDirections } from 'educoder'
|
||||
import ClipboardJS from 'clipboard'
|
||||
import './studentsList.css';
|
||||
/**
|
||||
角色数组, CREATOR: 创建者, PROFESSOR: 教师, ASSISTANT_PROFESSOR: 助教, STUDENT: 学生
|
||||
course_members_count: 0
|
||||
id: 2441
|
||||
invite_code: "WUNX9K"
|
||||
member_manager: "全部教师"
|
||||
name: "e'e'e"
|
||||
*/
|
||||
|
||||
const clipboardMap = {}
|
||||
function CourseGroupListTable(props) {
|
||||
const [serachValue, setSerachValue] = useState('')
|
||||
|
||||
const courseId = props.match.params.coursesId
|
||||
|
||||
useEffect(() => {
|
||||
const course_groups = props.course_groups
|
||||
if (!course_groups) {
|
||||
return;
|
||||
}
|
||||
course_groups.forEach((record) => {
|
||||
const id = record.id
|
||||
let _clipboard = new ClipboardJS(`.copyBtn_${id}`);
|
||||
_clipboard.on('success', (e) => {
|
||||
props.showNotification('复制成功')
|
||||
});
|
||||
clipboardMap[id] = _clipboard
|
||||
})
|
||||
return () => {
|
||||
course_groups.forEach((record) => {
|
||||
const id = record.id
|
||||
|
||||
if (clipboardMap[id]) {
|
||||
clipboardMap[id].destroy();
|
||||
clipboardMap[id] = null;
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [props.course_groups])
|
||||
function buildColumns() {
|
||||
const columns=[{
|
||||
title: '序号',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
align:'center',
|
||||
width:"5%",
|
||||
className:"color-grey-6",
|
||||
render: (id, record, index) => {
|
||||
return index + 1
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '分班名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
align:'center',
|
||||
width:"25%",
|
||||
className:"color-grey-6",
|
||||
render: (name, record, index) => {
|
||||
return <WordsBtn title={name.length > 11 ? name : ''} onClick={() => onGoDetail(record)} style={''}
|
||||
className="overflowHidden1 color-dark" style2={{maxWidth: '180px', verticalAlign: 'bottom'}}>
|
||||
{name}</WordsBtn>
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
title: '学生成员',
|
||||
dataIndex: 'course_members_count',
|
||||
key: 'course_members_count',
|
||||
align:'center',
|
||||
width:"8%",
|
||||
className:"color-grey-6",
|
||||
render: (course_members_count, record, index) => {
|
||||
return course_members_count
|
||||
}
|
||||
}
|
||||
];
|
||||
if (!isNotMember) {
|
||||
columns.push({
|
||||
title: '管理教师',
|
||||
dataIndex: 'member_manager',
|
||||
key: 'member_manager',
|
||||
align:'center',
|
||||
width:"27%",
|
||||
className:"color-grey-6",
|
||||
render: (member_manager, record, index) => {
|
||||
// 加title 文本太长会出现卡死 https://www.trustie.net/issues/24950
|
||||
// title={record.subStringOfMember_manager ? member_manager : ''}
|
||||
return <span className=""
|
||||
>{record.subStringOfMember_manager || member_manager}</span>
|
||||
}
|
||||
})
|
||||
const aCol = (isAdmin ? {
|
||||
title: '邀请码',
|
||||
dataIndex: 'invite_code',
|
||||
key: 'invite_code',
|
||||
align:'center',
|
||||
width:"21%",
|
||||
className:"color-grey-6",
|
||||
render: (invite_code, record, index) => {
|
||||
return <React.Fragment>
|
||||
<span>{invite_code}</span>
|
||||
{
|
||||
record.edit_auth ?
|
||||
<span onClick={()=>changeInviteCode(record.id,record.invite_code_halt)} className={record.invite_code_halt ?"codeBtnStyle codeBtn_green ml10":"codeBtnStyle codeBtn_blue ml10"}>
|
||||
{record.invite_code_halt ?"启用":"停用"}
|
||||
</span>
|
||||
:""
|
||||
}
|
||||
{isAdmin && !record.invite_code_halt &&
|
||||
<Tooltip title={
|
||||
<div>
|
||||
<div>成员可以通过邀请码主动加入分班</div>
|
||||
<div>点击复制邀请码</div>
|
||||
</div>
|
||||
}>
|
||||
<WordsBtn data-clipboard-text={record.invite_code}
|
||||
className={`copyBtn_${record.id} codeBtnStyle codeBtn_yellow ml10`} style={''}>复制</WordsBtn>
|
||||
</Tooltip>
|
||||
}
|
||||
</React.Fragment>
|
||||
}
|
||||
} : {
|
||||
title: '你当前所在分班',
|
||||
dataIndex: 'group',
|
||||
key: 'group',
|
||||
align:'center',
|
||||
width:"20%",
|
||||
className:"color-grey-6",
|
||||
render: (invite_code, record, index) => {
|
||||
return props.current_group_id == record.id && <Badge status="processing" text="" />
|
||||
}
|
||||
})
|
||||
columns.push( aCol );
|
||||
}
|
||||
|
||||
columns.push({
|
||||
title: '操作',
|
||||
dataIndex: 'setting',
|
||||
key: 'setting',
|
||||
align:'center',
|
||||
width:"14%",
|
||||
className:"color-grey-6",
|
||||
render: (none, record, index) => {
|
||||
return <React.Fragment>
|
||||
{!isCourseEnd && isAdmin && <WordsBtn style2={{ marginRight: '12px' }} onClick={() => onDelete(record)} style={'grey'}>删除分班</WordsBtn>}
|
||||
|
||||
{isStudent && <WordsBtn style2={{ marginRight: '12px' }} onClick={() => addToDir(record)} style={''}>加入分班</WordsBtn>}
|
||||
<WordsBtn onClick={() => onGoDetail(record)} style={''} className="color-dark">查看</WordsBtn>
|
||||
</React.Fragment>
|
||||
}
|
||||
})
|
||||
|
||||
return columns
|
||||
}
|
||||
const doAddToDir = async (record) => {
|
||||
const courseId = props.match.params.coursesId
|
||||
const url = `/courses/${courseId}/join_course_group.json`
|
||||
const course_group_id = record.id
|
||||
|
||||
const response = await axios.post(url, {
|
||||
course_group_id
|
||||
})
|
||||
if (response && response.data.status == 0) {
|
||||
props.showNotification(`已加入分班:${record.name}`)
|
||||
props.updataleftNavfun()
|
||||
props.onOperationSuccess && props.onOperationSuccess()
|
||||
}
|
||||
}
|
||||
const addToDir = (record) => {
|
||||
props.confirm({
|
||||
|
||||
content: `是否确认加入分班: ${record.name}?`,
|
||||
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
|
||||
onOk: () => {
|
||||
doAddToDir(record)
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function onDelete(record) {
|
||||
props.confirm({
|
||||
content: <div>
|
||||
<div>该分班的学生将被移动到“未分班”</div>
|
||||
<div>是否确认删除?</div>
|
||||
</div>,
|
||||
onOk: () => {
|
||||
// const cid = this.props.match.params.coursesId
|
||||
|
||||
const url = `/course_groups/${record.id}.json`
|
||||
axios.delete(url)
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
props.showNotification('删除成功')
|
||||
props.onOperationSuccess && props.onOperationSuccess()
|
||||
// props.history.push(response.data.right_url)
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
function onGoDetail(record) {
|
||||
props.history.push(`/classrooms/${courseId}/course_groups/${record.id}`)
|
||||
}
|
||||
// 停用和启用邀请码
|
||||
function changeInviteCode(id,flag){
|
||||
if(flag){
|
||||
changeInviteCodeFunc(id,flag);
|
||||
}else{
|
||||
props.confirm({
|
||||
content:"分班邀请码停用后,用户不能主动加入该分班了",
|
||||
subContent:'您是否确认停用?',
|
||||
onOk:() => {
|
||||
changeInviteCodeFunc(id,flag)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function changeInviteCodeFunc(id,flag){
|
||||
const url= `/course_groups/${id}/set_invite_code_halt.json`;
|
||||
axios.post(url).then(result=>{
|
||||
if(result){
|
||||
props.showNotification(`邀请码${flag?"启用":"停用"}成功!`);
|
||||
props.onOperationSuccess && props.onOperationSuccess();
|
||||
}
|
||||
}).catch(error=>{
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
const isAdmin = props.isAdmin();
|
||||
const isSuperAdmin = props.isSuperAdmin();
|
||||
const isStudent = props.isStudent()
|
||||
const isNotMember = props.isNotMember()
|
||||
|
||||
|
||||
const isParent = true;
|
||||
const isCourseEnd= props.isCourseEnd();
|
||||
|
||||
const course_groups = props.course_groups
|
||||
const columns = buildColumns()
|
||||
const dataSource = course_groups.map(item => {
|
||||
return {
|
||||
...item,
|
||||
subStringOfMember_manager : (item.member_manager && item.member_manager.length > 92)
|
||||
? item.member_manager.substring(0, 92) + '...' : null
|
||||
}
|
||||
})
|
||||
return (
|
||||
<React.Fragment>
|
||||
<style>{`
|
||||
.groupListTable .ant-badge-status-processing {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
`}</style>
|
||||
{/* onChange={onTableChange} */}
|
||||
<Table columns={columns} dataSource={dataSource} pagination={false} className="groupListTable"></Table>
|
||||
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
export default CourseGroupListTable
|
|
@ -1,2 +0,0 @@
|
|||
export const ROLE_TEACHER_NUM = 2;
|
||||
export const ROLE_ASSISTANT_NUM = 3;
|
|
@ -1,234 +0,0 @@
|
|||
import React, { Component } from "react";
|
||||
import { Modal, Checkbox, Input, Spin, Select, Divider, Radio } from "antd";
|
||||
import axios from 'axios'
|
||||
import ModalWrapper from "../../common/ModalWrapper"
|
||||
import InfiniteScroll from 'react-infinite-scroller';
|
||||
import { ROLE_TEACHER_NUM, ROLE_ASSISTANT_NUM } from '../common'
|
||||
import NoneData from '../../coursesPublic/NoneData'
|
||||
import { ConditionToolTip } from 'educoder'
|
||||
import SchoolSelect from '../../coursesPublic/form/SchoolSelect'
|
||||
|
||||
const RadioGroup = Radio.Group;
|
||||
|
||||
const Option = Select.Option;
|
||||
const pageCount = 15;
|
||||
class AddAdminModal extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
radioBoxValue: [],
|
||||
users: [],
|
||||
hasMore: true,
|
||||
loading: false,
|
||||
courseGroup: '',
|
||||
page: 1
|
||||
}
|
||||
}
|
||||
fetchTeacherList = (arg_page) => {
|
||||
const courseId = this.props.match.params.coursesId
|
||||
const page = arg_page || this.state.page;
|
||||
const { name, school_name } = this.state
|
||||
|
||||
let url = `/courses/${courseId}/teachers.json`
|
||||
this.setState({ loading: true })
|
||||
axios.get(url, {
|
||||
params: {
|
||||
page: page,
|
||||
limit: pageCount
|
||||
}
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response.data.teacher_list || response.data.teacher_list.length == 0) {
|
||||
this.setState({
|
||||
teacher_list: page == 1 ? response.data.teacher_list : this.state.teacher_list,
|
||||
page,
|
||||
loading: false,
|
||||
hasMore: false,
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
teacher_list: page == 1 ? response.data.teacher_list : this.state.teacher_list.concat(response.data.teacher_list),
|
||||
page,
|
||||
loading: false,
|
||||
hasMore: response.data.teacher_list.length == pageCount
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
componentDidMount() {
|
||||
|
||||
|
||||
}
|
||||
setVisible = (visible) => {
|
||||
if (visible) {
|
||||
this.fetchTeacherList()
|
||||
}
|
||||
this.refs.modalWrapper.setVisible(visible)
|
||||
if (visible == false) {
|
||||
this.setState({
|
||||
radioBoxValue: ''
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
onSendOk = () => {
|
||||
if(!this.state.radioBoxValue || this.state.radioBoxValue.length == 0) {
|
||||
this.props.showNotification('请从列表中先选择用户。')
|
||||
return;
|
||||
}
|
||||
const courseId = this.props.match.params.coursesId
|
||||
const params = {
|
||||
"user_ids": this.state.radioBoxValue
|
||||
}
|
||||
const { courseGroup } = this.state
|
||||
|
||||
if (courseGroup) {
|
||||
params.course_group_id = courseGroup
|
||||
}
|
||||
const url = `/courses/${courseId}/change_course_admin.json`
|
||||
axios.post(url, {
|
||||
course_member_id: this.state.radioBoxValue.course_member_id,
|
||||
user_id: this.state.radioBoxValue.user_id
|
||||
}).then((result)=>{
|
||||
if(result.data.status==0){
|
||||
this.props.showNotification('操作成功。')
|
||||
if (this.props.isCourseAdmin()) {
|
||||
window.location.reload()
|
||||
}
|
||||
// this.fetchAll()
|
||||
this.setVisible(false)
|
||||
this.props.changeAdminSuccess && this.props.changeAdminSuccess()
|
||||
}
|
||||
}).catch((error)=>{
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
onOk = () => {
|
||||
this.onSendOk()
|
||||
}
|
||||
|
||||
onCheckBoxChange = (e) => {
|
||||
this.setState({
|
||||
radioBoxValue: e.target.value
|
||||
})
|
||||
}
|
||||
|
||||
handleInfiniteOnLoad = () => {
|
||||
this.fetchTeacherList(this.state.page + 1)
|
||||
}
|
||||
|
||||
onSearch = () => {
|
||||
this.fetchTeacherList(1)
|
||||
}
|
||||
handleCourseGroupChange = (value) => {
|
||||
this.setState({
|
||||
courseGroup: value
|
||||
})
|
||||
}
|
||||
render(){
|
||||
const { teacher_list, radioBoxValue, loading, hasMore, name, school_name
|
||||
, courseGroup, course_groups, } = this.state
|
||||
const { moduleName } = this.props
|
||||
return(
|
||||
<ModalWrapper
|
||||
ref="modalWrapper"
|
||||
width="600px"
|
||||
title={`更换管理员`}
|
||||
{...this.props }
|
||||
onOk={this.onOk}
|
||||
className="addStudentModal"
|
||||
>
|
||||
<style>
|
||||
{`
|
||||
.demo-loading-container {
|
||||
position: absolute;
|
||||
bottom: 93px;
|
||||
width: 82%;
|
||||
text-align: center;
|
||||
}
|
||||
.df {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin: 12px 0;
|
||||
}
|
||||
.firstLabel {
|
||||
flex: 0 0 60px;
|
||||
}
|
||||
.df span.label {
|
||||
margin-right: 8px;
|
||||
text-align: right;
|
||||
margin-left: 12px;
|
||||
}
|
||||
.df .ant-input-affix-wrapper {
|
||||
width: 32%;
|
||||
}
|
||||
|
||||
.addTeacherModal label.task-hide {
|
||||
width: 100%;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
|
||||
<div className="df" style={{ alignItems: 'center', flexDirection: 'column'}}>
|
||||
<p>选择的成员将会成为新的管理员</p>
|
||||
<p>您将不再拥有管理员的权限,但您仍是教师团队的一员</p>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
{/* <p className="clearfix mb2" style={{ margin: '0px 15px 6px' }}>
|
||||
<Checkbox className="fl" style={{ visibility: 'hidden' }} ></Checkbox>
|
||||
<span className="fl with25"><label className="task-hide fl" style={{"maxWidth":"208px;"}}>{'姓名'}</label></span>
|
||||
<span className="fl with25"><label className="task-hide fl" style={{"maxWidth":"208px;"}}>{'学号'}</label></span>
|
||||
<span className="fl with45"><label className="task-hide fl" style={{"maxWidth":"208px;"}}>{'单位'}</label></span>
|
||||
</p> */}
|
||||
{ teacher_list && teacher_list.length ? <div>
|
||||
{/* https://github.com/CassetteRocks/react-infinite-scroller/issues/70 */}
|
||||
<div className="edu-back-skyblue padding10-15" style={{"height":"300px", overflowY: "scroll", overflowAnchor: 'none' }}>
|
||||
<InfiniteScroll
|
||||
threshold={10}
|
||||
initialLoad={false}
|
||||
pageStart={0}
|
||||
loadMore={this.handleInfiniteOnLoad}
|
||||
hasMore={!loading && hasMore}
|
||||
useWindow={false}
|
||||
>
|
||||
<RadioGroup style={{ width: '100%' }} onChange={this.onCheckBoxChange} value={radioBoxValue}>
|
||||
|
||||
{ teacher_list.map( candidate => {
|
||||
return (
|
||||
<p className="clearfix mb7" key={candidate.user_id}>
|
||||
<Radio className="fl" value={candidate} disabled={candidate.role == "管理员"}></Radio>
|
||||
<span className="fl with25">
|
||||
<label className="task-hide fl" style={{"maxWidth":"208px"}}>{candidate.name || ' '}{candidate.role == "管理员" ? '(当前管理员)' : '' }</label>
|
||||
</span>
|
||||
{/* <span className="fl with25">
|
||||
<ConditionToolTip title={candidate.student_id} condition={candidate.student_id && candidate.student_id.length > 12 }>
|
||||
<label className="task-hide fl" style={{"maxWidth":"208px;"}}>{candidate.student_id || ' '}</label>
|
||||
</ConditionToolTip>
|
||||
</span>
|
||||
<span className="fl with45"><label className="task-hide fl" style={{"maxWidth":"208px;"}}>{candidate.school_name}</label></span> */}
|
||||
|
||||
</p>
|
||||
)
|
||||
}) }
|
||||
</RadioGroup>
|
||||
{loading && hasMore && (
|
||||
<div className="demo-loading-container">
|
||||
<Spin />
|
||||
</div>
|
||||
)}
|
||||
|
||||
</InfiniteScroll>
|
||||
</div>
|
||||
</div> : <NoneData></NoneData> }
|
||||
</ModalWrapper>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default AddAdminModal;
|
|
@ -1,75 +0,0 @@
|
|||
import React, { Component } from "react";
|
||||
import { Input} from "antd";
|
||||
import axios from 'axios'
|
||||
import ModalWrapper from "../../common/ModalWrapper"
|
||||
class AddStudentModal extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
name: ''
|
||||
}
|
||||
}
|
||||
componentDidMount() {
|
||||
|
||||
|
||||
}
|
||||
setVisible = (visible) => {
|
||||
this.refs.modalWrapper.setVisible(visible)
|
||||
if (visible == false) {
|
||||
this.setState({
|
||||
name: ''
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
onSendOk = () => {
|
||||
if(!this.state.name || !this.state.name.trim()) {
|
||||
this.props.showNotification('请先输入答辩组名称。')
|
||||
return;
|
||||
}
|
||||
const courseId = this.props.match.params.coursesId
|
||||
const url = `/courses/${courseId}/create_graduation_group.json`
|
||||
const params = {
|
||||
"name": this.state.name
|
||||
}
|
||||
axios.post(url, params)
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.setVisible(false)
|
||||
this.props.onOk && this.props.onOk();
|
||||
this.props.showNotification('添加成功')
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
onOk = () => {
|
||||
this.onSendOk()
|
||||
}
|
||||
|
||||
render(){
|
||||
const { name } = this.state
|
||||
const { moduleName } = this.props
|
||||
|
||||
return(
|
||||
<ModalWrapper
|
||||
ref="modalWrapper"
|
||||
width="600px"
|
||||
title={`添加答辩组`}
|
||||
{...this.props }
|
||||
onOk={this.onOk}
|
||||
className="addGraduationGroupModal"
|
||||
>
|
||||
<div style={{width: '100%', textAlign: 'center'}}>
|
||||
<span>名称:</span>
|
||||
<Input style={{width: '210px'}} value={name} onChange={(e)=> this.setState({name: e.target.value})}
|
||||
placeholder={'示例:李老师答辩组'}
|
||||
></Input>
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default AddStudentModal;
|
|
@ -1,394 +0,0 @@
|
|||
import React, { Component } from "react";
|
||||
import { Modal, Checkbox, Input, Spin, Select, Divider } from "antd";
|
||||
import axios from "axios";
|
||||
import ModalWrapper from "../../common/ModalWrapper";
|
||||
import InfiniteScroll from "react-infinite-scroller";
|
||||
import { ROLE_TEACHER_NUM, ROLE_ASSISTANT_NUM } from "../common";
|
||||
import NoneData from "../../coursesPublic/NoneData";
|
||||
import { ConditionToolTip, ThemeContext } from "educoder";
|
||||
import SchoolSelect from "../../coursesPublic/form/SchoolSelect";
|
||||
import moment from "moment";
|
||||
|
||||
const formatTime = (time) => {
|
||||
if (time) {
|
||||
return moment(time).format("YYYY-MM-DD HH:mm");
|
||||
} else {
|
||||
return "-";
|
||||
}
|
||||
};
|
||||
const Option = Select.Option;
|
||||
const pageCount = 15;
|
||||
class AddStudentModal extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
checkBoxValues: [],
|
||||
users: [],
|
||||
hasMore: true,
|
||||
loading: false,
|
||||
courseGroup: "",
|
||||
page: 1,
|
||||
isSpin: false,
|
||||
};
|
||||
}
|
||||
fetchMemberList = (arg_page) => {
|
||||
const courseId = this.props.match.params.coursesId;
|
||||
const page = arg_page || this.state.page;
|
||||
const { name, school_name } = this.state;
|
||||
let url = `/courses/${courseId}/search_users.json?page=${page}&limit=${pageCount}&school_name=${
|
||||
school_name || ""
|
||||
}&name=${name || ""}`;
|
||||
this.setState({ loading: true });
|
||||
axios
|
||||
.get(encodeURI(url))
|
||||
.then((response) => {
|
||||
if (!response.data.users || response.data.users.length == 0) {
|
||||
this.setState({
|
||||
users: page == 1 ? response.data.users : this.state.users,
|
||||
page,
|
||||
loading: false,
|
||||
hasMore: false,
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
users:
|
||||
page == 1
|
||||
? response.data.users
|
||||
: this.state.users.concat(response.data.users),
|
||||
page,
|
||||
loading: false,
|
||||
hasMore: response.data.users.length == pageCount,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
componentDidMount() {}
|
||||
fetchOptions = () => {
|
||||
// add_teacher_popup
|
||||
const courseId = this.props.match.params.coursesId;
|
||||
|
||||
let url = `/courses/${courseId}/all_course_groups.json`;
|
||||
|
||||
axios
|
||||
.get(url, {})
|
||||
.then((response) => {
|
||||
if (response.data.course_groups && response.data.course_groups.length) {
|
||||
this.setState({
|
||||
course_groups: response.data.course_groups,
|
||||
courseGroup: "0", // response.data.course_groups[0].id
|
||||
});
|
||||
} else {
|
||||
// showNotification('')
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
setVisible = (visible) => {
|
||||
if (visible) {
|
||||
this.setState(
|
||||
{
|
||||
school_name: this.props.user.user_school,
|
||||
name: undefined,
|
||||
},
|
||||
() => {
|
||||
this.fetchMemberList();
|
||||
}
|
||||
);
|
||||
this.fetchOptions();
|
||||
}
|
||||
this.refs.modalWrapper.setVisible(visible);
|
||||
if (visible == false) {
|
||||
this.setState({
|
||||
checkBoxValues: [],
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onSendOk = () => {
|
||||
if (!this.state.checkBoxValues || this.state.checkBoxValues.length == 0) {
|
||||
this.props.showNotification("请从列表中先选择用户。");
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
isSpin: true,
|
||||
});
|
||||
const courseId = this.props.match.params.coursesId;
|
||||
const url = `/courses/${courseId}/add_students_by_search.json`;
|
||||
const params = {
|
||||
user_ids: this.state.checkBoxValues,
|
||||
};
|
||||
const { courseGroup } = this.state;
|
||||
if (courseGroup) {
|
||||
params.course_group_id = courseGroup;
|
||||
}
|
||||
axios
|
||||
.post(url, params)
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.setVisible(false);
|
||||
this.props.showNotification("添加成功");
|
||||
this.props.addStudentSuccess && this.props.addStudentSuccess(params);
|
||||
this.setState({
|
||||
isSpin: false,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
|
||||
onOk = () => {
|
||||
this.onSendOk();
|
||||
};
|
||||
|
||||
onCheckBoxChange = (checkBoxValues) => {
|
||||
this.setState({
|
||||
checkBoxValues: checkBoxValues,
|
||||
});
|
||||
};
|
||||
|
||||
handleInfiniteOnLoad = () => {
|
||||
this.fetchMemberList(this.state.page + 1);
|
||||
};
|
||||
|
||||
onSearch = () => {
|
||||
this.fetchMemberList(1);
|
||||
};
|
||||
handleCourseGroupChange = (value) => {
|
||||
this.setState({
|
||||
courseGroup: value,
|
||||
});
|
||||
};
|
||||
render() {
|
||||
const {
|
||||
users,
|
||||
checkBoxValues,
|
||||
loading,
|
||||
hasMore,
|
||||
name,
|
||||
school_name,
|
||||
courseGroup,
|
||||
course_groups,
|
||||
isSpin,
|
||||
} = this.state;
|
||||
const { moduleName } = this.props;
|
||||
let theme = this.context;
|
||||
return (
|
||||
<ModalWrapper
|
||||
ref="modalWrapper"
|
||||
width="700px"
|
||||
title={`添加${moduleName}`}
|
||||
{...this.props}
|
||||
onOk={this.onOk}
|
||||
className="addStudentModal courseForm"
|
||||
>
|
||||
<style>
|
||||
{`
|
||||
.demo-loading-container {
|
||||
position: absolute;
|
||||
bottom: 93px;
|
||||
width: 82%;
|
||||
text-align: center;
|
||||
}
|
||||
.df {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin: 12px 0;
|
||||
}
|
||||
.firstLabel {
|
||||
flex: 0 0 60px;
|
||||
}
|
||||
.df span.label {
|
||||
margin-right: 8px;
|
||||
text-align: right;
|
||||
margin-left: 12px;
|
||||
}
|
||||
.df .ant-input-affix-wrapper {
|
||||
width: 32%;
|
||||
}
|
||||
|
||||
.addTeacherModal label.task-hide {
|
||||
width: 100%;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
<div className="df">
|
||||
<span className="mr10">姓名:</span>
|
||||
<Input
|
||||
allowClear
|
||||
placeholder="请输入真实姓名"
|
||||
value={name}
|
||||
onChange={(e) => {
|
||||
this.setState({ name: e.target.value });
|
||||
}}
|
||||
style={{ width: "221px" }}
|
||||
></Input>
|
||||
<span className="label" style={{ minWidth: "36px" }}>
|
||||
单位:
|
||||
</span>
|
||||
{/* <Input allowClear placeholder="请输入单位名称" value={school_name} onChange={(e) => {this.setState({school_name: e.target.value})}}
|
||||
style={{ width: '200px'}}>
|
||||
</Input> */}
|
||||
<SchoolSelect
|
||||
value={school_name}
|
||||
onChange={(value) => {
|
||||
this.setState({ school_name: value });
|
||||
}}
|
||||
></SchoolSelect>
|
||||
<a
|
||||
className="task-btn task-btn-orange"
|
||||
onClick={() => this.fetchMemberList(1)}
|
||||
style={{
|
||||
height: "30px",
|
||||
lineHeight: "30px",
|
||||
marginLeft: "10px",
|
||||
width: "70px",
|
||||
}}
|
||||
>
|
||||
搜索
|
||||
</a>
|
||||
</div>
|
||||
{/* <Divider /> */}
|
||||
|
||||
<p className="clearfix mb2" style={{ margin: "0px 20px 6px" }}>
|
||||
<Checkbox className="fl" style={{ visibility: "hidden" }}></Checkbox>
|
||||
<span className="fl task-hide with20" style={{ maxWidth: "208px;" }}>
|
||||
{"姓名"}
|
||||
</span>
|
||||
<span className="fl task-hide with23" style={{ maxWidth: "208px;" }}>
|
||||
{"学号"}
|
||||
</span>
|
||||
<span className="fl task-hide with23" style={{ maxWidth: "208px;" }}>
|
||||
{"最后登录时间"}
|
||||
</span>
|
||||
<span className="fl task-hide with20" style={{ maxWidth: "208px;" }}>
|
||||
{"单位"}
|
||||
</span>
|
||||
<span
|
||||
className="fl task-hide with5"
|
||||
style={{ maxWidth: "48px;" }}
|
||||
></span>
|
||||
</p>
|
||||
<Spin size="large" spinning={isSpin}>
|
||||
{loading || users.length ? (
|
||||
<div>
|
||||
{/* https://github.com/CassetteRocks/react-infinite-scroller/issues/70 */}
|
||||
<div
|
||||
className="edu-back-skyblue padding10-15"
|
||||
style={{
|
||||
height: "300px",
|
||||
overflowY: "scroll",
|
||||
overflowAnchor: "none",
|
||||
}}
|
||||
>
|
||||
<InfiniteScroll
|
||||
threshold={10}
|
||||
initialLoad={false}
|
||||
pageStart={0}
|
||||
loadMore={this.handleInfiniteOnLoad}
|
||||
hasMore={!loading && hasMore}
|
||||
useWindow={false}
|
||||
>
|
||||
<Checkbox.Group
|
||||
style={{ width: "100%" }}
|
||||
onChange={this.onCheckBoxChange}
|
||||
value={checkBoxValues}
|
||||
>
|
||||
{users.map((candidate) => {
|
||||
return (
|
||||
<p className="clearfix mb7" key={candidate.id}>
|
||||
<Checkbox
|
||||
className="fl"
|
||||
value={candidate.id}
|
||||
key={candidate.id}
|
||||
disabled={candidate.added}
|
||||
></Checkbox>
|
||||
<span className="fl task-hide with20 ml5">
|
||||
{candidate.name ? (
|
||||
<a
|
||||
href={`/users/${candidate.login}`}
|
||||
title={candidate.name}
|
||||
target="_blank"
|
||||
>
|
||||
{candidate.name}
|
||||
</a>
|
||||
) : (
|
||||
<span> </span>
|
||||
)}
|
||||
</span>
|
||||
<span
|
||||
className="fl task-hide with23"
|
||||
title={candidate.student_id}
|
||||
style={{ height: "20px" }}
|
||||
>
|
||||
{candidate.student_id || "-"}
|
||||
</span>
|
||||
<span
|
||||
className="fl task-hide with23"
|
||||
title={formatTime(candidate.last_login_on)}
|
||||
style={{ height: "20px" }}
|
||||
>
|
||||
{formatTime(candidate.last_login_on)}
|
||||
</span>
|
||||
<span
|
||||
className="fl task-hide with20"
|
||||
title={candidate.school_name}
|
||||
style={{ height: "20px" }}
|
||||
>
|
||||
{candidate.school_name||'-'}
|
||||
</span>
|
||||
<span
|
||||
className="fl task-hide with5"
|
||||
style={{
|
||||
maxWidth: "48px",
|
||||
color: theme.foreground_select,
|
||||
}}
|
||||
>
|
||||
{candidate.added ? "已加入" : ""}
|
||||
</span>
|
||||
</p>
|
||||
);
|
||||
})}
|
||||
</Checkbox.Group>
|
||||
{loading && hasMore && (
|
||||
<div className="demo-loading-container">
|
||||
<Spin />
|
||||
</div>
|
||||
)}
|
||||
</InfiniteScroll>
|
||||
</div>
|
||||
{course_groups && course_groups.length && (
|
||||
<div className="df" style={{ marginTop: "12px",width:'100%' }}>
|
||||
<span className="mr10" style={{ width: "180PX" }}>
|
||||
所选学生分班至(选填):
|
||||
</span>
|
||||
<Select
|
||||
style={{ width: "100%" }}
|
||||
onChange={this.handleCourseGroupChange}
|
||||
value={courseGroup}
|
||||
>
|
||||
<Option value={"0"}>{"未分班"}</Option>
|
||||
{course_groups.map((item) => {
|
||||
return <Option value={item.id}>{item.name}</Option>;
|
||||
})}
|
||||
</Select>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<NoneData></NoneData>
|
||||
)}
|
||||
</Spin>
|
||||
</ModalWrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AddStudentModal.contextType = ThemeContext;
|
||||
export default AddStudentModal;
|
|
@ -1,474 +0,0 @@
|
|||
import React, { Component } from "react";
|
||||
import { Modal, Checkbox, Input, Spin, Select, Divider, Icon } from "antd";
|
||||
import axios from "axios";
|
||||
import ModalWrapper from "../../common/ModalWrapper";
|
||||
import InfiniteScroll from "react-infinite-scroller";
|
||||
import { ROLE_TEACHER_NUM, ROLE_ASSISTANT_NUM } from "../common";
|
||||
import { ConditionToolTip, ActionBtn } from "educoder";
|
||||
import NoneData from "../../coursesPublic/NoneData";
|
||||
import AddGraduationGroupModal from "./AddGraduationGroupModal";
|
||||
import SchoolSelect from "../../coursesPublic/form/SchoolSelect";
|
||||
import moment from "moment";
|
||||
|
||||
const formatTime = (time) => {
|
||||
if (time) {
|
||||
return moment(time).format("YYYY-MM-DD HH:mm");
|
||||
} else {
|
||||
return "-";
|
||||
}
|
||||
};
|
||||
const formatePhone = (phone) => {
|
||||
if (phone && typeof phone === "string") {
|
||||
return phone.substring(0, 3) + "****" + phone.substring(7);
|
||||
} else {
|
||||
return "-";
|
||||
}
|
||||
};
|
||||
const Option = Select.Option;
|
||||
const pageCount = 15;
|
||||
let timeout, currentValue;
|
||||
class AddTeacherModal extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
school_names: [],
|
||||
checkBoxValues: [],
|
||||
candidates: [],
|
||||
hasMore: true,
|
||||
loading: false,
|
||||
page: 1,
|
||||
};
|
||||
}
|
||||
fetchMemberList = (arg_page) => {
|
||||
const courseId = this.props.match.params.coursesId;
|
||||
const page = arg_page || this.state.page;
|
||||
const { name, school_name } = this.state;
|
||||
let url = `/courses/${courseId}/search_teacher_candidate.json`;
|
||||
this.setState({ loading: true });
|
||||
axios
|
||||
.post(url, {
|
||||
page: page,
|
||||
limit: pageCount,
|
||||
school_name: school_name || "",
|
||||
name: name || "",
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response.data.candidates || response.data.candidates.length == 0) {
|
||||
this.setState({
|
||||
candidates:
|
||||
page == 1 ? response.data.candidates : this.state.candidates,
|
||||
page,
|
||||
loading: false,
|
||||
hasMore: false,
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
candidates:
|
||||
page == 1
|
||||
? response.data.candidates
|
||||
: this.state.candidates.concat(response.data.candidates),
|
||||
page,
|
||||
loading: false,
|
||||
hasMore: response.data.candidates.length == pageCount,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
componentDidMount() {}
|
||||
onAddGraduationGroupOk = () => {
|
||||
this.fetchOptions();
|
||||
};
|
||||
fetchOptions = () => {
|
||||
// add_teacher_popup
|
||||
const courseId = this.props.match.params.coursesId;
|
||||
|
||||
let url = `/courses/${courseId}/add_teacher_popup.json`;
|
||||
|
||||
axios
|
||||
.get(url, {})
|
||||
.then((response) => {
|
||||
if (response.data.school_name) {
|
||||
this.setState(
|
||||
{
|
||||
school_name: response.data.school_name,
|
||||
},
|
||||
() => this.fetchMemberList()
|
||||
);
|
||||
} else {
|
||||
this.fetchMemberList();
|
||||
}
|
||||
if (response.data.graduation_groups) {
|
||||
this.setState({
|
||||
graduation_groups: response.data.graduation_groups,
|
||||
});
|
||||
}
|
||||
if (response.data.course_groups) {
|
||||
this.setState({
|
||||
course_groups: response.data.course_groups,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
setVisible = (visible) => {
|
||||
if (visible) {
|
||||
this.fetchOptions();
|
||||
}
|
||||
this.refs.modalWrapper.setVisible(visible);
|
||||
if (visible == false) {
|
||||
this.setState({
|
||||
checkBoxValues: [],
|
||||
});
|
||||
}
|
||||
this.setState({
|
||||
name: undefined,
|
||||
graduationGroup: undefined,
|
||||
courseGroup: undefined,
|
||||
});
|
||||
};
|
||||
|
||||
onSendOk = () => {
|
||||
const courseId = this.props.match.params.coursesId;
|
||||
const url = `/courses/${courseId}/add_teacher.json`;
|
||||
if (this.state.checkBoxValues.length == 0) {
|
||||
this.props.showNotification("请先在下面列表中选择要添加教师的成员");
|
||||
return;
|
||||
}
|
||||
const params = {
|
||||
user_list: this.state.checkBoxValues.map((item) => {
|
||||
return { user_id: item };
|
||||
}),
|
||||
// "graduation_group_id": "2",
|
||||
// "course_group_id": "820",
|
||||
role: this.props.isTeacher ? ROLE_TEACHER_NUM : ROLE_ASSISTANT_NUM,
|
||||
};
|
||||
const { graduationGroup, courseGroup } = this.state;
|
||||
if (graduationGroup) {
|
||||
params.graduation_group_id = graduationGroup;
|
||||
}
|
||||
if (courseGroup) {
|
||||
params.course_group_id = courseGroup;
|
||||
}
|
||||
axios
|
||||
.post(url, params)
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.setVisible(false);
|
||||
this.props.showNotification("添加成功");
|
||||
this.props.addTeacherSuccess && this.props.addTeacherSuccess(params);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
|
||||
onOk = () => {
|
||||
this.onSendOk();
|
||||
};
|
||||
|
||||
onCheckBoxChange = (checkBoxValues) => {
|
||||
this.setState({
|
||||
checkBoxValues: checkBoxValues,
|
||||
});
|
||||
};
|
||||
|
||||
handleInfiniteOnLoad = () => {
|
||||
this.fetchMemberList(this.state.page + 1);
|
||||
};
|
||||
|
||||
onSearch = () => {
|
||||
this.fetchMemberList(1);
|
||||
};
|
||||
handleGradationGroupChange = (value) => {
|
||||
this.setState({
|
||||
graduationGroup: value,
|
||||
});
|
||||
};
|
||||
handleCourseGroupChange = (value) => {
|
||||
this.setState({
|
||||
courseGroup: value,
|
||||
});
|
||||
};
|
||||
onOrgNameChange = (value) => {
|
||||
// console.log('school_name: ', value)
|
||||
this.setState({ school_name: value });
|
||||
};
|
||||
|
||||
hasGraduationModule = () => {
|
||||
const { course_modules } = this.props;
|
||||
const result =
|
||||
course_modules &&
|
||||
course_modules.filter((item) => {
|
||||
return item.type == "graduation";
|
||||
});
|
||||
return result && result.length > 0;
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
candidates,
|
||||
checkBoxValues,
|
||||
loading,
|
||||
hasMore,
|
||||
name,
|
||||
school_name,
|
||||
school_names,
|
||||
graduationGroup,
|
||||
graduation_groups,
|
||||
courseGroup,
|
||||
course_groups,
|
||||
} = this.state;
|
||||
const { moduleName } = this.props;
|
||||
|
||||
return (
|
||||
<ModalWrapper
|
||||
ref="modalWrapper"
|
||||
width="700px"
|
||||
title={`添加${moduleName}`}
|
||||
{...this.props}
|
||||
onOk={this.onOk}
|
||||
className="addTeacherModal courseForm"
|
||||
>
|
||||
<AddGraduationGroupModal
|
||||
ref="addGraduationGroupModal"
|
||||
{...this.props}
|
||||
onOk={this.onAddGraduationGroupOk}
|
||||
></AddGraduationGroupModal>
|
||||
<style>
|
||||
{`
|
||||
.demo-loading-container {
|
||||
position: absolute;
|
||||
bottom: 210px;
|
||||
width: 82%;
|
||||
text-align: center;
|
||||
}
|
||||
.df {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin: 12px 0;
|
||||
}
|
||||
.firstLabel {
|
||||
flex: 0 0 60px;
|
||||
}
|
||||
.df span.label {
|
||||
margin-right: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
.df .ant-input-affix-wrapper {
|
||||
width: 32%;
|
||||
}
|
||||
|
||||
.addTeacherModal label.task-hide {
|
||||
width: 100%;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
<div className="df">
|
||||
<span className="firstLabel label" style={{ flex: "0 0 40px" }}>
|
||||
姓名:
|
||||
</span>
|
||||
<Input
|
||||
allowClear
|
||||
placeholder="请输入真实姓名"
|
||||
value={name}
|
||||
onChange={(e) => {
|
||||
this.setState({ name: e.target.value });
|
||||
}}
|
||||
style={{ width: "200px", marginRight: "18px" }}
|
||||
></Input>
|
||||
<span
|
||||
className="label"
|
||||
style={{ minWidth: "36px", flex: "0 0 40px" }}
|
||||
>
|
||||
单位:
|
||||
</span>
|
||||
<SchoolSelect
|
||||
value={school_name}
|
||||
onChange={this.onOrgNameChange}
|
||||
></SchoolSelect>
|
||||
{/* <Select allowClear placeholder="请输入单位名称" value={school_name}
|
||||
style={{ width: '200px'}} showArrow={false}
|
||||
filterOption={false} onSearch={this.onOrgNameSearch}
|
||||
onChange={this.onOrgNameChange} notFoundContent={null}
|
||||
showSearch defaultActiveFirstOption={false}
|
||||
>
|
||||
{ school_names && school_names.map((item, index) => {
|
||||
return <Option value={item} key={index}>{item}</Option>
|
||||
})}
|
||||
</Select> */}
|
||||
<a
|
||||
className="task-btn task-btn-orange"
|
||||
onClick={() => this.fetchMemberList(1)}
|
||||
style={{
|
||||
height: "30px",
|
||||
lineHeight: "30px",
|
||||
marginLeft: "10px",
|
||||
width: "70px",
|
||||
}}
|
||||
>
|
||||
搜索
|
||||
</a>
|
||||
</div>
|
||||
{/* graduation_groups && !!graduation_groups.length */}
|
||||
|
||||
<p className="clearfix mb2" style={{ margin: "0px 20px 6px" }}>
|
||||
<Checkbox className="fl" style={{ visibility: "hidden" }}></Checkbox>
|
||||
<span className="fl task-hide with20" style={{ maxWidth: "208px;" }}>
|
||||
{"姓名"}
|
||||
</span>
|
||||
<span className="fl task-hide with23" style={{ maxWidth: "208px;" }}>
|
||||
{"手机号/邮箱"}
|
||||
</span>
|
||||
<span className="fl task-hide with23" style={{ maxWidth: "208px;" }}>
|
||||
{"最后登录时间"}
|
||||
</span>
|
||||
<span className="fl task-hide with20" style={{ maxWidth: "208px;" }}>
|
||||
{"单位"}
|
||||
</span>
|
||||
<span className="fl task-hide with5" style={{ maxWidth: "48px" }}>
|
||||
{""}
|
||||
</span>
|
||||
</p>
|
||||
{loading || candidates.length ? (
|
||||
<div>
|
||||
{/* https://github.com/CassetteRocks/react-infinite-scroller/issues/70 */}
|
||||
<div
|
||||
className="edu-back-skyblue padding10-15"
|
||||
style={{
|
||||
height: "300px",
|
||||
overflowY: "scroll",
|
||||
overflowAnchor: "none",
|
||||
}}
|
||||
>
|
||||
<InfiniteScroll
|
||||
threshold={10}
|
||||
initialLoad={false}
|
||||
pageStart={0}
|
||||
loadMore={this.handleInfiniteOnLoad}
|
||||
hasMore={!loading && hasMore}
|
||||
useWindow={false}
|
||||
>
|
||||
<Checkbox.Group
|
||||
style={{ width: "100%" }}
|
||||
onChange={this.onCheckBoxChange}
|
||||
value={checkBoxValues}
|
||||
>
|
||||
{candidates &&
|
||||
candidates.map((candidate) => {
|
||||
return (
|
||||
<p className="clearfix mb7" key={candidate.id}>
|
||||
<Checkbox
|
||||
className="fl"
|
||||
value={candidate.id}
|
||||
key={candidate.id}
|
||||
disabled={candidate.added}
|
||||
></Checkbox>
|
||||
<span
|
||||
className="fl task-hide with20 ml5"
|
||||
style={{ height: "20px" }}
|
||||
>
|
||||
<a
|
||||
href={`/users/${candidate.login}`}
|
||||
target="_blank"
|
||||
title={candidate.name}
|
||||
>
|
||||
{candidate.name}
|
||||
</a>
|
||||
</span>
|
||||
<span
|
||||
className="fl task-hide with23"
|
||||
title={
|
||||
candidate.phone
|
||||
? formatePhone(candidate.phone)
|
||||
: formatePhone(candidate.email)
|
||||
}
|
||||
style={{ height: "20px" }}
|
||||
>
|
||||
{candidate.phone
|
||||
? formatePhone(candidate.phone)
|
||||
: formatePhone(candidate.email)}
|
||||
</span>
|
||||
<span
|
||||
className="fl task-hide with23"
|
||||
title={formatTime(candidate.last_login_on)}
|
||||
style={{ height: "20px" }}
|
||||
>
|
||||
{formatTime(candidate.last_login_on)}
|
||||
</span>
|
||||
<span
|
||||
className="fl task-hide with20"
|
||||
title={candidate.school_name}
|
||||
style={{ height: "20px" }}
|
||||
>
|
||||
{candidate.school_name||'-'}
|
||||
</span>
|
||||
<span
|
||||
className="fl task-hide with5 color-blue"
|
||||
style={{ maxWidth: "48px;" }}
|
||||
>
|
||||
{candidate.added ? "已加入" : ""}
|
||||
</span>
|
||||
</p>
|
||||
);
|
||||
})}
|
||||
</Checkbox.Group>
|
||||
{loading && hasMore && (
|
||||
<div className="demo-loading-container">
|
||||
<Spin />
|
||||
</div>
|
||||
)}
|
||||
</InfiniteScroll>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<NoneData></NoneData>
|
||||
)}
|
||||
<div className="df">
|
||||
{/* { this.hasGraduationModule() && <div className="df" style={{ marginTop: '24px' }} >
|
||||
<span className="firstLabel label" style={{ flex: '0 0 96px' }}>添加至答辩组:</span>
|
||||
<Select style={{ width: 218, marginRight: '18px' }} onChange={this.handleGradationGroupChange} value={graduationGroup}
|
||||
dropdownRender={menu => (
|
||||
<div>
|
||||
{menu}
|
||||
<Divider style={{ margin: '4px 0' }} />
|
||||
<div style={{ padding: '8px', cursor: 'pointer' }}
|
||||
onMouseDown={() => { ; this.refs['addGraduationGroupModal'].setVisible(true) }}
|
||||
>
|
||||
<Icon type="plus" /> 添加答辩组
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
{ graduation_groups && graduation_groups.map((item) => {
|
||||
return <Option value={item.id}>{item.name}</Option>
|
||||
})}
|
||||
</Select>
|
||||
</div>} */}
|
||||
|
||||
{course_groups && !!course_groups.length && (
|
||||
<div className="df" style={{ width: "100%" }}>
|
||||
<span className="firstLabel label">管理权限:</span>
|
||||
<Select
|
||||
style={{ width: "100%" }}
|
||||
onChange={this.handleCourseGroupChange}
|
||||
value={courseGroup}
|
||||
>
|
||||
{course_groups &&
|
||||
course_groups.map((item) => {
|
||||
return <Option value={item.id}>{item.name}</Option>;
|
||||
})}
|
||||
</Select>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default AddTeacherModal;
|
|
@ -1,127 +0,0 @@
|
|||
import React, { useState, useEffect, useRef, useMemo } from 'react'
|
||||
import { trigger } from 'educoder'
|
||||
import { Input, Checkbox } from "antd";
|
||||
import CourseGroupChooser from '../CourseGroupChooser'
|
||||
import ModalWrapper from "../../common/ModalWrapper"
|
||||
import axios from 'axios'
|
||||
/**
|
||||
arg_course_groups 选中的id数组
|
||||
joinCourseGroup 选中时触发 joinCourseGroup(checkedValues, item, index) 传入item:数据对象,index: 数据对象index
|
||||
checkAllValue 是否全选
|
||||
onCheckAllChange 全选 onCheckAllChange(e, item, index)
|
||||
course_groups 所有的group
|
||||
*/
|
||||
function CourseGroupChooserModal({ course_groups = [], isAdminOrCreator, item, index,
|
||||
setVisible, visible, record = {}, props = {}, fetchAll
|
||||
}) {
|
||||
// , arg_course_groups, checkAllValue , onCheckAllChange, joinCourseGroup
|
||||
const [checkAllValue, setCheckAllValue] = useState(true)
|
||||
const [arg_course_groups, setArg_course_groups] = useState(course_groups.map(item => item.id))
|
||||
const modalEl = useRef(null);
|
||||
useEffect(() => {
|
||||
setCheckAllValue(true)
|
||||
setArg_course_groups(course_groups.map(item => item.id))
|
||||
}, [course_groups, visible])
|
||||
|
||||
useEffect(() => {
|
||||
if (visible != undefined) {
|
||||
modalEl.current.setVisible(true)
|
||||
}
|
||||
}, [visible])
|
||||
|
||||
const joinCourseGroup = (checks) => {
|
||||
setArg_course_groups(checks)
|
||||
}
|
||||
const onCheckAllChange = (e) => {
|
||||
if (checkAllValue) {
|
||||
setArg_course_groups([])
|
||||
} else {
|
||||
setArg_course_groups(course_groups.map(item => item.id))
|
||||
}
|
||||
setCheckAllValue(!checkAllValue)
|
||||
}
|
||||
const onOk = async () => {
|
||||
let approval = 1
|
||||
const courseId = props.match.params.coursesId
|
||||
let url = `/courses/${courseId}/teacher_application_review.json`
|
||||
const response = await axios.post(url, {
|
||||
user_id: record.user_id,
|
||||
application_id: record.application_id,
|
||||
approval: approval,
|
||||
group_id: arg_course_groups
|
||||
}).then((result) => {
|
||||
if (result.data.status === 0) {
|
||||
props.showNotification(`已${approval == 1? '同意' : '拒绝'}`)
|
||||
fetchAll(1)
|
||||
modalEl.current.setVisible(false)
|
||||
}})
|
||||
}
|
||||
return (
|
||||
<ModalWrapper
|
||||
ref={modalEl}
|
||||
width="600px"
|
||||
title={`同意`}
|
||||
visible={visible}
|
||||
onOk={onOk}
|
||||
className="courseGroupChooserModal"
|
||||
>
|
||||
<style>{`
|
||||
.courseGroupChooserModal .ant-modal-body{
|
||||
padding:20px 30px;
|
||||
}
|
||||
.courseGroupChooserModal .description {
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.courseGroupChooserModal .marginauto{
|
||||
margin-top:10px!important;
|
||||
}
|
||||
.courseGroupChooserModal .drop_down_menu {
|
||||
position: relative;
|
||||
top: auto;
|
||||
box-shadow: none;
|
||||
padding:0px;
|
||||
}
|
||||
.courseGroupChooserModal .drop_down_menu .mainGroup{
|
||||
background: #f2f9ff;
|
||||
padding: 0 20px;
|
||||
}
|
||||
.courseGroupChooserModal .drop_down_menu li:hover,.courseGroupChooserModal .drop_down_normal li:hover{
|
||||
background: #f2f9ff;
|
||||
}
|
||||
.courseGroupChooserModal .drop_down_menu .mainGroup.ant-checkbox-group {
|
||||
width: 100%;
|
||||
max-height: 300px!important;
|
||||
height: 300px;
|
||||
}
|
||||
.courseGroupChooserModal .drop_down_search {
|
||||
margin: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.courseGroupChooserModal .drop_down_menu li {
|
||||
padding: 0px;
|
||||
}
|
||||
.courseGroupChooserModal .drop_down_menu .drop_down_btn {
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
padding: 0px 20px;
|
||||
margin: 0;
|
||||
}
|
||||
.mainGroup .drop_down_menu .drop_down_btn{
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
}
|
||||
`}</style>
|
||||
{/* <React.Fragment>
|
||||
<React.Fragment> */}
|
||||
<div className="description">确认同意TA的加入,并设置TA的分班管理权限</div>
|
||||
<CourseGroupChooser
|
||||
{...{ checkAllValue, isAdminOrCreator, course_groups, arg_course_groups, item, index,
|
||||
joinCourseGroup, onCheckAllChange, alwaysShow: true }}
|
||||
></CourseGroupChooser>
|
||||
|
||||
</ModalWrapper>
|
||||
)
|
||||
}
|
||||
export default (CourseGroupChooserModal)
|
|
@ -1,153 +0,0 @@
|
|||
import React, { Component } from "react";
|
||||
import { Modal, Checkbox, Input, Spin, Upload, Divider, Icon } from "antd";
|
||||
import axios from 'axios'
|
||||
import ModalWrapper from "../../common/ModalWrapper"
|
||||
|
||||
import { ConditionToolTip, getUploadActionUrl } from 'educoder'
|
||||
|
||||
const { Dragger } = Upload;
|
||||
|
||||
|
||||
|
||||
class CreateGroupByImportModal extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
}
|
||||
}
|
||||
fetchMemberList = (arg_page) => {
|
||||
}
|
||||
componentDidMount() {
|
||||
|
||||
|
||||
}
|
||||
onSendOk = () => {
|
||||
const courseId = this.props.match.params.coursesId
|
||||
|
||||
let url = `/courses/${courseId}/create_group_by_importing_file.json`
|
||||
let { fileList } =this.state;
|
||||
|
||||
if (!fileList || fileList.length == 0) {
|
||||
// this.props.showNotification('请先上传附件')
|
||||
this.setState({
|
||||
errorTip :'请先上传附件',
|
||||
})
|
||||
return;
|
||||
}
|
||||
let newfileList=[];
|
||||
if(fileList!=undefined&&fileList.length>0) {
|
||||
for (var list of fileList) {
|
||||
newfileList.push(list.response.id)
|
||||
}
|
||||
}
|
||||
axios.post(url, {
|
||||
attachment_ids: newfileList
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.props.showNotification(response.data.message)
|
||||
this.props.createGroupImportSuccess && this.props.createGroupImportSuccess()
|
||||
this.setVisible(false)
|
||||
} else {
|
||||
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
setVisible = (visible) => {
|
||||
if (visible) {
|
||||
this.setState({ fileList: [] });
|
||||
}
|
||||
this.refs.modalWrapper.setVisible(visible)
|
||||
|
||||
}
|
||||
handleChange = (info) => {
|
||||
let fileList = info.fileList;
|
||||
console.log(fileList)
|
||||
this.setState({ fileList });
|
||||
}
|
||||
|
||||
onOk = () => {
|
||||
this.onSendOk()
|
||||
}
|
||||
|
||||
onAttachmentRemove = (file) => {
|
||||
if(!file.percent || file.percent == 100){
|
||||
this.props.confirm({
|
||||
content: '是否确认删除?',
|
||||
|
||||
onOk: () => {
|
||||
this.deleteAttachment(file)
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
deleteAttachment = (file) => {
|
||||
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
|
||||
axios.delete(url, {
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data) {
|
||||
// const { status } = response.data;
|
||||
if (response.data.status === 0) {
|
||||
|
||||
this.setState((state) => {
|
||||
const index = state.fileList.indexOf(file);
|
||||
const newFileList = state.fileList.slice();
|
||||
newFileList.splice(index, 1);
|
||||
return {
|
||||
fileList: newFileList,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
const { candidates, checkBoxValues, loading, hasMore, name, school_name, school_names
|
||||
, graduationGroup, graduation_groups, courseGroup, course_groups , fileList } = this.state
|
||||
const { moduleName } = this.props
|
||||
|
||||
const props = {
|
||||
name: 'file',
|
||||
multiple: true,
|
||||
fileList:fileList,
|
||||
action: getUploadActionUrl(),
|
||||
onRemove: this.onAttachmentRemove,
|
||||
onChange: this.handleChange
|
||||
};
|
||||
return(
|
||||
<ModalWrapper
|
||||
ref="modalWrapper"
|
||||
width="700px"
|
||||
title={`导入创建分班`}
|
||||
{...this.props }
|
||||
onOk={this.onOk}
|
||||
className="createGroupByImport"
|
||||
>
|
||||
<Dragger {...props}>
|
||||
<p className="ant-upload-drag-icon">
|
||||
<Icon type="inbox" />
|
||||
</p>
|
||||
<p className="ant-upload-text">点击或拖拽文件到这里上传</p>
|
||||
<p className="ant-upload-hint">
|
||||
单个文件最大150MB
|
||||
</p>
|
||||
</Dragger>
|
||||
</ModalWrapper>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default CreateGroupByImportModal;
|
|
@ -1,51 +0,0 @@
|
|||
.stu_table .ant-table-thead > tr > th, .stu_table .ant-table-tbody > tr > td,
|
||||
.courseGroupList .ant-table-thead > tr > th, .courseGroupList .ant-table-tbody > tr > td {
|
||||
padding: 14px 6px;
|
||||
}
|
||||
|
||||
.E9F8FF{
|
||||
background-color: #E9F8FF;
|
||||
}
|
||||
|
||||
.codeBtnStyle{
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
padding:0px 5px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.codeBtn_yellow{
|
||||
border:1px solid #FF6B06;
|
||||
color: #FF6B06!important;
|
||||
}
|
||||
.codeBtn_green{
|
||||
border:1px solid #00BA38;
|
||||
color: #00BA38!important;
|
||||
}
|
||||
|
||||
.codeBtn_blue{
|
||||
border:1px solid #4CACFF;
|
||||
color: #4CACFF!important;
|
||||
}
|
||||
|
||||
.course_publicNav{
|
||||
display: flex;
|
||||
}
|
||||
.course_publicNav li{
|
||||
position: relative;
|
||||
margin-right: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.course_publicNav li.active{
|
||||
color: #4CACFF
|
||||
}
|
||||
.course_publicNav li.active::after{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
content: '';
|
||||
left: 0px;
|
||||
bottom: -33px;
|
||||
background: #4CACFF;
|
||||
}
|
|
@ -1,937 +0,0 @@
|
|||
import React, { Component } from "react";
|
||||
import { Input, Checkbox, Table, Pagination, Modal, Menu, Spin, Tooltip, Divider, Popconfirm } from "antd";
|
||||
import ClipboardJS from 'clipboard'
|
||||
import '../css/Courses.css'
|
||||
import '../css/members.css'
|
||||
import CourseLayoutcomponent from '../common/CourseLayoutComponent'
|
||||
|
||||
import Titlesearchsection from '../common/titleSearch/TitleSearchSection'
|
||||
import ColorCountText from '../common/titleSearch/ColorCountText'
|
||||
import { WordsBtn, trigger, on, off, getRandomcode, getRandomNumber, sortDirections } from 'educoder'
|
||||
import Modals from "../../modals/Modals";
|
||||
import axios from 'axios'
|
||||
import _ from 'lodash'
|
||||
import NoneData from "../coursesPublic/NoneData"
|
||||
import DownloadMessageysl from "../../modals/DownloadMessageysl";
|
||||
import CreateGroupByImportModal from './modal/CreateGroupByImportModal'
|
||||
import ChangeRolePop from './ChangeRolePop'
|
||||
import "./studentsList.css"
|
||||
|
||||
const Search = Input.Search;
|
||||
const TYPE_STUDENTS = 1
|
||||
const TYPE_COURSE_GOURP_PARENT = 2
|
||||
const TYPE_COURSE_GOURP_CHILD = 3
|
||||
const buildColumns = (that, isParent) => {
|
||||
const { course_groups, sortedInfo } = that.state
|
||||
let showSorter = isParent == true
|
||||
const courseId = that.props.match.params.coursesId
|
||||
const columns = [{
|
||||
title: '序号',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
align: 'center',
|
||||
width: "8%",
|
||||
className: "color-grey-6",
|
||||
render: (id, student, index) => {
|
||||
return (that.state.page - 1) * 20 + index + 1
|
||||
}
|
||||
},
|
||||
// {
|
||||
// title: '用户id',
|
||||
// dataIndex: 'login',
|
||||
// key: 'login',
|
||||
// align:'center',
|
||||
// width:"10%",
|
||||
// className:"color-grey-6",
|
||||
// render: (login, record) => {
|
||||
// return <span className="color-dark overflowHidden1" style={{maxWidth: '160px'}}
|
||||
// title={login && login.length > 10 ? login : ''}
|
||||
// >{login}</span>
|
||||
// }
|
||||
// },
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
align: 'center',
|
||||
width: "10%",
|
||||
className: "color-grey-6",
|
||||
render: (name, record) => {
|
||||
return <a className="color-dark overflowHidden1" target="_blank"
|
||||
style={{ maxWidth: '120px' }} href={`/users/${record.login}`}>{name}</a>
|
||||
}
|
||||
}, {
|
||||
title: '学号',
|
||||
dataIndex: 'student_id',
|
||||
key: 'student_id',
|
||||
align: 'center',
|
||||
width: "10%",
|
||||
className: "color-grey-6",
|
||||
sorter: true,
|
||||
sortDirections: sortDirections,
|
||||
sortOrder: sortedInfo.columnKey === 'student_id' && sortedInfo.order,
|
||||
render: (student_id, record) => {
|
||||
return <span className="color-dark overflowHidden1 " title={student_id && student_id.length > 10 ? student_id : ''}
|
||||
style={{ maxWidth: '160px' }} >{student_id}</span>
|
||||
}
|
||||
}
|
||||
, {
|
||||
title: '手机号',
|
||||
dataIndex: 'user_phone',
|
||||
key: 'user_phone',
|
||||
align: 'center',
|
||||
width: "10%",
|
||||
className: "color-grey-6",
|
||||
// sorter: true,
|
||||
// sortDirections: sortDirections,
|
||||
// sortOrder: sortedInfo.columnKey === 'user_phone' && sortedInfo.order,
|
||||
render: (user_phone, record) => {
|
||||
return <span className="color-dark overflowHidden1 " title={user_phone && user_phone.length > 10 ? user_phone : ''}
|
||||
style={{ maxWidth: '160px' }} >{user_phone}</span>
|
||||
}
|
||||
}
|
||||
, {
|
||||
title: '邮箱',
|
||||
dataIndex: 'user_mail',
|
||||
key: 'user_mail',
|
||||
align: 'center',
|
||||
width: "10%",
|
||||
className: "color-grey-6",
|
||||
// sorter: true,
|
||||
// sortDirections: sortDirections,
|
||||
// sortOrder: sortedInfo.columnKey === 'user_mail' && sortedInfo.order,
|
||||
render: (user_mail, record) => {
|
||||
return <span className="color-dark overflowHidden1 " title={user_mail && user_mail.length > 10 ? user_mail : ''}
|
||||
style={{ maxWidth: '160px' }} >{user_mail}</span>
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
if (that.hasGroupModule()) {
|
||||
that.isStudentPage && columns.push({
|
||||
title: '分班',
|
||||
dataIndex: 'course_group_name',
|
||||
key: 'course_group_name',
|
||||
align: 'center',
|
||||
width: "25%",
|
||||
className: "color-grey-6",
|
||||
sorter: showSorter,
|
||||
sortDirections: sortDirections,
|
||||
sortOrder: sortedInfo.columnKey === 'course_group_name' && sortedInfo.order,
|
||||
})
|
||||
}
|
||||
const isAdminOrStudent = that.props.isAdminOrStudent()
|
||||
if (!isAdminOrStudent) {
|
||||
columns.some((item, key) => {
|
||||
if (item.title === "学号") {
|
||||
columns.splice(key, 1)
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
const isAdmin = that.props.isAdmin()
|
||||
if (isAdmin) {
|
||||
!that.isStudentPage && columns.unshift({
|
||||
title: '',
|
||||
dataIndex: 'check',
|
||||
key: 'check',
|
||||
render: (text, item) => {
|
||||
return <Checkbox value={item.course_member_id} key={item.course_member_id} ></Checkbox>
|
||||
},
|
||||
width: "5%"
|
||||
})
|
||||
|
||||
columns.push({
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: '22%',
|
||||
align: 'center',
|
||||
render: (text, record) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<WordsBtn onClick={() => that.onDelete(record)} style={'grey'}>删除学生</WordsBtn>
|
||||
{record.member_roles && record.member_roles.length && <ChangeRolePop
|
||||
style={{ marginLeft: '12px' }}
|
||||
courseId={courseId}
|
||||
record={record}
|
||||
member_roles={record.member_roles}
|
||||
onChangeRoleSuccess={that.onChangeRoleSuccess}
|
||||
showNotification={that.props.showNotification}
|
||||
getUserId={that.props.isUserid}
|
||||
fetchUser={that.props.fetchUser}
|
||||
></ChangeRolePop>}
|
||||
</React.Fragment>
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
return columns;
|
||||
}
|
||||
|
||||
// 1-按照学生学号 2-按照分班名称,
|
||||
const ORDER_BY_NUM = 1;
|
||||
const ORDER_BY_GROUP = 2;
|
||||
|
||||
class studentsList extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
page: 1,
|
||||
order: ORDER_BY_NUM,
|
||||
searchValue: '',
|
||||
course_groups: [],
|
||||
students: [],
|
||||
checkBoxValues: [],
|
||||
|
||||
stu_new_flag: false,
|
||||
StudentList_value: "",
|
||||
modalsType: "",
|
||||
modalsTopval: "",
|
||||
modalsBottomval: "",
|
||||
modalCancel: "",
|
||||
n_And_e: 1,
|
||||
isSpin: false,
|
||||
DownloadType: false,
|
||||
DownloadMessageval: undefined,
|
||||
sortedInfo: { order: 'ascend', columnKey: 'student_id' }
|
||||
}
|
||||
}
|
||||
/// 确认是否下载
|
||||
confirmysl(url, urls) {
|
||||
// this.props.showGlobalLoading('正在生成文件,请稍后...')
|
||||
axios.get(url + 'export=true').then((response) => {
|
||||
if (response === undefined) {
|
||||
return
|
||||
}
|
||||
if (response.data.status && response.data.status === -1) {
|
||||
|
||||
} else if (response.data.status && response.data.status === -2) {
|
||||
if (response.data.message === "100") {
|
||||
// 已超出文件导出的上限数量(100 ),建议:
|
||||
|
||||
this.setState({
|
||||
DownloadType: true,
|
||||
DownloadMessageval: 100
|
||||
})
|
||||
} else {
|
||||
//因附件资料超过500M
|
||||
this.setState({
|
||||
DownloadType: true,
|
||||
DownloadMessageval: 500
|
||||
})
|
||||
}
|
||||
} else {
|
||||
|
||||
// this.props.showNotification(`正在下载中`);
|
||||
// window.open("/api"+url, '_blank');
|
||||
this.props.slowDownload(getRandomcode(url))
|
||||
|
||||
// getUrl() + "/api"+
|
||||
// const fileUrl = url;
|
||||
|
||||
// this.props.slowDownload(fileUrl)
|
||||
// return;
|
||||
|
||||
// downloadFile({
|
||||
// url: fileUrl,
|
||||
// successCallback: (url) => {
|
||||
// console.log('successCallback')
|
||||
// },
|
||||
// failCallback: (responseHtml, url) => {
|
||||
// console.log('failCallback')
|
||||
// }
|
||||
// })
|
||||
// window.open(fileUrl, "_self");// , '_blank'
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
});
|
||||
}
|
||||
hasGroupModule = () => {
|
||||
const { course_modules } = this.props;
|
||||
const result = course_modules && course_modules.filter(item => {
|
||||
return item.type == 'course_group'
|
||||
})
|
||||
return result && result.length > 0
|
||||
}
|
||||
|
||||
Downloadcal = () => {
|
||||
this.setState({
|
||||
DownloadType: false,
|
||||
DownloadMessageval: undefined
|
||||
})
|
||||
}
|
||||
|
||||
inputStudent = (e) => {
|
||||
this.setState({
|
||||
StudentList_value: e.target.value
|
||||
})
|
||||
}
|
||||
// 有关新建分班和分班重命名
|
||||
showStuNewBox = (index) => {
|
||||
this.setState({
|
||||
stu_new_flag: true,
|
||||
n_And_e: index
|
||||
})
|
||||
}
|
||||
hideStuNewBox = () => {
|
||||
this.setState({
|
||||
stu_new_flag: false
|
||||
})
|
||||
}
|
||||
// 有关删除分班
|
||||
delClasses = () => {
|
||||
this.setState({
|
||||
modalsType: true,
|
||||
modalsTopval: "该分班的学生将被移动到“XX班”",
|
||||
modalsBottomval: "是否确认删除?",
|
||||
modalCancel: true
|
||||
})
|
||||
}
|
||||
cancelDelClasses = () => {
|
||||
this.setState({
|
||||
modalsType: false,
|
||||
modalsTopval: "",
|
||||
modalsBottomval: "",
|
||||
modalCancel: false
|
||||
})
|
||||
}
|
||||
// 确认删除
|
||||
sureDelClasses = () => {
|
||||
this.setState({
|
||||
modalsType: false,
|
||||
modalsTopval: "",
|
||||
modalsBottomval: "",
|
||||
modalCancel: false
|
||||
})
|
||||
}
|
||||
|
||||
onChange = () => {
|
||||
|
||||
}
|
||||
onChangeRoleSuccess = () => {
|
||||
const { page, searchValue } = this.state;
|
||||
this.fetchAll(page, searchValue);
|
||||
}
|
||||
componentDidMount() {
|
||||
this.setState({
|
||||
isSpin: true
|
||||
})
|
||||
const { page, searchValue } = this.state;
|
||||
this.fetchAll(page, searchValue);
|
||||
const isAdmin = this.props.isAdmin()
|
||||
// if (isAdmin) {
|
||||
this.fetchCourseGroups();
|
||||
// }
|
||||
|
||||
isAdmin && on('addStudentSuccess', this.addStudentSuccessListener)
|
||||
isAdmin && on('updateNavSuccess', this.updateNavSuccess)
|
||||
}
|
||||
componentWillUnmount() {
|
||||
if (this.clipboard) {
|
||||
this.clipboard.destroy()
|
||||
}
|
||||
const isAdmin = this.props.isAdmin()
|
||||
if (isAdmin) {
|
||||
off('addStudentSuccess', this.addStudentSuccessListener)
|
||||
off('updateNavSuccess', this.updateNavSuccess)
|
||||
}
|
||||
}
|
||||
createGroupImportSuccess = () => {
|
||||
this.props.updataleftNavfun()
|
||||
}
|
||||
updateNavSuccess = () => {
|
||||
this.fetchCourseGroups();
|
||||
const { page, searchValue } = this.state;
|
||||
|
||||
this.fetchAll(page, searchValue);
|
||||
}
|
||||
|
||||
addStudentSuccessListener = (e, data) => {
|
||||
const params = JSON.parse(data)
|
||||
this.props.updataleftNavfun()
|
||||
const course_group_id = this.props.match.params.course_group_id;
|
||||
const coursesId = this.props.match.params.coursesId;
|
||||
const { searchValue } = this.state;
|
||||
if (params.course_group_id === course_group_id) {
|
||||
this.fetchAll(1, searchValue);
|
||||
} else {
|
||||
this.props.history.push(`/classrooms/${coursesId}/course_groups/${params.course_group_id || '0'}`)
|
||||
}
|
||||
// console.log('addStudentSuccessListener', data)
|
||||
}
|
||||
fetchCourseGroups = () => {
|
||||
const courseId = this.props.match.params.coursesId
|
||||
|
||||
let url = `/courses/${courseId}/all_course_groups.json`
|
||||
|
||||
axios.get(url, {
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.course_groups && response.data.course_groups.length) {
|
||||
this.setState({
|
||||
course_groups: response.data.course_groups
|
||||
})
|
||||
} else {
|
||||
// showNotification('')
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.match.params.course_group_id != this.props.match.params.course_group_id) {
|
||||
this.setState({ checkBoxValues: [], checkAllValue: false })
|
||||
|
||||
this.fetchAll(1, this.state.searchValue)
|
||||
}
|
||||
// 加载了2次
|
||||
// else if (prevProps.coursesids != this.props.coursesids) {
|
||||
// this.fetchAll(1)
|
||||
// }
|
||||
}
|
||||
fetchAll = (argPage, searchValue) => {
|
||||
this.setState({
|
||||
isSpin: true
|
||||
})
|
||||
let id = this.props.match.params.coursesId
|
||||
let course_group_id = this.props.match.params.course_group_id
|
||||
|
||||
const { coursesids } = this.props
|
||||
// if (!coursesids) {
|
||||
// return;
|
||||
// }
|
||||
if (!course_group_id || course_group_id == coursesids) {
|
||||
course_group_id = ''
|
||||
}
|
||||
if (argPage) {
|
||||
this.setState({ page: argPage })
|
||||
}
|
||||
let page = argPage || this.state.page
|
||||
let { sortedInfo } = this.state
|
||||
let order = 1;
|
||||
if (sortedInfo.columnKey == 'student_id') {
|
||||
order = 1;
|
||||
} else if (sortedInfo.columnKey == 'course_group_name') {
|
||||
order = 2;
|
||||
}
|
||||
let sort = 'desc';
|
||||
if (sortedInfo.order == 'ascend') {
|
||||
sort = 'asc'
|
||||
}
|
||||
|
||||
let url = `/courses/${id}/students.json?order=${order}&sort=${sort}&page=${page}&limit=20&course_group_id=${course_group_id}`;
|
||||
if (!!searchValue) {
|
||||
url += '&search=' + searchValue;
|
||||
}
|
||||
axios.get(encodeURI(url)).then((result) => {
|
||||
if (result.data.students) {
|
||||
this.setState({
|
||||
students: result.data.students,
|
||||
total_count: result.data.students_count,
|
||||
course_group_name: result.data.course_group_name,
|
||||
invite_code: result.data.invite_code,
|
||||
isSpin: false
|
||||
}, () => {
|
||||
if (course_group_id) {
|
||||
if (!this.clipboard) {
|
||||
const clipboard = new ClipboardJS('.copybtn');
|
||||
clipboard.on('success', (e) => {
|
||||
this.props.showNotification('复制成功')
|
||||
});
|
||||
this.clipboard = clipboard
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
isSpin: false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
onInputSearchChange = (e) => {
|
||||
this.setState({
|
||||
searchValue: e.target.value
|
||||
})
|
||||
|
||||
// if (this.timeoutHandler) {
|
||||
// clearTimeout(this.timeoutHandler)
|
||||
// }
|
||||
// this.timeoutHandler = setTimeout(() => {
|
||||
// this.fetchAll(1)
|
||||
// }, 1200)
|
||||
}
|
||||
onSortTypeChange = (order) => {
|
||||
const { page, searchValue } = this.state;
|
||||
this.setState({ order: order }, () => {
|
||||
this.fetchAll(page, searchValue)
|
||||
})
|
||||
}
|
||||
onPageChange = (page) => {
|
||||
const { searchValue } = this.state;
|
||||
this.fetchAll(page, searchValue)
|
||||
this.setState({ checkAllValue: false })
|
||||
}
|
||||
|
||||
onPressEnter = (e) => {
|
||||
this.setState({
|
||||
page: 1,
|
||||
searchValue: e
|
||||
})
|
||||
this.fetchAll(1, e)
|
||||
}
|
||||
|
||||
onCheckBoxChange = (checkedValues) => {
|
||||
this.setState({
|
||||
checkBoxValues: checkedValues,
|
||||
checkAllValue: checkedValues.length == this.state.students.length
|
||||
})
|
||||
}
|
||||
// 多选
|
||||
moveToGroup = (group) => {
|
||||
const len = this.state.checkBoxValues.length
|
||||
if (len == 0) {
|
||||
this.props.showNotification('请从列表先选择要移动的学生')
|
||||
return;
|
||||
}
|
||||
|
||||
let id = this.props.match.params.coursesId
|
||||
let { order, searchValue, page } = this.state
|
||||
let url = `/courses/${id}/transfer_to_course_group.json`;
|
||||
axios.post((url), {
|
||||
students: this.state.checkBoxValues.map(item => { return { course_member_id: item } }),
|
||||
course_group_id: group.id
|
||||
}).then((result) => {
|
||||
if (result.data.status == 0) {
|
||||
this.props.showNotification('移动成功')
|
||||
this.setState({ checkBoxValues: [] })
|
||||
this.fetchAll(page, searchValue);
|
||||
this.props.updataleftNavfun()
|
||||
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
onCheckAll = (e) => {
|
||||
this.setState({
|
||||
checkAllValue: e.target.checked
|
||||
})
|
||||
const values = this.state.students.map(item => {
|
||||
return item.course_member_id
|
||||
})
|
||||
if (e.target.checked) {
|
||||
const concated = this.state.checkBoxValues.concat(values);
|
||||
const sortedUniqed = _.uniq(concated)
|
||||
this.setState({
|
||||
checkBoxValues: sortedUniqed
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
checkBoxValues: _.difference(this.state.checkBoxValues, values)
|
||||
})
|
||||
}
|
||||
}
|
||||
// 多选
|
||||
onDelete = (record) => {
|
||||
if (!record) {
|
||||
const len = this.state.checkBoxValues.length
|
||||
if (len == 0) {
|
||||
this.props.showNotification('请先从列表选择要删除的学生')
|
||||
return;
|
||||
}
|
||||
}
|
||||
const { page, searchValue } = this.state;
|
||||
|
||||
this.props.confirm({
|
||||
// content: `确认要删除所选的${len}个学生吗?`,
|
||||
content: `是否确认删除?`,
|
||||
onOk: () => {
|
||||
let id = this.props.match.params.coursesId
|
||||
let url = `/courses/${id}/delete_from_course.json`;
|
||||
axios.post((url), {
|
||||
students: [{ course_member_id: record.course_member_id }] // this.state.checkBoxValues.map(item => {return {course_member_id: item} }),
|
||||
}).then((result) => {
|
||||
if (result.data.status == 0) {
|
||||
this.props.showNotification('删除成功')
|
||||
this.props.updataleftNavfun()
|
||||
this.fetchAll(page, searchValue);
|
||||
this.setState({ checkBoxValues: [] })
|
||||
trigger('updatabanner')
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
addDir = () => {
|
||||
trigger('groupAdd', this.props.coursesids)
|
||||
}
|
||||
doAddToDir = async () => {
|
||||
const courseId = this.props.match.params.coursesId
|
||||
const url = `/courses/${courseId}/join_course_group.json`
|
||||
const course_group_id = this.props.match.params.course_group_id
|
||||
|
||||
const response = await axios.post(url, {
|
||||
course_group_id
|
||||
})
|
||||
const { page, searchValue } = this.state;
|
||||
|
||||
if (response && response.data.status == 0) {
|
||||
this.props.showNotification(`已加入分班:${this.state.course_group_name}`)
|
||||
this.props.updataleftNavfun()
|
||||
this.fetchAll(page, searchValue)
|
||||
}
|
||||
}
|
||||
addToDir = (record) => {
|
||||
this.props.confirm({
|
||||
|
||||
content: `是否确认加入分班: ${this.state.course_group_name}?`,
|
||||
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
|
||||
onOk: () => {
|
||||
this.doAddToDir()
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
}
|
||||
renameDir = () => {
|
||||
const course_group_id = this.props.match.params.course_group_id
|
||||
trigger('groupRename', { id: parseInt(course_group_id), name: this.state.course_group_name })
|
||||
}
|
||||
deleteDir = () => {
|
||||
this.props.confirm({
|
||||
content: <div>
|
||||
<div>该分班的学生将被移动到“未分班”</div>
|
||||
<div>是否确认删除?</div>
|
||||
</div>,
|
||||
onOk: () => {
|
||||
const course_group_id = this.props.match.params.course_group_id
|
||||
const courseId = this.props.match.params.coursesId
|
||||
|
||||
const url = `/course_groups/${course_group_id}.json`
|
||||
axios.delete(url)
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.props.showNotification('删除成功')
|
||||
this.props.history.push(`/classrooms/${courseId}/course_groups`)
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
jsCopy = () => {
|
||||
var e = document.getElementById("copy_invite_code");
|
||||
e.select();
|
||||
document.execCommand("Copy");
|
||||
this.props.showNotification('复制成功')
|
||||
}
|
||||
|
||||
onTableChange = (pagination, filters, sorter) => {
|
||||
const { page, searchValue } = this.state;
|
||||
|
||||
this.setState({
|
||||
sortedInfo: sorter,
|
||||
}, () => {
|
||||
this.fetchAll(page, searchValue);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const isAdmin = this.props.isAdmin()
|
||||
const isStudent = this.props.isStudent()
|
||||
const isSuperAdmin = this.props.isSuperAdmin()
|
||||
const isCourseEnd = this.props.isCourseEnd()
|
||||
let {
|
||||
page,
|
||||
|
||||
order,
|
||||
StudentList_value,
|
||||
stu_new_flag,
|
||||
modalsType,
|
||||
modalsTopval,
|
||||
modalsBottomval,
|
||||
n_And_e,
|
||||
|
||||
students,
|
||||
searchValue,
|
||||
total_count,
|
||||
course_groups,
|
||||
checkBoxValues,
|
||||
checkAllValue
|
||||
} = this.state;
|
||||
let currentOrderName = '学生学号排序'
|
||||
if (order == ORDER_BY_GROUP) {
|
||||
currentOrderName = '分班名称排序'
|
||||
}
|
||||
const { coursesids } = this.props
|
||||
const course_group_id = this.props.match.params.course_group_id
|
||||
const isParent = !course_group_id || course_group_id == coursesids
|
||||
const { course_group_name, invite_code } = this.state;
|
||||
|
||||
const courseId = this.props.match.params.coursesId
|
||||
let exportUrl = `/courses/${courseId}/export_member_scores_excel.xlsx?`; //总成绩
|
||||
let exportUrltwo = `/courses/${courseId}/export_couser_info.xlsx?`; //课堂信息
|
||||
let exportUrlthree = `/courses/${courseId}/export_member_act_score.xlsx?`; //活跃度
|
||||
|
||||
|
||||
|
||||
const params = {}
|
||||
if (course_group_id) {
|
||||
params.group_id = course_group_id
|
||||
}
|
||||
if (searchValue) {
|
||||
searchValue = searchValue.trim()
|
||||
if (searchValue) {
|
||||
params.search = searchValue
|
||||
}
|
||||
}
|
||||
let paramsString = ''
|
||||
for (let key in params) {
|
||||
paramsString += `&${key}=${params[key]}&`
|
||||
}
|
||||
exportUrl += paramsString;
|
||||
exportUrltwo += paramsString;
|
||||
exportUrlthree += paramsString;
|
||||
|
||||
|
||||
// console.log(paramsString);
|
||||
// console.log(checkBoxValues);
|
||||
// console.log(searchValue);
|
||||
let pageType = TYPE_STUDENTS
|
||||
if (this.props.match.path.endsWith('students')) {
|
||||
|
||||
} else if (course_group_id) {
|
||||
pageType = TYPE_COURSE_GOURP_CHILD
|
||||
} else {
|
||||
pageType = TYPE_COURSE_GOURP_PARENT
|
||||
}
|
||||
// 本页面有2个状态,学生列表、具体分班
|
||||
const isStudentPage = pageType == TYPE_STUDENTS
|
||||
this.isStudentPage = isStudentPage
|
||||
const isGroupChildPage = pageType == TYPE_COURSE_GOURP_CHILD
|
||||
let studentlist = buildColumns(this, isParent);
|
||||
if (this.props.isexcellent === true) {
|
||||
studentlist.some((item, key) => {
|
||||
if (item.title === "手机号") {
|
||||
studentlist.splice(key, 1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (this.props.isexcellent === true) {
|
||||
studentlist.some((item, key) => {
|
||||
if (item.title === "邮箱") {
|
||||
studentlist.splice(key, 1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment >
|
||||
<DownloadMessageysl
|
||||
{...this.props}
|
||||
value={this.state.DownloadMessageval}
|
||||
modalCancel={this.Downloadcal}
|
||||
modalsType={this.state.DownloadType}
|
||||
/>
|
||||
<Titlesearchsection
|
||||
title={isParent ? (pageType == TYPE_STUDENTS ? "全部学生" : "学生列表") :
|
||||
<React.Fragment>
|
||||
{
|
||||
course_group_name ?
|
||||
<span>
|
||||
<Tooltip title="返回至分班列表">
|
||||
<i className="icon-zuojiantou iconfont font-14" onClick={() => { this.props.history.push(`/classrooms/${courseId}/course_groups`) }}
|
||||
style={{ color: '#212121', verticalAlign: 'initial', marginRight: '14px' }}
|
||||
></i>
|
||||
</Tooltip>{course_group_name}
|
||||
</span>
|
||||
:
|
||||
<ul className="course_publicNav">
|
||||
<li onClick={() => { this.props.history.push(`/classrooms/${courseId}/course_groups`) }}>分班列表</li>
|
||||
<li className="active">未分班</li>
|
||||
</ul>
|
||||
}
|
||||
|
||||
{isAdmin && invite_code && <React.Fragment>
|
||||
<span className="color-grey-9 font-16 ml10">邀请码:</span>
|
||||
<span className="color-orange font-16">
|
||||
{invite_code}
|
||||
</span>
|
||||
<Tooltip title={<div>
|
||||
<div>成员可以通过邀请码主动加入分班</div>
|
||||
<div>点击立刻复制邀请码</div>
|
||||
</div>}>
|
||||
<span>
|
||||
<i className="iconfont icon-fuzhi font-14 ml10 copybtn" style={{ color: '#FF6800', cursor: 'pointer', verticalAlign: 'baseline' }} data-clipboard-text={invite_code} ></i>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
</React.Fragment>
|
||||
}
|
||||
searchValue={searchValue}
|
||||
onInputSearchChange={this.onInputSearchChange}
|
||||
allowClearonChange={this.onInputSearchChange}
|
||||
showSearchInput={total_count >= 10}
|
||||
onPressEnter={this.onPressEnter}
|
||||
searchPlaceholder={'请输入姓名、学号进行搜索'}
|
||||
firstRowRight={
|
||||
<React.Fragment>
|
||||
{
|
||||
!isStudentPage && isAdmin && !isParent && course_group_id != 0 && <WordsBtn style="blue" className="mr30" onClick={() => this.deleteDir()}>删除分班</WordsBtn>}
|
||||
{
|
||||
!isStudentPage && isAdmin && !isParent && course_group_id != 0 && <WordsBtn style="blue" className="mr30" onClick={() => this.renameDir()}>分班重命名</WordsBtn>}
|
||||
{
|
||||
!isStudentPage && !isCourseEnd && isAdmin && <WordsBtn style="blue" className="mr30" onClick={() => this.addDir()}>新建分班</WordsBtn>}
|
||||
|
||||
{
|
||||
!isStudentPage && isStudent && !isParent && course_group_id != 0 && <WordsBtn style="blue" className="" onClick={() => this.addToDir()}>加入分班</WordsBtn>}
|
||||
<style>{`
|
||||
.drop_down_menu li a {
|
||||
padding: 0px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.drop_down_menu {
|
||||
/*width: 93px;*/
|
||||
}
|
||||
.drop_down_menu li {
|
||||
width:100%;
|
||||
box-sizing:boder-box;
|
||||
float:unset;
|
||||
line-height:30px!important;
|
||||
flex: 0 0 30px;
|
||||
}
|
||||
.drop_down_menu, .drop_down_normal {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
.drop_down_menu .drop_down_btn{
|
||||
border-top:none;
|
||||
}
|
||||
.dividerStyle.ant-divider-horizontal{
|
||||
margin: 0px;
|
||||
}
|
||||
`}</style>
|
||||
{isAdmin &&
|
||||
<li className="li_line drop_down fr color-blue font-16">
|
||||
导出<i className="iconfont icon-xiajiantou font-12 ml2"></i>
|
||||
<ul className="drop_down_menu" style={{ "right": "-20px", "left": "unset", "height": "auto" }}>
|
||||
|
||||
<li><a
|
||||
onClick={(i) => this.confirmysl(exportUrltwo)}>课堂信息</a>
|
||||
</li>
|
||||
<li><a
|
||||
onClick={(i) => this.confirmysl(exportUrlthree)}>活跃度</a>
|
||||
</li>
|
||||
<li><a
|
||||
onClick={(i) => this.confirmysl(exportUrl)}>总成绩</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
}
|
||||
{/*<WordsBtn style="blue" className="" onClick={(url)=>this.confirmysl(exportUrl)} >导出成绩</WordsBtn>*/}
|
||||
{/* */}
|
||||
</React.Fragment>
|
||||
}
|
||||
secondRowLeft={
|
||||
total_count ? <ColorCountText count={total_count} name="个学生"></ColorCountText> : ''
|
||||
}
|
||||
></Titlesearchsection>
|
||||
{
|
||||
total_count > 0 || this.state.isSpin == true ?
|
||||
<div className="mt20 edu-back-white padding20">
|
||||
<div className="clearfix stu_head" style={{ paddingLeft: '5px' }}>
|
||||
{isAdmin && !isStudentPage && <Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue} >已选 {checkBoxValues.length} 个</Checkbox>}
|
||||
<div className="studentList_operation_ul">
|
||||
{/* {isAdmin && <li className="li_line"><a className="color-grey-9" onClick={this.onDelete}>删除</a></li>} */}
|
||||
{isAdmin && !isStudentPage && <li className="drop_down">
|
||||
移动到<i className="iconfont icon-xiajiantou font-12 ml2"></i>
|
||||
<ul className="drop_down_menu" style={{ "right": "0px", "left": "unset", width: '200px', maxHeight: '324px', overflowY: 'auto' }}>
|
||||
{
|
||||
course_groups && course_groups.length > 9 ?
|
||||
(<p className="drop_down_search">
|
||||
<Input placeholder="搜索" value={this.state.groupSearchValue} onChange={(e) => { this.setState({ groupSearchValue: e.target.value }) }} />
|
||||
</p>) :
|
||||
''
|
||||
}
|
||||
{
|
||||
course_group_id != 0 && course_groups && course_groups.length > 0 &&
|
||||
<li key={0} onClick={() => this.moveToGroup({ id: 0 })}>未分班</li>
|
||||
}
|
||||
{course_groups.filter((item) => {
|
||||
return item.id != course_group_id && (!this.state.groupSearchValue || item.name.indexOf(this.state.groupSearchValue) != -1)
|
||||
}).map(item => {
|
||||
return (
|
||||
<li key={item.id} onClick={() => this.moveToGroup(item)} title={item.name}>{item.name}</li>
|
||||
)
|
||||
})}
|
||||
{course_groups && course_groups.length > 0 && <Divider className="dividerStyle"></Divider>}
|
||||
{isAdmin && !isCourseEnd &&
|
||||
|
||||
<p className="drop_down_btn">
|
||||
<a className="color-grey-6"
|
||||
onClick={() => this.addDir()}
|
||||
>新建分班...</a>
|
||||
</p>
|
||||
|
||||
}
|
||||
</ul>
|
||||
</li>}
|
||||
|
||||
{/* <li className="drop_down">
|
||||
{currentOrderName}
|
||||
{ course_groups && !!course_groups.length &&
|
||||
<React.Fragment>
|
||||
<i className="iconfont icon-xiajiantou font-12 ml2"></i>
|
||||
<ul className="drop_down_normal" style={{width: '124px'}}>
|
||||
<li onClick={() => this.onSortTypeChange(ORDER_BY_NUM)} >学生学号排序</li>
|
||||
<li onClick={() => this.onSortTypeChange(ORDER_BY_GROUP)} >分班名称排序</li>
|
||||
</ul>
|
||||
</React.Fragment>
|
||||
}
|
||||
</li> */}
|
||||
</div>
|
||||
</div>
|
||||
<Spin size="large" spinning={this.state.isSpin}>
|
||||
<div className="clearfix stu_table">
|
||||
{students && !!students.length && <Checkbox.Group style={{ width: '100%' }} onChange={this.onCheckBoxChange} value={checkBoxValues}>
|
||||
<Table columns={studentlist} dataSource={students} onChange={this.onTableChange} pagination={false}></Table>
|
||||
</Checkbox.Group>}
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
:
|
||||
<NoneData></NoneData>
|
||||
}
|
||||
{/* showQuickJumper */}
|
||||
{total_count > 20 && <div className="clearfix mt30 mb50 edu-txt-center">
|
||||
<Pagination showQuickJumper defaultCurrent={page} current={page} pageSize={20} total={total_count} onChange={this.onPageChange} />
|
||||
</div>}
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default studentsList;
|
|
@ -1,840 +0,0 @@
|
|||
import React, { Component } from "react";
|
||||
import { Input, Checkbox, Table, Divider, Tooltip, Spin, Menu, Popconfirm } from "antd";
|
||||
|
||||
import CourseLayoutcomponent from '../common/CourseLayoutComponent'
|
||||
import NoneData from "../coursesPublic/NoneData"
|
||||
|
||||
import Titlesearchsection from '../common/titleSearch/TitleSearchSection'
|
||||
import ColorCountText from '../common/titleSearch/ColorCountText'
|
||||
import update from 'immutability-helper'
|
||||
|
||||
import { WordsBtn, ConditionToolTip, on, off, trigger, sortDirections } from 'educoder'
|
||||
|
||||
import axios from 'axios'
|
||||
|
||||
import _ from 'lodash'
|
||||
// import { RouteHOC } from './common.js'
|
||||
|
||||
import '../css/members.css'
|
||||
import { from } from "array-flatten";
|
||||
// import AddTeacherModal from './modal/AddTeacherModal'
|
||||
// import AddStudentModal from './modal/AddStudentModal'
|
||||
import AddGraduationGroupModal from './modal/AddGraduationGroupModal'
|
||||
import AddAdminModal from './modal/AddAdminModal'
|
||||
import CourseGroupChooserModal from './modal/CourseGroupChooserModal'
|
||||
import { ROLE_TEACHER_NUM, ROLE_ASSISTANT_NUM } from './common'
|
||||
import CourseGroupChooser from './CourseGroupChooser'
|
||||
import ChangeRolePop from './ChangeRolePop'
|
||||
|
||||
const Search = Input.Search;
|
||||
const ROLE_ADMIN = "管理员"
|
||||
const ROLE_TEACHER = "教师"
|
||||
const ROLE_TEACHER_ASSISTANT = "助教"
|
||||
const pageSize = 20;
|
||||
|
||||
function buildColumns(that) {
|
||||
let sortedInfo = that.state.sortedInfo || {}
|
||||
const isAdmin = that.props.isAdmin()
|
||||
const isAdminOrCreator = that.props.isAdminOrCreator();
|
||||
const isAdminOrTeacher = that.props.isAdminOrTeacher()
|
||||
const { course_groups, filterKey } = that.state
|
||||
const showSorter = filterKey == '1'
|
||||
const courseId = that.props.match.params.coursesId
|
||||
|
||||
const columns = [{
|
||||
title: '序号',
|
||||
dataIndex: 'name',
|
||||
key: 'index',
|
||||
width: 78,
|
||||
render: (content, item, index) => {
|
||||
return index + 1
|
||||
// return item.isApply == true ? '' : <a href="javascript:;">{(that.state.page - 1) * 20 + index + 1
|
||||
// - (that.state.application_list ? that.state.application_list.length : 0)} </a>
|
||||
}
|
||||
}
|
||||
// ,{
|
||||
// title: '用户ID',
|
||||
// width: 120,
|
||||
// dataIndex: 'login',
|
||||
// key: 'login',
|
||||
// render: (login, record) => {
|
||||
// return <span className="overflowHidden1" style={{ maxWidth: '110px'}} title={`${login.length > 8 ? login : ''}`}>{login}</span>
|
||||
// }
|
||||
// }
|
||||
, {
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 120,
|
||||
key: 'name',
|
||||
sorter: showSorter,
|
||||
sortDirections: sortDirections,
|
||||
sortOrder: sortedInfo.columnKey === 'name' && sortedInfo.order,
|
||||
render: (name, record) => {
|
||||
return <a href={`/users/${record.login}`} target="_blank" className="overflowHidden1" style={{ maxWidth: '110px' }}
|
||||
title={`${name.length > 4 ? name : ''}`}>{name}</a>
|
||||
}
|
||||
}, {
|
||||
title: '角色',
|
||||
dataIndex: 'role',
|
||||
key: 'role',
|
||||
sorter: showSorter,
|
||||
width: 86,
|
||||
// 'ascend' | 'descend'
|
||||
defaultSortOrder: 'ascend',
|
||||
sortDirections: sortDirections,
|
||||
sortOrder: sortedInfo.columnKey === 'role' && sortedInfo.order,
|
||||
|
||||
}]
|
||||
that.state.course_groups && that.state.course_groups.length && showSorter && columns.push({
|
||||
title: <Tooltip title="仅能批阅指定分班的作品">管理权限</Tooltip>,
|
||||
width: 260,
|
||||
key: 'course_groups',
|
||||
dataIndex: 'course_groups',
|
||||
// onClick={() => that.joinCourseGroup(item.id)}
|
||||
// "right":"0px",
|
||||
render: (arg_course_groups, item, index) => {
|
||||
if (!arg_course_groups) {
|
||||
return ''
|
||||
}
|
||||
// ((!course_groups || course_groups.length == 0) && <p>暂未有分班信息,不能操作</p>)
|
||||
const noGroups = (!course_groups || course_groups.length == 0);
|
||||
|
||||
return (
|
||||
<ConditionToolTip title={`暂未有分班信息,不能操作`} condition={noGroups}>
|
||||
<span className="drop_down" style={{ color: '#29BD8B', display: 'inline-block' }}>
|
||||
{(arg_course_groups.length === 0 || arg_course_groups.length === course_groups.length) ? '全部分班' : arg_course_groups.map(item => item.name).join(', ')}
|
||||
{isAdmin &&
|
||||
<React.Fragment>
|
||||
<i className="iconfont icon-xiajiantou font-12 ml2"></i>
|
||||
{!noGroups && <CourseGroupChooser
|
||||
{...{
|
||||
course_groups, isAdminOrCreator, item, index, arg_course_groups,
|
||||
checkAllValue: arg_course_groups.length === course_groups.length,
|
||||
joinCourseGroup: that.joinCourseGroup,
|
||||
onCheckAllChange: that.onCheckAllChange
|
||||
}}
|
||||
></CourseGroupChooser>}
|
||||
</React.Fragment>}
|
||||
</span>
|
||||
</ConditionToolTip>)
|
||||
}
|
||||
,
|
||||
});
|
||||
const hasGraduationModule = that.hasGraduationModule()
|
||||
if (hasGraduationModule && showSorter) {
|
||||
columns.push({
|
||||
title: '所在答辩组',
|
||||
// width: 90,
|
||||
sorter: showSorter,
|
||||
sortDirections: sortDirections,
|
||||
key: 'graduation_group',
|
||||
dataIndex: 'graduation_group',
|
||||
sortOrder: sortedInfo.columnKey === 'graduation_group' && sortedInfo.order,
|
||||
|
||||
render: text => (
|
||||
<span className="overflowHidden1" style={{ maxWidth: '160px' }}
|
||||
title={`${text && text.length > 10 ? text : ''}`}
|
||||
>
|
||||
{text}
|
||||
</span>
|
||||
),
|
||||
})
|
||||
}
|
||||
if (isAdminOrTeacher) {
|
||||
columns.push({
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
render: (text, record) => {
|
||||
const isAdmin = record.role == ROLE_ADMIN
|
||||
const isTeacher = record.role == ROLE_TEACHER
|
||||
const isAssitant = record.role == ROLE_TEACHER_ASSISTANT
|
||||
if (record.application_id) {
|
||||
return (
|
||||
<span>
|
||||
<WordsBtn onClick={() => that.onRefuse(record)} style={'grey'}>拒绝</WordsBtn>
|
||||
<Divider type="vertical" />
|
||||
<a onClick={() => that.onAgree(record)} style={{ color: '#4CACFF' }}>同意</a>
|
||||
</span>)
|
||||
} else {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<WordsBtn style2={{ marginRight: '12px' }} onClick={() => that.onDelete(record)} style={'grey'}>删除</WordsBtn>
|
||||
<ChangeRolePop
|
||||
courseId={courseId}
|
||||
record={record}
|
||||
member_roles={record.member_roles}
|
||||
onChangeRoleSuccess={that.onChangeRoleSuccess}
|
||||
showNotification={that.props.showNotification}
|
||||
getUserId={that.props.isUserid}
|
||||
fetchUser={that.props.fetchUser}
|
||||
|
||||
></ChangeRolePop>
|
||||
{/* <Popconfirm
|
||||
placement="bottom"
|
||||
icon={null}
|
||||
title={
|
||||
<React.Fragment>
|
||||
<Checkbox disable={isAdmin}>管理员</Checkbox>
|
||||
<Checkbox disable={isAdmin}>助教</Checkbox>
|
||||
<Checkbox >学生</Checkbox>
|
||||
</React.Fragment>
|
||||
}
|
||||
>
|
||||
<WordsBtn style={'blue'}>修改角色</WordsBtn>
|
||||
</Popconfirm> */}
|
||||
</React.Fragment>
|
||||
|
||||
|
||||
// <span>
|
||||
// {record.role != ROLE_ADMIN && <WordsBtn onClick={() => that.onDelete(record)} style={'grey'}>删除</WordsBtn>}
|
||||
// {(record.role == ROLE_TEACHER || record.role == ROLE_TEACHER_ASSISTANT || isAdminOrCreator) && record.role != ROLE_ADMIN
|
||||
// && <Divider type="vertical" />}
|
||||
// { record.role == ROLE_TEACHER ? <a style={{color: '#4CACFF'}} onClick={() => that.changeToAssistant(record)}>变更为助教</a> : '' }
|
||||
// { record.role == ROLE_TEACHER_ASSISTANT ? <a style={{color: '#4CACFF'}} onClick={() => that.changeToTeacher(record)}>变更为教师</a> : '' }
|
||||
// { record.role == ROLE_ADMIN && isAdminOrCreator ? <a style={{color: '#4CACFF', marginLeft: '44px'}} onClick={() => that.showChangeAdminModal(record)}>更换管理员</a> : '' }
|
||||
|
||||
// </span>
|
||||
)
|
||||
}
|
||||
|
||||
},
|
||||
})
|
||||
}
|
||||
// 待审批不需要
|
||||
if (filterKey == '1' && isAdminOrTeacher && hasGraduationModule) {
|
||||
columns.unshift({
|
||||
title: '',
|
||||
dataIndex: 'course_member_id',
|
||||
key: 'course_member_id',
|
||||
render: (content, item, key) => {
|
||||
return content ? <Checkbox value={content} key={content}></Checkbox> : ''
|
||||
}
|
||||
})
|
||||
}
|
||||
return columns
|
||||
}
|
||||
|
||||
const ORDER_BY_NAME = 1;
|
||||
const ORDER_BY_DATE = 2;
|
||||
const ORDER_BY_GRADUATION_GROUP = 3;
|
||||
|
||||
class studentsList extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
headIndex: "1",
|
||||
page: 1,
|
||||
sortedInfo: { columnKey: 'role', order: 'ascend' },
|
||||
totalPage: undefined,
|
||||
searchValue: "",
|
||||
order: ORDER_BY_DATE,
|
||||
search: "",
|
||||
groupList: undefined,
|
||||
teachers: [],
|
||||
checkBoxValues: [],
|
||||
isSpin: false,
|
||||
application_list: [],
|
||||
course_groups: [],
|
||||
checkAllArray: [],
|
||||
filterKey: 1, // 1 已审批 2 待审批
|
||||
}
|
||||
}
|
||||
onCheckAllChange = (e, item, index) => {
|
||||
const that = this;
|
||||
const checkAllArray = that.state.checkAllArray.slice(0)
|
||||
checkAllArray[index] = !checkAllArray[index]
|
||||
that.setState({ checkAllArray })
|
||||
if (checkAllArray[index]) {
|
||||
that.joinCourseGroup(that.state.course_groups.map((item) => item.id), item, index)
|
||||
} else {
|
||||
that.joinCourseGroup([], item, index)
|
||||
}
|
||||
}
|
||||
inputSearch = (e) => {
|
||||
this.setState({
|
||||
searchValue: e.target.value
|
||||
})
|
||||
}
|
||||
// approval 2 - 拒绝
|
||||
onAgree = (record, approval = 1) => {
|
||||
const isAdminOrCreator = this.props.isAdminOrCreator()
|
||||
const { course_groups, filterKey, searchValue } = this.state
|
||||
if (approval == 1 && isAdminOrCreator && course_groups && course_groups.length) {
|
||||
this.setState({ clickRecord: record }, () => {
|
||||
this.setGroupChooserModalVisible(true)
|
||||
})
|
||||
return;
|
||||
}
|
||||
const courseId = this.props.match.params.coursesId
|
||||
|
||||
let url = `/courses/${courseId}/teacher_application_review.json`
|
||||
|
||||
this.props.confirm({
|
||||
content: `是否确认${approval == 1 ? '同意' : '拒绝'}TA的加入?`,
|
||||
onOk: () => {
|
||||
axios.post(url, {
|
||||
user_id: record.user_id,
|
||||
application_id: record.application_id,
|
||||
approval: approval
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.props.showNotification(`已${approval == 1 ? '同意' : '拒绝'}`)
|
||||
this.fetchAll(1, filterKey, searchValue)
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
onRefuse = (record) => {
|
||||
this.onAgree(record, 2)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({
|
||||
isSpin: true
|
||||
})
|
||||
let newmenuid = this.props.location.search.replace('?tab=', '');
|
||||
if (newmenuid === undefined || newmenuid === "" || newmenuid === "1" || newmenuid === 1) {
|
||||
this.setState({
|
||||
filterKey: '1'
|
||||
})
|
||||
this.fetchAll(1, '1');
|
||||
} else {
|
||||
this.setState({
|
||||
filterKey: '2'
|
||||
})
|
||||
this.fetchAll(1, '2');
|
||||
}
|
||||
|
||||
|
||||
const isAdminOrTeacher = this.props.isAdminOrTeacher()
|
||||
const isAdmin = this.props.isAdmin()
|
||||
|
||||
isAdminOrTeacher && this.getGroupList();
|
||||
this.getCourseGroups();
|
||||
|
||||
on('addTeacherSuccess', this.addTeacherSuccessListener)
|
||||
isAdmin && on('updateNavSuccess', this.updateNavSuccess)
|
||||
|
||||
}
|
||||
componentWillUnmount() {
|
||||
off('addTeacherSuccess', this.addTeacherSuccessListener)
|
||||
const isAdmin = this.props.isAdmin()
|
||||
isAdmin && off('updateNavSuccess', this.updateNavSuccess)
|
||||
}
|
||||
updateNavSuccess = () => {
|
||||
this.getCourseGroups()
|
||||
}
|
||||
addTeacherSuccessListener = (e, data) => {
|
||||
const { searchValue } = this.state;
|
||||
// const params = JSON.parse(data)
|
||||
// const coursesId = this.props.match.params.coursesId
|
||||
if (window.location.pathname.endsWith('teachers')) {
|
||||
this.fetchAll(1, this.state.filterKey, searchValue)
|
||||
} else {
|
||||
// this.props.history.push(`/courses/${coursesId}/teachers`)
|
||||
}
|
||||
// console.log('addTeacherSuccessListener', data)
|
||||
}
|
||||
getCourseGroups = () => {
|
||||
const courseId = this.props.match.params.coursesId
|
||||
|
||||
let url = `/courses/${courseId}/all_course_groups.json`
|
||||
|
||||
axios.get(url, {
|
||||
params: { all: true }
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.course_groups && response.data.course_groups.length) {
|
||||
let course_groups_map = {}
|
||||
response.data.course_groups.forEach(item => {
|
||||
course_groups_map[item.id] = item.name
|
||||
})
|
||||
this.setState({
|
||||
course_groups: response.data.course_groups,
|
||||
course_groups_map
|
||||
})
|
||||
} else {
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
joinCourseGroup = (ids, item, index) => {
|
||||
// console.log('join ', ids, item)
|
||||
|
||||
const courseId = this.props.match.params.coursesId
|
||||
|
||||
let url = `/courses/${courseId}/set_course_group.json`
|
||||
|
||||
axios.post(url, {
|
||||
course_group_ids: ids,
|
||||
user_id: item.user_id,
|
||||
course_member_id: item.course_member_id
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.props.showNotification('修改成功')
|
||||
this.props.updatabanners()
|
||||
const newArray = ids.map((item) => { return { id: item, name: this.state.course_groups_map[item] } });
|
||||
this.setState(
|
||||
(prevState) => ({
|
||||
teachers: update(prevState.teachers, { [this.state.page == 1 ? index - this.state.application_list.length : index]: { course_groups: { $set: newArray } } })
|
||||
}))
|
||||
// this.fetchAll()
|
||||
} else {
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
onChangeRoleSuccess = () => {
|
||||
this.fetchAll(undefined, this.state.filterKey, this.state.searchValue)
|
||||
}
|
||||
fetchAll = async (argPage, filterKey, searchValue) => {
|
||||
this.setState({
|
||||
isSpin: true
|
||||
})
|
||||
let id = this.props.match.params.coursesId
|
||||
if (argPage) {
|
||||
this.setState({ page: argPage })
|
||||
}
|
||||
|
||||
const sortedInfo = this.state.sortedInfo;
|
||||
let page = argPage || this.state.page
|
||||
|
||||
let order = 1;
|
||||
if (sortedInfo.columnKey == 'role') {
|
||||
order = 1;
|
||||
} else if (sortedInfo.columnKey == 'name') {
|
||||
order = 2;
|
||||
} else if (sortedInfo.columnKey == 'graduation_group') {
|
||||
order = 3;
|
||||
}
|
||||
let sort = 'desc'
|
||||
if (sortedInfo.order == 'ascend') {
|
||||
sort = 'asc'
|
||||
}
|
||||
let url = `/courses/${id}/teachers.json?order=${order}&page=${page}&sort=${sort}`;
|
||||
if (filterKey == '1') {
|
||||
|
||||
} else if (filterKey == '2') {
|
||||
url = `/courses/${id}/apply_teachers.json?_a=1`
|
||||
}
|
||||
if (searchValue) {
|
||||
url += '&search=' + searchValue;
|
||||
}
|
||||
const { updatabanners } = this.props;
|
||||
updatabanners && updatabanners();
|
||||
const result = await axios.get(encodeURI(url))
|
||||
if (result.data.teacher_list) {
|
||||
this.setState({
|
||||
teachers: result.data.teacher_list,
|
||||
total_count: result.data.teacher_list_size,
|
||||
application_list: result.data.application_list || [],
|
||||
is_admin: result.data.is_admin,
|
||||
apply_size: result.data.apply_size,
|
||||
isSpin: false
|
||||
})
|
||||
|
||||
} else if (result.data.application_list) {
|
||||
this.setState({
|
||||
total_count: result.data.teacher_list_size,
|
||||
application_list: result.data.application_list || [],
|
||||
is_admin: result.data.is_admin,
|
||||
apply_size: result.data.apply_size,
|
||||
isSpin: false
|
||||
})
|
||||
}
|
||||
}
|
||||
getGroupList() {
|
||||
let id = this.props.match.params.coursesId
|
||||
let url = '/courses/' + id + '/graduation_group_list.json';
|
||||
axios.get((url)).then((result) => {
|
||||
if (result.status == 200) {
|
||||
this.setState({
|
||||
groupList: result.data
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
onAddGraduationGroupOk = () => {
|
||||
this.getGroupList()
|
||||
}
|
||||
|
||||
// join_graduation_group
|
||||
joinGraduationGroup = (graduation_group_id) => {
|
||||
const courseId = this.props.match.params.coursesId
|
||||
let { filterKey, searchValue } = this.state
|
||||
let url = `/courses/${courseId}/join_graduation_group.json`;
|
||||
axios.post(url, {
|
||||
course_member_list: this.state.checkBoxValues.map(item => { return { course_member_id: item } }),
|
||||
graduation_group_id: graduation_group_id
|
||||
}).then((result) => {
|
||||
if (result.data.status == 0) {
|
||||
this.props.showNotification('操作成功。')
|
||||
this.fetchAll(undefined, filterKey, searchValue);
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
onInputSearchChange = (e) => {
|
||||
// let {filterKey}=this.state;
|
||||
this.setState({
|
||||
searchValue: e.target.value
|
||||
})
|
||||
|
||||
// if (this.timeoutHandler) {
|
||||
// clearTimeout(this.timeoutHandler)
|
||||
// }
|
||||
// this.timeoutHandler = setTimeout(() => {
|
||||
// this.fetchAll(1,filterKey,e.target.value)
|
||||
// }, 1200)
|
||||
}
|
||||
|
||||
onPressEnter = (value) => {
|
||||
this.setState({
|
||||
searchValue: value
|
||||
})
|
||||
this.fetchAll(1, this.state.filterKey, value);
|
||||
}
|
||||
|
||||
|
||||
onCheckBoxChange = (checkedValues) => {
|
||||
this.setState({
|
||||
checkBoxValues: checkedValues,
|
||||
checkAllValue: checkedValues.length == this.state.teachers.length
|
||||
})
|
||||
}
|
||||
onCheckAll = (e) => {
|
||||
this.setState({
|
||||
checkAllValue: e.target.checked
|
||||
})
|
||||
const values = this.state.teachers.map(item => {
|
||||
return item.course_member_id
|
||||
})
|
||||
if (e.target.checked) {
|
||||
const concated = this.state.checkBoxValues.concat(values);
|
||||
const sortedUniqed = _.uniq(concated)
|
||||
this.setState({
|
||||
checkBoxValues: sortedUniqed
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
checkBoxValues: _.difference(this.state.checkBoxValues, values),
|
||||
})
|
||||
}
|
||||
}
|
||||
onSortTypeChange = (order) => {
|
||||
const { page, searchValue } = this.state;
|
||||
this.setState({ order: order }, () => {
|
||||
this.fetchAll(page, undefined, searchValue);
|
||||
})
|
||||
}
|
||||
changeRole = (member, role) => {
|
||||
|
||||
const courseId = this.props.match.params.coursesId
|
||||
let { filterKey } = this.state;
|
||||
let url = `/courses/${courseId}/change_course_teacher.json`;
|
||||
axios.post(url, {
|
||||
course_member_id: member.course_member_id
|
||||
// "user_list": [
|
||||
// { "user_id": member.user_id }
|
||||
// ],
|
||||
// "graduation_group_id": member.graduation_group_id,
|
||||
// "course_group_id": "820",
|
||||
// "role": role
|
||||
}).then((result) => {
|
||||
if (result.data.status == 0) {
|
||||
this.props.showNotification('操作成功。')
|
||||
this.fetchAll(undefined, filterKey)
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
changeToAssistant = (member) => {
|
||||
this.changeRole(member, ROLE_ASSISTANT_NUM)
|
||||
}
|
||||
changeToTeacher = (member) => {
|
||||
this.changeRole(member, ROLE_TEACHER_NUM)
|
||||
}
|
||||
showChangeAdminModal = () => {
|
||||
this.refs.addAdminModal.setVisible(true)
|
||||
}
|
||||
changeAdminSuccess = () => {
|
||||
let { filterKey } = this.state;
|
||||
this.fetchAll(undefined, filterKey)
|
||||
}
|
||||
onDelete = (member) => {
|
||||
let { filterKey } = this.state;
|
||||
this.props.confirm({
|
||||
content: `确认要将“${member.name}”从教师列表中移除吗?`,
|
||||
onOk: () => {
|
||||
// const cid = this.props.match.params.coursesId
|
||||
const courseId = this.props.match.params.coursesId
|
||||
|
||||
const url = `/courses/${courseId}/delete_course_teacher.json`
|
||||
axios.post(url, {
|
||||
course_member_id: member.course_member_id
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
// {"status":1,"message":"删除成功"}
|
||||
this.props.showNotification('删除成功')
|
||||
trigger('updatabanner')
|
||||
this.fetchAll(undefined, filterKey)
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
addTeacher = () => {
|
||||
this.refs.addTeacherModal.setVisible(true)
|
||||
}
|
||||
addStudent = () => {
|
||||
this.refs.addStudentModal.setVisible(true)
|
||||
}
|
||||
|
||||
hasGraduationModule = () => {
|
||||
const { course_modules } = this.props;
|
||||
const result = course_modules && course_modules.filter(item => {
|
||||
return item.type == 'graduation'
|
||||
})
|
||||
return result && result.length > 0
|
||||
}
|
||||
|
||||
onTableChange = (pagination, filters, sorter) => {
|
||||
let { filterKey } = this.state;
|
||||
console.log('Various parameters', pagination, filters, sorter);
|
||||
this.setState({
|
||||
page: pagination.current,
|
||||
sortedInfo: sorter,
|
||||
}, () => {
|
||||
this.fetchAll(undefined, filterKey)
|
||||
});
|
||||
};
|
||||
clearSelection = () => {
|
||||
this.setState({ checkBoxValues: [] })
|
||||
}
|
||||
selectedStatus = (e) => {
|
||||
this.clearSelection()
|
||||
this.setState({
|
||||
filterKey: e.key,
|
||||
page: 1,
|
||||
isSpin: true
|
||||
}, () => {
|
||||
this.fetchAll(undefined, e.key);
|
||||
})
|
||||
}
|
||||
setGroupChooserModalVisible = (visible) => {
|
||||
// 这里只会调用open
|
||||
this.setState({ groupChooserModalVisible: !this.state.groupChooserModalVisible })
|
||||
}
|
||||
render() {
|
||||
const isAdmin = this.props.isAdmin()
|
||||
const columns = buildColumns(this)
|
||||
let {
|
||||
searchValue, checkBoxValues, checkAllValue, course_groups,
|
||||
groupList, total_count, teachers, order, page, apply_size, filterKey
|
||||
} = this.state
|
||||
let currentOrderName = '加入时间排序'
|
||||
if (order == ORDER_BY_NAME) {
|
||||
currentOrderName = '姓名排序'
|
||||
} else if (order == ORDER_BY_GRADUATION_GROUP) {
|
||||
currentOrderName = '答辩组排序'
|
||||
}
|
||||
let combineArray = teachers.slice(0)
|
||||
if (page == 1 && filterKey == '2') {
|
||||
// this.state.application_list && this.state.application_list.slice(0).reverse().forEach(item => {
|
||||
// item.isApply = true
|
||||
// combineArray.unshift(item)
|
||||
// })
|
||||
combineArray = this.state.application_list
|
||||
}
|
||||
const isAdminOrTeacher = this.props.isAdminOrTeacher()
|
||||
const isAdminOrCreator = this.props.isAdminOrCreator()
|
||||
const isSuperAdmin = this.props.isSuperAdmin()
|
||||
const hasGraduationModule = this.hasGraduationModule()
|
||||
const coursesId = this.props.match.params.coursesId
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{/* <AddTeacherModal ref="addTeacherModal"
|
||||
{...this.props}
|
||||
moduleName="教师"
|
||||
></AddTeacherModal>
|
||||
<AddStudentModal ref="addStudentModal"
|
||||
{...this.props}
|
||||
moduleName="学生"
|
||||
></AddStudentModal> */}
|
||||
{isAdminOrTeacher && <AddGraduationGroupModal ref="addGraduationGroupModal"
|
||||
{...this.props} onOk={this.onAddGraduationGroupOk}
|
||||
></AddGraduationGroupModal>}
|
||||
<AddAdminModal ref="addAdminModal"
|
||||
{...this.props} onOk={this.showChangeAdminModal}
|
||||
changeAdminSuccess={this.changeAdminSuccess}
|
||||
></AddAdminModal>
|
||||
|
||||
<Titlesearchsection
|
||||
title={<React.Fragment>
|
||||
<span>教师列表</span>
|
||||
{!isSuperAdmin && coursesId == '1309' && <span style={{ color: '#848484', fontSize: '14px', marginLeft: '10px' }}>(示例课堂,部分成员不可见)</span>}
|
||||
</React.Fragment>}
|
||||
searchValue={searchValue}
|
||||
onInputSearchChange={this.onInputSearchChange}
|
||||
showSearchInput={total_count >= 10}
|
||||
searchPlaceholder={'请输入姓名进行搜索'}
|
||||
firstRowRight={
|
||||
<React.Fragment>
|
||||
{/* { isAdmin && <WordsBtn style="blue" className="mr30" onClick={()=>this.addTeacher()}>添加教师</WordsBtn> }
|
||||
{ isAdmin && <WordsBtn style="blue" className="mr30" onClick={()=>this.addStudent()}>添加学生</WordsBtn> } */}
|
||||
|
||||
{isAdminOrCreator && <WordsBtn style="blue" className="fr" onClick={() => this.showChangeAdminModal()}>更换管理员</WordsBtn>}
|
||||
|
||||
</React.Fragment>
|
||||
}
|
||||
secondRowLeft={
|
||||
isAdminOrTeacher ? <div className="fl mt6 task_menu_ul " style={{ width: '600px' }}>
|
||||
<Menu mode="horizontal" selectedKeys={[`${this.state.filterKey}`]} onClick={this.selectedStatus}>
|
||||
<Menu.Item key="1">已审批({total_count})</Menu.Item>
|
||||
<Menu.Item key="2">待审批({apply_size})</Menu.Item>
|
||||
</Menu>
|
||||
{/* */}
|
||||
</div> :
|
||||
(!!total_count ? <ColorCountText count={total_count} name="个教师"></ColorCountText> : '')
|
||||
}
|
||||
onPressEnter={this.onPressEnter}
|
||||
></Titlesearchsection>
|
||||
|
||||
<style>{`
|
||||
/* CourseGroupChooser */
|
||||
.drop_down_menu .mainGroup.ant-checkbox-group {
|
||||
max-height: 170px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.task_menu_ul .ant-menu-item, .task_menu_ul .ant-menu-submenu-title{
|
||||
padding:0px;
|
||||
margin-right: 30px;
|
||||
line-height: 68px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.teacherList .ant-table-pagination.ant-pagination {
|
||||
float: none;
|
||||
text-align: center;
|
||||
}
|
||||
.drop_down_menu .drop_down_btn{
|
||||
border-top:none;
|
||||
}
|
||||
.dividerStyle.ant-divider-horizontal{
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.drop_down_menu li {
|
||||
line-height:30px!important;
|
||||
flex: 0 0 30px;
|
||||
}
|
||||
|
||||
.teacher_table .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
|
||||
padding: 16px 10px;
|
||||
}
|
||||
`}</style>
|
||||
<div className="mt20 edu-back-white padding20 teacherList">
|
||||
|
||||
{course_groups && !!course_groups.length && <CourseGroupChooserModal
|
||||
{...this.state}
|
||||
{...this.props}
|
||||
props={{ match: this.props.match, showNotification: this.props.showNotification }}
|
||||
record={this.state.clickRecord}
|
||||
fetchAll={(e) => this.fetchAll(e, this.state.filterKey)}
|
||||
course_groups={course_groups}
|
||||
visible={this.state.groupChooserModalVisible}
|
||||
setVisible={this.setGroupChooserModalVisible}
|
||||
></CourseGroupChooserModal>}
|
||||
{filterKey == '1' && <div className="clearfix stu_head" style={{ paddingLeft: '15px' }}>
|
||||
{isAdminOrTeacher && hasGraduationModule && <Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue} >已选 {checkBoxValues.length} 个</Checkbox>}
|
||||
{filterKey == '1' && <div className="studentList_operation_ul">
|
||||
{hasGraduationModule && isAdminOrTeacher && <li className="li_line drop_down">
|
||||
加入答辩组<i className="iconfont icon-xiajiantou font-12 ml2"></i>
|
||||
<ul className="drop_down_menu" style={{ "right": "0px", "left": "unset", minWidth: '222px' }}>
|
||||
|
||||
{
|
||||
groupList && groupList.graduation_groups_count > 10 ?
|
||||
(<p className="drop_down_search">
|
||||
<Input placeholder="搜索" value={this.state.graduationGroupSearchValue} onChange={(e) => { this.setState({ graduationGroupSearchValue: e.target.value }) }} allowClear />
|
||||
</p>) :
|
||||
(groupList && groupList.graduation_groups_count == 0 && <p style={{ textAlign: 'left', margin: '0px 20px' }}>暂无数据</p>)
|
||||
}
|
||||
{
|
||||
groupList && groupList.graduation_group_list && groupList.graduation_group_list.filter((item) => {
|
||||
return (!this.state.graduationGroupSearchValue || item.name.indexOf(this.state.graduationGroupSearchValue) != -1)
|
||||
}).map((item, key) => {
|
||||
return (
|
||||
<li key={key} value={item.id} onClick={() => this.joinGraduationGroup(item.id)}>{item.name}</li>
|
||||
)
|
||||
})
|
||||
}
|
||||
{groupList && groupList.graduation_groups_count > 0 && <Divider className="dividerStyle"></Divider>}
|
||||
<p className="drop_down_btn">
|
||||
<a className="color-grey-6"
|
||||
onClick={() => this.refs['addGraduationGroupModal'].setVisible(true)}
|
||||
>添加答辩组...</a>
|
||||
</p>
|
||||
</ul>
|
||||
</li>}
|
||||
{/* <li className="drop_down">
|
||||
{currentOrderName} <i className="iconfont icon-xiajiantou font-12 ml2"></i>
|
||||
<ul className="drop_down_normal">
|
||||
<li onClick={() => this.onSortTypeChange(ORDER_BY_NAME)} >姓名排序</li>
|
||||
<li onClick={() => this.onSortTypeChange(ORDER_BY_DATE)} style={{width: '125px'}}>加入时间排序</li>
|
||||
{this.hasGraduationModule() && <li onClick={() => this.onSortTypeChange(ORDER_BY_GRADUATION_GROUP)} >答辩组排序</li>}
|
||||
</ul>
|
||||
</li> */}
|
||||
</div>}
|
||||
</div>}
|
||||
<Spin size="large" spinning={this.state.isSpin}>
|
||||
<div className="clearfix stu_table teacher_table">
|
||||
{combineArray.length ?
|
||||
<Checkbox.Group style={{ width: '100%' }} onChange={this.onCheckBoxChange} value={checkBoxValues}>
|
||||
{/* pagination={{ current: page, total: total_count, pageSize:20, onChange: this.onPageChange }} */}
|
||||
<Table columns={columns} dataSource={combineArray}
|
||||
onChange={this.onTableChange}
|
||||
pagination={total_count > 20 && filterKey == '1' ? { //分页
|
||||
total: page == 1 && this.state.application_list.length ? total_count + total_count / Math.floor(this.state.application_list.length + 20) : total_count, //数据总数量
|
||||
pageSize: page == 1 && this.state.application_list.length ? this.state.application_list.length + 20 : 20, //显示几条一页
|
||||
current: page,
|
||||
// onChange: this.onPageChange
|
||||
} : false}
|
||||
></Table>
|
||||
</Checkbox.Group>
|
||||
:
|
||||
<NoneData></NoneData>}
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default studentsList;
|
|
@ -1,140 +0,0 @@
|
|||
import React, {Component} from "react";
|
||||
import { WordsBtn,on, off, trigger,MarkdownToHtml,getImageUrl} from 'educoder';
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
message,
|
||||
InputNumber,
|
||||
DatePicker,
|
||||
Radio,
|
||||
Tooltip,
|
||||
notification,
|
||||
} from "antd";
|
||||
import GroupPackage from '../groupjobbank/GroupPackage'
|
||||
import './questionbank.css';
|
||||
import AttachmentsList from '../../../common/components/attachment/AttachmentList';
|
||||
import NoneData from '../../courses/coursesPublic/NoneData'
|
||||
|
||||
class Generaljobanswer extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
console.log("Generaljobanswer");
|
||||
console.log("componentDidMount");
|
||||
// let query = this.props.location.pathname;
|
||||
// const type = query.split('/');
|
||||
// this.setState({n
|
||||
// shixuntypes:type[3]
|
||||
// })
|
||||
// this.props.triggerRef(this);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
// 获取数据地方
|
||||
getTrainingjobsetting = () => {
|
||||
var homeworkid = this.props.match.params.homeworkid;
|
||||
}
|
||||
|
||||
//跳转道描点的地方
|
||||
scrollToAnchor = (anchorName) => {
|
||||
if (anchorName) {
|
||||
// 找到锚点
|
||||
let anchorElement = document.getElementById(anchorName);
|
||||
// 如果对应id的锚点存在,就跳转到锚点
|
||||
if(anchorElement) { anchorElement.scrollIntoView(); }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
let{datas}=this.props;
|
||||
console.log("Generaljobanswer");
|
||||
console.log(datas.reference_attachments);
|
||||
console.log(datas.reference_answer);
|
||||
return (
|
||||
<div className=" clearfix edu-back-white " ref='targetElementTrainingjobsetting' style={{margin: "auto", minWidth:"1200px"}}>
|
||||
<div className="yslquestionbank1">
|
||||
{/*{*/}
|
||||
{/* datas&&(datas.reference_answer===null?*/}
|
||||
{/* <NoneData></NoneData>*/}
|
||||
{/* :datas.reference_answer==="null"?*/}
|
||||
{/* <NoneData></NoneData>*/}
|
||||
{/* :*/}
|
||||
{/* datas.reference_answer===""?*/}
|
||||
{/* <NoneData></NoneData>*/}
|
||||
{/* :*/}
|
||||
{/* <MarkdownToHtml content={datas.reference_answer} selector="work_content" className="mb10 yslquesHeigth "></MarkdownToHtml>*/}
|
||||
|
||||
{/* // <div id="MakedownHTML"className="markdown-body yslquesHeigth yslquesmarkdowntext" dangerouslySetInnerHTML={{__html: markdownToHTML(datas.reference_answer).replace(/▁/g, "▁▁▁")}}/>*/}
|
||||
{/* )*/}
|
||||
{/*}*/}
|
||||
{/*/!*<div id="MakedownHTML"className="markdown-body yslquesHeigth yslquesmarkdowntext" dangerouslySetInnerHTML={{__html: markdownToHTML(datas&&(datas.reference_answer===null?"无":datas.reference_answer==="null"?"无":datas.reference_answer)).replace(/▁/g, "▁▁▁")}}/>*!/*/}
|
||||
{/*<div className="mt16px">*/}
|
||||
{/*{datas.reference_attachments === undefined ? "" :*/}
|
||||
{/* <AttachmentsList {...this.state} {...this.props} attachments={datas.reference_attachments} ></AttachmentsList>}*/}
|
||||
{/*</div>*/}
|
||||
|
||||
{
|
||||
datas.reference_answer===null?
|
||||
""
|
||||
:datas.reference_answer==="null"?
|
||||
"" :
|
||||
datas.reference_answer===""?
|
||||
""
|
||||
:
|
||||
<MarkdownToHtml content={datas.reference_answer} selector="work_content" className="mb10 yslquesHeigth "></MarkdownToHtml>
|
||||
|
||||
}
|
||||
|
||||
{datas.reference_attachments === undefined ?
|
||||
(datas.reference_answer===undefined || datas.reference_answer===null|| datas.reference_answer===""?
|
||||
<NoneData></NoneData>
|
||||
:
|
||||
""
|
||||
)
|
||||
:
|
||||
datas.reference_attachments === "" ?
|
||||
(datas.reference_answer===undefined || datas.reference_answer===null|| datas.reference_answer===""?
|
||||
<NoneData></NoneData>
|
||||
:
|
||||
""
|
||||
)
|
||||
:
|
||||
datas.reference_attachments === null ?
|
||||
(datas.reference_answer===undefined || datas.reference_answer===null|| datas.reference_answer===""?
|
||||
<NoneData></NoneData>
|
||||
:
|
||||
""
|
||||
)
|
||||
:
|
||||
datas.reference_attachments.length === 0 ?
|
||||
(datas.reference_answer===undefined || datas.reference_answer===null|| datas.reference_answer===""?
|
||||
<NoneData></NoneData>
|
||||
:
|
||||
""
|
||||
)
|
||||
:
|
||||
<div className="mt24">
|
||||
<AttachmentsList {...this.state} {...this.props} attachments={datas.reference_attachments} ></AttachmentsList>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Generaljobanswer;
|
|
@ -1,170 +0,0 @@
|
|||
import React, {Component} from "react";
|
||||
import {BrowserRouter as Router,Route,Switch,Link, NavLin} from 'react-router-dom';
|
||||
import {WordsBtn, ActionBtn,getImageUrl} from 'educoder';
|
||||
import { Input,Checkbox,Table, Pagination, Modal,Menu, Tooltip,Spin,Button,Form } from "antd";
|
||||
import axios from 'axios';
|
||||
import BanksMenu from '../../user/usersInfo/banks/banksMenu'
|
||||
import Loadable from 'react-loadable';
|
||||
import Loading from '../../../Loading';
|
||||
import '../css/members.css';
|
||||
import "../common/formCommon.css";
|
||||
import '../css/Courses.css';
|
||||
import '../css/busyWork.css';
|
||||
import '../poll/pollStyle.css';
|
||||
// 问卷内容
|
||||
const Generaljobdetails = Loadable({
|
||||
loader: () => import('./Generaljobdetails'),
|
||||
loading: Loading,
|
||||
})
|
||||
// 试卷详情
|
||||
const Generaljobanswer = Loadable({
|
||||
loader: () => import('./Generaljobanswer'),
|
||||
loading: Loading,
|
||||
});
|
||||
class Generaljobbankdetails extends Component {
|
||||
//普通作业内容详情
|
||||
constructor(props) {
|
||||
super(props);
|
||||
// this.answerMdRef = React.createRef();
|
||||
this.state = {
|
||||
tab: ["0"],
|
||||
workid:1,
|
||||
isSpin:false,
|
||||
datas:[],
|
||||
visible:false,
|
||||
banksMenu:undefined
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getonedata();
|
||||
|
||||
}
|
||||
|
||||
getonedata=()=>{
|
||||
if( this.props.match.params.workid){
|
||||
this.setState({
|
||||
workid: this.props.match.params.workid,
|
||||
})
|
||||
}
|
||||
this.getdata(this.props.match.params.workid);
|
||||
};
|
||||
//获取数据的地方
|
||||
getdata=(workid)=>{
|
||||
var workids= workid;
|
||||
if(workids){
|
||||
|
||||
}else{
|
||||
workids=this.state.workid;
|
||||
}
|
||||
this.setState({
|
||||
isSpin:true,
|
||||
})
|
||||
let url = `/homework_banks/${workids}.json`;
|
||||
//
|
||||
axios.get(url).then((response) => {
|
||||
if(response){
|
||||
if(response.data){
|
||||
this.setState({
|
||||
datas:response.data,
|
||||
})
|
||||
try {
|
||||
const crumbData={
|
||||
title:response && response.data && response.data.name,
|
||||
is_public:response && response.data && response.data.is_public,
|
||||
crumbArray:[
|
||||
{content:'详情'}
|
||||
]
|
||||
};
|
||||
const menuData={
|
||||
tab:'0',//tab选中的index
|
||||
menuArray:[//tab以及tab路由
|
||||
{to:`/banks/normal/${workids}/${this.props.match.params.type}?tab=0`,content:'内容详情'},
|
||||
{to:`/banks/normal/${workids}/${this.props.match.params.type}/answer?tab=1`,content:'参考答案'}
|
||||
],
|
||||
category:'normal',//毕设选题
|
||||
tos:`/banks/normal/${workids}/edit/${this.props.match.params.type}?tab=0`,
|
||||
id:workids,
|
||||
is_public:response && response.data && response.data.is_public,
|
||||
type:this.props.match.params.type,
|
||||
authorize:response && response.data && response.data.authorize,
|
||||
|
||||
}
|
||||
this.setState({
|
||||
banksMenu:menuData
|
||||
})
|
||||
this.props.initPublic(crumbData,response.data);
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
}else {
|
||||
this.setState({
|
||||
datas:[],
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
}else {
|
||||
this.setState({
|
||||
datas:[],
|
||||
})
|
||||
|
||||
}
|
||||
this.setState({
|
||||
isSpin:false,
|
||||
})
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
this.setState({
|
||||
datas:[],
|
||||
isSpin:false,
|
||||
})
|
||||
});
|
||||
};
|
||||
// initPublic = (crumbData,menuData) =>{
|
||||
// this.setState({
|
||||
// banksMenu:menuData
|
||||
// })
|
||||
// this.props.initPublic(crumbData);
|
||||
// }
|
||||
|
||||
render() {
|
||||
let {tab,datas,visible} = this.state;
|
||||
|
||||
let{
|
||||
banksMenu
|
||||
}=this.state
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="pd30">
|
||||
{
|
||||
banksMenu &&
|
||||
<BanksMenu
|
||||
banksMenu={banksMenu}
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
></BanksMenu>
|
||||
}
|
||||
<Switch {...this.props}>
|
||||
<Route path={`/banks/normal/:workid/${this.props.match.params.type}/answer`}
|
||||
render={
|
||||
(props) => {
|
||||
return (<Generaljobanswer {...this.props} {...props} {...this.state} datas={datas} />)
|
||||
}
|
||||
}></Route>
|
||||
<Route path={`/banks/normal/:workid/${this.props.match.params.type}`}
|
||||
render={
|
||||
(props) => {
|
||||
return (<Generaljobdetails {...this.props} {...props} {...this.state} datas={datas} />)
|
||||
}
|
||||
}></Route>
|
||||
|
||||
</Switch>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Generaljobbankdetails;
|
|
@ -1,117 +0,0 @@
|
|||
|
||||
import React, {Component} from "react";
|
||||
import { WordsBtn,on, off, trigger,markdownToHTML, MarkdownToHtml ,getImageUrl} from 'educoder';
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
message,
|
||||
InputNumber,
|
||||
DatePicker,
|
||||
Radio,
|
||||
Tooltip,
|
||||
notification,
|
||||
} from "antd";
|
||||
import GroupPackage from '../groupjobbank/GroupPackage'
|
||||
import './questionbank.css';
|
||||
import AttachmentsList from "../../../common/components/attachment/AttachmentList";
|
||||
import NoneData from '../../courses/coursesPublic/NoneData'
|
||||
//内容详情
|
||||
class Generaljobdetails extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
console.log("Generaljobdetails");
|
||||
console.log("componentDidMount");
|
||||
// let query = this.props.location.pathname;
|
||||
// const type = query.split('/');
|
||||
// this.setState({
|
||||
// shixuntypes:type[3]
|
||||
// })
|
||||
// this.props.triggerRef(this);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
// 获取数据地方
|
||||
getTrainingjobsetting = () => {
|
||||
var homeworkid = this.props.match.params.homeworkid;
|
||||
}
|
||||
|
||||
//跳转道描点的地方
|
||||
scrollToAnchor = (anchorName) => {
|
||||
if (anchorName) {
|
||||
// 找到锚点
|
||||
let anchorElement = document.getElementById(anchorName);
|
||||
// 如果对应id的锚点存在,就跳转到锚点
|
||||
if(anchorElement) { anchorElement.scrollIntoView(); }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
let{datas}=this.props;
|
||||
return (
|
||||
<div className=" clearfix edu-back-white " ref='targetElementTrainingjobsetting' style={{margin: "auto", minWidth:"1200px"}}>
|
||||
<div className="yslquestionbank1">
|
||||
{
|
||||
datas.description===null?
|
||||
""
|
||||
:datas.description==="null"?
|
||||
""
|
||||
:datas&&datas.description===""?
|
||||
""
|
||||
:
|
||||
<MarkdownToHtml content={datas.description} selector="work_content" className="mb10 yslquesHeigth"></MarkdownToHtml>
|
||||
// <div id="MakedownHTML "className="markdown-body yslquesHeigth yslquesmarkdowntext" dangerouslySetInnerHTML={{__html: markdownToHTML(datas.description).replace(/▁/g, "▁▁▁")}}/>
|
||||
}
|
||||
{datas.attachments === undefined ?
|
||||
(datas.description === undefined || datas.description === null || datas.description === "" ?
|
||||
<NoneData></NoneData>
|
||||
:
|
||||
""
|
||||
)
|
||||
:
|
||||
datas.attachments=== "" ?
|
||||
(datas.description === undefined || datas.description === null || datas.description === "" ?
|
||||
<NoneData></NoneData>
|
||||
:
|
||||
""
|
||||
)
|
||||
:
|
||||
datas.attachments=== null ?
|
||||
(datas.description === undefined || datas.description === null || datas.description === "" ?
|
||||
<NoneData></NoneData>
|
||||
:
|
||||
""
|
||||
)
|
||||
:
|
||||
datas.attachments.length === 0 ?
|
||||
(datas.description === undefined || datas.description === null || datas.description === "" ?
|
||||
<NoneData></NoneData>
|
||||
:
|
||||
""
|
||||
)
|
||||
:
|
||||
<div className="mt16px">
|
||||
<AttachmentsList {...this.state} {...this.props}
|
||||
attachments={datas.attachments}></AttachmentsList>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Generaljobdetails;
|
|
@ -1,33 +0,0 @@
|
|||
.yslquestionbank1{
|
||||
padding-top: 30px !important;
|
||||
padding-right: 30px !important;
|
||||
padding-left: 30px !important;
|
||||
min-height: 500px !important;
|
||||
}
|
||||
.yslquesHeigth{
|
||||
width: 100% !important;
|
||||
}
|
||||
.yslquesmarkdowntext{
|
||||
font-size: 16px;
|
||||
color: #707070;
|
||||
|
||||
}
|
||||
.yslquesmat26{
|
||||
margin-top: 26px;
|
||||
padding-bottom: 44px !important;
|
||||
}
|
||||
.ysltextcolor9999{
|
||||
color: #999999;
|
||||
font-size: 14px;
|
||||
}
|
||||
.ysltextcolor99999{
|
||||
color: #999999;
|
||||
font-size: 16px;
|
||||
}
|
||||
.mt16px{
|
||||
margin-top: 16px;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
.pd30{
|
||||
padding-bottom: 30px;
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
import React, {Component} from "react";
|
||||
import {Menu, Dropdown, Icon, Input, Checkbox} from "antd";
|
||||
import {getImageUrl} from 'educoder';
|
||||
|
||||
const {Search} = Input;
|
||||
|
||||
class Dropdownbox extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
activeKey: '1',
|
||||
visible: false,
|
||||
onSearchvalue: undefined,
|
||||
checkedValues: []
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let {group_ids} = this.props;
|
||||
if (group_ids) {
|
||||
this.setState({
|
||||
checkedValues: group_ids
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate = (prevProps) => {
|
||||
if (prevProps != this.props) {
|
||||
let {group_ids} = this.props;
|
||||
if (group_ids) {
|
||||
this.setState({
|
||||
checkedValues: group_ids
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
SaveChange = () => {
|
||||
this.props.postwork_scoredata(this.state.checkedValues)
|
||||
}
|
||||
|
||||
|
||||
handleVisibleChange = flag => {
|
||||
this.setState({visible: flag});
|
||||
};
|
||||
|
||||
CheckboxonChange = (checkedValues) => {
|
||||
this.setState({
|
||||
checkedValues: checkedValues
|
||||
})
|
||||
}
|
||||
|
||||
unCheckboxonChange = () => {
|
||||
this.setState({
|
||||
checkedValues: [],
|
||||
onSearchvalue: undefined
|
||||
})
|
||||
}
|
||||
|
||||
onSearch = (value) => {
|
||||
this.setState({
|
||||
onSearchvalue: value
|
||||
})
|
||||
}
|
||||
|
||||
onSearchonChange = (e) => {
|
||||
this.setState({
|
||||
onSearchvalue: e.target.value
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
let {course_groups} = this.props;
|
||||
|
||||
const menu = (
|
||||
<Checkbox.Group style={{width: 220}} className={"StatisticsMenubox"} value={this.state.checkedValues}
|
||||
onChange={(checkedValues) => this.CheckboxonChange(checkedValues)}>
|
||||
<Menu className="Statisticslibox">
|
||||
<li className={"Statisticsli"}>
|
||||
{course_groups && course_groups.length > 10 ? <Search
|
||||
placeholder="请输入名称搜索"
|
||||
onSearch={(value) => this.onSearch(value)}
|
||||
onChange={(e) => this.onSearchonChange(e)}
|
||||
value={this.state.onSearchvalue}
|
||||
style={{width: 200}}
|
||||
/> : ""}
|
||||
</li>
|
||||
{course_groups && course_groups.map((item, key) => {
|
||||
if (this.state.onSearchvalue) {
|
||||
if (item.name.indexOf(this.state.onSearchvalue) != -1) {
|
||||
return (
|
||||
<Menu.Item key={key}>
|
||||
<Checkbox value={item.id} key={item.id}> {item.name}</Checkbox>
|
||||
</Menu.Item>
|
||||
)
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<Menu.Item key={key}>
|
||||
<Checkbox value={item.id} key={item.id}> {item.name}</Checkbox>
|
||||
</Menu.Item>
|
||||
)
|
||||
}
|
||||
})}
|
||||
<Menu.Divider/>
|
||||
<li className={"Statisticsli"}>
|
||||
<span onClick={() => this.SaveChange()} className={"ant-btn-link"}>确定</span>
|
||||
<span className={"ml20 ant-btn-link"} onClick={() => this.unCheckboxonChange()}>重置</span>
|
||||
</li>
|
||||
</Menu>
|
||||
</Checkbox.Group>
|
||||
);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Dropdown overlay={menu}
|
||||
onVisibleChange={this.handleVisibleChange}
|
||||
visible={this.state.visible}
|
||||
>
|
||||
<a className="ant-dropdown-link">
|
||||
分班 <Icon type="down"/>
|
||||
</a>
|
||||
</Dropdown>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Dropdownbox;
|
|
@ -1,90 +0,0 @@
|
|||
import React,{ Component } from "react";
|
||||
import {Row, Col,Popover,Button,Icon} from "antd";
|
||||
import {
|
||||
G2,
|
||||
Chart,
|
||||
Geom,
|
||||
Axis,
|
||||
Tooltip,
|
||||
Coord,
|
||||
Label,
|
||||
Legend,
|
||||
View,
|
||||
Guide,
|
||||
Shape,
|
||||
Facet,
|
||||
Util
|
||||
} from "bizcharts";
|
||||
|
||||
class Dynamiclist extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render(){
|
||||
const data = []
|
||||
let {course_members}=this.props;
|
||||
if(course_members){
|
||||
if(course_members.length>0){
|
||||
course_members.map((item,key)=>{
|
||||
data.push({'name':item.user_name,'活跃度':item.total_score})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const content = (
|
||||
<div className={"Statisticscircle"}>
|
||||
<p>
|
||||
作业完成数(*10)
|
||||
</p>
|
||||
<p>
|
||||
试卷完成数(*10)
|
||||
</p>
|
||||
<p>
|
||||
问卷完成数(*7)
|
||||
</p>
|
||||
<p>
|
||||
资源发布数(*5)
|
||||
</p>
|
||||
<p>
|
||||
帖子发布数(*2)
|
||||
</p>
|
||||
<p>
|
||||
帖子回复数(*1)
|
||||
</p>
|
||||
<p>
|
||||
作业回复数(*1)
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
return(
|
||||
<React.Fragment>
|
||||
<Row>
|
||||
<Col span={12} className={"top10s"}>Top 10</Col>
|
||||
<Col span={12} className={"Statisticsliboxjsgz"}>
|
||||
<span className={"mr10"}>计算规则</span>
|
||||
<Popover placement="bottom" title={"活动规则计算说明"} content={content} trigger="hover">
|
||||
<Icon type="info-circle" />
|
||||
</Popover>
|
||||
</Col>
|
||||
</Row>
|
||||
{/*scale={cols}*/}
|
||||
<Chart height={400} data={data} forceFit>
|
||||
<Axis name="name" />
|
||||
<Axis name="活跃度" />
|
||||
<Tooltip
|
||||
crosshairs={{
|
||||
type: "y"
|
||||
}}
|
||||
/>
|
||||
<Geom type="interval" position="name*活跃度" />
|
||||
</Chart>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default Dynamiclist;
|
|
@ -1,148 +0,0 @@
|
|||
.height-60{
|
||||
line-height: 60px;
|
||||
height:60px;
|
||||
background:rgba(255,208,88,1);
|
||||
border-radius:4px 4px 0px 0px;
|
||||
}
|
||||
.height-40{
|
||||
line-height: 40px;
|
||||
height:40px;
|
||||
background:rgba(224,229,234,1);
|
||||
border-radius:4px 0px 0px 0px;
|
||||
}
|
||||
.height-20{
|
||||
line-height: 20px;
|
||||
height:20px;
|
||||
background:rgba(229,168,102,1);
|
||||
border-radius:0px 4px 0px 0px;
|
||||
}
|
||||
.Statisticscenter{
|
||||
text-align: center;
|
||||
}
|
||||
.Statisticscenter div:nth-child(1){
|
||||
margin-top: 5px;
|
||||
font-size:12px;
|
||||
color:rgba(51,51,51,1);
|
||||
}
|
||||
|
||||
.Statisticscenter div:nth-child(2){
|
||||
margin-top: 5px;
|
||||
font-size: 12px;
|
||||
color: rgba(153,153,153,1);
|
||||
}
|
||||
|
||||
.rankingss {
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.rankingss a img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
border:1px solid #F4F4F4;
|
||||
/*box-shadow: 0px 0px 12px rgba(0,0,0,0.2);*/
|
||||
}
|
||||
|
||||
.huangguans{
|
||||
width: 36px;
|
||||
height: 17px;
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: 71px;
|
||||
}
|
||||
|
||||
.relatives{
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.statisticsTabs{
|
||||
padding: 30px;
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.statisticsTabs .ant-tabs-tab{
|
||||
height: 80px;
|
||||
text-align: center;
|
||||
line-height: 61px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.Statisticsli{
|
||||
clear: both;
|
||||
margin: 0;
|
||||
padding: 5px 12px;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
-webkit-transition: all 0.3s;
|
||||
-o-transition: all 0.3s;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.StatisticsMenubox{
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 4px 0;
|
||||
text-align: left;
|
||||
list-style-type: none;
|
||||
background-color: #fff;
|
||||
background-clip: padding-box;
|
||||
border-radius: 4px;
|
||||
outline: none;
|
||||
-webkit-box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
.Statisticslibox li label{
|
||||
width: 200px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.Statisticslibox .ant-menu-item{
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
text-overflow: clip;
|
||||
}
|
||||
|
||||
.top10s{
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: rgba(51,51,51,1);
|
||||
}
|
||||
|
||||
.Statisticsliboxjsgz{
|
||||
font-size:12px;
|
||||
color:rgba(51,51,51,1);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.Statisticscircle p{
|
||||
height: 30px;
|
||||
font-size: 12px;
|
||||
color: rgba(153,153,153,1);
|
||||
line-height: 20px;
|
||||
}
|
||||
.Statisticsmxxy{
|
||||
font-size: 16px;
|
||||
margin-left:15px;
|
||||
}
|
||||
.maxnamewidth200 {
|
||||
max-width: 200px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
}
|
||||
.maxnamewidth180 {
|
||||
max-width: 180px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
}
|
|
@ -1,665 +0,0 @@
|
|||
import React,{ Component } from "react";
|
||||
import {Table, Pagination,Popover,Spin, Row, Col ,Tabs, Icon} from "antd";
|
||||
import { WordsBtn,on, off, getRandomcode ,getImageUrl,sortDirections} from 'educoder';
|
||||
import axios from'axios';
|
||||
import Dropdownbox from './Dropdownbox';
|
||||
import Dynamiclist from './Dynamiclist';
|
||||
import NoneData from "../../courses/coursesPublic/NoneData";
|
||||
import './Statistics.css';
|
||||
const qs = require('qs');
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
class Statistics extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
nd1:60,
|
||||
nd2:40,
|
||||
nd3:20,
|
||||
data:undefined,
|
||||
bomdata:undefined,
|
||||
topisSpin:true,
|
||||
bomisSpin:true,
|
||||
sort:'desc',
|
||||
course_groups:[],
|
||||
page:1,
|
||||
all_count:null,
|
||||
activeKey:'1',
|
||||
visible: false,
|
||||
group_ids:[],
|
||||
course_members:undefined
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getdatas()
|
||||
}
|
||||
|
||||
getdatas=()=>{
|
||||
let {page,group_ids,sort}=this.state;
|
||||
let courseId=this.props.match.params.coursesId;
|
||||
let url=`/courses/${courseId}/statistics.json`;
|
||||
axios.get(url).then((result) => {
|
||||
if (result) {
|
||||
this.setState({
|
||||
data:result.data.top_scores,
|
||||
topisSpin:false
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
topisSpin:false,
|
||||
})
|
||||
})
|
||||
let courseurl=`/courses/${courseId}/all_course_groups.json`;
|
||||
axios.get(courseurl).then((result) => {
|
||||
if (result) {
|
||||
this.setState({
|
||||
course_groups:result.data.course_groups
|
||||
})
|
||||
let list=result.data.course_groups;
|
||||
// if(list.length>0){
|
||||
// this.setState({
|
||||
// group_ids:[list[0].id],
|
||||
// })
|
||||
// }
|
||||
this.getwork_scoredata(page,undefined,sort);
|
||||
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
getDynamiclistdatas=(group_ids,key)=>{
|
||||
if(key==='2') {
|
||||
let courseId = this.props.match.params.coursesId;
|
||||
let url = `/courses/${courseId}/act_score.json`;
|
||||
let data = {
|
||||
group_ids: group_ids,
|
||||
}
|
||||
axios.get(url, {
|
||||
params:
|
||||
data
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
this.setState({
|
||||
course_members: result.data.course_members,
|
||||
bomisSpin: false
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
bomisSpin: false,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
getwork_scoredata=(page,group_ids,sort,key)=>{
|
||||
this.setState({
|
||||
page:page,
|
||||
sort:sort,
|
||||
group_ids:this.props.isStudent()===true?undefined:group_ids,
|
||||
bomisSpin:true,
|
||||
})
|
||||
|
||||
if(key==='1'||key===undefined){
|
||||
let courseId=this.props.match.params.coursesId;
|
||||
let url=`/courses/${courseId}/work_score.json`;
|
||||
let data={
|
||||
limit:20,
|
||||
page:page,
|
||||
group_ids:this.props.isStudent()===true?undefined:group_ids,
|
||||
sort:sort
|
||||
}
|
||||
axios.get(url,{params:
|
||||
data
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
this.setState({
|
||||
bomdata:result.data.course_members,
|
||||
all_count:result.data.all_count,
|
||||
bomisSpin:false
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
bomisSpin:false,
|
||||
})
|
||||
})
|
||||
}else{
|
||||
this.getDynamiclistdatas(group_ids)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
activeKey=(key)=>{
|
||||
if(key==="1"){
|
||||
let {page,group_ids,sort}=this.state;
|
||||
// this.getdatas()
|
||||
this.getwork_scoredata(page,group_ids,sort,key)
|
||||
}else if(key==="2"){
|
||||
let{group_ids}=this.state;
|
||||
this.getDynamiclistdatas(group_ids,key)
|
||||
}
|
||||
this.setState({
|
||||
activeKey:key
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
PaginationCourse=(pageNumber)=>{
|
||||
let {group_ids,sort}=this.state;
|
||||
|
||||
this.getwork_scoredata(pageNumber,group_ids,sort);
|
||||
}
|
||||
|
||||
derivefun=(url)=>{
|
||||
let{group_ids}=this.state;
|
||||
let list=group_ids;
|
||||
let urllist="";
|
||||
if(list!=undefined&&list.length!=0)
|
||||
list.map((item,key)=>{
|
||||
if(key===0){
|
||||
urllist=`group_id[]=${item}`
|
||||
}else{
|
||||
urllist=urllist+`&group_id[]=${item}`
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
// console.log(getRandomcode(`${url}?${urllist}`))
|
||||
this.props.slowDownload(getRandomcode(`${url}?${urllist}`));
|
||||
}
|
||||
|
||||
|
||||
// 筛选
|
||||
handleTableChange =(pagination, filters, data)=>{
|
||||
let order=data.order;
|
||||
let {page,group_ids}=this.state;
|
||||
if(order==="descend"){
|
||||
this.getwork_scoredata(page,group_ids,'desc')
|
||||
}else{
|
||||
this.getwork_scoredata(page,group_ids,'asc')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//计算成绩
|
||||
setComputeTimet = (homeworkid) => {
|
||||
let url = `/courses/${homeworkid}/calculate_all_shixun_scores.json`;
|
||||
try {
|
||||
this.props.yslslowCheckresults();
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
axios.get(url).then((response) => {
|
||||
if (response) {
|
||||
if (response.data.status === 0) {
|
||||
let{page,group_ids,sort}=this.state;
|
||||
setTimeout(() => {
|
||||
try {
|
||||
this.props.showNotification(`${response.data.message}`);
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
try {
|
||||
this.props.yslslowCheckresultsNo();
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
this.getwork_scoredata(page,group_ids,sort);
|
||||
}, 2500);
|
||||
}
|
||||
}
|
||||
}).catch((error) => {
|
||||
try {
|
||||
this.props.yslslowCheckresultsNo();
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
console.log(error)
|
||||
});
|
||||
};
|
||||
|
||||
render(){
|
||||
let {nd1,nd2,nd3,data,bomdata,course_members,activeKey}=this.state;
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: this.props.isAdmin()===true?'序号':'排名',
|
||||
dataIndex: 'index',
|
||||
render: (text, record,index) => {
|
||||
return this.props.isAdmin()===true?(this.state.page - 1) * 20 + index + 1:record.rank
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex:'user_name',
|
||||
className: 'maxnamewidth180',
|
||||
render: (text, record) => (
|
||||
<a title={record.user_name} className="maxnamewidth180">{record.user_name}</a>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: '分班',
|
||||
dataIndex: 'course_group',
|
||||
className: 'maxnamewidth200',
|
||||
render: (text, record) => (
|
||||
<a title={record.course_group} className="maxnamewidth200">{record.course_group}</a>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: '实训作业',
|
||||
dataIndex: 'practice_score',
|
||||
render: (text, record) => (
|
||||
<span >{record.practice_score.toFixed(2)}</span>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: '普通作业',
|
||||
dataIndex: 'common_score',
|
||||
render: (text, record) => (
|
||||
<span >{record.common_score.toFixed(2)}</span>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: '分组作业',
|
||||
dataIndex: 'group_score',
|
||||
render: (text, record) => (
|
||||
<span >{record.group_score.toFixed(2)}</span>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: '毕设任务',
|
||||
dataIndex: 'graduation_score',
|
||||
render: (text, record) => (
|
||||
<span >{record.graduation_score.toFixed(2)}</span>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: '试卷',
|
||||
dataIndex: 'exercise_score',
|
||||
render: (text, record) => (
|
||||
<span >{record.exercise_score}</span>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: '总成绩',
|
||||
dataIndex: 'total_score',
|
||||
sorter: this.props.isAdmin()===true?true:false,
|
||||
defaultSortOrder: 'descend',
|
||||
sortDirections: sortDirections,
|
||||
render: (text, record) => (
|
||||
<span >{record.total_score.toFixed(2)}</span>
|
||||
)
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
let shixun_homeworktype=false;
|
||||
let common_homeworktype=false;
|
||||
let group_homeworktype=false;
|
||||
let graduationtype=false;
|
||||
let exercisetype=false;
|
||||
let course_grouptype=false;
|
||||
if(this.props&&this.props.course_modules!=undefined){
|
||||
{this.props&&this.props.course_modules.map((item,key)=>{
|
||||
if(item.type==="course_group"){
|
||||
course_grouptype=true
|
||||
}
|
||||
|
||||
if(item.type==="shixun_homework"){
|
||||
shixun_homeworktype=true
|
||||
}
|
||||
if(item.type==="common_homework"){
|
||||
common_homeworktype=true
|
||||
}
|
||||
if(item.type==="group_homework"){
|
||||
group_homeworktype=true
|
||||
} if(item.type==="graduation"){
|
||||
graduationtype=true
|
||||
}
|
||||
|
||||
if(item.type==="exercise"){
|
||||
exercisetype=true
|
||||
}
|
||||
|
||||
})}
|
||||
}
|
||||
|
||||
|
||||
if(course_grouptype===false){
|
||||
columns.some((item,key)=> {
|
||||
if (item.title === "分班") {
|
||||
columns.splice(key, 1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if(shixun_homeworktype===false){
|
||||
columns.some((item,key)=> {
|
||||
if (item.title === "实训作业") {
|
||||
columns.splice(key, 1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if(common_homeworktype===false){
|
||||
columns.some((item,key)=> {
|
||||
if (item.title === "普通作业") {
|
||||
columns.splice(key, 1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if(group_homeworktype===false){
|
||||
columns.some((item,key)=> {
|
||||
if (item.title === "分组作业") {
|
||||
columns.splice(key, 1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if(graduationtype===false){
|
||||
columns.some((item,key)=> {
|
||||
if (item.title === "毕设任务") {
|
||||
columns.splice(key, 1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if(exercisetype===false){
|
||||
columns.some((item,key)=> {
|
||||
if (item.title === "试卷") {
|
||||
columns.splice(key, 1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// console.log("Statistics");
|
||||
// console.log(this.props.user.course_is_end)
|
||||
|
||||
const course_is_endismy=this.props&&this.props.user&&this.props.user.course_is_end;
|
||||
const operations = <React.Fragment>
|
||||
{course_grouptype===false||this.state.course_groups.length===0?"":
|
||||
this.props.isAdmin()===true?
|
||||
<Dropdownbox
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
postwork_scoredata={(group_idss)=>this.getwork_scoredata(1,group_idss,'desc')
|
||||
}
|
||||
/>
|
||||
:""
|
||||
}
|
||||
{
|
||||
this.state.activeKey==="1"?
|
||||
(
|
||||
course_is_endismy===false?
|
||||
<a className={"ml20 ant-btn-link"} onClick={()=>this.setComputeTimet(this.props.match.params.coursesId)}>获取最新成绩</a>
|
||||
:
|
||||
""
|
||||
)
|
||||
:""
|
||||
}
|
||||
{
|
||||
this.props.isAdmin()===true?
|
||||
// 这里是文件下载 不能替换路由
|
||||
<a className={"ml20 ant-btn-link"} onClick={()=>this.derivefun(this.state.activeKey==="1"?`/courses/${this.props.match.params.coursesId}/export_member_scores_excel.xlsx`:`/courses/${this.props.match.params.coursesId}/export_member_act_score.xlsx`)}>导出</a>
|
||||
:""
|
||||
}
|
||||
</React.Fragment>;
|
||||
|
||||
const content = (
|
||||
<div className={"Statisticscircle"}>
|
||||
<p>
|
||||
课堂总成绩 * 70 %
|
||||
</p>
|
||||
<p>
|
||||
课堂活跃度 * 10%
|
||||
</p>
|
||||
<p>
|
||||
课外学习成绩 * 20%
|
||||
</p>
|
||||
<p>
|
||||
其中,课外学习成绩= 当前学生经验值 / 课堂学生经验值 最大值*100
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
return(
|
||||
<React.Fragment>
|
||||
<div className="edu-back-white">
|
||||
<Spin size="large" spinning={this.state.topisSpin}>
|
||||
<p className="clearfix padding30">
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
明星学员
|
||||
</Col>
|
||||
<Col span={12} className={"Statisticsliboxjsgz"}>
|
||||
<span className={"mr10"}>计算规则</span>
|
||||
<Popover placement="bottom" title={"明星学员计算说明"} content={content} trigger="hover">
|
||||
<Icon type="info-circle" />
|
||||
</Popover>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row type="flex" justify="center" align="bottom">
|
||||
{data&&data.map((item,key)=>{
|
||||
if(key===3){
|
||||
return(
|
||||
<Col span={3}>
|
||||
<li className="pr rankingss">
|
||||
<a href={`/users/${item.user_login}`} className="color-dark">
|
||||
<img src={getImageUrl(`images/${item.avatar_url}`)}/>
|
||||
</a>
|
||||
</li>
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
|
||||
})}
|
||||
{data&&data.map((item,key)=>{
|
||||
if(key===1){
|
||||
return(
|
||||
<Col span={5}>
|
||||
<li className="pr rankingss">
|
||||
<a href={`/users/${item.user_login}`} className="color-dark">
|
||||
<img src={getImageUrl(`images/${item.avatar_url}`)} className={"mb10"}/>
|
||||
</a>
|
||||
</li>
|
||||
<Col className={`height-${nd2}`}>
|
||||
|
||||
</Col>
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
|
||||
})}
|
||||
|
||||
{data&&data.map((item,key)=>{
|
||||
if(key===0){
|
||||
return(
|
||||
<Col span={5} className={"relatives"}>
|
||||
<li className="pr rankingss">
|
||||
<img src={getImageUrl("images/educoder/imperialcrown.png")} className="huangguans mb5" />
|
||||
<a href={`/users/${item.user_login}`} className="color-dark">
|
||||
<img src={getImageUrl(`images/${item.avatar_url}`)} className={"mb10 mt5"}/>
|
||||
</a>
|
||||
</li>
|
||||
<Col className={`height-${nd1}`}>
|
||||
|
||||
</Col>
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
|
||||
})}
|
||||
|
||||
{data&&data.map((item,key)=>{
|
||||
if(key===2){
|
||||
return(
|
||||
<Col span={5}>
|
||||
<li className="pr rankingss">
|
||||
<a href={`/users/${item.user_login}`} className="color-dark">
|
||||
<img src={getImageUrl(`images/${item.avatar_url}`)} className={"mb10"}/>
|
||||
</a>
|
||||
</li>
|
||||
<Col className={`height-${nd3}`}>
|
||||
|
||||
</Col>
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
|
||||
})}
|
||||
|
||||
|
||||
{data&&data.map((item,key)=>{
|
||||
if(key===4){
|
||||
return(
|
||||
<Col span={3}>
|
||||
<li className="pr rankingss">
|
||||
<a href={`/users/${item.user_login}`} className="color-dark">
|
||||
<img src={getImageUrl(`images/${item.avatar_url}`)}/>
|
||||
</a>
|
||||
</li>
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
|
||||
})}
|
||||
|
||||
|
||||
</Row>
|
||||
|
||||
|
||||
<Row className="mt10" type="flex" justify="center" align="bottom">
|
||||
|
||||
{data&&data.map((item,key)=>{
|
||||
if(key===3){
|
||||
return(
|
||||
<Col span={3} className={"Statisticscenter"}>
|
||||
<Col>{item.user_name}</Col>
|
||||
<Col>4th</Col>
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
})}
|
||||
{data&&data.map((item,key)=>{
|
||||
if(key===1){
|
||||
return(
|
||||
<Col span={5} className={"Statisticscenter"}>
|
||||
<Col>{item.user_name}</Col>
|
||||
<Col>2nd</Col>
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
})}
|
||||
{data&&data.map((item,key)=>{
|
||||
if(key===0){
|
||||
return(
|
||||
<Col span={5} className={"Statisticscenter"}>
|
||||
<Col>{item.user_name}</Col>
|
||||
<Col>1st</Col>
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
})}
|
||||
{data&&data.map((item,key)=>{
|
||||
if(key===2){
|
||||
return(
|
||||
<Col span={5} className={"Statisticscenter"}>
|
||||
<Col>{item.user_name}</Col>
|
||||
<Col>3rd</Col>
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
})}
|
||||
{data&&data.map((item,key)=>{
|
||||
if(key===4){
|
||||
return(
|
||||
<Col span={3} className={"Statisticscenter"}>
|
||||
<Col>{item.user_name}</Col>
|
||||
<Col>5th</Col>
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
})}
|
||||
|
||||
</Row>
|
||||
</p>
|
||||
</Spin>
|
||||
</div>
|
||||
|
||||
<div className="mt20 edu-back-white">
|
||||
<Spin size="large" spinning={this.state.bomisSpin}>
|
||||
<style>{
|
||||
`
|
||||
.ant-select-dropdown-menu {
|
||||
max-height: 320px;
|
||||
}
|
||||
.ant-tabs-extra-content{
|
||||
margin-top:20px;
|
||||
}
|
||||
.ant-table-thead > tr > th, .ant-table-tbody > tr > td {
|
||||
padding: 16px 0px;
|
||||
text-align: center;
|
||||
}
|
||||
`
|
||||
}</style>
|
||||
<Tabs className="statisticsTabs" activeKey={this.state.activeKey} onChange={this.activeKey} tabBarExtraContent={operations}>
|
||||
<TabPane tab="学习成绩" key="1" className={"statisticsTabs1"} >
|
||||
{bomdata===undefined||bomdata===null?"":bomdata.length===0?<NoneData/>:<Table
|
||||
columns={columns}
|
||||
dataSource={bomdata}
|
||||
pagination={false}
|
||||
onChange={this.handleTableChange}
|
||||
/>}
|
||||
</TabPane>
|
||||
<TabPane tab="课堂活跃度" key="2">
|
||||
{course_members===undefined||course_members===null?"":course_members.length===0?<NoneData/>:<Dynamiclist
|
||||
{...this.state}
|
||||
{...this.props}
|
||||
/>}
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</Spin>
|
||||
</div>
|
||||
|
||||
{this.state.all_count===undefined||this.state.all_count===null||this.state.activeKey==="2"?'':this.state.all_count >20&&this.props.isAdmin()===true?<div className="mb40 edu-txt-center padding20-30"
|
||||
|
||||
>
|
||||
|
||||
<Pagination
|
||||
showQuickJumper
|
||||
defaultCurrent={1}
|
||||
pageSize={20}
|
||||
total={this.state.all_count===undefined?0:this.state.all_count===null?0:this.state.all_count}
|
||||
current={this.state.page}
|
||||
onChange={this.PaginationCourse}
|
||||
/>
|
||||
|
||||
</div>:""}
|
||||
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default Statistics;
|
|
@ -1,134 +0,0 @@
|
|||
import React,{ Component } from "react";
|
||||
import axios from 'axios';
|
||||
import '../signin/css/signincdi.css';
|
||||
import Videostatisticscom from './component/Videostatisticscom';
|
||||
import Videostatisticslist from './component/Videostatisticslist';
|
||||
import Videostatisticscomtwo from './component/Videostatisticscomtwo';
|
||||
import Studenticscom from './component/Studenticscom';
|
||||
import Studentstatistics from './component/Studentstatistics';
|
||||
|
||||
|
||||
//在线学习
|
||||
class Videostatistics extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
watch_staticsdata:[],
|
||||
tisticsbool:false,
|
||||
tisid:null,
|
||||
mytitle:""
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const myisAdmin= this.props&& this.props.isAdmin();
|
||||
if(myisAdmin===true){
|
||||
this.togetdatas();
|
||||
}else{
|
||||
this.togetdataStudent();
|
||||
}
|
||||
|
||||
}
|
||||
details=()=>{
|
||||
|
||||
}
|
||||
|
||||
togetdatas(){
|
||||
console.log("视频统计老师");
|
||||
const CourseId=this.props.match.params.coursesId;
|
||||
let url=`/courses/${CourseId}/watch_statics.json`;
|
||||
axios.get(url,{params: {all:true}}).then((response) => {
|
||||
if(response){
|
||||
this.setState({
|
||||
watch_staticsdata:response.data,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
togetdataStudent(){
|
||||
console.log("视频统计学生数据");
|
||||
const CourseId=this.props.match.params.coursesId;
|
||||
let url=`/courses/${CourseId}/watch_statics.json`;
|
||||
axios.get(url).then((response) => {
|
||||
if(response){
|
||||
this.setState({
|
||||
watch_staticsdata:response.data,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
tisticsbools=(bool,id,mytitle)=>{
|
||||
this.setState({
|
||||
tisticsbool:bool,
|
||||
tisid:id,
|
||||
mytitle:mytitle
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
render(){
|
||||
let {watch_staticsdata,tisticsbool,tisid,mytitle}= this.state;
|
||||
const isAdmin = this.props&& this.props.isAdmin();
|
||||
|
||||
return(
|
||||
<React.Fragment>
|
||||
<div className="ws100s">
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{text-decoration:none !important;}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
|
||||
`
|
||||
}
|
||||
</script>
|
||||
{
|
||||
tisticsbool===false?
|
||||
<div className="ws100s" style={{
|
||||
position: "relative",
|
||||
}}>
|
||||
{
|
||||
isAdmin?
|
||||
<Videostatisticscom {...this.state} {...this.props} watch_staticsdata={watch_staticsdata} statisticsy={(b)=>this.props.statisticsy(b)}></Videostatisticscom>
|
||||
:
|
||||
<Studenticscom {...this.state} {...this.props} watch_staticsdata={watch_staticsdata} statisticsy={(b)=>this.props.statisticsy(b)}></Studenticscom>
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
<div>
|
||||
{ isAdmin?
|
||||
<Videostatisticslist {...this.state} {...this.props} tisticsbools={(b,id,t)=>this.tisticsbools(b,id,t)}></Videostatisticslist>
|
||||
:
|
||||
<Studentstatistics {...this.state} {...this.props} tisticsbools={(b,id,t)=>this.tisticsbools(b,id,t)}></Studentstatistics>
|
||||
}
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<Videostatisticscomtwo {...this.state} {...this.props} tisid={tisid} mytitle={mytitle} tisticsbools={(b,id,t)=>this.tisticsbools(b,id,t)}></Videostatisticscomtwo>
|
||||
}
|
||||
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default Videostatistics;
|
|
@ -1,119 +0,0 @@
|
|||
import React, {Component} from "react";
|
||||
import '../../signin/css/signincdi.css';
|
||||
import {Progress, message,Tooltip} from 'antd';
|
||||
import {getImageUrl,formatSeconds} from 'educoder';
|
||||
import axios from 'axios';
|
||||
|
||||
|
||||
|
||||
//条目
|
||||
class Studenticscom extends Component {
|
||||
//条目组件
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
}
|
||||
|
||||
componentDidUpdate = (prevProps) => {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="ws100s edu-back-white sortinxdirection" style={{
|
||||
position: "relative"
|
||||
}}>
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{text-decoration:none !important;}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
<div className="ws100s teacherentrydivss ">
|
||||
<div className="ws100s sortinxdirection">
|
||||
<p className="sortinxdirection h40s" onClick={()=>this.props.statisticsy(false)} >
|
||||
<i className="iconfont icon-zuojiantou1 font-14 posiivsiconmyss mr5 colorbluesigin xiaoshou h36s" style={{color:'#BBBBBB'}} onClick={()=>this.props.statisticsy(false)} ></i>
|
||||
</p>
|
||||
<div className="ws47s sptits font-18" style={{
|
||||
color:"#333333"
|
||||
}}><span className="ml10">视频统计总览</span></div>
|
||||
<div className="ws50s sptitss xaxisreverseorder">播放数据从{this.props.watch_staticsdata&&this.props.watch_staticsdata.begin_at?this.props.watch_staticsdata.begin_at:0}开始统计</div>
|
||||
</div>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.yslsprenshu{
|
||||
background-image: url(${getImageUrl(`images/qiandao/studentbz1.png`)});
|
||||
background-repeat:no-repeat;
|
||||
-moz-background-size:100% 100%;
|
||||
background-size:100% 100%;
|
||||
}
|
||||
.yslspcishu{
|
||||
background-image: url(${getImageUrl(`images/qiandao/studentbz2.png`)});
|
||||
background-repeat:no-repeat;
|
||||
-moz-background-size:100% 100%;
|
||||
background-size:100% 100%;
|
||||
}
|
||||
.yslshipingshi{
|
||||
background-image: url(${getImageUrl(`images/qiandao/studentbz3.png`)});
|
||||
background-repeat:no-repeat;
|
||||
-moz-background-size:100% 100%;
|
||||
background-size:100% 100%;
|
||||
}
|
||||
|
||||
`
|
||||
}
|
||||
</style>
|
||||
<div className="ws100s spacearound mt10">
|
||||
<div className="yslsprenshu mr30" style={{width:260,height:100}}>
|
||||
<div className="ws100s verticallayout tbrt">
|
||||
<div className="ws100s ts">观看总次数(次)</div>
|
||||
<div className="ws100s tss">{this.props.watch_staticsdata&&this.props.watch_staticsdata.freq?this.props.watch_staticsdata.freq:0}</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="yslspcishu mr30" style={{width:260,height:100}}>
|
||||
<div className="ws100s verticallayout tbrt">
|
||||
<div className="ws100s ts">观看总个数(个)</div>
|
||||
<div className="ws100s tss">{this.props.watch_staticsdata&&this.props.watch_staticsdata.num?this.props.watch_staticsdata.num:0}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="yslshipingshi" style={{width:260,height:100}}>
|
||||
<div className="ws100s verticallayout tbrt">
|
||||
<div className="ws100 ts">总观看时长(时)</div>
|
||||
<Tooltip placement="bottom" title={this.props.watch_staticsdata&&this.props.watch_staticsdata.total_duration?formatSeconds(this.props.watch_staticsdata.total_duration):0}>
|
||||
<div className="maxnamewidth166ss tss">{this.props.watch_staticsdata&&this.props.watch_staticsdata.total_duration?formatSeconds(this.props.watch_staticsdata.total_duration):0}</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Studenticscom;
|
|
@ -1,350 +0,0 @@
|
|||
import React, {Component} from "react";
|
||||
import '../../signin/css/signincdi.css';
|
||||
import {Pagination,Table,Spin} from 'antd';
|
||||
import {getImageUrl,sortDirections,formatSeconds} from 'educoder';
|
||||
import axios from 'axios';
|
||||
import LoadingSpin from "../../../../common/LoadingSpin";
|
||||
import NoneDatas from "../../signin/component/NoneDatas";
|
||||
|
||||
|
||||
//条目
|
||||
class Studentstatistics extends Component {
|
||||
//条目组件
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
columnsstu: [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'number',
|
||||
key: 'number',
|
||||
align: "center",
|
||||
className: 'font-14',
|
||||
width: '90px',
|
||||
render: (text, record) => (
|
||||
<span style={{width: '90px'}}>{record.number}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '视频名称',
|
||||
dataIndex: 'title',
|
||||
key: 'title',
|
||||
align: "left",
|
||||
className: 'font-14 maxnamewidth150s',
|
||||
width: '150px',
|
||||
render: (text, record) => (
|
||||
<div style={{width: '150px'}} className="maxnamewidth150s textalignlefts">
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{text-decoration:none !important;}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
<a className="maxnamewidth150s textalignlefts xiaoshout" style={{
|
||||
color:"#333333"
|
||||
}} title={record.title}>{record.title}</a>
|
||||
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '观看次数(次)',
|
||||
dataIndex: 'feq',
|
||||
key: 'feq',
|
||||
align: "center",
|
||||
className: 'font-14',
|
||||
width: '98px',
|
||||
sorter: true,
|
||||
sortDirections: sortDirections,
|
||||
render: (text, record) => (
|
||||
<span style={{width: '98px'}}>{record.feq}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '观看时长',
|
||||
dataIndex: 'total_duration',
|
||||
key: 'total_duration',
|
||||
align: "center",
|
||||
className: 'font-14 maxnamewidth100s',
|
||||
width: '100px',
|
||||
sorter: true,
|
||||
sortDirections: sortDirections,
|
||||
render: (text, record) => (
|
||||
<div style={{width: '100px'}} className="maxnamewidth100s ">
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{text-decoration:none !important;}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
<a className="maxnamewidth100s xiaoshout" style={{
|
||||
color:"#333333"
|
||||
}} title={record.total_duration}>{record.total_duration}</a>
|
||||
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '发布人',
|
||||
dataIndex: 'user_name',
|
||||
key: 'user_name',
|
||||
align: "center",
|
||||
className: 'font-14 maxnamewidth100s',
|
||||
width: '100px',
|
||||
render: (text, record) => (
|
||||
<span style={{width: '100px'}} className="maxnamewidth100s">
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{text-decoration:none !important;}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
<a className="maxnamewidth100s xiaoshout" style={{
|
||||
color:"#333333"
|
||||
}} title={record.user_name}>{record.user_name}</a>
|
||||
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '是否看完',
|
||||
dataIndex: 'is_finished',
|
||||
key: 'is_finished',
|
||||
align: "center",
|
||||
className: 'font-14',
|
||||
width: '90px',
|
||||
render: (text, record) => (
|
||||
<span style={{width: '90px'}}>{record.is_finished === true ?
|
||||
<span style={{color: "#333333"}}>是</span> : <span style={{color: "#E02020"}}>否</span>}</span>
|
||||
),
|
||||
},
|
||||
],
|
||||
loading:false,
|
||||
data:[],
|
||||
page:1,
|
||||
limit:20,
|
||||
members_count:0,
|
||||
order:undefined,
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let data={
|
||||
page:1,
|
||||
order:this.state.order
|
||||
}
|
||||
this.togetdatas(data);
|
||||
|
||||
}
|
||||
|
||||
componentDidUpdate = (prevProps) => {
|
||||
|
||||
|
||||
}
|
||||
paginationonChange = (pageNumber) => {
|
||||
this.setState({
|
||||
page: pageNumber,
|
||||
})
|
||||
let data={
|
||||
page:pageNumber,
|
||||
order:this.state.order
|
||||
}
|
||||
this.togetdatas(data);
|
||||
}
|
||||
|
||||
|
||||
togetdatas(data){
|
||||
this.setState({
|
||||
loading:true
|
||||
})
|
||||
const CourseId=this.props.match.params.coursesId;
|
||||
let url=`/courses/${CourseId}/own_watch_histories.json`;
|
||||
axios.get(url,{params:data
|
||||
}).then((response) => {
|
||||
if (response) {
|
||||
if (response.data) {
|
||||
if (response.data.data.length > 0) {
|
||||
let datalists = [];
|
||||
for (var i = 0; i < response.data.data.length; i++) {
|
||||
datalists.push({
|
||||
number: (parseInt(this.state.page) - 1) * parseInt(this.state.limit) + (i + 1),
|
||||
title: response.data.data[i].title,
|
||||
user_name: response.data.data[i].user_name,
|
||||
is_finished: response.data.data[i].is_finished,
|
||||
total_duration:response.data.data[i].total_duration?formatSeconds(response.data.data[i].total_duration):0,
|
||||
feq:response.data.data[i].freq,
|
||||
start_at:response.data.data[i].start_at,
|
||||
end_at:response.data.data[i].end_at,
|
||||
})
|
||||
}
|
||||
|
||||
this.setState({
|
||||
data: datalists,
|
||||
members_count: response.data.count,
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
data: [],
|
||||
members_count: response.data.count,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.setState({
|
||||
data: [],
|
||||
members_count: response.data.count,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.setState({
|
||||
loading:false
|
||||
})
|
||||
}).catch((error) => {
|
||||
this.setState({
|
||||
loading:false
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//实训作业tbale 列表塞选数据
|
||||
table1handleChange = (pagination, filters, sorter) => {
|
||||
if (JSON.stringify(sorter) === "{}") {
|
||||
//没有选择
|
||||
} else {
|
||||
try {
|
||||
//学生学号排序
|
||||
if (sorter.columnKey === "feq"||sorter.columnKey === "total_duration") {
|
||||
let mysorder="";
|
||||
if (sorter.order === "ascend") {
|
||||
if(sorter.columnKey === "feq"){
|
||||
mysorder="freq-asc";
|
||||
}else{
|
||||
mysorder="total_duration-asc";
|
||||
|
||||
}
|
||||
//升序
|
||||
let data={
|
||||
page:this.state.page,
|
||||
order:mysorder
|
||||
}
|
||||
this.togetdatas(data);
|
||||
this.setState({
|
||||
order: mysorder,
|
||||
})
|
||||
} else if (sorter.order === "descend") {
|
||||
if(sorter.columnKey === "feq"){
|
||||
mysorder="freq-desc";
|
||||
}else{
|
||||
mysorder="total_duration-desc";
|
||||
|
||||
}
|
||||
//降序
|
||||
let data={
|
||||
page:this.state.page,
|
||||
order:mysorder
|
||||
}
|
||||
this.togetdatas(data);
|
||||
this.setState({
|
||||
order: mysorder,
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
let {loading,data,columnsstu,page,members_count,limit}=this.state;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="ws100s mt20">
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{text-decoration:none !important;}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
<div className="ws100s edu-back-white">
|
||||
<div className="ws100s teacherentrydivss pd15s">
|
||||
<div className="ws100s sortinxdirection">
|
||||
<div className="ws100s sptits font-18">统计列表</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.ysltableo .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
|
||||
padding: 10px 5px;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
|
||||
<div className="ws100s ysltableo teacherentrydivs pdinstop0" style={{ minHeight: "400px"}}>
|
||||
{
|
||||
data&&data.length===0?
|
||||
<div style={{
|
||||
minHeight: "400px",
|
||||
}} className="ws100s">
|
||||
<NoneDatas></NoneDatas>
|
||||
</div>
|
||||
: data&&data.length>0?
|
||||
<Spin spinning={loading}>
|
||||
<Table
|
||||
columns={columnsstu}
|
||||
dataSource={data}
|
||||
pagination={false}
|
||||
onChange={this.table1handleChange}
|
||||
/>
|
||||
</Spin>:
|
||||
""
|
||||
}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="mb30 clearfix educontent mt40 intermediatecenter">
|
||||
{
|
||||
data&&data.length>0?
|
||||
<Pagination showQuickJumper current={this.state.page} onChange={this.paginationonChange}
|
||||
pageSize={this.state.limit}
|
||||
total={this.state.members_count}></Pagination>
|
||||
:""
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Studentstatistics;
|
|
@ -1,119 +0,0 @@
|
|||
import React, {Component} from "react";
|
||||
import '../../signin/css/signincdi.css';
|
||||
import {Progress, message,Tooltip} from 'antd';
|
||||
import {getImageUrl,formatSeconds} from 'educoder';
|
||||
import axios from 'axios';
|
||||
|
||||
|
||||
|
||||
//条目
|
||||
class Videostatisticscom extends Component {
|
||||
//条目组件
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
}
|
||||
|
||||
componentDidUpdate = (prevProps) => {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="ws100s edu-back-white sortinxdirection" style={{
|
||||
position: "relative"
|
||||
}}>
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{text-decoration:none !important;}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
<div className="ws100s teacherentrydivss ">
|
||||
<div className="ws100s sortinxdirection">
|
||||
<p className="sortinxdirection h40s" onClick={()=>this.props.statisticsy(false)} >
|
||||
<i className="iconfont icon-zuojiantou1 font-14 posiivsiconmyss mr5 colorbluesigin xiaoshou h36s" style={{color:'#BBBBBB'}} onClick={()=>this.props.statisticsy(false)} ></i>
|
||||
</p>
|
||||
<div className="ws47s sptits font-18" style={{
|
||||
color:"#333333"
|
||||
}}><span className="ml10">视频统计总览</span></div>
|
||||
<div className="ws50s sptitss xaxisreverseorder">播放数据从{this.props.watch_staticsdata&&this.props.watch_staticsdata.begin_at?this.props.watch_staticsdata.begin_at:0}开始统计</div>
|
||||
</div>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.yslsprenshu{
|
||||
background-image: url(${getImageUrl(`images/qiandao/sprenshu.png`)});
|
||||
background-repeat:no-repeat;
|
||||
-moz-background-size:100% 100%;
|
||||
background-size:100% 100%;
|
||||
}
|
||||
.yslspcishu{
|
||||
background-image: url(${getImageUrl(`images/qiandao/spcishu.png`)});
|
||||
background-repeat:no-repeat;
|
||||
-moz-background-size:100% 100%;
|
||||
background-size:100% 100%;
|
||||
}
|
||||
.yslshipingshi{
|
||||
background-image: url(${getImageUrl(`images/qiandao/shipingshi.png`)});
|
||||
background-repeat:no-repeat;
|
||||
-moz-background-size:100% 100%;
|
||||
background-size:100% 100%;
|
||||
}
|
||||
|
||||
`
|
||||
}
|
||||
</style>
|
||||
<div className="ws100s spacearound mt10">
|
||||
<div className="yslsprenshu mr30" style={{width:260,height:100}}>
|
||||
<div className="ws100s verticallayout tbrt">
|
||||
<div className="ws100s ts">观看总人数(人)</div>
|
||||
<div className="ws100s tss">{this.props.watch_staticsdata&&this.props.watch_staticsdata.num?this.props.watch_staticsdata.num:0}</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="yslspcishu mr30" style={{width:260,height:100}}>
|
||||
<div className="ws100s verticallayout tbrt">
|
||||
<div className="ws100s ts">观看总人次(次)</div>
|
||||
<div className="ws100s tss">{this.props.watch_staticsdata&&this.props.watch_staticsdata.freq?this.props.watch_staticsdata.freq:0}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="yslshipingshi" style={{width:260,height:100}}>
|
||||
<div className="ws100s verticallayout tbrt">
|
||||
<div className="ws100 ts">总观看时长(时)</div>
|
||||
<Tooltip placement="bottom" title={this.props.watch_staticsdata&&this.props.watch_staticsdata.total_duration?formatSeconds(this.props.watch_staticsdata.total_duration):0}>
|
||||
<div className="maxnamewidth166ss tss">{this.props.watch_staticsdata&&this.props.watch_staticsdata.total_duration?formatSeconds(this.props.watch_staticsdata.total_duration):0}</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Videostatisticscom;
|
|
@ -1,641 +0,0 @@
|
|||
import React, {Component} from "react";
|
||||
import '../../signin/css/signincdi.css';
|
||||
import {Pagination, Table, Menu, Dropdown,Spin} from 'antd';
|
||||
import {getImageUrl, sortDirections,formatSeconds} from 'educoder';
|
||||
import axios from 'axios';
|
||||
import LoadingSpin from "../../../../common/LoadingSpin";
|
||||
import NoneDatas from "../../signin/component/NoneDatas";
|
||||
import moment from 'moment';
|
||||
|
||||
|
||||
//条目
|
||||
class Videostatisticscomtwo extends Component {
|
||||
//条目组件
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
data: [],
|
||||
page: 1,
|
||||
limit: 20,
|
||||
members_count: 0,
|
||||
columnsstu: [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'number',
|
||||
key: 'number',
|
||||
align: "center",
|
||||
className: 'font-14',
|
||||
width: '50px',
|
||||
render: (text, record) => (
|
||||
<div style={{width: '50px'}}>{record.number}</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '用户',
|
||||
dataIndex: 'user_name',
|
||||
key: 'user_name',
|
||||
align: "center",
|
||||
className: 'font-14 maxnamewidth100s',
|
||||
width: '100px',
|
||||
render: (text, record) => (
|
||||
<div style={{width: "100px",wordWrap: 'break-word', wordBreak: 'break-word'}} className="maxnamewidth100s">
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{text-decoration:none !important;}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
<a className="maxnamewidth100s xiaoshout" style={{
|
||||
color:"#333333"
|
||||
}} title={record.user_name}>{record.user_name}</a>
|
||||
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '是否看完',
|
||||
dataIndex: 'is_finished',
|
||||
key: 'is_finished',
|
||||
align: "center",
|
||||
className: 'font-14 maxnamewidth90s',
|
||||
width: '90px',
|
||||
render: (text, record) => (
|
||||
<div style={{width: '90px'}} className="maxnamewidth90s">{record.is_finished === true ?
|
||||
<span style={{color: "#333333"}}>是</span> : <span style={{color: "#E02020"}}>否</span>}</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '观看时长',
|
||||
dataIndex: 'total_duration',
|
||||
key: 'total_duration',
|
||||
align: "center",
|
||||
className: 'font-14 maxnamewidth100s',
|
||||
width: '100px',
|
||||
sorter: true,
|
||||
sortDirections: sortDirections,
|
||||
render: (text, record) => (
|
||||
<div style={{width: '100px'}} className="maxnamewidth100s">
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{text-decoration:none !important;}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
<a className="maxnamewidth100s xiaoshout" style={{
|
||||
color:"#333333"
|
||||
}} title={record.total_duration}>{record.total_duration}</a></div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '观看次数',
|
||||
dataIndex: 'feq',
|
||||
key: 'feq',
|
||||
align: "center",
|
||||
className: 'font-14 maxnamewidth100s',
|
||||
width: '100px',
|
||||
sorter: true,
|
||||
sortDirections: sortDirections,
|
||||
render: (text, record) => (
|
||||
<div style={{width: '100px'}} className="maxnamewidth100s">
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{text-decoration:none !important;}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
<a className="maxnamewidth100s xiaoshout" style={{
|
||||
color:"#333333"
|
||||
}} title={record.feq}>{record.feq}</a>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '最早观看时间',
|
||||
dataIndex: 'start_at',
|
||||
key: 'start_at',
|
||||
align: "center",
|
||||
className: 'font-14 ',
|
||||
render: (text, record) => (
|
||||
<div>
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{text-decoration:none !important;}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
{
|
||||
record.start_at?
|
||||
<a className="xiaoshout" style={{
|
||||
color:"#333333"
|
||||
}} title={moment(record.start_at).format('YYYY-MM-DD HH:mm:ss')}>{moment(record.start_at).format('YYYY-MM-DD HH:mm:ss')}</a>
|
||||
:
|
||||
<span style={{color:"#333333"}}>--</span>
|
||||
}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '最后观看时间',
|
||||
dataIndex: 'end_at',
|
||||
key: 'end_at',
|
||||
align: "center",
|
||||
className: 'font-14 ',
|
||||
render: (text, record) => (
|
||||
<div>
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{text-decoration:none !important;}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
{
|
||||
record.end_at?
|
||||
<a className="xiaoshout" style={{
|
||||
color:"#333333"
|
||||
}} title={moment(record.end_at).format('YYYY-MM-DD HH:mm:ss')}>{moment(record.end_at).format('YYYY-MM-DD HH:mm:ss')}</a>
|
||||
:
|
||||
<span style={{color:"#333333"}}>--</span>
|
||||
|
||||
}
|
||||
|
||||
</div>
|
||||
),
|
||||
}
|
||||
],
|
||||
loading: false,
|
||||
order: undefined,
|
||||
course_groups: [],
|
||||
fbbool: false,
|
||||
groupsid: null,
|
||||
none_group_member_count:0,
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({
|
||||
order: undefined
|
||||
})
|
||||
if (this.props.isAdmin()) {
|
||||
//老师
|
||||
const CourseId = this.props.match.params.coursesId;
|
||||
|
||||
var data = {
|
||||
id: CourseId,
|
||||
page: this.state.page,
|
||||
}
|
||||
this.getdatas(data);
|
||||
|
||||
} else {
|
||||
//学生
|
||||
var data = {
|
||||
page: this.state.page,
|
||||
}
|
||||
this.getdatas(data);
|
||||
}
|
||||
this.fenbans();
|
||||
}
|
||||
|
||||
componentDidUpdate = (prevProps) => {
|
||||
|
||||
|
||||
}
|
||||
|
||||
//分班
|
||||
fenbans = () => {
|
||||
const CourseId = this.props.match.params.coursesId;
|
||||
let url = `/courses/${CourseId}/course_groups.json`;
|
||||
axios.get(url).then((response) => {
|
||||
if (response) {
|
||||
// console.log("分班");
|
||||
// console.log("response");
|
||||
// console.log(response);
|
||||
this.setState({
|
||||
course_groups: response.data.course_groups,
|
||||
current_group_id: response.data.current_group_id,
|
||||
none_group_member_count: response.data.none_group_member_count,
|
||||
group_count: response.data.group_count,
|
||||
})
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
//学生
|
||||
getdatas = (data) => {
|
||||
this.setState({
|
||||
loading: true
|
||||
})
|
||||
const CourseId = this.props.match.params.coursesId;
|
||||
let url = "";
|
||||
if (this.props.isAdmin()) {
|
||||
url = `/course_videos/${this.props.tisid}/watch_histories.json`;
|
||||
} else {
|
||||
url = `/courses/${CourseId}/own_watch_histories.json`;
|
||||
}
|
||||
axios.get(url, {params: data}).then((response) => {
|
||||
if (response) {
|
||||
if (response.data) {
|
||||
if (response.data.data.length > 0) {
|
||||
let datalists = [];
|
||||
for (var i = 0; i < response.data.data.length; i++) {
|
||||
datalists.push({
|
||||
number: (parseInt(this.state.page) - 1) * parseInt(this.state.limit) + (i + 1),
|
||||
user_name: response.data.data[i].user_name,
|
||||
is_finished: response.data.data[i].is_finished,
|
||||
total_duration: response.data.data[i].total_duration?formatSeconds(response.data.data[i].total_duration):0,
|
||||
feq: response.data.data[i].feq,
|
||||
start_at: response.data.data[i].start_at?response.data.data[i].start_at:null,
|
||||
end_at: response.data.data[i].end_at?response.data.data[i].end_at:null,
|
||||
title: response.data.data[i].title,
|
||||
})
|
||||
}
|
||||
|
||||
this.setState({
|
||||
data: datalists,
|
||||
members_count: response.data.count,
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
data: [],
|
||||
members_count: response.data.count,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.setState({
|
||||
data: [],
|
||||
members_count: response.data.count,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
this.setState({
|
||||
loading: false
|
||||
})
|
||||
}).catch((error) => {
|
||||
this.setState({
|
||||
loading: false
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
paginationonChange = (pageNumber) => {
|
||||
this.setState({
|
||||
page: pageNumber,
|
||||
})
|
||||
let data = {}
|
||||
if (this.props.isAdmin()) {
|
||||
//老师
|
||||
const CourseId = this.props.match.params.coursesId;
|
||||
data = {
|
||||
id: CourseId,
|
||||
page: pageNumber,
|
||||
group_id: this.state.groupsid,
|
||||
order: this.state.order,
|
||||
}
|
||||
} else {
|
||||
//学生
|
||||
data = {
|
||||
page: pageNumber,
|
||||
order: this.state.order,
|
||||
}
|
||||
}
|
||||
this.getdatas(data);
|
||||
}
|
||||
fenbanone = () => {
|
||||
if (this.state.fbbool === false) {
|
||||
this.setState({
|
||||
fbbool: true
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
fbbool: false
|
||||
})
|
||||
}
|
||||
}
|
||||
setcourse_groups = (id) => {
|
||||
this.setState({
|
||||
groupsid: id
|
||||
})
|
||||
//老师
|
||||
const CourseId = this.props.match.params.coursesId;
|
||||
|
||||
var data = {};
|
||||
if (id) {
|
||||
data = {
|
||||
id: CourseId,
|
||||
page: this.state.page,
|
||||
group_id: id
|
||||
}
|
||||
|
||||
} else {
|
||||
try {
|
||||
if(id!==null&&id===0){
|
||||
data = {
|
||||
id: CourseId,
|
||||
page: this.state.page,
|
||||
group_id: id
|
||||
}
|
||||
}else{
|
||||
data = {
|
||||
id: CourseId,
|
||||
page: this.state.page
|
||||
}
|
||||
}
|
||||
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
this.getdatas(data);
|
||||
}
|
||||
|
||||
//实训作业tbale 列表塞选数据
|
||||
table1handleChange = (pagination, filters, sorter) => {
|
||||
if (JSON.stringify(sorter) === "{}") {
|
||||
//没有选择
|
||||
} else {
|
||||
try {
|
||||
//学生学号排序
|
||||
if (sorter.columnKey === "total_duration" || sorter.columnKey === "feq") {
|
||||
let mysorder = "";
|
||||
if (sorter.order === "ascend") {
|
||||
if (sorter.columnKey === "total_duration") {
|
||||
mysorder = "total_duration-asc";
|
||||
} else {
|
||||
mysorder = "freq-asc";
|
||||
|
||||
}
|
||||
//升序
|
||||
let data = {}
|
||||
if (this.props.isAdmin()) {
|
||||
//老师
|
||||
const CourseId = this.props.match.params.coursesId;
|
||||
if (this.state.groupsid) {
|
||||
data = {
|
||||
id: CourseId,
|
||||
page: this.state.page,
|
||||
group_id: this.state.groupsid,
|
||||
order: mysorder,
|
||||
}
|
||||
} else {
|
||||
data = {
|
||||
id: CourseId,
|
||||
page: this.state.page,
|
||||
order: mysorder,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//学生
|
||||
data = {
|
||||
page: this.state.page,
|
||||
order: mysorder,
|
||||
}
|
||||
}
|
||||
|
||||
this.getdatas(data);
|
||||
this.setState({
|
||||
order: mysorder,
|
||||
})
|
||||
} else if (sorter.order === "descend") {
|
||||
if (sorter.columnKey === "total_duration") {
|
||||
mysorder = "total_duration-desc";
|
||||
|
||||
} else {
|
||||
mysorder = "freq-desc";
|
||||
|
||||
}
|
||||
//降序
|
||||
let data = {}
|
||||
if (this.props.isAdmin()) {
|
||||
//老师
|
||||
const CourseId = this.props.match.params.coursesId;
|
||||
if (this.state.groupsid) {
|
||||
data = {
|
||||
id: CourseId,
|
||||
page: this.state.page,
|
||||
group_id: this.state.groupsid,
|
||||
order: mysorder,
|
||||
}
|
||||
} else {
|
||||
data = {
|
||||
id: CourseId,
|
||||
page: this.state.page,
|
||||
order: mysorder,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//学生
|
||||
data = {
|
||||
page: this.state.page,
|
||||
order: mysorder,
|
||||
}
|
||||
}
|
||||
|
||||
this.getdatas(data);
|
||||
this.setState({
|
||||
order: mysorder,
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
let {loading, data, page, limit, members_count, columnsstu, fbbool, course_groups} = this.state;
|
||||
const isAdmin = this.props&& this.props.isAdmin();
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item>
|
||||
<a onClick={() => this.setcourse_groups(null)}>
|
||||
<p className="maxnamewidth200yss">全部</p>
|
||||
</a>
|
||||
</Menu.Item>
|
||||
{
|
||||
course_groups && course_groups.length > 0 ?
|
||||
(
|
||||
course_groups.map((item, key) => {
|
||||
return (
|
||||
<Menu.Item>
|
||||
<a onClick={() => this.setcourse_groups(item.id)} key={key}>
|
||||
<p className="maxnamewidth200yss">{item.name}</p>
|
||||
</a>
|
||||
</Menu.Item>
|
||||
)
|
||||
})
|
||||
)
|
||||
:
|
||||
""
|
||||
}
|
||||
{
|
||||
this.state.none_group_member_count&&this.state.none_group_member_count>0?
|
||||
<Menu.Item>
|
||||
<a onClick={() => this.setcourse_groups(0)}>
|
||||
<p className="maxnamewidth200yss">未分班</p>
|
||||
</a>
|
||||
</Menu.Item>
|
||||
:
|
||||
""
|
||||
}
|
||||
</Menu>
|
||||
);
|
||||
|
||||
let mytitle="";
|
||||
if(isAdmin){
|
||||
mytitle=this.props&&this.props.mytitle;
|
||||
|
||||
}else{
|
||||
if(this.state.data){
|
||||
if(this.state.data.length>0){
|
||||
try {
|
||||
if(this.state.data[0].title){
|
||||
mytitle=this.state.data[0].title;
|
||||
}
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="ws100s">
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{
|
||||
text-decoration:none !important;
|
||||
}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
<div className="ws100s teacherentrydivss edu-back-white ">
|
||||
<div className="ws100s sortinxdirection">
|
||||
<p className="sortinxdirection h40s" onClick={() => this.props.tisticsbools(false, null)} >
|
||||
<i className="iconfont icon-zuojiantou1 font-14 posiivsiconmyss mr5 colorbluesigin xiaoshou h36s" style={{color:'#BBBBBB'}} ></i>
|
||||
</p>
|
||||
<div className="ws50s sptits font-18">
|
||||
<div className="ml10">{mytitle}</div>
|
||||
</div>
|
||||
<div className="ws50s sptitss xaxisreverseorder font-14" style={{
|
||||
color: "#5091FF",
|
||||
lineHeight: "42px",
|
||||
}}>
|
||||
{/*{*/}
|
||||
{/* isAdmin === true ?*/}
|
||||
{/* <div className="xiaoshou ml32" onClick={() => this.props.tisticsbools(false, null)}>*/}
|
||||
{/* <span className="mr5 xiaoshou">视频统计总览</span><i className="iconfont icon-fanhui font-13 xiaoshou"></i>*/}
|
||||
{/* </div>*/}
|
||||
{/* :""*/}
|
||||
{/*}*/}
|
||||
|
||||
{
|
||||
isAdmin === true ?
|
||||
<div className="xiaoshou" onClick={() => this.fenbanone()}>
|
||||
<Dropdown getPopupContainer={trigger => trigger.parentNode} overlay={menu}
|
||||
placement="bottomLeft">
|
||||
<span>
|
||||
<span className="mr5 xiaoshou">分班</span>
|
||||
{
|
||||
fbbool === true ?
|
||||
<i className="iconfont icon-sanjiaoxing-up font-13 xiaoshou"></i>
|
||||
:
|
||||
<i className="iconfont icon-sanjiaoxing-down font-13 xiaoshou"></i>
|
||||
}
|
||||
</span>
|
||||
</Dropdown>
|
||||
</div>
|
||||
:
|
||||
""
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.ysltableo .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
|
||||
padding: 10px 5px;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
|
||||
<div className="ws100s ysltableo mt10" style={{ minHeight: "400px"}}>
|
||||
{
|
||||
data.length === 0 ?
|
||||
<div style={{
|
||||
minHeight: "400px",
|
||||
}} className="ws100s">
|
||||
<NoneDatas></NoneDatas>
|
||||
</div>
|
||||
:
|
||||
<Spin spinning={loading}>
|
||||
<Table
|
||||
columns={columnsstu}
|
||||
dataSource={data}
|
||||
pagination={false}
|
||||
onChange={this.table1handleChange}
|
||||
/>
|
||||
</Spin>
|
||||
}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div className="mb30 clearfix educontent mt40 intermediatecenter">
|
||||
{
|
||||
data && data.length > 0 ?
|
||||
<Pagination showQuickJumper current={this.state.page} onChange={this.paginationonChange}
|
||||
pageSize={this.state.limit}
|
||||
total={this.state.members_count}></Pagination>
|
||||
: ""
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Videostatisticscomtwo;
|
|
@ -1,350 +0,0 @@
|
|||
import React, {Component} from "react";
|
||||
import '../../signin/css/signincdi.css';
|
||||
import {Pagination,Table,Spin} from 'antd';
|
||||
import {getImageUrl,sortDirections,formatSeconds} from 'educoder';
|
||||
import axios from 'axios';
|
||||
import LoadingSpin from "../../../../common/LoadingSpin";
|
||||
import NoneDatas from "../../signin/component/NoneDatas";
|
||||
|
||||
|
||||
//条目
|
||||
class Videostatisticslist extends Component {
|
||||
//条目组件
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
columnsstu: [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'number',
|
||||
key: 'number',
|
||||
align: "center",
|
||||
className: 'font-14',
|
||||
width: '100px',
|
||||
render: (text, record) => (
|
||||
<span style={{width: '100px'}}>{record.number}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '视频名称',
|
||||
dataIndex: 'title',
|
||||
key: 'title',
|
||||
align: "left",
|
||||
className: 'font-14 width200s widh150wpos',
|
||||
width:200,
|
||||
render: (text, record) => (
|
||||
<div className="maxnamewidth200ss textalignlefts" style={{ wordWrap: 'break-word', wordBreak: 'break-word' }}>
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{text-decoration:none !important;}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
<a className="maxnamewidth200ss textalignlefts xiaoshout" style={{
|
||||
color:"#333333"
|
||||
}} title={record.title}>{record.title}</a>
|
||||
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '观看人数',
|
||||
dataIndex: 'people_num',
|
||||
key: 'people_num',
|
||||
align: "center",
|
||||
className: 'font-14 width150s',
|
||||
sorter: true,
|
||||
sortDirections: sortDirections,
|
||||
width:150,
|
||||
render: (text, record) => (
|
||||
<span>{record.people_num}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '观看时长',
|
||||
dataIndex: 'total_time',
|
||||
key: 'total_time',
|
||||
align: "center",
|
||||
className: 'font-14 width100s ',
|
||||
sorter: true,
|
||||
sortDirections: sortDirections,
|
||||
width:100,
|
||||
render: (text, record) => (
|
||||
<div className="maxnamewidth100s ">
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{text-decoration:none !important;}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
<a className="maxnamewidth100s xiaoshout" style={{
|
||||
color:"#333333"
|
||||
}} title={record.total_time}>{record.total_time}</a>
|
||||
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '发布人',
|
||||
dataIndex: 'user_name',
|
||||
key: 'user_name',
|
||||
align: "center",
|
||||
className: 'font-14 width150s',
|
||||
width:150,
|
||||
render: (text, record) => (
|
||||
<span className="maxnamewidth150ss">
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{text-decoration:none !important;}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
<a className="maxnamewidth150ss xiaoshout" style={{
|
||||
color:"#333333"
|
||||
}} title={record.user_name}>{record.user_name}</a>
|
||||
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '详情',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
align: "center",
|
||||
className: 'font-14',
|
||||
render: (text, record) => (
|
||||
<span style={{color:'#5091FF'}} className="xiaoshou" onClick={()=>this.props.tisticsbools(true,record.id,record.title)}>详情</span>
|
||||
),
|
||||
}
|
||||
],
|
||||
loading:false,
|
||||
data:[],
|
||||
page:1,
|
||||
limit:20,
|
||||
members_count:0,
|
||||
order:undefined,
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let data={
|
||||
page:1,
|
||||
order:this.state.order
|
||||
}
|
||||
this.togetdatas(data);
|
||||
|
||||
}
|
||||
|
||||
componentDidUpdate = (prevProps) => {
|
||||
|
||||
|
||||
}
|
||||
paginationonChange = (pageNumber) => {
|
||||
this.setState({
|
||||
page: pageNumber,
|
||||
})
|
||||
let data={
|
||||
page:pageNumber,
|
||||
order:this.state.order
|
||||
}
|
||||
this.togetdatas(data);
|
||||
}
|
||||
|
||||
|
||||
togetdatas(data){
|
||||
this.setState({
|
||||
loading:true
|
||||
})
|
||||
const CourseId=this.props.match.params.coursesId;
|
||||
let url=`/courses/${CourseId}/watch_video_histories.json`;
|
||||
axios.get(url,{params:data
|
||||
}).then((response) => {
|
||||
if (response) {
|
||||
if (response.data) {
|
||||
if (response.data.videos.length > 0) {
|
||||
let datalists = [];
|
||||
for (var i = 0; i < response.data.videos.length; i++) {
|
||||
datalists.push({
|
||||
number: (parseInt(this.state.page) - 1) * parseInt(this.state.limit) + (i + 1),
|
||||
title: response.data.videos[i].title,
|
||||
people_num: response.data.videos[i].people_num,
|
||||
total_time: response.data.videos[i].total_time?formatSeconds(response.data.videos[i].total_time):0,
|
||||
user_name: response.data.videos[i].user_name,
|
||||
id: response.data.videos[i].id,
|
||||
})
|
||||
}
|
||||
|
||||
this.setState({
|
||||
data: datalists,
|
||||
members_count: response.data.count,
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
data: [],
|
||||
members_count: response.data.count,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.setState({
|
||||
data: [],
|
||||
members_count: response.data.count,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.setState({
|
||||
loading:false
|
||||
})
|
||||
}).catch((error) => {
|
||||
this.setState({
|
||||
loading:false
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//实训作业tbale 列表塞选数据
|
||||
table1handleChange = (pagination, filters, sorter) => {
|
||||
if (JSON.stringify(sorter) === "{}") {
|
||||
//没有选择
|
||||
} else {
|
||||
try {
|
||||
//学生学号排序
|
||||
if (sorter.columnKey === "people_num"||sorter.columnKey === "total_time") {
|
||||
let mysorder="";
|
||||
if (sorter.order === "ascend") {
|
||||
if(sorter.columnKey === "people_num"){
|
||||
mysorder="people_num-asc";
|
||||
}else{
|
||||
mysorder="total_time-asc";
|
||||
|
||||
}
|
||||
//升序
|
||||
let data={
|
||||
page:this.state.page,
|
||||
order:mysorder
|
||||
}
|
||||
this.togetdatas(data);
|
||||
this.setState({
|
||||
order: mysorder,
|
||||
})
|
||||
} else if (sorter.order === "descend") {
|
||||
if(sorter.columnKey === "people_num"){
|
||||
mysorder="people_num-desc";
|
||||
}else{
|
||||
mysorder="total_time-desc";
|
||||
|
||||
}
|
||||
//降序
|
||||
let data={
|
||||
page:this.state.page,
|
||||
order:mysorder
|
||||
}
|
||||
this.togetdatas(data);
|
||||
this.setState({
|
||||
order: mysorder,
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
let {loading,data,columnsstu,page,members_count,limit}=this.state;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="ws100s mt20">
|
||||
<script>
|
||||
{
|
||||
`
|
||||
a{
|
||||
text-decoration:none !important;
|
||||
}
|
||||
a:hover {text-decoration: none !important;}
|
||||
a:active{text-decoration:none !important;}
|
||||
`
|
||||
}
|
||||
</script>
|
||||
<div className="ws100s edu-back-white">
|
||||
<div className="ws100s teacherentrydivss pd15s">
|
||||
<div className="ws100s sortinxdirection">
|
||||
<div className="ws100s sptits font-18">统计列表</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.ysltableo .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
|
||||
padding: 10px 10px;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
|
||||
<div className="ws100s ysltableo teacherentrydivs pdinstop0" style={{ minHeight: "400px"}}>
|
||||
{
|
||||
data&&data.length===0?
|
||||
<div style={{
|
||||
minHeight: "400px",
|
||||
}} className="ws100s">
|
||||
<NoneDatas></NoneDatas>
|
||||
</div>
|
||||
: data&&data.length>0?
|
||||
<Spin spinning={loading}>
|
||||
<Table
|
||||
columns={columnsstu}
|
||||
dataSource={data}
|
||||
pagination={false}
|
||||
onChange={this.table1handleChange}
|
||||
|
||||
/>
|
||||
</Spin>
|
||||
:
|
||||
""
|
||||
}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="mb30 clearfix educontent mt40 intermediatecenter">
|
||||
{
|
||||
data&&data.length>0?
|
||||
<Pagination showQuickJumper current={this.state.page} onChange={this.paginationonChange}
|
||||
pageSize={this.state.limit}
|
||||
total={this.state.members_count}></Pagination>
|
||||
:""
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Videostatisticslist;
|
|
@ -156,16 +156,7 @@ class Loginqq extends Component {
|
|||
return (
|
||||
<div style={newContainer} className=" clearfix" >
|
||||
<Spin size="large" spinning={spinnings} >
|
||||
<style>
|
||||
{
|
||||
`
|
||||
#root{
|
||||
background:#fff !important;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<div>
|
||||
<div style={{
|
||||
"width": "100%"
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
|
||||
import { Redirect } from 'react-router';
|
||||
|
||||
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
|
||||
|
||||
import Loading from '../../Loading'
|
||||
|
||||
import Loadable from 'react-loadable';
|
||||
import { TPMIndexHOC } from '../tpm/TPMIndexHOC'
|
||||
import { SnackbarHOC } from 'educoder'
|
||||
|
||||
|
||||
const PackageIndex = Loadable({
|
||||
loader: () => import('../user/usersInfo/InfosTopics'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
|
||||
class Topic_bank extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="newMain clearfix">
|
||||
|
||||
<Switch>
|
||||
<Route path="/topicbank/:username/:topicstype"
|
||||
render={
|
||||
(props) => (<PackageIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route path="/topicbank/:topicstype"
|
||||
render={
|
||||
(props) => (<PackageIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
</Switch>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SnackbarHOC() (TPMIndexHOC (Topic_bank)) ;
|
Loading…
Reference in New Issue