修改后的上线

This commit is contained in:
sylor_huang@126.com 2020-05-21 16:47:59 +08:00
commit ac39faceca
76 changed files with 1478 additions and 11057 deletions

View File

@ -30,6 +30,72 @@
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe75e;</span>
<div class="name">TAR</div>
<div class="code-name">&amp;#xe75e;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe75d;</span>
<div class="name">ZIP</div>
<div class="code-name">&amp;#xe75d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe75c;</span>
<div class="name">文件夹</div>
<div class="code-name">&amp;#xe75c;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe75b;</span>
<div class="name">文件</div>
<div class="code-name">&amp;#xe75b;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe75a;</span>
<div class="name">下载</div>
<div class="code-name">&amp;#xe75a;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe759;</span>
<div class="name">复制</div>
<div class="code-name">&amp;#xe759;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe758;</span>
<div class="name">仓库</div>
<div class="code-name">&amp;#xe758;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe757;</span>
<div class="name">贡献者</div>
<div class="code-name">&amp;#xe757;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe755;</span>
<div class="name">发行版</div>
<div class="code-name">&amp;#xe755;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe754;</span>
<div class="name">标签</div>
<div class="code-name">&amp;#xe754;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe753;</span>
<div class="name">分支</div>
<div class="code-name">&amp;#xe753;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe751;</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>

View File

@ -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

View File

@ -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": "项目类别",

View File

@ -20,6 +20,39 @@ Created by iconfont
/>
<missing-glyph />
<glyph glyph-name="TAR" unicode="&#59230;" 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="&#59229;" 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="&#59228;" 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="&#59227;" 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="&#59226;" 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="&#59225;" 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="&#59224;" 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="&#59223;" 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="&#59221;" 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="&#59220;" 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="&#59219;" 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="&#59217;" 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.

View File

@ -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() {

View File

@ -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>

View File

@ -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}>
<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,11 +81,14 @@ 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>
<span>
<span className="color-grey-9 mr3">分支:</span>
<a className="ant-dropdown-link">
{branch} <Icon type="down" />
{branch}
</a>
</span>
<Icon type="down" />
</span>
</Dropdown>
</div>
)

View File

@ -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;

View File

@ -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} />
<React.Fragment>
<div className="main">
<div className="branchTable">
<p className="branchTitle">分支列表</p>
<p className="branchTitle bor-bottom-greyE">分支列表</p>
{list()}
</div>
</div>
</React.Fragment>
)
}

View File

@ -81,38 +81,6 @@ 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(
@ -132,24 +100,42 @@ class CoderRootCommit extends Component{
}
}
return(
<div>
<Top { ...this.props } {...this.state} />
<div className="f-wrap-between mt20">
<React.Fragment>
<div className="main">
<div className="f-wrap-between">
<SelectBranch branch={branch} branchs={branchs} changeBranch={this.changeBranch}></SelectBranch>
</div>
<Spin spinning={isSpin}>
<Table
className="mt20 wrap-commit-table"
columns={columns}
dataSource={data}
showHeader={false}
size="small"
pagination={false}
title={() => title()}
/>
<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>
</React.Fragment>
)
}
}

View File

@ -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>
}
{/* 子目录列表、文件 */}
{

View File

@ -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,

View File

@ -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} />)

View File

@ -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>
)
}

View File

@ -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';
@ -91,28 +90,6 @@ const MessageCount = Loadable({
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,
@ -174,9 +151,6 @@ class Detail extends Component{
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);
const { projectsId } = this.props.match.params;
this.getBranch(projectsId);
}
@ -336,7 +310,6 @@ class Detail extends Component{
<div className="normal">
<div className="f-wrap-between mb15" style={{ position: "relative" }}>
<p className="font-18 color-white df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
{projectDetail && projectDetail.author &&
<Link to={`/users/${projectDetail.author.login}/projects`} className="show-user-link color-white">
{projectDetail.author.name}
@ -344,37 +317,19 @@ class Detail extends Component{
}
<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>
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" />
@ -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>
@ -530,26 +530,8 @@ class Detail extends Component{
(props) => (<MessageCount {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/version/new"
render={
(props) => (<NewVersionIndex {...this.props} {...props} {...this.state}/>)
}
></Route>
<Route path="/projects/:projectsId/version/:versionId/upversion"
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} />)

View File

@ -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>
)
}

View File

@ -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>

View File

@ -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;
@ -612,3 +646,62 @@ a.color-grey-ccc:hover{
color: #4cacff !important;
}
.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;
}

View File

@ -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>
<span className="ant-form-item-required"></span>
</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>
<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>

View File

@ -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;
}
}

View File

@ -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,18 +39,20 @@ class Index extends Component{
const { pathname } = this.props.location;
const urlroot = pathname.split("newfile")[1];
return(
<React.Fragment>
<Top {...this.props} {...this.state}/>
<div className="main">
<div className="f-wrap-alignCenter">
<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>
<div className="branchTable">
<p className="branchTitle">新建文件</p>
<Editor
height="320px"
theme={"vs-dark"}
theme={"vs-grey"}
value={editorValue}
onChange={this.changeEditor}
/>
@ -61,6 +64,7 @@ class Index extends Component{
content={editorValue}
></UserSubmitComponent>
</div>
</React.Fragment>
)
}
}

View File

@ -50,40 +50,34 @@ 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">
<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>
@ -93,19 +87,27 @@ class UserSubmitComponent extends Component{
<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"><i className="iconfont icon-banbenku font-16 mr5"></i><span>{branch}</span></Radio>
<Radio value="0" className="mb10"><i className="iconfont icon-banbenku font-16 mr5"></i><span className="color-orange">{branch}</span></Radio>
<Radio value="1"><Icon type="pull-request" className="mr5" />为此提交创建一个<span className="font-bd">新的分支</span></Radio>
</Radio.Group>
{changeSubmitBranch()}
<Form.Item className="mt10" style={{marginBottom:"0px"}}>
<Button type="primary" onClick={this.subMitFrom} className="mr20">提交变更</Button>
</Form.Item>
</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>
)
}
}

View File

@ -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{

View File

@ -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: "所有分类",

52
src/forge/Version/New.jsx Normal file
View File

@ -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">单个附件不能超过 100MGVP 项目200M每个仓库总附件不可超过 1G推荐项目不可超过 5GGVP 项目不可超过 20G附件总容量统计包括仓库附件和发行版附件</p>
</div>
</div>
</div>
)
}

View File

@ -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 '../Order/order.css';
import './version.css';
@ -184,7 +183,6 @@ class NewVersion extends Component{
}],
})(
<TextArea placeholder="添加描述内容..." style={{ 'min-height': "150px" }} />
)}
</Form.Item>
{/* <UploadComponent load={this.UploadFunc} style={{width:80,marginLeft:15}}></UploadComponent> */}

View File

@ -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%;
}
@ -114,3 +169,20 @@
.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;
}

View File

@ -1,6 +1,5 @@
import React, { Component } from "react";
import { Link } from 'react-router-dom';
import { Input } from 'antd';
import NoneData from '../Nodata';
import './version.css';
import { getImageUrl } from 'educoder';
@ -11,13 +10,6 @@ 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) {
@ -25,15 +17,11 @@ class version extends Component{
this.state = {
issue_chosen: undefined,
data: undefined,
releases:undefined,
issues: undefined,
isSpin: false,
search: undefined,
author_id:undefined,
assigned_to_id:undefined,
limit:15,
page:1,
search_count: undefined,
issue_type:undefined
}
}
@ -41,15 +29,15 @@ class version extends Component{
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) {
this.setState({
data: result.data,
releases:result.data.releases,
issues: result.data.issues,
search_count:result.data.search_count,
isSpin: false
})
}
@ -58,88 +46,52 @@ class version extends Component{
})
}
// 显示版本描述
showBody=(key,flag)=>{
let { releases } = this.state;
releases[key].bodyshow = !flag;
this.setState({
releases
})
}
render() {
const { projectsId } = this.props.match.params;
const{data}=this.state
const { data , releases } = this.state
const renderList = () => {
if(data && data.releases && data.releases.length>0 ){
if (releases && 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>
: ''
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>
}
</h1>
<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 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>
:
""
}
</div>
)
})
@ -156,15 +108,14 @@ class version extends Component{
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>

View File

@ -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;

View File

@ -136,10 +136,6 @@ pre.prettyprint {
color: #FF6545
}
.color-orange {
color: #ee4a1f !important;
}
.color-orange02 {
color: #f79f88 !important;
}

View File

@ -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>

View File

@ -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

View File

@ -1,7 +0,0 @@
.indexdiv {
background:#ffffff;
}
.indexdiv:hover {
background:#ccc;
}

View File

@ -582,8 +582,8 @@ span.CodeMirror-selectedtext {
}
#root {
background: rgb(250, 250, 250);
body #root {
background: #EAEBEC;
}
.newedu-class-leftnav {

View File

@ -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;

View File

@ -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>*/}

View File

@ -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;
}

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,2 +0,0 @@
export const ROLE_TEACHER_NUM = 2;
export const ROLE_ASSISTANT_NUM = 3;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -156,15 +156,6 @@ class Loginqq extends Component {
return (
<div style={newContainer} className=" clearfix" >
<Spin size="large" spinning={spinnings} >
<style>
{
`
#root{
background:#fff !important;
}
`
}
</style>
<div>
<div style={{

View File

@ -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)) ;