Merge branch 'dev_aliyun' of http://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun

newyslclassrooms
cxt 5 years ago
commit 5cd1ffec32

@ -1,6 +1,6 @@
class Users::VideosController < Users::BaseController
before_action :private_user_resources!, :check_account
before_action :require_teacher!
before_action :require_teacher!, except: [:destroy]
before_action :require_auth_teacher!, except: [:index, :review]
helper_method :current_video
@ -53,6 +53,19 @@ class Users::VideosController < Users::BaseController
render_error(ex.message)
end
def destroy
video = observed_user.videos.find_by(id: params[:video_id])
render_forbidden unless video.user_id != observed_user.id || !current_user.admin_or_business?
return render_not_found if video.blank?
return render_error('该状态下不能删除视频') unless video.pending?
video.destroy!
AliyunVod::Service.delete_video([video.uuid]) rescue nil
render_ok
end
private
def current_video

@ -30,6 +30,54 @@
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe734;</span>
<div class="name">移动</div>
<div class="code-name">&amp;#xe734;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe732;</span>
<div class="name">下移2</div>
<div class="code-name">&amp;#xe732;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe731;</span>
<div class="name">上移2</div>
<div class="code-name">&amp;#xe731;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe730;</span>
<div class="name">下移</div>
<div class="code-name">&amp;#xe730;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe72f;</span>
<div class="name">上移</div>
<div class="code-name">&amp;#xe72f;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe72e;</span>
<div class="name">编辑</div>
<div class="code-name">&amp;#xe72e;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe72d;</span>
<div class="name">删除</div>
<div class="code-name">&amp;#xe72d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe72c;</span>
<div class="name">选择</div>
<div class="code-name">&amp;#xe72c;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe72a;</span>
<div class="name">编辑</div>
@ -2012,6 +2060,78 @@
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-yidong"></span>
<div class="name">
移动
</div>
<div class="code-name">.icon-yidong
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-xiayi1"></span>
<div class="name">
下移2
</div>
<div class="code-name">.icon-xiayi1
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-shangyi1"></span>
<div class="name">
上移2
</div>
<div class="code-name">.icon-shangyi1
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-xiayi"></span>
<div class="name">
下移
</div>
<div class="code-name">.icon-xiayi
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-shangyi"></span>
<div class="name">
上移
</div>
<div class="code-name">.icon-shangyi
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-bianji5"></span>
<div class="name">
编辑
</div>
<div class="code-name">.icon-bianji5
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-shanchu3"></span>
<div class="name">
删除
</div>
<div class="code-name">.icon-shanchu3
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-xuanze"></span>
<div class="name">
选择
</div>
<div class="code-name">.icon-xuanze
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-bianji4"></span>
<div class="name">
@ -4939,6 +5059,70 @@
<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-yidong"></use>
</svg>
<div class="name">移动</div>
<div class="code-name">#icon-yidong</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-xiayi1"></use>
</svg>
<div class="name">下移2</div>
<div class="code-name">#icon-xiayi1</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-shangyi1"></use>
</svg>
<div class="name">上移2</div>
<div class="code-name">#icon-shangyi1</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-xiayi"></use>
</svg>
<div class="name">下移</div>
<div class="code-name">#icon-xiayi</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-shangyi"></use>
</svg>
<div class="name">上移</div>
<div class="code-name">#icon-shangyi</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-bianji5"></use>
</svg>
<div class="name">编辑</div>
<div class="code-name">#icon-bianji5</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-shanchu3"></use>
</svg>
<div class="name">删除</div>
<div class="code-name">#icon-shanchu3</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-xuanze"></use>
</svg>
<div class="name">选择</div>
<div class="code-name">#icon-xuanze</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-bianji4"></use>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -5,6 +5,62 @@
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "13353315",
"name": "移动",
"font_class": "yidong",
"unicode": "e734",
"unicode_decimal": 59188
},
{
"icon_id": "13247262",
"name": "下移2",
"font_class": "xiayi1",
"unicode": "e732",
"unicode_decimal": 59186
},
{
"icon_id": "13247261",
"name": "上移2",
"font_class": "shangyi1",
"unicode": "e731",
"unicode_decimal": 59185
},
{
"icon_id": "13247178",
"name": "下移",
"font_class": "xiayi",
"unicode": "e730",
"unicode_decimal": 59184
},
{
"icon_id": "13247175",
"name": "上移",
"font_class": "shangyi",
"unicode": "e72f",
"unicode_decimal": 59183
},
{
"icon_id": "13247173",
"name": "编辑",
"font_class": "bianji5",
"unicode": "e72e",
"unicode_decimal": 59182
},
{
"icon_id": "13247168",
"name": "删除",
"font_class": "shanchu3",
"unicode": "e72d",
"unicode_decimal": 59181
},
{
"icon_id": "13183780",
"name": "选择",
"font_class": "xuanze",
"unicode": "e72c",
"unicode_decimal": 59180
},
{
"icon_id": "2077714",
"name": "编辑",

@ -20,6 +20,30 @@ Created by iconfont
/>
<missing-glyph />
<glyph glyph-name="yidong" unicode="&#59188;" d="M855.341176-121.976471H174.682353c-90.352941 0-156.611765 72.282353-156.611765 156.611765V721.317647C18.070588 811.670588 90.352941 877.929412 174.682353 877.929412h680.658823c90.352941 0 156.611765-72.282353 156.611765-156.611765v-78.305882h-90.352941V721.317647c0 36.141176-30.117647 66.258824-66.258824 66.258824H174.682353c-36.141176 0-66.258824-30.117647-66.258824-66.258824v-680.658823c0-36.141176 30.117647-66.258824 66.258824-66.258824h680.658823c36.141176 0 66.258824 30.117647 66.258824 66.258824v78.305882h90.352941v-78.305882c6.023529-90.352941-66.258824-162.635294-156.611765-162.635295zM951.717647 299.670588H271.058824c-24.094118 0-48.188235 18.070588-48.188236 48.188236s18.070588 48.188235 48.188236 48.188235h680.658823c24.094118 0 48.188235-18.070588 48.188235-48.188235s-24.094118-48.188235-48.188235-48.188236zM1084.235294 347.858824L921.6 173.176471V534.588235L1084.235294 359.905882v-12.047058z" horiz-adv-x="1084" />
<glyph glyph-name="xiayi1" unicode="&#59186;" d="M512 384m-481.882353 0a481.882353 481.882353 0 1 1 963.764706 0 481.882353 481.882353 0 1 1-963.764706 0ZM512-128C228.894118-128 0 100.894118 0 384S228.894118 896 512 896 1024 667.105882 1024 384 795.105882-128 512-128z m0 963.764706C265.035294 835.764706 60.235294 630.964706 60.235294 384S265.035294-67.764706 512-67.764706 963.764706 137.035294 963.764706 384 758.964706 835.764706 512 835.764706zM502.964706 143.058824c-18.070588 0-30.117647 12.047059-30.117647 30.117647V588.8c0 18.070588 12.047059 30.117647 30.117647 30.117647s30.117647-12.047059 30.117647-30.117647V173.176471c0-18.070588-12.047059-30.117647-30.117647-30.117647zM502.964706 88.847059c-6.023529 0-12.047059 0-18.070588 6.023529l-144.564706 132.517647c-12.047059 12.047059-12.047059 30.117647 0 42.164706 12.047059 12.047059 30.117647 12.047059 42.164706 0l126.494117-108.423529 132.517647 108.423529c12.047059 12.047059 30.117647 12.047059 42.164706-6.023529 6.023529-6.023529 6.023529-30.117647-12.047059-36.141177l-150.588235-132.517647c-6.023529 0-12.047059-6.023529-18.070588-6.023529z" horiz-adv-x="1024" />
<glyph glyph-name="shangyi1" unicode="&#59185;" d="M512 384m-481.882353 0a481.882353 481.882353 0 1 1 963.764706 0 481.882353 481.882353 0 1 1-963.764706 0ZM512-128C228.894118-128 0 100.894118 0 384S228.894118 896 512 896 1024 667.105882 1024 384 795.105882-128 512-128z m0 963.764706C265.035294 835.764706 60.235294 630.964706 60.235294 384S265.035294-67.764706 512-67.764706 963.764706 137.035294 963.764706 384 758.964706 835.764706 512 835.764706zM502.964706 106.917647c-18.070588 0-30.117647 12.047059-30.117647 30.117647V552.658824c0 18.070588 12.047059 30.117647 30.117647 30.117647s30.117647-12.047059 30.117647-30.117647v-415.62353c0-18.070588-12.047059-30.117647-30.117647-30.117647zM653.552941 444.235294c-6.023529 0-12.047059 0-18.070588 6.02353l-132.517647 114.447058-126.494118-108.423529c-12.047059-12.047059-30.117647-12.047059-42.164706 0-12.047059 12.047059-12.047059 30.117647 0 42.164706l144.564706 126.494117c12.047059 12.047059 30.117647 12.047059 42.164706 0l150.588235-126.494117c12.047059-12.047059 12.047059-30.117647 6.02353-42.164706-6.023529-6.023529-12.047059-12.047059-24.094118-12.047059z" horiz-adv-x="1024" />
<glyph glyph-name="xiayi" unicode="&#59184;" d="M512 384m-481.882353 0a481.882353 481.882353 0 1 1 963.764706 0 481.882353 481.882353 0 1 1-963.764706 0ZM512-128C228.894118-128 0 100.894118 0 384S228.894118 896 512 896 1024 667.105882 1024 384 795.105882-128 512-128z m0 963.764706C265.035294 835.764706 60.235294 630.964706 60.235294 384S265.035294-67.764706 512-67.764706 963.764706 137.035294 963.764706 384 758.964706 835.764706 512 835.764706zM502.964706 143.058824c-18.070588 0-30.117647 12.047059-30.117647 30.117647V588.8c0 18.070588 12.047059 30.117647 30.117647 30.117647s30.117647-12.047059 30.117647-30.117647V173.176471c0-18.070588-12.047059-30.117647-30.117647-30.117647zM502.964706 88.847059c-6.023529 0-12.047059 0-18.070588 6.023529l-144.564706 132.517647c-12.047059 12.047059-12.047059 30.117647 0 42.164706 12.047059 12.047059 30.117647 12.047059 42.164706 0l126.494117-108.423529 132.517647 108.423529c12.047059 12.047059 30.117647 12.047059 42.164706-6.023529 6.023529-6.023529 6.023529-30.117647-12.047059-36.141177l-150.588235-132.517647c-6.023529 0-12.047059-6.023529-18.070588-6.023529z" horiz-adv-x="1024" />
<glyph glyph-name="shangyi" unicode="&#59183;" d="M512 384m-481.882353 0a481.882353 481.882353 0 1 1 963.764706 0 481.882353 481.882353 0 1 1-963.764706 0ZM512-128C228.894118-128 0 100.894118 0 384S228.894118 896 512 896 1024 667.105882 1024 384 795.105882-128 512-128z m0 963.764706C265.035294 835.764706 60.235294 630.964706 60.235294 384S265.035294-67.764706 512-67.764706 963.764706 137.035294 963.764706 384 758.964706 835.764706 512 835.764706zM502.964706 106.917647c-18.070588 0-30.117647 12.047059-30.117647 30.117647V552.658824c0 18.070588 12.047059 30.117647 30.117647 30.117647s30.117647-12.047059 30.117647-30.117647v-415.62353c0-18.070588-12.047059-30.117647-30.117647-30.117647zM653.552941 444.235294c-6.023529 0-12.047059 0-18.070588 6.02353l-132.517647 114.447058-126.494118-108.423529c-12.047059-12.047059-30.117647-12.047059-42.164706 0-12.047059 12.047059-12.047059 30.117647 0 42.164706l144.564706 126.494117c12.047059 12.047059 30.117647 12.047059 42.164706 0l150.588235-126.494117c12.047059-12.047059 12.047059-30.117647 6.02353-42.164706-6.023529-6.023529-12.047059-12.047059-24.094118-12.047059z" horiz-adv-x="1024" />
<glyph glyph-name="bianji5" unicode="&#59182;" d="M704.752941-97.882353H198.776471c-78.305882 0-138.541176 60.235294-138.541177 132.517647V667.105882c0 72.282353 66.258824 132.517647 138.541177 132.517647h319.247058c18.070588 0 30.117647-12.047059 30.117647-30.117647s-12.047059-24.094118-30.117647-24.094117H198.776471c-42.164706 0-78.305882-36.141176-78.305883-72.282353v-632.470588c0-42.164706 36.141176-72.282353 78.305883-72.282353h499.952941c42.164706 0 78.305882 36.141176 78.305882 72.282353V293.647059c0 18.070588 12.047059 30.117647 30.117647 30.117647s30.117647-12.047059 30.117647-30.117647v-259.011765c6.023529-72.282353-60.235294-132.517647-132.517647-132.517647zM313.223529 161.129412c-24.094118 0-54.211765 18.070588-60.235294 48.188235v30.117647l36.141177 126.494118 445.741176 445.741176c48.188235 48.188235 120.470588 48.188235 168.658824 0 48.188235-48.188235 48.188235-120.470588 0-168.658823l-445.741177-445.741177-126.494117-30.117647c-6.023529-6.023529-12.047059-6.023529-18.070589-6.023529z m36.141177 174.682353l-36.141177-114.447059 120.470589 30.117647 433.694117 433.694118c12.047059 12.047059 18.070588 24.094118 18.070589 42.164705 0 18.070588-6.023529 30.117647-18.070589 42.164706-24.094118 24.094118-60.235294 24.094118-84.329411 0L349.364706 335.811765z" horiz-adv-x="1024" />
<glyph glyph-name="shanchu3" unicode="&#59181;" d="M654.222222-99.555556H375.466667c-68.266667 0-125.155556 56.888889-136.533334 142.222223L142.222222 571.733333c0 17.066667 5.688889 28.444444 22.755556 34.133334 17.066667 0 28.444444-5.688889 34.133333-22.755556l91.022222-534.755555c11.377778-51.2 45.511111-91.022222 85.333334-91.022223h278.755555c39.822222 0 73.955556 39.822222 85.333334 91.022223l91.022222 534.755555c0 17.066667 17.066667 28.444444 34.133333 22.755556 17.066667 0 28.444444-17.066667 22.755556-34.133334L796.444444 42.666667c-17.066667-85.333333-73.955556-142.222222-142.222222-142.222223zM597.333333 708.266667v5.688889c0 51.2-39.822222 96.711111-85.333333 96.711111s-85.333333-45.511111-85.333333-102.4h-56.888889C369.777778 793.6 432.355556 867.555556 512 867.555556c73.955556 0 136.533333-68.266667 142.222222-147.911112v-5.688888l-56.888889-5.688889zM398.222222 36.977778c-11.377778 0-28.444444 11.377778-28.444444 22.755555L284.444444 577.422222c0 17.066667 11.377778 34.133333 22.755556 34.133334 17.066667 5.688889 34.133333-5.688889 34.133333-22.755556l85.333334-517.688889c0-17.066667-5.688889-34.133333-28.444445-34.133333 5.688889 0 0 0 0 0zM625.777778 36.977778s-5.688889 0 0 0c-22.755556 5.688889-28.444444 17.066667-28.444445 34.133333L682.666667 588.8c0 17.066667 17.066667 28.444444 34.133333 22.755556 11.377778 0 22.755556-17.066667 22.755556-34.133334l-85.333334-517.688889c0-11.377778-17.066667-22.755556-28.444444-22.755555zM512 36.977778c-17.066667 0-28.444444 11.377778-28.444444 28.444444V583.111111c0 17.066667 11.377778 28.444444 28.444444 28.444445s28.444444-11.377778 28.444444-28.444445v-517.688889c0-17.066667-11.377778-28.444444-28.444444-28.444444zM938.666667 645.688889H85.333333c-17.066667 0-28.444444 17.066667-28.444444 28.444444s11.377778 28.444444 28.444444 28.444445h853.333334c17.066667 0 28.444444-11.377778 28.444444-28.444445s-11.377778-28.444444-28.444444-28.444444z" horiz-adv-x="1024" />
<glyph glyph-name="xuanze" unicode="&#59180;" d="M870.4 896H153.6C66.56 896 0 829.44 0 742.4v-716.8c0-87.04 66.56-153.6 153.6-153.6h716.8c87.04 0 153.6 66.56 153.6 153.6V742.4c0 87.04-66.56 153.6-153.6 153.6z m-40.96-394.24l-337.92-358.4c-10.24-10.24-25.6-15.36-40.96-15.36-10.24 0-20.48 5.12-30.72 10.24L174.08 332.8c-20.48 15.36-25.6 51.2-10.24 71.68 15.36 20.48 51.2 25.6 71.68 10.24l209.92-163.84 307.2 327.68c20.48 20.48 51.2 20.48 71.68 0 20.48-20.48 25.6-56.32 5.12-76.8z" horiz-adv-x="1024" />
<glyph glyph-name="bianji4" unicode="&#59178;" d="M934.724189 617.173271L834.414864 516.863946 653.380212 697.898598l100.394659 100.351991A42.257063 42.257063 0 0 0 783.769535 810.666588c6.527999 0 19.157332-1.621333 29.951997-12.415999l121.002657-121.002656a42.538663 42.538663 0 0 0 0-60.074662zM299.374908-18.176009l-200.661316-19.626665 19.669331 200.661316L593.049551 637.52527 774.084202 456.533285l-474.709294-474.709294z m695.679942 755.79727L874.09486 858.581251A127.317323 127.317323 0 0 1 783.769535 895.999915c-32.725331 0-65.407995-12.458666-90.367993-37.418664l-646.229279-646.229279c-7.082666-7.082666-11.434666-16.469332-12.287999-26.495998l-26.197331-267.818645c-2.133333-25.002665 17.706665-46.037329 42.239996-46.037329 1.194667 0 2.432 0.042667 3.626666 0.128l267.818645 26.239998a42.12053 42.12053 0 0 1 26.495998 12.287999l646.186612 646.186613c49.919996 49.919996 49.919996 130.858656 0 180.778651z" horiz-adv-x="1032" />

Before

Width:  |  Height:  |  Size: 394 KiB

After

Width:  |  Height:  |  Size: 404 KiB

@ -508,7 +508,11 @@ class CoursesIndex extends Component{
}
></Route>
{/*视频列表*/}
<Route path="/courses/:coursesId/course_video/:videoId"
render={
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/courses/:coursesId/course_videos"
render={
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)

@ -244,7 +244,11 @@ class ListPageIndex extends Component{
}
></Route>
{/*视频列表*/}
<Route path="/courses/:coursesId/course_video/:videoId"
render={
(props) => (<CourseVideo {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/courses/:coursesId/course_videos"
render={
(props) => (<CourseVideo {...this.props} {...props} {...this.state} />)

@ -0,0 +1,128 @@
import React,{ Component } from "react";
import { Radio , Modal } from 'antd';
import './video.css';
import axios from 'axios';
class MoveBox extends Component{
constructor(props){
super(props);
this.state={
data:undefined,
selectSubId:undefined
}
}
componentDidUpdate=(prevProps)=>{
if(this.props.id && this.props.visible && this.props.id !== prevProps.id){
this.getSubList(this.props.mainId);
}
}
getSubList=(id)=>{
const url = `/course_modules/${id}.json`;
axios.get(url).then(result=>{
if(result){
let list = result.data.course_module && result.data.course_module.course_second_categories;
let defaultId = list.length>0 ? list[0].id : undefined;
this.setState({
data:result.data.course_module,
selectSubId:defaultId
})
}
}).catch(error=>{
console.log(error);
})
}
cancelMove=()=>{
const { setMoveVisible } = this.props;
setMoveVisible && setMoveVisible(false);
}
// 选择子目录
selectSub=(e)=>{
this.setState({
selectSubId:e.target.value
})
}
handleSubmit=()=>{
const CourseId = this.props.match.params.coursesId;
const { id } = this.props;
const { selectSubId } = this.state;
const url = `/courses/${CourseId}/move_to_category.json`;
axios.post(url,{
video_ids:[id],
new_category_id:selectSubId
}).then(result=>{
if(result){
const { setMoveVisible , successFunc , updataleftNavfun} = this.props;
updataleftNavfun && updataleftNavfun();
setMoveVisible && setMoveVisible(false);
successFunc && successFunc();
}
}).catch(error=>{
console.log(error);
})
}
render(){
const { visible , id } = this.props;
const { data , selectSubId } = this.state;
let list = data && data.course_second_categories && data.course_second_categories.length>0?data.course_second_categories:undefined;
return(
<Modal
visible={visible}
width="560px"
title={'移动到'}
footer={null}
closable={false}
>
<div>
<style>
{
`
.ant-radio-group.ant-radio-group-outline{
display: flex;
flex-direction: column;
}
.ant-radio-wrapper{
margin-bottom:5px;
display:flex;
}
.ant-radio{
margin-top:2px;
}
.ant-radio-group.ant-radio-group-outline span:last-child{
max-height: 450px;
display: block;
flex: 1;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
`
}
</style>
<Radio.Group onChange={this.selectSub} value={selectSubId}>
{
list && list.map((item,key)=>{
return(
<Radio value={item.id} key={item.id}>
{item.name}
</Radio>
)
})
}
</Radio.Group>
<div className="clearfix mt30 edu-txt-center">
<a onClick={this.cancelMove} className="task-btn mr30">取消</a>
<a type="submit" onClick={this.handleSubmit} className="task-btn task-btn-orange">确定</a>
</div>
</div>
</Modal>
)
}
}
export default MoveBox;

@ -5,7 +5,8 @@ import { NoneData, ActionBtn } from 'educoder';
import VideoUploadList from '../../user/usersInfo/video/VideoUploadList';
import VideoInReviewItem from '../../user/usersInfo/video/VideoInReviewItem';
import HeadlessModal from '../../user/usersInfo/common/HeadlessModal';
import EditVideoModal from '../../user/usersInfo/video/EditVideoModal'
import EditVideoModal from '../../user/usersInfo/video/EditVideoModal';
import MoveBox from './MoveBox';
import ClipboardJS from 'clipboard'
import VideoPanel from './video-play'
@ -28,7 +29,10 @@ class Video extends Component {
videoId: undefined,
videoVisible: false,
visible: false
visible: false,
moveVisible:false,
moveVideoId:undefined
}
}
@ -69,7 +73,7 @@ class Video extends Component {
// 编辑成功后回调的方法
editSuccess = () => {
this.props.showNotification("视频名称修改成功!");
this.props.showNotification("视频信息修改成功!");
const { listFunc, page } = this.props;
listFunc && listFunc(page);
}
@ -77,7 +81,8 @@ class Video extends Component {
onEditVideo = (item) => {
let videoId = {
videoId: item.id,
title: item.title
title: item.title,
link:item.link
}
this.setState({
videoId,
@ -142,7 +147,8 @@ class Video extends Component {
const url = `/courses/${CourseId}/delete_course_video.json`;
axios.delete(url, {
params: {
video_id: item.id
video_id: item.id,
is_link:item.link ? true : undefined
}
}).then(result => {
if (result) {
@ -161,8 +167,22 @@ class Video extends Component {
});
}
// 移动到
moveVideo=(id)=>{
this.setState({
moveVisible:true,
moveVideoId:id
})
}
setMoveVisible=(flag)=>{
this.setState({
moveVisible:flag,
moveVideoId:undefined
})
}
render() {
const { visible, videoVisible, videoId } = this.state;
const { visible, videoVisible, videoId , moveVisible , moveVideoId } = this.state;
const CourseId = this.props.match.params.coursesId;
const login = this.props.user && this.props.user.login;
const _inputValue = videoId && this.getCopyText(videoId.file_url, videoId.cover_url);
@ -178,6 +198,14 @@ class Video extends Component {
editSuccess={this.editSuccess}
{...videoId} CourseUser={login}
></EditVideoModal>
<MoveBox
{...this.props}
visible={moveVisible}
mainId={videoData && videoData.course_module_id}
setMoveVisible={(flag)=>this.setMoveVisible(flag)}
successFunc={()=>uploadVideo()}
id={moveVideoId}
></MoveBox>
<HeadlessModal
visible={videoVisible}
setVisible={this.setVideoVisible}
@ -217,6 +245,7 @@ class Video extends Component {
getCopyText={this.getCopyText}
operation={operation}
deleteVideo={(admin || item.user_id === user_id) ? this.deleteVideo : undefined}
moveVideo={videoData && videoData.has_category && operation ?()=>this.moveVideo(item.id):undefined}
>
</VideoInReviewItem>
)

@ -1,13 +1,13 @@
import React,{ Component } from "react";
import { WordsBtn,on, trigger ,publicSearchs} from 'educoder';
import { Menu, Spin } from 'antd';
import { WordsBtn } from 'educoder';
import axios from 'axios';
import Videos from './Video';
import Lives from './Live';
import LivesNew from './LiveNew';
import VideoLink from './VideoLink';
import './video.css';
import '../css/Courses.css';
@ -28,6 +28,7 @@ class VideoIndex extends Component{
upload:false,
videos:undefined,
videoData:undefined,
otherLinkVisible:false,
type:"video",
isSpining:false,
@ -37,6 +38,7 @@ class VideoIndex extends Component{
liveId:undefined,
liveVisible:false
}
}
@ -69,6 +71,12 @@ class VideoIndex extends Component{
this.checkType("video",page);
}
}
componentDidUpdate = (prevProps) => {
if(this.props.match.params.videoId !== prevProps.match.params.videoId ){
const { page } = this.state;
this.checkType("video",page);
}
}
// 获取直播列表
getLiveList=(page)=>{
const CourseId=this.props.match.params.coursesId;
@ -93,12 +101,13 @@ class VideoIndex extends Component{
// 获取视频列表
getList=(page)=>{
const CourseId=this.props.match.params.coursesId;
const fetchUrl = `/courses/${CourseId}/course_videos.json`;
const { coursesId , videoId }=this.props.match.params;
const fetchUrl = `/courses/${coursesId}/course_videos.json`;
axios.get(fetchUrl, {
params: {
page,
limit: PAGE_SIZE,
category_id:videoId
}
})
.then((response) => {
@ -141,6 +150,7 @@ class VideoIndex extends Component{
this.setVisible(true);
}
uploadVideo=(upload)=>{
this.setState({
upload,
isSpining:true
@ -200,12 +210,46 @@ class VideoIndex extends Component{
})
this.setliveVisibel(true);
}
// 新增目录
addDir=()=>{
let {videoData}=this.state;
trigger('videoAdd', parseInt(videoData.course_module_id));
}
// 目录重命名
editDir=(name,id)=>{
let data={id,name,update:this.getList}
trigger('editVideo',data);
}
// 增加外链
setLinkeVisible=(flag,refresh)=>{
this.setState({
otherLinkVisible:flag
})
if(refresh){
const { page } = this.state;
this.getList(page);
}
}
render(){
const { videos , upload , videoData , type , liveData , lives , page , liveVisible , isSpining , liveId } = this.state;
const { videos , upload , videoData , type , liveData , lives , page , liveVisible , isSpining , liveId , otherLinkVisible } = this.state;
const { admin , is_teacher , business } = this.props.user;
const { coursesId , videoId }=this.props.match.params;
const {course_identity} = this.props.coursedata;
const flag = parseInt(course_identity) < 4;
console.log(flag);
const newOperation = flag;
const new_upload = flag || admin || is_teacher;
// console.log("p",this.props);
return(
<React.Fragment>
<VideoLink
coursesId={coursesId}
visible={otherLinkVisible}
notification={this.props.showNotification}
setVisible={this.setLinkeVisible}
></VideoLink>
<LivesNew
visible={liveVisible}
liveId={liveId}
@ -235,30 +279,51 @@ class VideoIndex extends Component{
<div className="edu-back-white" style={{marginBottom:"1px"}}>
<div className="clearfix pl30 pr30 menuDiv">
<div className="task_menu_ul fl">
{
videoData && videoData.category_name && type === "video" ?
<span className="font-18 fl color-dark-21 mt20 mb20">{videoData.category_name}</span>
:
<div className="task_menu_ul fl mt2">
<Menu mode="horizontal" selectedKeys={[type]} onClick={this.changeType}>
<Menu.Item key="video">视频</Menu.Item>
<Menu.Item key="live">直播</Menu.Item>
</Menu>
</div>
{
(admin || is_teacher || business) &&
<li className="fr mt18">
}
<li className="fr mt20 mb20">
{
type === "video" ?
<React.Fragment>
{
newOperation ?
<span>
{
videoId ?
<WordsBtn style="blue" onClick={()=>this.editDir(videoData && videoData.category_name,videoId)} className={"mr30 font-16"}>目录重命名</WordsBtn>
:
<React.Fragment>
<WordsBtn style="blue" className="mr30 font-16" onClick={this.addDir}>新建目录</WordsBtn>
<WordsBtn style="blue" className="mr30 font-16" onClick={()=>this.setLinkeVisible(true)}>增加外链</WordsBtn>:""
</React.Fragment>
}
</span>:""
}
{
new_upload ?
<span>
{
upload ?
<WordsBtn style="grey" className="font-16" onClick={()=>this.uploadVideo(false)}>取消</WordsBtn>
:
<WordsBtn style="blue" className="font-16" onClick={this.toUpload}>上传视频</WordsBtn>
}
</span>:""
}
</React.Fragment>
:
<WordsBtn style="blue" className="font-16 ml30" onClick={this.liveSetting}>添加直播</WordsBtn>
<WordsBtn style="blue" className="font-16 ml30" onClick={()=>this.setLinkeVisible(true)}>添加直播</WordsBtn>
}
</li>
}
</div>
</div>
<Spin spinning={isSpining}>

@ -0,0 +1,86 @@
import React,{ Component } from "react";
import { Modal , Form , Input , Spin , Select , AutoComplete , DatePicker , InputNumber } from 'antd';
import axios from 'axios';
class VideoLink extends Component{
cancelNew=()=>{
const { setVisible } = this.props;
setVisible && setVisible(false);
}
validateDesc= (rule, value, callback) => {
if(!value){
callback();
}
if (value.length > 60) {
callback("视频名称不能超过60个字");
}else{
callback();
}
}
// 提交
handleSubmit=()=>{
this.props.form.validateFields((err, values) => {
if(!err){
const { coursesId } = this.props;
const url = `/courses/${coursesId}/course_videos.json`;
axios.post(url,{
...values
}).then(result=>{
if(result){
const { notification , setVisible } = this.props;
notification && notification('视频外链新增成功!');
setVisible && setVisible(false,true);
}
}).catch(error=>{
console.log(error);
})
}
})
}
render(){
const {getFieldDecorator} = this.props.form;
const { visible } = this.props;
const layout = {
labelCol: { span: 5 },
wrapperCol: { span: 19 },
}
return(
<Modal
visible={visible}
width="560px"
title={'添加外链'}
footer={null}
closable={false}
>
<div className="task-popup-content">
<Form onSubmit={this.handleSubmit} {...layout}>
<Form.Item label={`视频名称:`}>
{getFieldDecorator('name', {
rules: [{required: true, message: "请输入名称"},{
validator: this.validateDesc,
}],
})(
<Input placeholder="请输入名称最大限制60个字符" />
)}
</Form.Item>
<Form.Item label={`链接地址:`}>
{getFieldDecorator('link', {
rules: [{required: true, message: "请输入链接地址"}],
})(
<Input placeholder="请输入链接地址" />
)}
</Form.Item>
<div className="clearfix mt30 edu-txt-center">
<a onClick={this.cancelNew} className="task-btn mr30">取消</a>
<a type="submit" onClick={this.handleSubmit} className="task-btn task-btn-orange">确定</a>
</div>
</Form>
</div>
</Modal>
)
}
}
const WrappedVideoLink = Form.create({name: 'VideoLink'})(VideoLink);
export default WrappedVideoLink;

@ -61,6 +61,8 @@ class Coursesleftnav extends Component{
sandiantypes:undefined,
antIcon:false,
chapterupdate:false,
successFunc:undefined
}
}
@ -138,53 +140,62 @@ class Coursesleftnav extends Component{
off('shixun_homeworkadd',this.addshixunchild)
off('editshixunname',this.editshixunchild)
off('editshixunmainname',this.editshixunmainname)
off('videoAdd',this.addVideo)
off('editVideo',this.editVideo)
}
addshixunchild=(e, data)=>{
this.Navmodalnames(e,1,"shixun_homework",data)
this.Navmodalnames(e,1,"shixun_homework",data);
}
editshixunchild=(e, data)=>{
this.Navmodalnames(e,4,"editSecondname",data.id,data.name)
this.Navmodalnames(e,4,"editSecondname",data.id,data.name);
}
editshixunmainname=(e, data)=>{
this.Navmodalnames(e,3,"editname",data.id,data.name)
this.Navmodalnames(e,3,"editname",data.id,data.name);
}
boardAddListener = (e, data) => {
this.Navmodalnames(e,6,"board", data)
this.Navmodalnames(e,6,"board", data);
}
addVideo=(e,id)=>{
this.Navmodalnames(e,1,"video",id);
}
editVideo=(e,data)=>{
this.setState({
successFunc:data.update
})
this.Navmodalnames(e,4,"editSecondname",data.id,data.name);
}
boardRenameListener = (e, data) => {
this.Navmodalnames(e,7,"editSecondname", data.category_id, data.category_name)
this.Navmodalnames(e,7,"editSecondname", data.category_id, data.category_name);
}
groupAddListener = (e, data) => {
this.Navmodalnames(e,2,"course_group", data)
this.Navmodalnames(e,2,"course_group", data);
}
groupRenameListener = (e, data) => {
this.Navmodalnames(e,5,"editSecondname", data.id, data.name)
this.Navmodalnames(e,5,"editSecondname", data.id, data.name);
}
attachmentAddlog=(e,data)=>{
this.Navmodalnames(e,1,"attachment",data)
this.Navmodalnames(e,1,"attachment",data);
}
flieseditDir=(e, data)=>{
this.Navmodalnames(e,4,"editSecondname",data.id,data.name)
this.Navmodalnames(e,4,"editSecondname",data.id,data.name);
}
componentDidMount() {
this.setState({
url:this.props.match.url
})
on('boardAdd', this.boardAddListener)
on('boardRename', this.boardRenameListener)
on('groupAdd', this.groupAddListener)
on('groupRename', this.groupRenameListener)
on('attachmentAddlog', this.attachmentAddlog)
on('flieseditDir', this.flieseditDir)
on('shixun_homeworkadd',this.addshixunchild)
on('editshixunname',this.editshixunchild)
on('editshixunmainname',this.editshixunmainname)
on('boardAdd', this.boardAddListener);
on('boardRename', this.boardRenameListener);
on('groupAdd', this.groupAddListener);
on('groupRename', this.groupRenameListener);
on('attachmentAddlog', this.attachmentAddlog);
on('flieseditDir', this.flieseditDir);
on('shixun_homeworkadd',this.addshixunchild);
on('editshixunname',this.editshixunchild);
on('editshixunmainname',this.editshixunmainname);
on('videoAdd',this.addVideo);
on('editVideo',this.editVideo)
// this.props.updataleftNavfun();
// this.props.getleftNavid && this.props.getleftNavid("shixun_homework");
// const position =parseInt(this.props.match.params.position);
let courstype=this.props.match.url;
@ -192,8 +203,6 @@ class Coursesleftnav extends Component{
courstype=courstype[3];
// console.log(courstype)
const query =this.props.location.search;
// const type = query.split('?type=');
@ -520,7 +529,9 @@ class Coursesleftnav extends Component{
// loadtype:true,
// NavmodalValue:""
// })
navidtype=true
navidtype=true;
const { successFunc } = this.state;
successFunc && successFunc(1);
}
saveNavmodapost=(url,value,positiontype,coursesId)=>{
@ -658,32 +669,28 @@ class Coursesleftnav extends Component{
updatadeleteSecondary=(url)=>{
this.props.updataleftNavfun();
// this.setState({
// ModalsType:true,
// Modalstopval:"删除成功",
// loadtype:true,
// })
// notification.open({
// message: "删除成功",
// });
this.setState({
ModalsType:false,
Modalstopval:"",
loadtype:false,
})
notification.open({
message: "删除成功",
});
this.props.history.replace(url);
// this.props.history.replace(url);
window.location.href = url;
// window.location.href = url;
}
deletenavchilds=(url,mainurl)=>{
console.log(this.props);
this.setState({
antIcon:true
})
axios.delete(url).then((result)=>{
if(result.data.status===0){
if(mainurl===undefined){
this.updatadeleteSecondary(result.data.right_url)
}else{
this.updatadeleteSecondary(mainurl)
}
this.updatadeleteSecondary(mainurl || result.data.right_url);
}
}).catch((error)=>{
console.log(error)
@ -698,8 +705,8 @@ class Coursesleftnav extends Component{
ModalsType:true,
Modalstopval:"该目录下的内容将被移动到父目录,",
ModalsBottomval:"是否确认删除?",
ModalSave:()=>this.deletenavchilds(url),
ModalSave:()=>this.deletenavchilds(url,mainurl),
loadtype:false
})
}else if(type===2){
@ -709,7 +716,7 @@ class Coursesleftnav extends Component{
Modalstopval:"该分班的学生将被移动到“未分班”,",
ModalsBottomval:"是否确认删除?",
ModalSave:()=>this.deletenavchilds(url),
loadtype:false
})
}else if(type===3){
let url="/boards/"+id+".json"
@ -718,7 +725,7 @@ class Coursesleftnav extends Component{
Modalstopval:"该目录下的内容将被移动到父目录,",
ModalsBottomval:"是否确认删除?",
ModalSave:()=>this.deletenavchilds(url,mainurl),
loadtype:false
})
}
@ -838,6 +845,8 @@ class Coursesleftnav extends Component{
{item.type==="shixun_homework"?<div onClick={e=>this.Navmodalnames(e,1,"shixun_homework",item.id)}>新建目录</div>:""}
{/*资源*/}
{item.type==="attachment"?<div onClick={e=>this.Navmodalnames(e,1,"attachment",item.id)}>新建目录</div>:""}
{/* 视频 */}
{item.type==="video"?<div onClick={e=>this.Navmodalnames(e,1,"video",item.id)}>新建目录</div>:""}
{/*毕业设计*/}
{/*{item.type==="graduation"?<div onClick={()=>this.Navmodalnames(1,"attachment",item.id)}>添加目录</div>:""}*/}
{/*讨论区*/}
@ -872,6 +881,9 @@ class Coursesleftnav extends Component{
{/*讨论区*/}
{item.type==="board"?<div onClick={e=>this.Navmodalnames(e,7,"editSecondname",iem.category_id,iem.category_name)}>重命名</div>:""}
{item.type==="board"?<div onClick={e=>this.deleteSecondary(e,3,iem.category_id,item.category_url)}>删除</div>:""}
{/*视频*/}
{item.type==="video"?<div onClick={e=>this.Navmodalnames(e,4,"editSecondname",iem.category_id,iem.category_name)}>重命名</div>:""}
{item.type==="video"?<div onClick={e=>this.deleteSecondary(e,1,iem.category_id,item.category_url)}>删除</div>:""}
</div>)
};

@ -8,10 +8,12 @@ function EditVideoModal (props) {
const modalEl = useRef(null);
const theme = useContext(ThemeContext);
const { history, videoId, cover_url, title, created_at, isReview, onEditVideo, visible, setVisible,
form, editSuccess } = props;
form, editSuccess , link } = props;
const getFieldDecorator = form.getFieldDecorator
let username = props.match.params.username
const _title = form.getFieldsValue().title;
const _link = form.getFieldsValue().link;
if(props.CourseUser){
username = props.CourseUser;
@ -27,9 +29,14 @@ function EditVideoModal (props) {
form.validateFieldsAndScroll((err, values) => {
if (!err) {
const url = `/users/${username}/videos/${videoId}.json`
axios.put(url, {
title: _title
const url = link?`/course_videos/${videoId}.json`:`/users/${username}/videos/${videoId}.json`;
axios.put(url, link ? {
name:_title,
link:_link
}:{
title: _title,
link:_link
}).then((response) => {
if (response.data) {
onCancel()
@ -54,7 +61,7 @@ function EditVideoModal (props) {
}, [visible])
useEffect(() => {
visible && form.setFieldsValue({
title,
title,link
})
}, [visible])
return (
@ -74,7 +81,6 @@ function EditVideoModal (props) {
border-right: none !important;
height: 40px !important;
}
`
}
</style>
@ -94,6 +100,23 @@ function EditVideoModal (props) {
addonAfter={String(_title ? `${String(_title.length)}/${MAX_LENGTH}` : 0)} />
)}
</Form.Item>
{
link ?
<Form.Item
label="视频链接"
className="title formItemInline"
>
{getFieldDecorator('link', {
rules: [{
required: true, message: '请输入视频链接',
}],
})(
<Input placeholder="请输入视频链接" className="titleInput exercicenewinputysl" />
)}
</Form.Item>
:""
}
</ModalWrapper>
)
}

@ -143,3 +143,25 @@
box-shadow:0px 4px 10px 0px rgba(3,7,45,0.1);
border-radius:12px;
}
.otherLink{
position: absolute;
height:30px;
line-height: 30px;
padding:0px 18px;
background:rgba(249,117,26,1);
border-radius:0px 100px 100px 0px;
display: block;
left: 0;
top:32px;
color: #fff;
z-index:2;
}
.otherLinkPanel{
display: block;
position: absolute;
width: 100%;
top:0px;
left:0px;
height: 220px;
z-index: 1;
}

@ -5,7 +5,8 @@ import axios from 'axios'
import moment from 'moment'
import playIcon from './images/play.png'
import ClipboardJS from 'clipboard'
import defaultImg from './images/default.png';
import './InfosVideo.css';
/**
cover_url: "http://video.educoder.net/f6ba49c3944b43ee98736898e31b7d88/snapshots/12da3f7df07c499b8f0fc6dc410094e9-00005.jpg"
created_at: "2019-08-12 13:48:26"
@ -20,7 +21,7 @@ const clipboardMap = {}
function VideoInReviewItem (props) {
const theme = useContext(ThemeContext);
const { history, file_url, cover_url, title, created_at, published_at, isReview, id
, onEditVideo, onMaskClick, getCopyText, showNotification,vv,play_duration,operation , deleteVideo} = props;
, onEditVideo, onMaskClick, getCopyText, showNotification,vv,play_duration,operation , deleteVideo , moveVideo ,link} = props;
useEffect(()=> {
if (!isReview) {
_clipboard = new ClipboardJS(`.copybtn_item_${id}`);
@ -46,12 +47,16 @@ function VideoInReviewItem (props) {
return (
<div className={`${isReview ? 'videoInReviewItem' : 'nItem'} videoItem`}>
<img className="cover" src={cover_url || "http://video.educoder.net/e7d18970482a46d2a6f0e951b504256c/snapshots/491e113950d74f1dab276097dae287dd-00005.jpg"}
></img>
{!isReview && <div className="mask" onClick={() => onMaskClick(props)}>
<img className="cover" src={cover_url || defaultImg} alt=""></img>
{ link ?
<a href={link} target='_blank' className="otherLinkPanel">
<span className="otherLink">外链</span>
</a>
: ""
}
</div>}
{!isReview &&
{!isReview && <div className="mask" onClick={() => onMaskClick(props)}></div>}
{!isReview && !link &&
<div className="playWrap" onClick={() => onMaskClick(props)}>
<img className="play mp23" src={playIcon}></img>
{play_duration===0?"":<div className={"play_duration"}>累计学习时长{play_duration} h</div>}
@ -68,11 +73,19 @@ function VideoInReviewItem (props) {
<div className="df buttonRow">
{/* 2019-09-01 10:00:22 */}
<span className={"dianjilianicon"}>
{vv===0?"":<Tooltip title="播放次数" placement="bottom">
{!vv || (vv && vv)===0 ? "" : <Tooltip title="播放次数" placement="bottom">
<i className={`icon-dianjiliang iconfont dianjilianicon`}></i>
</Tooltip> } {vv===0?"":vv}
</Tooltip> } {!vv || (vv && vv)===0?"":vv}
</span>
{ isReview != true && <div>
{
moveVideo &&
<Tooltip title="移动到" placement="bottom">
<i className="icon-yidong iconfont font-15" onClick={() => moveVideo(props)}
style={{ marginTop: '1px', display: 'inline-block'}}
></i>
</Tooltip>
}
{
deleteVideo &&
<Tooltip title="删除" placement="bottom">

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Loading…
Cancel
Save