new version

This commit is contained in:
caishi 2020-05-20 18:11:32 +08:00
parent ed778853ca
commit 62be5c0388
74 changed files with 1431 additions and 11058 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}>
<Input placeholder="请输入分支名称进行搜索" autocomplete="off" id="input-btn" value={value} className="OptionsInput" onChange={this.changeValue} onClick={this.InputClick}/>
<div className="padding10 bor-bottom-greyE">
<Input placeholder="请输入分支名称进行搜索" autocomplete="off" id="input-btn" value={value} className="OptionsInput" onChange={this.changeValue} onClick={this.InputClick}/>
</div>
<ul className="OptionsUl" id="ul-btn">
{
branchsFilter && branchsFilter.map((item,key)=>{
@ -79,10 +81,13 @@ class SelectBranch extends Component{
<div className="branchDropdown f-wrap-alignCenter" onClick={()=>this.ChangeVisible(visible)}>
<Dropdown overlay={menu} trigger={['click']} placement="bottomLeft" visible={visible}>
<span>
<span className="color-grey-9 mr3"><i className="iconfont icon-fenzhi font-20 color-grey-6 mr3"></i>:</span>
<a className="ant-dropdown-link">
{branch} <Icon type="down" />
</a>
<span>
<span className="color-grey-9 mr3">分支:</span>
<a className="ant-dropdown-link">
{branch}
</a>
</span>
<Icon type="down" />
</span>
</Dropdown>
</div>

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

View File

@ -81,39 +81,7 @@ class CoderRootCommit extends Component{
render(){
const { branch , data , dataCount , limit , page , isSpin } = this.state;
const { branchs } = this.props;
const columns=[{
title:"作者",
dataIndex: 'name',
width:"10%",
render: (text,item) => (
<span className="f-wrap-alignCenter">
<Link to={`/users/${item.login}/projects`} className="show-user-link">
<img src={getImageUrl(`images/${item.image_url}`)} alt="" width="28px" height="28px" className="mr3 radius"/>
<label className="hide-1" style={{maxWidth:"75px",'verticalAlign':'middle'}}>{text}</label>
</Link>
</span>
),
},{
title:"SHA",
dataIndex: 'sha',
render: (text) => (
<span className="commitKey">{truncateCommitId(text)}</span>
)
},{
title:"备注",
dataIndex: 'message',
render: (text) => (
<span>{text}</span>
)
},{
title:"提交时间",
className:"edu-txt-right",
dataIndex: 'time_from_now',
render: (text) => (
<span>{text}</span>
)
}]
const title =()=>{
return(
<div className="f-wrap-between" style={{alignItems:"center"}}>
@ -132,24 +100,42 @@ class CoderRootCommit extends Component{
}
}
return(
<div>
<Top { ...this.props } {...this.state} />
<div className="f-wrap-between mt20">
<SelectBranch branch={branch} branchs={branchs} changeBranch={this.changeBranch}></SelectBranch>
<React.Fragment>
<div className="main">
<div className="f-wrap-between">
<SelectBranch branch={branch} branchs={branchs} changeBranch={this.changeBranch}></SelectBranch>
</div>
<Spin spinning={isSpin}>
<div className="commonBox">
<div className="commonBox-title">
{title()}
</div>
<div className="commitList">
{
data && data.length > 0 && data.map((item,key)=>{
return(
<div>
<p className="df">
<span className="commitKey" style={{marginLeft:0}}>{truncateCommitId(`${item.sha}`)}</span>
<span className="flex1 ml20 font-16 color-grey-3">{item.message}</span>
{/* <Link to={''} className="color-blue">浏览代码</Link> */}
</p>
<p className="f-wrap-alignCenter mt15">
<Link to={`/users/${item.login}/projects`} className="show-user-link">
<img src={getImageUrl(`images/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>
<label className="font-14 color-grey-6" style={{'verticalAlign':'middle'}}>{item.name}:提交于 {item.time_from_now}</label>
</Link>
</p>
</div>
)
})
}
</div>
</div>
{ Pagination() }
</Spin>
</div>
<Spin spinning={isSpin}>
<Table
className="mt20 wrap-commit-table"
columns={columns}
dataSource={data}
showHeader={false}
size="small"
pagination={false}
title={() => title()}
/>
{ Pagination() }
</Spin>
</div>
</React.Fragment>
)
}
}

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

@ -1,6 +1,6 @@
import React , { Component } from 'react';
import { Spin , Tooltip } from 'antd';
import { Link , Route , Switch,withRouter } from 'react-router-dom';
import React, { Component } from 'react';
import { Spin, Tooltip } from 'antd';
import { Link, Route, Switch, withRouter } from 'react-router-dom';
import '../css/index.css'
import './list.css';
@ -23,362 +23,385 @@ import img_focused from '../Images/focused.png';
import img_fork from '../Images/fork.png';
import img_milepost from '../Images/milepost.png';
const FileNew = Loadable({
loader: () => import('../Newfile/Index'),
loading: Loading,
loader: () => import('../Newfile/Index'),
loading: Loading,
})
const Setting = Loadable({
loader: () => import('../Settings/Index'),
loading: Loading,
loader: () => import('../Settings/Index'),
loading: Loading,
})
const TagList = Loadable({
loader: () => import('../Order/Tags'),
loading: Loading,
loader: () => import('../Order/Tags'),
loading: Loading,
})
const OrderNew = Loadable({
loader: () => import('../Order/New'),
loading: Loading,
loader: () => import('../Order/New'),
loading: Loading,
})
const OrderDetail = Loadable({
loader: () => import('../Order/Detail'),
loading: Loading,
loader: () => import('../Order/Detail'),
loading: Loading,
})
const OrderIndex = Loadable({
loader: () => import('../Order/order'),
loading: Loading,
loader: () => import('../Order/order'),
loading: Loading,
})
const CoderRootIndex = Loadable({
loader: () => import('./CoderRootIndex'),
loading: Loading,
loader: () => import('./CoderRootIndex'),
loading: Loading,
})
const OrderMilepost = Loadable({
loader: () => import('../Order/Milepost'),
loading: Loading,
loader: () => import('../Order/Milepost'),
loading: Loading,
})
const OrdernewMilepost = Loadable({
loader: () => import('../Order/newMilepost'),
loading: Loading,
loader: () => import('../Order/newMilepost'),
loading: Loading,
})
const OrderupdateMilepost = Loadable({
loader: () => import('../Order/UpdateMilepost'),
loading: Loading,
loader: () => import('../Order/UpdateMilepost'),
loading: Loading,
})
const OrderupdateDetail = Loadable({
loader: () => import('../Order/UpdateDetail'),
loading: Loading,
loader: () => import('../Order/UpdateDetail'),
loading: Loading,
})
const OrdercopyDetail = Loadable({
loader: () => import('../Order/CopyDetail'),
loading: Loading,
loader: () => import('../Order/CopyDetail'),
loading: Loading,
})
//合并请求
const MergeIndexDetail = Loadable({
loader: () => import('../Merge/merge'),
loading: Loading,
loader: () => import('../Merge/merge'),
loading: Loading,
})
const CreateMerge = Loadable({
loader: () => import('../Merge/NewMerge'),
loading: Loading,
loader: () => import('../Merge/NewMerge'),
loading: Loading,
})
const MessageCount = Loadable({
loader: () => import('../Merge/MessageCount'),
loading: Loading,
loader: () => import('../Merge/MessageCount'),
loading: Loading,
})
const MergeSubmit = Loadable({
loader: () => import('../Merge/MergeSubmit'),
loading: Loading,
loader: () => import('../Merge/MergeSubmit'),
loading: Loading,
})
const UpdateMerge = Loadable({
loader: () => import('../Merge/UpdateMerge'),
loading: Loading,
loader: () => import('../Merge/UpdateMerge'),
loading: Loading,
})
//版本发布
const VersionIndex = Loadable({
loader: () => import('../Version/version'),
loading: Loading,
loader: () => import('../Version/version'),
loading: Loading,
})
const NewVersionIndex = Loadable({
loader: () => import('../Version/NewVersion'),
loading: Loading,
loader: () => import('../Version/NewVersion'),
loading: Loading,
})
const UpVersionIndex = Loadable({
loader: () => import('../Version/UpdateVersion'),
loading: Loading,
loader: () => import('../Version/UpdateVersion'),
loading: Loading,
})
const MilepostDetail = Loadable({
loader: () => import('../Order/MilepostDetail'),
loading: Loading,
loader: () => import('../Order/MilepostDetail'),
loading: Loading,
})
const TrendsIndex = Loadable({
loader: () => import('../Activity/Activity'),
loading: Loading,
loader: () => import('../Activity/Activity'),
loading: Loading,
})
/**
* permissionManager:管理员Reporter报告人员(只有读取权限)Developer开发人员除不能设置仓库信息外
*/
class Detail extends Component{
constructor(props){
class Detail extends Component {
constructor(props) {
super(props);
this.state={
isSpin:false,
projectDetail:undefined,
isManager:false,
isReporter:false,
isDeveloper:false,
project_id:undefined,
watchers_count:undefined ,
praises_count:undefined ,
forked_count:undefined,
watched: false,
praised: false,
this.state = {
isSpin: false,
projectDetail: undefined,
isManager: false,
isReporter: false,
isDeveloper: false,
project_id: undefined,
watchers_count: undefined,
praises_count: undefined,
forked_count: undefined,
watched: false,
praised: false,
http_url: undefined,
author:undefined,
branchs:undefined,
branchList:undefined,
branchLastCommit:undefined,
author: undefined,
branchs: undefined,
branchList: undefined,
branchLastCommit: undefined,
}
}
componentDidMount=()=>{
componentDidMount = () => {
this.getDetail();
}
componentDidUpdate=(prevState)=>{
if((prevState.match.params.projectsId !== this.props.match.params.projectsId)){
componentDidUpdate = (prevState) => {
if ((prevState.match.params.projectsId !== this.props.match.params.projectsId)) {
this.getDetail();
}
const { search } = this.props.location;
const search_c = prevState.location && prevState.location.search;
if( search && search!== search_c){
// console.log("branches",this.props.location);
// console.log("branches_p",prevState.location);
// console.log("111",this.props.dataquerys);
if (search && search !== search_c) {
const { projectsId } = this.props.match.params;
this.getBranch(projectsId);
}
}
getDetail=()=>{
getDetail = () => {
const { projectsId } = this.props.match.params;
const url = `/repositories/${projectsId}.json`;
axios.get(url).then((result)=>{
if(result){
axios.get(url).then((result) => {
if (result) {
this.setState({
projectDetail:result.data,
project_id:result.data.project_id,
isManager:result.data.permission && result.data.permission === "Manager",
isReporter:result.data.permission && result.data.permission === "Reporter",
isDeveloper:result.data.permission && result.data.permission === "Developer",
projectDetail: result.data,
project_id: result.data.project_id,
isManager: result.data.permission && result.data.permission === "Manager",
isReporter: result.data.permission && result.data.permission === "Reporter",
isDeveloper: result.data.permission && result.data.permission === "Developer",
http_url: result.data.clone_url,
author:result.data.author,
praised: result.data.praised,
watched: result.data.watched,
watchers_count:result.data.watchers_count,
praises_count:result.data.praises_count,
forked_count:result.data.forked_count,
author: result.data.author,
praised: result.data.praised,
watched: result.data.watched,
watchers_count: result.data.watchers_count,
praises_count: result.data.praises_count,
forked_count: result.data.forked_count,
})
if(result.data.project_id){
if (result.data.project_id) {
this.getBranch(result.data.project_id);
}
}
}).catch((error)=>{})
}).catch((error) => { })
}
// 关注和取消关注
focusFunc =(flag)=>{
focusFunc = (flag) => {
const { project_id } = this.state;
axios({
method: flag? 'delete' : 'post',
url: `/projects/${project_id}/watchers/${flag? 'unfollow' : 'follow'}.json`
})
.then(result => {
if(result && result.data.status === 0){
this.setWatchersCount(result.data.watchers_count, result.data.watched);
}
})
.catch(error => {
console.log(error);
});
axios({
method: flag ? 'delete' : 'post',
url: `/projects/${project_id}/watchers/${flag ? 'unfollow' : 'follow'}.json`
})
.then(result => {
if (result && result.data.status === 0) {
this.setWatchersCount(result.data.watchers_count, result.data.watched);
}
})
.catch(error => {
console.log(error);
});
}
// 点赞和取消点赞
pariseFunc=(flag)=>{
pariseFunc = (flag) => {
const { project_id } = this.state;
axios({
method: flag? 'delete' : 'post',
url: `/projects/${project_id}/praise_tread/${flag? 'unlike' : 'like'}.json`
})
.then(result => {
if(result && result.data.status === 0){
this.setPraisesCount(result.data.praises_count, result.data.praised)
}
})
.catch(error => {
console.log(error);
});
axios({
method: flag ? 'delete' : 'post',
url: `/projects/${project_id}/praise_tread/${flag ? 'unlike' : 'like'}.json`
})
.then(result => {
if (result && result.data.status === 0) {
this.setPraisesCount(result.data.praises_count, result.data.praised)
}
})
.catch(error => {
console.log(error);
});
}
setWatchersCount = (count, is_watched) => {
this.setState({
watched: is_watched,
watchers_count: count
})
}
setWatchersCount = (count, is_watched) => {
this.setState({
watched: is_watched,
watchers_count: count
})
}
setPraisesCount = (count, is_praised) => {
this.setState({
praised: is_praised,
praises_count: count
})
}
setPraisesCount = (count, is_praised) => {
this.setState({
praised: is_praised,
praises_count: count
})
}
// fork项目
forkFunc=()=>{
forkFunc = () => {
const { checkIfLogin } = this.props;
if(!checkIfLogin){
if (!checkIfLogin) {
this.props.showLoginDialog();
return;
}
this.setState({
isSpin:true
isSpin: true
})
const { project_id } = this.state;
const url = `/projects/${project_id}/forks.json`;
axios.post(url).then(result=>{
if (result && result.data.status === 0) {
axios.post(url).then(result => {
if (result && result.data.status === 0) {
this.props.history.push(`/projects/${result.data.id}/coders`);
this.props.showNotification(result.data.message);
}
this.setState({
isSpin:false
isSpin: false
})
}).catch(error=>{
}).catch(error => {
this.setState({
isSpin:false
isSpin: false
})
console.log(error);
})
}
// 获取分支列表
getBranch=(id)=>{
const url =`/projects/${id}/branches.json`;
axios.get(url).then((result)=>{
if(result && result.data.length>0){
getBranch = (id) => {
const url = `/projects/${id}/branches.json`;
axios.get(url).then((result) => {
if (result && result.data.length > 0) {
const branchs = [];
result.data.map((item,key)=>{
result.data.map((item, key) => {
branchs.push({
index:key,
name:item.name
index: key,
name: item.name
})
})
this.setState({
branchList:result.data,
branchList: result.data,
branchs,
branchLastCommit:result.data[0],
branchLastCommit: result.data[0],
})
}
}).catch((error)=>{})
}).catch((error) => { })
}
render(){
const { projectDetail , watchers_count , praises_count , forked_count , isSpin , isManager, watched, praised } = this.state;
render() {
const { projectDetail, watchers_count, praises_count, forked_count, isSpin, isManager, watched, praised } = this.state;
const url = this.props.history.location.pathname;
const urlArr= url.split("/");
const urlArr = url.split("/");
const urlFlag = (urlArr.length === 3);
const { projectsId } = this.props.match.params;
const { state } = this.props.history.location;
const text = (
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
<React.Fragment>
<span>forked from </span>
<Link to={`/users/${projectDetail.fork_info.fork_project_user_login}/projects`} className="show-user-link color-grey-ccc">{projectDetail.fork_info.fork_project_user_name}</Link>
<span> / </span>
<Link to={`/projects/${projectDetail.forked_from_project_id}/coders`} className="color-grey-ccc">{ projectDetail.fork_info.fork_form_name }</Link>
</React.Fragment>:""
);
return(
<Link to={`/projects/${projectDetail.forked_from_project_id}/coders`} className="color-grey-ccc">{projectDetail.fork_info.fork_form_name}</Link>
</React.Fragment> : ""
);
return (
<div>
<Spin spinning={isSpin}>
<div className="detailHeader-wrapper">
<div className="normal">
<div className="f-wrap-between mb15" style={{position:"relative"}}>
<p className="font-18 color-white df flex-1 lineH2 mt15" style={{alignItems:"center"}}>
<div className="f-wrap-between mb15" style={{ position: "relative" }}>
<p className="font-18 color-white df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
{projectDetail && projectDetail.author &&
<Link to={`/users/${projectDetail.author.login}/projects`} className="show-user-link color-white">
{projectDetail.author.name}
</Link>
<Link to={`/users/${projectDetail.author.login}/projects`} className="show-user-link color-white">
{projectDetail.author.name}
</Link>
}
<span className="ml5 mr5">/</span>
<span className="hide-1 flex-1 df">
<Link to={`/projects/${projectsId}/coders`} className="color-white">{ projectDetail && projectDetail.name }</Link>
<Link to={`/projects/${projectsId}/coders`} className="color-white font-22">{projectDetail && projectDetail.name}</Link>
{
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
<Tooltip placement={'right'} title={text}>
<Link to={`/projects/${projectDetail.forked_from_project_id}/coders`}
className="ml20" >
<i className="iconfont icon-fork color-grey-74 font-20 fl"></i>
</Link>
</Tooltip>:""
<Tooltip placement={'right'} title={text}>
<Link to={`/projects/${projectDetail.forked_from_project_id}/coders`}
className="ml10" >
<i className="iconfont icon-fork font-18 fl mt6" style={{ color: "#8D90E3" }}></i>
</Link>
</Tooltip> : ""
}
</span>
</p>
</div>
<div className="f-wrap-between">
<ul className="headerMenu-wrapper">
<li className={(url.indexOf("coders")>-1 || urlFlag) ? "active" : ""}>
<Link to={{pathname:`/projects/${projectsId}/coders`,state}}><img alt="" src={img_1} width="18" />代码库</Link>
</li>
<li className={(url.indexOf("orders")>-1 && !(url.indexOf("Milepost")>0 || url.indexOf("meilpost")>0 || url.indexOf("tags")>0))? "active" : ""}><Link to={{pathname:`/projects/${projectsId}/orders`,state}}><img alt="" src={img_2} width="12" />任务{projectDetail&&projectDetail.issues_count===0?"":projectDetail&&projectDetail.issues_count===0?projectDetail.issues_count:""}</Link></li>
<li className={url.indexOf("merge")>-1 ? "active" : ""}><Link to={{pathname:`/projects/${projectsId}/merge`,state}}><img alt="" src={img_3} width="13" />合并请求{projectDetail&&projectDetail.pull_requests_count===0?"":projectDetail&&projectDetail.pull_requests_count===0?projectDetail.pull_requests_count:""}</Link></li>
<li className={url.indexOf("version")>-1 ? "active" : ""}><Link to={{pathname:`/projects/${projectsId}/version`,state}}><img alt="" src={img_4} width="16" />版本发布</Link></li>
<li className={(url.indexOf("Milepost")>-1 || url.indexOf("meilpost")>-1) ? "active" : ""}><Link to={{pathname:`/projects/${projectsId}/orders/Milepost`,state}}><img alt="" src={img_milepost} width="16" />里程碑</Link></li>
<li className={url.indexOf("trends")>-1 ? "active" : ""}><Link to={{pathname:`/projects/${projectsId}/trends`,state}}><img alt="" src={img_6} width="16" />动态</Link></li>
{
isManager &&
<li className={url.indexOf("setting")>0 ? "active" : ""}><Link to={`/projects/${projectsId}/setting`}><img alt="" src={img_7} width="19" />仓库设置</Link></li>
}
</ul>
<span className="df">
<span className="df mt25">
<span className="detail_tag_btn">
<a className="detail_tag_btn_name" onClick={()=>this.focusFunc(watched)}>
<img src={watched ? img_focused : img_focus} alt="" width="14px"/>
{watched ? '取消关注':'关注'}
<a className="detail_tag_btn_name" onClick={() => this.focusFunc(watched)}>
<img src={watched ? img_focused : img_focus} alt="" width="14px" />
{watched ? '取消关注' : '关注'}
</a>
<span className="detail_tag_btn_count">{watchers_count}</span>
</span>
<span className="detail_tag_btn">
<a className="detail_tag_btn_name" onClick={()=>this.pariseFunc(praised)}>
<img src={praised ? img_parised : img_parise} width="13px" alt=""/>
{praised ? '取消点赞':'点赞'}
<a className="detail_tag_btn_name" onClick={() => this.pariseFunc(praised)}>
<img src={praised ? img_parised : img_parise} width="13px" alt="" />
{praised ? '取消点赞' : '点赞'}
</a>
<span className="detail_tag_btn_count">{praises_count}</span>
</span>
<span className="detail_tag_btn">
<a className="detail_tag_btn_name" onClick={this.forkFunc}>
<img src={img_fork} alt="" width="10px"/>Fork</a>
<img src={img_fork} alt="" width="10px" />Fork</a>
<span className="detail_tag_btn_count">{forked_count}</span>
</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>
@ -386,55 +409,55 @@ class Detail extends Component{
{/* 新建文件 */}
<Route path="/projects/:projectsId/coders/:branch/newfile/:path"
render={
(props) => (<FileNew {...this.props} {...props} {...this.state}/>)
(props) => (<FileNew {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/coders/:branch/newfile"
render={
(props) => (<FileNew {...this.props} {...props} {...this.state}/>)
(props) => (<FileNew {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 标签列表 */}
<Route path="/projects/:projectsId/orders/tags"
render={
(props) => (<TagList {...this.props} {...props} {...this.state}/>)
(props) => (<TagList {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 仓库设置 */}
<Route path="/projects/:projectsId/setting"
render={
(props) => (<Setting {...this.props} {...props} {...this.state} getDetail={this.getDetail}/>)
(props) => (<Setting {...this.props} {...props} {...this.state} getDetail={this.getDetail} />)
}
></Route>
{/* 任务详情 */}
<Route path="/projects/:projectsId/orders/:orderId/detail"
render={
(props) => (<OrderDetail {...this.props} {...props} {...this.state}/>)
(props) => (<OrderDetail {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 里程碑 */}
<Route path="/projects/:projectsId/orders/Milepost"
<Route path="/projects/:projectsId/orders/Milepost"
render={
(props) => (<OrderMilepost {...this.props} {...props} {...this.state}/>)
(props) => (<OrderMilepost {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 新建里程碑 */}
<Route path="/projects/:projectsId/orders/meilpost"
render={
(props) => (<OrdernewMilepost {...this.props} {...props} {...this.state}/>)
(props) => (<OrdernewMilepost {...this.props} {...props} {...this.state} />)
}
></Route>
{/*里程碑详情*/ }
{/*里程碑详情*/}
<Route path="/projects/:projectsId/orders/:meilid/MilepostDetail"
render={
(props) => (<MilepostDetail {...this.props} {...props} {...this.state}/>)
(props) => (<MilepostDetail {...this.props} {...props} {...this.state} />)
}
></Route>
{/*修改里程碑*/}
<Route path="/projects/:projectsId/orders/:meilid/meilpost"
{/*修改里程碑*/}
<Route path="/projects/:projectsId/orders/:meilid/meilpost"
render={
(props) => (<OrderupdateMilepost {...this.props} {...props} {...this.state}/>)
(props) => (<OrderupdateMilepost {...this.props} {...props} {...this.state} />)
}
></Route>
@ -442,34 +465,34 @@ class Detail extends Component{
{/* 里程碑页面新建任务 */}
<Route path="/projects/:projectsId/orders/:milepostId/new"
render={
(props) => (<OrderNew {...this.props} {...props} {...this.state}/>)
(props) => (<OrderNew {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 新建任务 */}
<Route path="/projects/:projectsId/orders/new"
render={
(props) => (<OrderNew {...this.props} {...props} {...this.state}/>)
(props) => (<OrderNew {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 修改详情 */}
<Route path="/projects/:projectsId/orders/:orderId/updatedetail"
<Route path="/projects/:projectsId/orders/:orderId/updatedetail"
render={
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state}/>)
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 复制详情 */}
<Route path="/projects/:projectsId/orders/:orderId/copyetail"
{/* 复制详情 */}
<Route path="/projects/:projectsId/orders/:orderId/copyetail"
render={
(props) => (<OrdercopyDetail {...this.props} {...props} {...this.state}/>)
(props) => (<OrdercopyDetail {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 动态 */}
<Route path="/projects/:projectsId/trends"
render={
(props) => (<TrendsIndex {...this.props} {...props} {...this.state}/>)
(props) => (<TrendsIndex {...this.props} {...props} {...this.state} />)
}
></Route>
@ -477,71 +500,53 @@ class Detail extends Component{
{/* 代码Index */}
<Route path="/projects/:projectsId/orders"
render={
(props) => (<OrderIndex {...this.props} {...props} {...this.state}/>)
(props) => (<OrderIndex {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/merge/new"
render={
(props) => (<CreateMerge {...this.props} {...props} {...this.state}/>)
(props) => (<CreateMerge {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/merge/:mergeId/UpdateMerge"
render={
(props) => (<MessageCount {...this.props} {...props} {...this.state}/>)
(props) => (<MessageCount {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/merge/:mergeId/Messagecount"
render={
(props) => (<MessageCount {...this.props} {...props} {...this.state}/>)
(props) => (<MessageCount {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/merge/:mergeId/MergeSubmit"
render={
(props) => (<MessageCount {...this.props} {...props} {...this.state}/>)
}
></Route>
<Route path="/projects/:projectsId/version/new"
render={
(props) => (<NewVersionIndex {...this.props} {...props} {...this.state}/>)
(props) => (<MessageCount {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/version/:versionId/upversion"
<Route path="/projects/:projectsId/merge"
render={
(props) => (<UpVersionIndex {...this.props} {...props} {...this.state}/>)
}
></Route>
<Route path="/projects/:projectsId/version"
render={
(props) => (<VersionIndex {...this.props} {...props} {...this.state}/>)
}
></Route>
<Route path="/projects/:projectsId/merge"
render={
(props) => (<MergeIndexDetail {...this.props} {...props} {...this.state}/>)
(props) => (<MergeIndexDetail {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/coders/filesurl"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state}/>)
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId/coders"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state}/>)
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/projects/:projectsId"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state}/>)
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} />)
}
></Route>
</Switch>

View File

@ -9,12 +9,28 @@ 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>
<Link to={`/projects/${projectsId}/coders/warehouse`} className={pathname.indexOf("/coders/warehouse") > 0 ? "active" : ""}>
<i className="iconfont icon-cangku font-18 mr3"></i>
仓库 <span>{projectDetail && projectDetail.size}</span>kb
</Link>
</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,43 +312,61 @@
color: #fff;
}
.detail_tag_btn_name img{
margin-right: 3px;
margin-right: 10px;
}
.detail_tag_btn_count{
padding:0px 10px;
color: #fff;
background: #1C91FF;
background: #71A6FF;
border-radius: 0px 4px 4px 0px;
font-size: 12px;
}
/* 详情-代码 */
.branch-wrapper{
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;
@ -349,14 +375,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{
@ -366,47 +391,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;
@ -507,16 +539,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;
@ -607,4 +641,63 @@ border: 1px solid #2185d0;
a.color-grey-ccc:hover{
color: #4cacff !important;
}
.pull-right{float: right;}
.pull-right{float: right;}
.commitList{
padding:0px 30px;
}
.commitList > div{
border-bottom: 1px solid #EEEEEE;
padding:16px 0px;
}
.commitList > div:last-child{
border-bottom: none;
}
/* 标签列表 */
.div_table{
border:1px solid #eee;
border-radius: 2px;
}
.ul_thead{
padding:0px 30px;
box-sizing: border-box;
background: #FAFAFA;
border-bottom: 1px solid #eee;
height: 50px;
line-height: 50px;
}
.ul_tbody{
padding:0px 30px;
}
.ul_thead li, .ul_tbody li{
display: flex;
align-items: center;
text-align: left
}
.ul_tbody li{
padding:18px 0px;
border-bottom: 1px solid #eee;
}
.ul_tbody li:last-child{
border-bottom: none;
}
.ul_thead li > span , .ul_tbody li > span{
width: 20%;
padding-right: 20px;
}
.ul_thead li > span:nth-child(2), .ul_tbody li > span:nth-child(2){
flex:1;
}
.ul_tbody_third{
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: left;
}
.ul_tbody_forth{
text-align: center;
display: flex;
justify-content: center;
}

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>
<div className="ant-col ant-form-item-control-wrapper color-grey-9">
<div className="ant-form-item-control">
<span className="ant-form-item-required"></span>
</div>
</div>
<div>
<span className="ant-form-item-required"></span>
</div>
<Form.Item className="formTip">
<Form.Item className="formTip mt20">
<Button type="primary" onClick={this.subMitFrom} className="mr20">创建项目</Button>
<Link to={'/projects'} className="btn_32">取消</Link>
</Form.Item>

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,29 +39,32 @@ class Index extends Component{
const { pathname } = this.props.location;
const urlroot = pathname.split("newfile")[1];
return(
<div className="main">
<div className="f-wrap-alignCenter">
<div className="setInputAddon">
<Input addonBefore={`/${projectDetail && projectDetail.identifier}${urlroot}/`} value={filename} onChange={this.changeFileName} placeholder="命名文件..."/>
<React.Fragment>
<Top {...this.props} {...this.state}/>
<div className="main">
<p className="pb15 bor-bottom-greyE font-16 color-grey-3 mb20">新建文件</p>
<div className="f-wrap-alignCenter mb20">
<div className="setInputAddon">
<Input addonBefore={`/${projectDetail && projectDetail.identifier}${urlroot}/`} value={filename} onChange={this.changeFileName} placeholder="命名文件..."/>
</div>
<a onClick={this.CancelAddFile} className="color-blue">取消</a>
</div>
<a onClick={this.CancelAddFile} className="color-blue">取消</a>
<div className="branchTable">
<Editor
height="320px"
theme={"vs-grey"}
value={editorValue}
onChange={this.changeEditor}
/>
</div>
<UserSubmitComponent
{...this.props}
{...this.state}
filepath={`${urlroot}/${filename}`}
content={editorValue}
></UserSubmitComponent>
</div>
<div className="branchTable">
<p className="branchTitle">新建文件</p>
<Editor
height="320px"
theme={"vs-dark"}
value={editorValue}
onChange={this.changeEditor}
/>
</div>
<UserSubmitComponent
{...this.props}
{...this.state}
filepath={`${urlroot}/${filename}`}
content={editorValue}
></UserSubmitComponent>
</div>
</React.Fragment>
)
}
}

View File

@ -50,61 +50,63 @@ class UserSubmitComponent extends Component{
const { submitType } = this.state;
const { getFieldDecorator } = this.props.form;
const { branch } = this.props.match.params;
const { branch , projectsId } = this.props.match.params;
const { current_user , filepath , projectDetail } = this.props;
const changeSubmitBranch = ()=>{
if(submitType==="1"){
return(
<div className="mt24">
<Form.Item style={{paddingLeft:"24px"}}>
{getFieldDecorator('desc', {
rules: [{
required:true,message:'请输入合并请求的描述内容'
}],
})(
<TextArea placeholder={`请输入合并请求的描述,(必填)`} authSize={{minRows:3,maxRows:5}}/>
)}
</Form.Item>
<div className="mt15">
<Form.Item style={{paddingLeft:"24px"}}>
{getFieldDecorator('branchname', {
rules: [{
required: true, message: '请输入分支名称'
}],
})(
<Input placeholder={`请输入分支名称`}/>
<Input placeholder={`请输入分支名称`} style={{width:"220px"}}/>
)}
</Form.Item>
</div>
)
}
}
return(
<div className="userScrew">
<img src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt="" className="screwImg"/>
<div className="screwPanel">
<Form>
<Form.Item>
{getFieldDecorator('path', {
rules: [],
})(
<Input placeholder={`/${projectDetail && projectDetail.identifier}${filepath}`} readOnly/>
)}
</Form.Item>
<div>
<span className="df mt20" style={{alignItems:"center"}}>
<img src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt="" className="screwImg"/>
<span className="color-grey-3">用户名<span className="color-grey-8">{current_user && current_user.username}</span></span>
</span>
<div className="userScrew">
<div className="screwPanel">
<Form>
<Form.Item>
{getFieldDecorator('path', {
rules: [],
})(
<Input placeholder={`/${projectDetail && projectDetail.identifier}${filepath}`} readOnly/>
)}
</Form.Item>
<Form.Item>
{getFieldDecorator('desc', {
rules: [{
required:true,message:'请输入合并请求的描述内容'
}],
})(
<TextArea placeholder={`请输入合并请求的描述,(必填)`} authSize={{minRows:3,maxRows:5}}/>
)}
</Form.Item>
<Radio.Group value={submitType} onChange={this.changeSubmittype}>
<Radio value="0" className="mb10"><i className="iconfont icon-banbenku font-16 mr5"></i><span className="color-orange">{branch}</span></Radio>
<Radio value="1"><Icon type="pull-request" className="mr5" />为此提交创建一个<span className="font-bd">新的分支</span></Radio>
</Radio.Group>
{changeSubmitBranch()}
<Radio.Group value={submitType} onChange={this.changeSubmittype}>
<Radio value="0"><i className="iconfont icon-banbenku font-16 mr5"></i><span>{branch}</span></Radio>
<Radio value="1"><Icon type="pull-request" className="mr5" />为此提交创建一个<span className="font-bd">新的分支</span></Radio>
</Radio.Group>
{changeSubmitBranch()}
<Form.Item className="mt10" style={{marginBottom:"0px"}}>
<Button type="primary" onClick={this.subMitFrom} className="mr20">提交变更</Button>
</Form.Item>
</Form>
</Form>
</div>
</div>
<Button type="primary" onClick={this.subMitFrom} className="mr20">提交变更</Button>
<Button type="primary grey" onClick={()=>{this.props.history.push(`/projects/${projectsId}/coders`)}} className="mr20">取消</Button>
</div>
)
}

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

@ -1,56 +1,56 @@
import React , { Component } from "react";
import React, { Component } from "react";
import { Upload, Button, Icon } from 'antd';
import { getUploadActionUrl, appendFileSizeToUploadFileAll } from 'educoder';
import axios from 'axios';
const { Dragger } = Upload;
class Index extends Component{
constructor(props){
class Index extends Component {
constructor(props) {
super(props);
this.state={
fileList:undefined,
this.state = {
fileList: undefined,
}
}
onAttachmentRemove = (file) => {
if(!file.percent || file.percent === 100){
// this.props.confirm({
// content: '是否确认删除?',
// onOk: () => {
// this.deleteAttachment(file)
// },
// onCancel() {
// console.log('Cancel');
// },
if (!file.percent || file.percent === 100) {
// this.props.confirm({
// content: '是否确认删除?',
// onOk: () => {
// this.deleteAttachment(file)
// },
// onCancel() {
// console.log('Cancel');
// },
// });
this.deleteAttachment(file)
return false;
}
return false;
}
}
deleteAttachment = (file) => {
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
axios.delete(url, {
}).then((response) => {
if (response.data) {
if (response.data.status === 0) {
this.setState((state) => {
const index = state.fileList.indexOf(file);
const newFileList = state.fileList.slice();
newFileList.splice(index, 1);
return {
fileList: newFileList,
};
});
this.fileIdList(this.state.fileList);
}else{
this.props.showNotification(response.data.message)
}
if (response.data) {
if (response.data.status === 0) {
this.setState((state) => {
const index = state.fileList.indexOf(file);
const newFileList = state.fileList.slice();
newFileList.splice(index, 1);
return {
fileList: newFileList,
};
});
this.fileIdList(this.state.fileList);
} else {
this.props.showNotification(response.data.message)
}
}).catch(function (error) {
console.log(error);
});
}
}).catch(function (error) {
console.log(error);
});
}
@ -65,36 +65,36 @@ class Index extends Component{
}
}
fileIdList=(fileList)=>{
fileIdList = (fileList) => {
let array = [];
fileList && fileList.length>0 && fileList.map((item)=>{
fileList && fileList.length > 0 && fileList.map((item) => {
return array.push(item.response && item.response.id);
})
array && this.props.load && this.props.load(array);
}
render(){
render() {
//判断是否已经提交,如已提交评论则上一条评论数据清除
const { isComplete } = this.props;
const { fileList } = this.state;
let list = isComplete === true ? fileList : undefined;
const upload = {
name: 'file',
fileList:list,
fileList: list,
action: `${getUploadActionUrl()}`,
onChange:this.handleChange,
onChange: this.handleChange,
onRemove: this.onAttachmentRemove,
};
return(
return (
<div>
<Dragger {...upload} >
<Icon type="inbox" />
<p className="ant-upload-text">拖动文件或者点击此处上传</p>
</Dragger>
<Icon type="inbox" />
<p className="ant-upload-text">拖动文件或者点击此处上传</p>
</Dragger>
</div>
)
}
}
}
export default Index;

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 React, { Component } from "react";
import { Form, Input, Select, Divider, Button, Checkbox, Dropdown, Menu, Spin } from 'antd';
import '../Order/order.css';
import './version.css';
@ -9,56 +8,56 @@ import axios from 'axios';
const Option = Select.Option;
const TextArea = Input.TextArea;
class NewVersion extends Component{
constructor(props){
class NewVersion extends Component {
constructor(props) {
super(props);
this.state={
branch_name:"",
issue_tag_ids:"",
fixed_version_id:"",
issue_chosen:undefined,
fileList:undefined,
ischeck:undefined,
branches:undefined,
pull:undefined,
tag_name:'',
this.state = {
branch_name: "",
issue_tag_ids: "",
fixed_version_id: "",
issue_chosen: undefined,
fileList: undefined,
ischeck: undefined,
branches: undefined,
pull: undefined,
tag_name: '',
isSpin: false
}
}
componentDidMount=()=>{
componentDidMount = () => {
this.InitData();
this.getSelectList();
}
InitData=()=>{
InitData = () => {
this.props.form.setFieldsValue({
...this.state
});
}
getSelectList=()=>{
getSelectList = () => {
const { projectsId } = this.props.match.params;
const url = `/projects/${projectsId}/version_releases/new.json`;
axios.get(url).then((result)=>{
if(result){
axios.get(url).then((result) => {
if (result) {
this.setState({
branches:result.data.branches,
pull:result.data.branches[0]
branches: result.data.branches,
pull: result.data.branches[0]
})
}
}).catch((error)=>{
}).catch((error) => {
console.log(error);
})
}
renderSelect=(list)=>{
if(list && list.length >0){
return(
list.map((item,key)=>{
return(
<Option key={key+1} value={item.id+""}>{item.name}</Option>
renderSelect = (list) => {
if (list && list.length > 0) {
return (
list.map((item, key) => {
return (
<Option key={key + 1} value={item.id + ""}>{item.name}</Option>
)
})
)
@ -66,36 +65,36 @@ class NewVersion extends Component{
}
// 创建
handleSubmit=(draft)=>{
handleSubmit = (draft) => {
this.setState({
isSpin: true
})
this.props.form.validateFieldsAndScroll((err, values) => {
if(!err){
if (!err) {
const { projectsId } = this.props.match.params;
const { pull,tag_name,ischeck} = this.state;
const { pull, tag_name, ischeck } = this.state;
const url = `/projects/${projectsId}/version_releases.json`;
// if(values.issue_type==="普通"){
// values.issue_type="1"
// }
axios.post(url,{
axios.post(url, {
...values,
tag_name:tag_name,
draft:draft,
prerelease:ischeck,
target_commitish:pull,
}).then(result=>{
if(result){
tag_name: tag_name,
draft: draft,
prerelease: ischeck,
target_commitish: pull,
}).then(result => {
if (result) {
this.setState({
isSpin: false
})
this.props.history.push(`/projects/${projectsId}/version`);
}
}).catch(error=>{
}).catch(error => {
console.log(error);
})
}else{
} else {
this.setState({
isSpin: false
})
@ -104,27 +103,27 @@ class NewVersion extends Component{
}
// 获取上传后的文件id数组
UploadFunc=(fileList)=>{
UploadFunc = (fileList) => {
this.setState({
fileList
})
}
RedieonChange=(e)=>{
this.setState({
ischeck:e.target.checked
})
RedieonChange = (e) => {
this.setState({
ischeck: e.target.checked
})
}
Preservation=()=>{
alert(this.state.ischeck)
Preservation = () => {
alert(this.state.ischeck)
}
renderMenu =(array,id)=>{
return(
renderMenu = (array, id) => {
return (
<Menu>
{
array && array.length > 0 && array.map((item,key)=>{
return(
<Menu.Item key={item} onClick={()=>this.getOption(item)}>{item}</Menu.Item>
array && array.length > 0 && array.map((item, key) => {
return (
<Menu.Item key={item} onClick={() => this.getOption(item)}>{item}</Menu.Item>
)
})
}
@ -132,78 +131,77 @@ class NewVersion extends Component{
)
}
getOption=(name)=>{
this.setState({
pull:name
})
getOption = (name) => {
this.setState({
pull: name
})
}
changmodelname=(e)=>{
changmodelname = (e) => {
this.setState({
tag_name:e.target.value
tag_name: e.target.value
})
}
render(){
render() {
const { getFieldDecorator } = this.props.form;
const {branches,pull,tag_name, isSpin} = this.state;
return(
<div className="main">
<Form>
<h1 style={{marginLeft:15,marginTop:20}}>发布新版</h1>
<h5 style={{marginLeft:15}}>发布一个特定的打包好的项目版本</h5>
<Divider/>
<div style={{display:'flex'}}>
<Input placeholder="标签名称" style={{width:180,marginLeft:15}} value={tag_name} onChange={this.changmodelname} />
<div style={{marginLeft:20,marginRight:20,lineHeight: '32px'}}>@ </div>
<Dropdown overlay={this.renderMenu(branches &&branches,'pull')} trigger={['click']} placement="bottomCenter">
<Button style={{width:180}}>{pull}</Button>
</Dropdown>
const { branches, pull, tag_name, isSpin } = this.state;
return (
<div className="main">
<Form>
<h1 style={{ marginLeft: 15, marginTop: 20 }}>发布新版</h1>
<h5 style={{ marginLeft: 15 }}>发布一个特定的打包好的项目版本</h5>
<Divider />
<div style={{ display: 'flex' }}>
<Input placeholder="标签名称" style={{ width: 180, marginLeft: 15 }} value={tag_name} onChange={this.changmodelname} />
<div style={{ marginLeft: 20, marginRight: 20, lineHeight: '32px' }}>@ </div>
<Dropdown overlay={this.renderMenu(branches && branches, 'pull')} trigger={['click']} placement="bottomCenter">
<Button style={{ width: 180 }}>{pull}</Button>
</Dropdown>
</div>
<div style={{display:'flex'}}>
<div className="versionmilepostleft">
<h1>标题</h1>
<div>
<Form.Item>
<div style={{ display: 'flex' }}>
<div className="versionmilepostleft">
<h1>标题</h1>
<div>
<Form.Item>
{getFieldDecorator('name', {
rules: [{
required: true, message: '请输入标题'
}],
})(
<Input placeholder="标题" maxLength="32"/>
<Input placeholder="标题" maxLength="32" />
)}
</Form.Item>
</div>
<h1>内容</h1>
<Form.Item>
{getFieldDecorator('body', {
rules: [{
required: true, message: '请输入描述内容'
}],
})(
<TextArea placeholder="添加描述内容..." style={{'min-height':"150px"}}/>
)}
</Form.Item>
{/* <UploadComponent load={this.UploadFunc} style={{width:80,marginLeft:15}}></UploadComponent> */}
</div>
<h1>内容</h1>
<Form.Item>
{getFieldDecorator('body', {
rules: [{
required: true, message: '请输入描述内容'
}],
})(
<TextArea placeholder="添加描述内容..." style={{ 'min-height': "150px" }} />
)}
</Form.Item>
{/* <UploadComponent load={this.UploadFunc} style={{width:80,marginLeft:15}}></UploadComponent> */}
</div>
</div>
<Divider />
<div className="fr mb15">
<Checkbox onChange={this.RedieonChange}>标记为预行版<span className="ml15 color-grey-9 font-13">(此版本不适合生产使用)</span></Checkbox>
</div>
<div className="clearfix mt15" style={{ marginTop: 5 }} >
<Spin spinning={isSpin}>
<a className='topWrapper_btn_close fr' onClick={() => this.handleSubmit(true)} style={{ marginLeft: 15 }} >保存草稿</a>
<a className='topWrapper_btn fr' onClick={() => this.handleSubmit(false)} style={{ marginRight: 15 }}>发布版本</a>
</Spin>
</div>
<Divider/>
<div className="fr mb15">
<Checkbox onChange={this.RedieonChange}>标记为预行版<span className="ml15 color-grey-9 font-13">(此版本不适合生产使用)</span></Checkbox>
</div>
<div className="clearfix mt15" style={{marginTop:5}} >
<Spin spinning={isSpin}>
<a className='topWrapper_btn_close fr' onClick={()=>this.handleSubmit(true)} style={{marginLeft:15}} >保存草稿</a>
<a className='topWrapper_btn fr' onClick={()=>this.handleSubmit(false)} style={{marginRight:15}}>发布版本</a>
</Spin>
</div>
</Form>
</div>
</div>
)
}
}

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

View File

@ -1,6 +1,5 @@
import React , { Component } from "react";
import {Link} from 'react-router-dom';
import { Input } from 'antd';
import React, { Component } from "react";
import { Link } from 'react-router-dom';
import NoneData from '../Nodata';
import './version.css';
import { getImageUrl } from 'educoder';
@ -11,160 +10,112 @@ import axios from 'axios';
* data:列表接口返回的所有数据,
* issues:列表数组,
* isSpin:加载中,
* search:搜索关键字,
* author_id:发布者id,
* assigned_to_id:指派给的id
* limit:每页条数,
* page:当前页,
* search_count:列表总条数
* issue_type:搜索条件
*/
class version extends Component{
constructor(props){
class version extends Component {
constructor(props) {
super(props);
this.state={
issue_chosen:undefined,
data:undefined,
issues:undefined,
isSpin:false,
search:undefined,
author_id:undefined,
assigned_to_id:undefined,
limit:15,
page:1,
search_count:undefined,
issue_type:undefined
this.state = {
issue_chosen: undefined,
data: undefined,
releases:undefined,
issues: undefined,
isSpin: false,
search: undefined,
search_count: undefined,
}
}
componentDidMount=()=>{
componentDidMount = () => {
this.getIssueList();
}
// 获取列表数据
getIssueList=(page,limit,search,author_id,assigned_to_id,id,value)=>{
getIssueList = () => {
const { projectsId } = this.props.match.params;
const url = `/projects/${projectsId}/version_releases.json`;
axios.get(url).then((result)=>{
if(result){
axios.get(url).then((result) => {
if (result) {
this.setState({
data:result.data,
issues:result.data.issues,
search_count:result.data.search_count,
isSpin:false
data: result.data,
releases:result.data.releases,
issues: result.data.issues,
isSpin: false
})
}
}).catch((error)=>{
}).catch((error) => {
console.log(error);
})
}
// 显示版本描述
showBody=(key,flag)=>{
let { releases } = this.state;
releases[key].bodyshow = !flag;
this.setState({
releases
})
}
render(){
render() {
const { projectsId } = this.props.match.params;
const{data}=this.state
const renderList =()=>{
if(data && data.releases && data.releases.length>0 ){
return(
<div>{
data.releases.map((item,key)=>{
return(
<div key={key}>
{
item && item.id ?
<div>
<div style={{display:'flex'}}>
<div className="versionleft">
<div className="versionrighe"></div><span  className={item&&item.draft===""?"opendversionetail":"closedversionetail"} style={{marginTop:5,margin:'auto',marginRight:15}}>{item.draft} </span>
</div>
<div className="version_line_one">
<p className="versionrectangle"> </p>
</div>
<div className="versionrighe">
<h1 style={{marginLeft:15,marginTop:5}}>{item.name}
{
data && data.user_permission ?
<Link to={`/projects/${projectsId}/version/${item.version_id}/upversion`} style={{color:'blue',fontSize:10,marginLeft:5}}>(编辑)</Link>
: ''
}
</h1>
</div>
</div>
<div style={{display:'flex'}}>
<div className="versionleft">
<span style={{marginTop:5,margin:'auto',marginRight:15}}>{item.tag_name} </span>
</div>
<div className="version_line_one">
<p style={{width:4}}> </p>
</div>
<div className="versionrighe">
<h5 style={{marginLeft:15,marginTop:10}}>{item.body} </h5>
<div className="ml15">
<Link to={`/users/${item && item.login}/projects`} className="show-user-link">
<img src={getImageUrl(`images/${item.image_url}`)} alt="" width="28px" height="28px" className="mr5 radius"/>
<span className="mr10 ver-middle">{item.user_name}</span>
</Link>
<span className="color-grey-9 ver-middle">发布于{item.created_at}</span>
</div>
</div>
</div>
<div style={{display:'flex'}}>
<div className="versionleft">
<span style={{marginTop:5,marginRight:15}}></span>
</div>
<div className="version_line_tpw">
<p style={{width:4}}> </p>
</div>
<div className="versionrighe">
<h1 style={{marginLeft:15,marginTop:10}}>下载附件
</h1>
<a href={item.zipball_url} download="源代码(ZIP)" style={{color:'blue',marginLeft:15}}>源代码(ZIP)</a>
<a href={item.tarball_url} download="源文件(TAR.GZ)" style={{color:'blue',marginLeft:15}}>源文件(TAR.GZ)</a>
</div>
</div>
<div style={{display:'flex'}}>
<div className="versionleft">
<span style={{marginTop:5,marginRight:15}}></span>
</div>
<div className="version_line_tpw">
<p style={{width:4}}> </p>
</div>
<div className="versionrighe">
</div>
</div>
</div>
:
""
}
const { data , releases } = this.state
const renderList = () => {
if (releases && releases.length > 0) {
return (
<div>
{
releases.map((item, key) => {
return (
<div className="versionInfo" key={key}>
<span className="versionInfo_left">
<span className={`${item.draft === "稳定" ?"versionTag green":"versionTag yellow"}`}>{item.draft}</span>
<span className="mt10">{item.created_at}</span>
<span className="color-grey-8">
<i className="iconfont icon-biaoqian3 mr3 font-14"></i>
{item.tag_name}
</span>
</span>
<div className="versionInfo_right">
<span className="versionName">
<span className="task-hide">{item.name}</span>
<Link to={`/projects/${projectsId}/coders/version/${item.version_id}/update`} className="color-blue ml3 font-12">编辑</Link>
</span>
<span className="color-grey-3">
<i className={`${item.bodyshow ? "iconfont icon-sanjiaoxing-down color-grey-8 mr3 font-14":"iconfont icon-triangle color-grey-8 mr3 font-14"}`} onClick={()=>this.showBody(key,item.bodyshow)}></i>
{item.user_name}:<span className="color-grey-8">发布了这个版本并在发布后提交给{item.target_commitish}</span>
</span>
{
item.bodyshow && <p className="mt10">{item.body}</p>
}
<p className="mt10 pl3">
{/* <span className="commitKey mr20">{item.commit_id}</span> */}
<a href={item.tarball_url} style={{color:"#4CC1DA"}} className="mr30"><i className="iconfont icon-TAR font-18 mr5"></i>TAR</a>
<a href={item.zipball_url} style={{color:"#28BD6C"}}><i className="iconfont icon-ZIP font-18 mr5"></i>ZIP</a>
</p>
</div>
</div>
)
})
}
</div>
)
}else{
return(
} else {
return (
<NoneData _html="暂时还没有相关数据哦!" />
)
}
}
return(
return (
<div className="main">
<div className="topWrapper">
<h1>版本发布</h1>
<span className="font-18 color-grey-3">版本发布</span>
{
data && data.user_permission ?
<Link to={`/projects/${projectsId}/version/new`} className="topWrapper_btn">发布新版</Link>
<Link to={`/projects/${projectsId}/coders/version/new`} className="topWrapper_btn_new">+ 发布新版</Link>
: ''
}
</div>
<div>
<div className="releasesVersion">
{renderList()}
</div>

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,16 +156,7 @@ class Loginqq extends Component {
return (
<div style={newContainer} className=" clearfix" >
<Spin size="large" spinning={spinnings} >
<style>
{
`
#root{
background:#fff !important;
}
`
}
</style>
<div>
<div style={{
"width": "100%"

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