1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-06-22 19:44:02 +08:00

去除弹幕

This commit is contained in:
xiaochong0302 2020-08-04 21:16:16 +08:00
parent c9bf425fc6
commit 4f9f6ff15e
52 changed files with 273 additions and 376 deletions

View File

@ -40,7 +40,7 @@ class CourseFavoriteList extends Builder
'id', 'title', 'cover',
'market_price', 'vip_price',
'rating', 'model', 'level', 'attrs',
'user_count', 'lesson_count',
'user_count', 'lesson_count', 'review_count', 'favorite_count',
];
$courses = $courseRepo->findByIds($ids, $columns);

View File

@ -192,34 +192,24 @@ class Course extends Service
$this->updateCourseGroup($course);
$this->rebuildCourseIndex($course);
return $course;
}
public function deleteCourse($id)
{
$course = $this->findOrFail($id);
$course->deleted = 1;
$course->update();
$this->rebuildCourseIndex($course);
return $course;
}
public function restoreCourse($id)
{
$course = $this->findOrFail($id);
$course->deleted = 0;
$course->update();
$this->rebuildCourseIndex($course);
return $course;
}

View File

@ -47,31 +47,6 @@ class ConsultController extends Controller
$this->view->setVar('consult', $consult);
}
/**
* @Route("/{id:[0-9]+}/reply", name="web.consult.reply")
*/
public function replyAction($id)
{
if ($this->request->isPost()) {
$service = new ConsultReplyService();
$service->handle($id);
$content = ['msg' => '回复咨询成功'];
return $this->jsonSuccess($content);
} else {
$service = new ConsultInfoService();
$consult = $service->handle($id);
$this->view->setVar('consult', $consult);
}
}
/**
* @Post("/create", name="web.consult.create")
*/
@ -118,6 +93,31 @@ class ConsultController extends Controller
return $this->jsonSuccess($content);
}
/**
* @Route("/{id:[0-9]+}/reply", name="web.consult.reply")
*/
public function replyAction($id)
{
if ($this->request->isPost()) {
$service = new ConsultReplyService();
$service->handle($id);
$content = ['msg' => '回复咨询成功'];
return $this->jsonSuccess($content);
} else {
$service = new ConsultInfoService();
$consult = $service->handle($id);
$this->view->setVar('consult', $consult);
}
}
/**
* @Post("/{id:[0-9]+}/like", name="web.consult.like")
*/

View File

@ -5,7 +5,6 @@
{% set chapter_full_url = full_url({'for':'web.chapter.show','id':chapter.id}) %}
{% set course_url = url({'for':'web.course.show','id':chapter.course.id}) %}
{% set learning_url = url({'for':'web.chapter.learning','id':chapter.id}) %}
{% set danmu_url = url({'for':'web.chapter.danmu','id':chapter.id}) %}
{% set like_url = url({'for':'web.chapter.like','id':chapter.id}) %}
{% set qrcode_url = url({'for':'web.qrcode'},{'text':chapter_full_url}) %}
{% set consult_url = url({'for':'web.consult.add'},{'chapter_id':chapter.id}) %}
@ -31,16 +30,6 @@
<div class="layout-content">
<div class="player-wrap wrap">
<div id="player"></div>
<div id="danmu"></div>
<form class="layui-form danmu-form" lay-filter="danmu.form" action="{{ url({'for':'web.danmu.create'}) }}">
{% if auth_user.id > 0 %}
<a href="javascript:" title="弹幕设置"><i class="layui-icon layui-icon-set icon-danmu-set"></i></a>
<input class="layui-input" type="text" name="danmu.text" autocomplete="off" maxlength="50" placeholder="快来发个弹幕吧" lay-verType="tips" lay-verify="required">
{% else %}
<input class="layui-input" type="text" name="danmu.text" placeholder="登录后才可以发送弹幕哦" readonly="readonly">
{% endif %}
<button class="layui-hide" type="submit" lay-submit="true" lay-filter="danmu.send">发送</button>
</form>
</div>
</div>
<div class="layout-sidebar">
@ -48,58 +37,11 @@
</div>
</div>
<div id="my-danmu-set" style="display:none;">
<form class="layui-form" lay-filter="danmu.form.set" style="padding:20px 0;">
<div class="layui-form-item">
<label class="layui-form-label">显示弹幕</label>
<div class="layui-input-block">
<input type="checkbox" name="danmu.status" lay-filter="danmu.status" lay-skin="switch" lay-text="是|否" checked="checked">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">透明度</label>
<div class="layui-input-block">
<input type="radio" name="danmu.opacity" lay-filter="danmu.opacity" value="1" title="0" checked="checked">
<input type="radio" name="danmu.opacity" lay-filter="danmu.opacity" value="0.75" title="25%">
<input type="radio" name="danmu.opacity" lay-filter="danmu.opacity" value="0.5" title="50%">
<input type="radio" name="danmu.opacity" lay-filter="danmu.opacity" value="0.25" title="75%">
<input type="radio" name="danmu.opacity" lay-filter="danmu.opacity" value="0" title="100%">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">颜色</label>
<div class="layui-input-block">
<input type="radio" name="danmu.color" value="white" title="白" checked="checked">
<input type="radio" name="danmu.color" value="red" title="红">
<input type="radio" name="danmu.color" value="orange" title="黄">
<input type="radio" name="danmu.color" value="blue" title="蓝">
<input type="radio" name="danmu.color" value="green" title="绿">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">位置</label>
<div class="layui-input-block">
<input type="radio" name="danmu.position" value="0" title="滚动" checked="checked">
<input type="radio" name="danmu.position" value="1" title="顶部">
<input type="radio" name="danmu.position" value="2" title="底部">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">字号</label>
<div class="layui-input-block">
<input type="radio" name="danmu.size" value="0" title="小" checked="checked">
<input type="radio" name="danmu.size" value="1" title="大">
</div>
</div>
</form>
</div>
<div class="layui-hide">
<input type="hidden" name="chapter.id" value="{{ chapter.id }}">
<input type="hidden" name="chapter.position" value="{{ chapter.me.position }}">
<input type="hidden" name="chapter.plan_id" value="{{ chapter.me.plan_id }}">
<input type="hidden" name="chapter.learning_url" value="{{ learning_url }}">
<input type="hidden" name="chapter.danmu_url" value="{{ danmu_url }}">
<input type="hidden" name="chapter.play_urls" value='{{ chapter.play_urls|json_encode }}'>
</div>
@ -116,8 +58,6 @@
<script src="//imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.3.js"></script>
{{ js_include('lib/jquery.min.js') }}
{{ js_include('lib/jquery.danmu.min.js') }}
{{ js_include('web/js/course.share.js') }}
{{ js_include('web/js/chapter.action.js') }}
{{ js_include('web/js/chapter.vod.player.js') }}

View File

@ -1,11 +1,11 @@
{% extends 'templates/layer.volt' %}
{% block content %}
<form class="layui-form" method="post" action="{{ url({'for':'web.consult.create'}) }}">
<form class="layui-form consult-form" method="post" action="{{ url({'for':'web.consult.create'}) }}">
<div class="layui-form-item">
<label class="layui-form-label">问题</label>
<label class="layui-form-label" for="question">问题</label>
<div class="layui-input-block">
<textarea name="question" class="layui-textarea" placeholder="请详细描述问题,我们会尽快回复您" lay-verify="required"></textarea>
<textarea class="layui-textarea" id="question" name="question" placeholder="请详细描述问题,我们会尽快回复您" lay-verify="required"></textarea>
</div>
</div>
<div class="layui-form-item">

View File

@ -4,7 +4,7 @@
{% set update_url = url({'for':'web.consult.update','id':consult.id}) %}
<form class="layui-form" method="post" action="{{ update_url }}">
<form class="layui-form consult-form" method="post" action="{{ update_url }}">
<div class="layui-form-item mb0">
<label class="layui-form-label">课程</label>
<div class="layui-form-mid">{{ consult.course.title }}</div>

View File

@ -4,7 +4,7 @@
{% set update_url = url({'for':'web.consult.reply','id':consult.id}) %}
<form class="layui-form" method="post" action="{{ update_url }}">
<form class="layui-form consult-form" method="post" action="{{ update_url }}">
<div class="layui-form-item mb0">
<label class="layui-form-label">课程</label>
<div class="layui-form-mid">{{ consult.course.title }}</div>
@ -32,3 +32,12 @@
</form>
{% endblock %}
{% block inline_js %}
<script>
var index = parent.layer.getFrameIndex(window.name);
parent.layer.iframeAuto(index);
</script>
{% endblock %}

View File

@ -2,25 +2,38 @@
{% block content %}
{% set answer = consult.answer ? consult.answer : '<span class="gray">稍安勿燥,请耐心等待回复吧</span>' %}
{% set consult.answer = consult.answer ? consult.answer : '请耐心等待回复吧' %}
<form class="layui-form review-form">
<div class="layui-form-item mb0">
<label class="layui-form-label">课程:</label>
<div class="layui-form-mid">{{ consult.course.title }}</div>
<div class="consult-info">
{% if consult.course.id is defined %}
<div class="item">
<div class="label">课程:</div>
<div class="title">{{ consult.course.title }}</div>
</div>
<div class="layui-form-item mb0">
<label class="layui-form-label">章节:</label>
<div class="layui-form-mid">{{ consult.chapter.title }}</div>
{% endif %}
{% if consult.chapter.id is defined %}
<div class="item">
<div class="label">章节:</div>
<div class="title">{{ consult.chapter.title }}</div>
</div>
<div class="layui-form-item mb0">
<label class="layui-form-label">提问:</label>
<div class="layui-form-mid">{{ consult.question }}</div>
{% endif %}
<div class="item">
<div class="label">提问:</div>
<div class="content">{{ consult.question }}</div>
</div>
<div class="item">
<div class="label">回答:</div>
<div class="content">{{ consult.answer }}</div>
</div>
<div class="layui-form-item mb0">
<label class="layui-form-label">回复:</label>
<div class="layui-form-mid">{{ answer }}</div>
</div>
</form>
{% endblock %}
{% block inline_js %}
<script>
var index = parent.layer.getFrameIndex(window.name);
parent.layer.iframeAuto(index);
</script>
{% endblock %}

View File

@ -2,20 +2,26 @@
<div class="review-list">
{% for item in pager.items %}
{% set item.answer = item.answer ? item.answer : '稍安勿燥,请耐心等待回复吧' %}
{% set owner_url = url({'for':'web.user.show','id':item.id}) %}
{% set owner_url = url({'for':'web.user.show','id':item.owner.id}) %}
{% set consult_url = url({'for':'web.consult.show','id':item.id}) %}
{% set like_url = url({'for':'web.consult.like','id':item.id}) %}
<div class="review-card clearfix">
<div class="avatar">
<a href="{{ owner_url }}">
<img src="{{ item.owner.avatar }}" alt="{{ item.owner.name }}" title="{{ item.owner.name }}">
<a href="{{ owner_url }}" title="{{ item.owner.name }}">
<img src="{{ item.owner.avatar }}" alt="{{ item.owner.name }}">
</a>
</div>
<div class="info">
<div class="title">{{ item.question }}</div>
<div class="more">
<a class="consult-details" href="javascript:" title="查看详情" data-url="{{ consult_url }}">
<i class="layui-icon layui-icon-more"></i>
</a>
</div>
<div class="title layui-elip">{{ item.question }}</div>
<div class="content">{{ item.answer }}</div>
<div class="footer">
<span class="time">{{ item.create_time|time_ago }}</span>
<a href="javascript:" class="like" title="点赞" data-url="{{ like_url }}">
<a class="like" href="javascript:" title="点赞" data-url="{{ like_url }}">
<i class="layui-icon layui-icon-praise icon-praise"></i>
<em class="like-count">{{ item.like_count }}</em>
</a>

View File

@ -1,4 +1,4 @@
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
{% if pager.total_pages > 0 %}
<div class="course-list clearfix">

View File

@ -1,4 +1,4 @@
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
{% if courses %}
<div class="layui-card">

View File

@ -1,4 +1,4 @@
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
{% if courses %}
<div class="layui-card">

View File

@ -1,4 +1,4 @@
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
{% if pager.total_pages > 0 %}
<div class="review-list">
@ -7,7 +7,9 @@
{% set like_url = url({'for':'web.review.like','id':item.id}) %}
<div class="review-card clearfix">
<div class="avatar">
<a href="{{ owner_url }}" title="{{ item.owner.name }}">
<img src="{{ item.owner.avatar }}" alt="{{ item.owner.name }}">
</a>
</div>
<div class="info">
<div class="rating">{{ star_info(item.rating) }}</div>

View File

@ -2,7 +2,7 @@
{% block content %}
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
{% set favorite_title = course.me.favorited ? '取消收藏' : '收藏' %}
{% set favorite_star = course.me.favorited ? 'layui-icon-star-fill' : 'layui-icon-star' %}

View File

@ -8,7 +8,7 @@
{% set teacher.title = teacher.title ? teacher.title : '小小教书匠' %}
<div class="sidebar-teacher-card clearfix">
<div class="avatar">
<img src="{{ teacher.avatar }}" alt="{{ teacher.name }}" title="{{ teacher.about }}">
<img src="{{ teacher.avatar }}" alt="{{ teacher.name }}">
</div>
<div class="info">
<div class="name layui-elip">

View File

@ -2,7 +2,7 @@
{% block content %}
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
{%- macro category_courses(courses) %}
<div class="layui-tab layui-tab-brief">

View File

@ -2,7 +2,7 @@
{% block content %}
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
<div class="layout-main">
<div class="my-sidebar">{{ partial('my/menu') }}</div>

View File

@ -2,7 +2,7 @@
{% block content %}
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
<div class="layout-main">
<div class="my-sidebar">{{ partial('my/menu') }}</div>

View File

@ -2,7 +2,7 @@
{% block content %}
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
<div class="layout-main">
<div class="my-sidebar">{{ partial('my/menu') }}</div>
@ -17,12 +17,14 @@
<col>
<col>
<col>
<col>
<col width="12%">
</colgroup>
<thead>
<tr>
<th>课程</th>
<th>人气</th>
<th>学员</th>
<th>收藏</th>
<th>评分</th>
<th>操作</th>
</tr>
@ -33,10 +35,11 @@
{% set favorite_url = url({'for':'web.course.favorite','id':item.id}) %}
<tr>
<td><a href="{{ course_url }}">{{ item.title }}</a> {{ model_info(item.model) }}</td>
<td><span class="layui-badge-rim">{{ item.user_count }}</span></td>
<td>{{ star_info(item.rating) }}</td>
<td>{{ item.user_count }}</td>
<td>{{ item.favorite_count }}</td>
<td>{{ item.rating }}</td>
<td align="center">
<button class="layui-btn layui-btn-xs kg-delete" data-tips="确定要取消收藏吗?" data-url="{{ favorite_url }}">取消</button>
<button class="layui-btn layui-btn-sm kg-delete" data-tips="确定要取消收藏吗?" data-url="{{ favorite_url }}">取消</button>
</td>
</tr>
{% endfor %}

View File

@ -4,11 +4,11 @@
{%- macro gender_info(value) %}
{% if value == 1 %}
<span class="layui-badge layui-bg-red"></span>
{% elseif value == 2 %}
<span class="layui-badge layui-bg-green"></span>
{% elseif value == 3 %}
<span class="layui-badge layui-bg-gray"></span>
{% endif %}
{%- endmacro %}
@ -47,7 +47,7 @@
<td>{{ item.location }}</td>
<td>{{ item.active_time|time_ago }}</td>
<td>
<button class="layui-btn layui-btn-xs kg-delete" data-url="{{ delete_url }}">删除</button>
<button class="layui-btn layui-btn-sm kg-delete" data-url="{{ delete_url }}">删除</button>
</td>
</tr>
{% endfor %}

View File

@ -4,12 +4,12 @@
<col>
<col>
<col>
<col width="15%">
<col width="12%">
</colgroup>
<thead>
<tr>
<th>名称</th>
<th>群主</th>
<th>组长</th>
<th>成员</th>
<th>操作</th>
</tr>
@ -21,9 +21,9 @@
<tr>
<td><span title="{{ item.about }}">{{ item.name }}</span> {{ type_info(item.type) }}</td>
<td><a href="{{ owner_url }}">{{ item.owner.name }}</a></td>
<td><span class="layui-badge-rim">{{ item.user_count }}</span></td>
<td>{{ item.user_count }}</td>
<td>
<button class="layui-btn layui-btn-xs kg-delete" data-tips="确定要退出吗?" data-url="{{ delete_url }}">退出</button>
<button class="layui-btn layui-btn-sm kg-delete" data-tips="确定要退出吗?" data-url="{{ delete_url }}">退出</button>
</td>
</tr>
{% endfor %}

View File

@ -20,8 +20,8 @@
{% set users_url = url({'for':'web.igm.users','id':item.id}) %}
<tr>
<td><span title="{{ item.about }}">{{ item.name }}</span> {{ type_info(item.type) }}</td>
<td><span class="layui-badge-rim">{{ item.user_count }}</span></td>
<td><span class="layui-badge-rim">{{ item.msg_count }}</span></td>
<td>{{ item.user_count }}</td>
<td>{{ item.msg_count }}</td>
<td>
<span class="layui-btn layui-btn-xs layui-bg-blue btn-group-user" data-url="{{ users_url }}">成员</span>
<span class="layui-btn layui-btn-xs btn-edit-group" data-url="{{ edit_url }}">编辑</span>

View File

@ -19,9 +19,9 @@
<div class="layui-card-body">
<ul class="my-menu">
<li><a href="{{ url({'for':'web.my.courses'}) }}">我的课程</a></li>
<li><a href="{{ url({'for':'web.my.consults'}) }}">我的咨询</a></li>
<li><a href="{{ url({'for':'web.my.favorites'}) }}">我的收藏</a></li>
<li><a href="{{ url({'for':'web.my.reviews'}) }}">我的评价</a></li>
<li><a href="{{ url({'for':'web.my.consults'}) }}">我的咨询</a></li>
</ul>
</div>
</div>

View File

@ -2,7 +2,7 @@
{% block content %}
{{ partial('partials/macro_order') }}
{{ partial('macros/order') }}
{% set status_types = {'all':'全部','pending':'待支付','finished':'已完成','closed':'已关闭','refunded':'已退款'} %}
{% set status = request.get('status','trim','all') %}

View File

@ -2,7 +2,7 @@
{% block content %}
{{ partial('partials/macro_refund') }}
{{ partial('macros/refund') }}
{% set status_types = {'all':'全部','pending':'待处理','canceled':'已取消','approved':'退款中','finished':'已完成'} %}
{% set status = request.get('status','trim','all') %}

View File

@ -2,7 +2,7 @@
{% block content %}
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
<div class="layout-main">
<div class="my-sidebar">{{ partial('my/menu') }}</div>
@ -33,12 +33,12 @@
<tr>
<td>
<p class="title layui-elip">课程:<a href="{{ course_url }}">{{ item.course.title }}</a></p>
<p class="content layui-elip" title="{{ item.content|e }}">评价:{{ item.content }}</p>
<p class="content layui-elip" title="{{ item.content }}">评价:{{ item.content }}</p>
</td>
<td>
<p class="rating">内容实用:{{ star_info(item.rating1) }}</p>
<p class="rating">通俗易懂:{{ star_info(item.rating2) }}</p>
<p class="rating">逻辑清晰:{{ star_info(item.rating3) }}</p>
<p class="rating">内容实用:{{ item.rating1 }}</p>
<p class="rating">通俗易懂:{{ item.rating2 }}</p>
<p class="rating">逻辑清晰:{{ item.rating3 }}</p>
</td>
<td>
<button class="layui-btn layui-btn-xs btn-edit-review" data-url="{{ edit_url }}">修改</button>

View File

@ -2,7 +2,7 @@
{% block content %}
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
{%- macro cart_course_card(course, user) %}
{% set course_url = url({'for':'web.course.show','id':course.id}) %}

View File

@ -2,7 +2,7 @@
{% block content %}
{{ partial('partials/macro_order') }}
{{ partial('macros/order') }}
{% set order_pay_url = url({'for':'web.order.pay'},{'sn':order.sn}) %}
{% set refund_confirm_url = url({'for':'web.refund.confirm'},{'sn':order.sn}) %}

View File

@ -2,7 +2,7 @@
{% block content %}
{{ partial('partials/macro_refund') }}
{{ partial('macros/refund') }}
{% set cancel_url = url({'for':'web.refund.cancel'}) %}

View File

@ -5,7 +5,7 @@
{% set type = request.get('type','trim','course') %}
{% set query = request.get('query','striptags','') %}
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
<div class="layui-breadcrumb breadcrumb">
<a href="/">首页</a>

View File

@ -22,33 +22,34 @@
<colgroup>
<col>
<col>
<col width="20%">
<col>
<col width="15%">
</colgroup>
<thead>
<tr>
<th>内容</th>
<th>优先级</th>
<th>时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for item in pager.items %}
{% set answer = item.answer ? item.answer : '<span class="gray">等待回复ing...</span>' %}
{% set answer = item.answer ? item.answer : '<span class="gray">等待回复...</span>' %}
{% set course_url = url({'for':'web.course.show','id':item.course.id}) %}
{% set show_url = url({'for':'web.consult.show','id':item.id}) %}
{% set reply_url = url({'for':'web.consult.reply','id':item.id}) %}
{% set delete_url = url({'for':'web.consult.delete','id':item.id}) %}
<tr>
<td>
<p>课程:<a href="{{ course_url }}" target="_blank">{{ item.course.title }}</a></p>
<p class="question layui-elip" title="{{ item.question }}">提问:{{ item.question }}</p>
<p class="answer layui-elip" title="{{ item.answer }}">回复:{{ answer }}</p>
</td>
<td>{{ item.priority }}</td>
<td>{{ date('Y-m-d',item.create_time) }}</td>
<td>
<button class="layui-btn layui-btn-xs layui-bg-green btn-show-consult" data-url="{{ show_url }}">详情</button>
<button class="layui-btn layui-btn-xs layui-bg-blue btn-reply-consult" data-url="{{ reply_url }}">回复</button>
<button class="layui-btn layui-btn-xs layui-bg-red kg-delete" data-url="{{ delete_url }}">删除</button>
</td>
</tr>
{% endfor %}

View File

@ -2,7 +2,7 @@
{% block content %}
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
<div class="layout-main">
<div class="my-sidebar">{{ partial('teaching/menu') }}</div>
@ -34,10 +34,10 @@
{% set course_url = url({'for':'web.course.show','id':item.id}) %}
<tr>
<td><a href="{{ course_url }}">{{ item.title }}</a> {{ model_info(item.model) }}</td>
<td><span class="layui-badge-rim">{{ item.lesson_count }}</span></td>
<td><span class="layui-badge-rim">{{ item.user_count }}</span></td>
<td><span class="layui-badge-rim">{{ item.favorite_count }}</span></td>
<td><span class="layui-badge-rim">{{ item.rating }}</span></td>
<td>{{ item.lesson_count }}</td>
<td>{{ item.user_count }}</td>
<td>{{ item.favorite_count }}</td>
<td>{{ item.rating }}</td>
</tr>
{% endfor %}
</tbody>

View File

@ -2,7 +2,7 @@
{% block content %}
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
<div class="layout-main">
<div class="my-sidebar">{{ partial('teaching/menu') }}</div>

View File

@ -1,4 +1,4 @@
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
{% if pager.total_pages > 0 %}
<div class="course-list clearfix">

View File

@ -1,4 +1,4 @@
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
{% if pager.total_pages > 0 %}
<div class="course-list learning-course-list clearfix">

View File

@ -1,4 +1,4 @@
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
{% if pager.total_pages > 0 %}
<div class="course-list clearfix">

View File

@ -2,7 +2,7 @@
{% block content %}
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
{% set vip_flag = user.vip ? '<i class="layui-icon layui-icon-diamond icon-vip"></i>' : '' %}

View File

@ -1,4 +1,4 @@
{{ partial('partials/macro_course') }}
{{ partial('macros/course') }}
{% if pager.total_pages > 0 %}
<div class="course-list clearfix">

View File

@ -3,6 +3,7 @@
namespace App\Models;
use App\Caches\MaxCourseId as MaxCourseIdCache;
use App\Services\Syncer\CourseIndex as CourseIndexSyncer;
use Phalcon\Mvc\Model\Behavior\SoftDelete;
use Phalcon\Text;
@ -304,6 +305,13 @@ class Course extends Model
$cache->rebuild();
}
public function afterUpdate()
{
$syncer = new CourseIndexSyncer();
$syncer->addItem($this->id);
}
public function afterFetch()
{
$this->market_price = (float)$this->market_price;

View File

@ -32,35 +32,44 @@ class ConsultInfo extends FrontendService
'like_count' => $consult->like_count,
'create_time' => $consult->create_time,
'update_time' => $consult->update_time,
'course' => new \stdClass(),
'chapter' => new \stdClass(),
'owner' => new \stdClass(),
];
$courseRepo = new CourseRepo();
$course = $courseRepo->findById($consult->course_id);
if ($course) {
$result['course'] = [
'id' => $course->id,
'title' => $course->title,
];
}
$chapterRepo = new ChapterRepo();
$chapter = $chapterRepo->findById($consult->chapter_id);
if ($chapter) {
$result['chapter'] = [
'id' => $chapter->id,
'title' => $chapter->title,
];
}
$userRepo = new UserRepo();
$owner = $userRepo->findById($consult->owner_id);
if ($owner) {
$result['owner'] = [
'id' => $owner->id,
'name' => $owner->name,
'avatar' => $owner->avatar,
];
}
return $result;
}

View File

@ -23,9 +23,12 @@ class ConsultReply extends FrontendService
$validator->checkTeacher($consult, $user);
$consult->answer = $validator->checkAnswer($post['answer']);
$consult->reply_time = time();
$consult->update();
$answer = $validator->checkAnswer($post['answer']);
$consult->update([
'answer' => $answer,
'reply_time' => time(),
]);
return $consult;
}

View File

@ -56,6 +56,7 @@ class ConsultList extends FrontendService
'id' => $consult['id'],
'question' => $consult['question'],
'answer' => $consult['answer'],
'priority' => $consult['priority'],
'like_count' => $consult['like_count'],
'reply_time' => $consult['reply_time'],
'create_time' => $consult['create_time'],

View File

@ -72,6 +72,7 @@ class ConsultList extends FrontendService
'id' => $consult['id'],
'question' => $consult['question'],
'answer' => $consult['answer'],
'priority' => $consult['priority'],
'like_count' => $consult['like_count'],
'reply_time' => $consult['reply_time'],
'create_time' => $consult['create_time'],
@ -107,7 +108,7 @@ class ConsultList extends FrontendService
}
}
$builder->orderBy('id DESC');
$builder->orderBy('priority ASC,id DESC');
$pager = new PagerQueryBuilder([
'builder' => $builder,

View File

@ -5,11 +5,10 @@ namespace App\Validators;
use App\Exceptions\BadRequest as BadRequestException;
use App\Exceptions\Forbidden as ForbiddenException;
use App\Models\Consult as ConsultModel;
use App\Models\CourseUser as CourseUserModel;
use App\Models\User as UserModel;
use App\Repos\Consult as ConsultRepo;
use App\Repos\ConsultLike as ConsultLikeRepo;
use App\Repos\CourseUser as CourseUserRepo;
use App\Repos\Course as CourseRepo;
class Consult extends Validator
{
@ -95,13 +94,18 @@ class Consult extends Validator
public function checkTeacher(ConsultModel $consult, UserModel $user)
{
$repo = new CourseUserRepo();
$repo = new CourseRepo();
$record = $repo->findCourseUser($consult->course_id, $user->id);
$teachers = $repo->findTeachers($consult->course_id);
$privOk = $record && $record->role_type == CourseUserModel::ROLE_TEACHER;
$isTeacher = false;
if (!$privOk) {
if ($teachers->count() > 0) {
$teacherIds = kg_array_column($teachers->toArray(), 'id');
$isTeacher = in_array($user->id, $teacherIds);
}
if (!$isTeacher) {
throw new ForbiddenException('sys.forbidden');
}
}

View File

@ -73,6 +73,7 @@
}
.pager {
margin-top: 20px;
text-align: center;
}
@ -239,10 +240,6 @@ body {
padding: 0 5px;
}
.search-course-list {
margin-bottom: 30px;
}
.search-course-card {
padding-bottom: 15px;
margin-bottom: 15px;
@ -270,7 +267,6 @@ body {
.search-course-card .info {
float: left;
width: 500px;
color: #666;
}
.search-course-card .title {
@ -283,8 +279,13 @@ body {
line-height: 1.5em;
max-height: 4.5em;
font-size: 12px;
word-wrap: break-word;
color: #666;
overflow: hidden;
overflow-wrap: break-word;
}
.search-course-card .meta {
color: #666;
}
.search-course-card .meta span {
@ -679,7 +680,7 @@ body {
width: 650px;
}
.review-card .rating {
.review-card .rating, .review-card .more {
position: absolute;
top: 0;
right: 0;
@ -691,6 +692,11 @@ body {
font-size: 12px;
}
.review-card .more {
color: #666;
cursor: pointer;
}
.review-card .title {
margin-bottom: 10px;
}
@ -702,8 +708,11 @@ body {
.review-card .content {
margin-bottom: 15px;
word-wrap: break-word;
line-height: 1.5em;
max-height: 6em;
overflow-wrap: break-word;
white-space: pre-wrap;
overflow: hidden;
color: #666;
}
@ -877,30 +886,6 @@ body {
margin-bottom: 0;
}
.danmu-form {
position: relative;
left: 180px;
bottom: 38px;
width: 420px;
z-index: 999;
display: none;
}
.danmu-form .icon-danmu-set {
margin-right: 5px;
color: white;
}
.danmu-form .layui-input {
width: 380px;
height: 28px;
display: inline;
line-height: 28px;
font-size: 12px;
color: white;
background-color: rgba(255, 255, 255, 0.1);
}
.chat-wrap .layui-card-header {
text-align: center;
}
@ -1445,26 +1430,64 @@ body {
}
.consult-table .question {
width: 400px;
width: 450px;
}
.consult-table .answer {
width: 400px;
width: 450px;
}
.review-table .title {
width: 350px;
width: 400px;
}
.review-table .content {
width: 350px;
color: #999;
width: 400px;
color: #666;
}
.review-form .layui-rate {
padding-top: 6px;
}
.consult-form .layui-form-label {
width: 50px;
padding: 9px 0;
}
.consult-form .layui-input-block {
margin-left: 70px;
}
.consult-form .layui-form-mid {
float: none;
margin-left: 70px;
}
.consult-info .item {
clear: both;
margin-bottom: 15px;
}
.consult-info .item .label {
float: left;
width: 50px;
height: 32px;
text-align: right;
}
.consult-info .item .title {
float: left;
width: 600px;
}
.consult-info .item .content {
float: left;
width: 600px;
color: #666;
word-wrap: break-word;
}
.security-item {
padding: 15px;
line-height: 50px;

View File

@ -1,8 +1,6 @@
layui.use(['jquery', 'form', 'layer', 'helper'], function () {
layui.use(['jquery', 'helper'], function () {
var $ = layui.jquery;
var form = layui.form;
var layer = layui.layer;
var helper = layui.helper;
var interval = null;
@ -13,30 +11,27 @@ layui.use(['jquery', 'form', 'layer', 'helper'], function () {
var planId = $('input[name="chapter.plan_id"]').val();
var lastPosition = $('input[name="chapter.position"]').val();
var learningUrl = $('input[name="chapter.learning_url"]').val();
var danmuListUrl = $('input[name="chapter.danmu_url"]').val();
var playUrls = JSON.parse($('input[name="chapter.play_urls"]').val());
var $danmuText = $('input[name="danmu.text"]');
var $danmuForm = $('.danmu-form');
var playerOptions = {
var options = {
autoplay: false,
width: 760,
height: 428
};
if (playUrls.od) {
playerOptions.m3u8 = playUrls.od.url;
options.m3u8 = playUrls.od.url;
}
if (playUrls.hd) {
playerOptions.m3u8_hd = playUrls.hd.url;
options.m3u8_hd = playUrls.hd.url;
}
if (playUrls.sd) {
playerOptions.m3u8_sd = playUrls.sd.url;
options.m3u8_sd = playUrls.sd.url;
}
playerOptions.listener = function (msg) {
options.listener = function (msg) {
if (msg.type === 'play') {
play();
} else if (msg.type === 'pause') {
@ -46,7 +41,7 @@ layui.use(['jquery', 'form', 'layer', 'helper'], function () {
}
};
var player = new TcPlayer('player', playerOptions);
var player = new TcPlayer('player', options);
var position = parseInt(lastPosition);
@ -57,91 +52,6 @@ layui.use(['jquery', 'form', 'layer', 'helper'], function () {
player.currentTime(position);
}
$('.icon-danmu-set').on('click', function () {
layer.open({
type: 1,
title: '弹幕设置',
area: '600px',
shadeClose: true,
content: $('#my-danmu-set')
});
});
var dt = null;
/**
* 控制弹幕表单的可见性
*/
$('#player').hover(function () {
clearTimeout(dt);
$danmuForm.show();
}, function () {
dt = setTimeout(function () {
$danmuForm.hide();
}, 2500);
});
/**
* 文本框获得焦点后清理dt不然对输入有干扰
*/
$danmuText.focus(function () {
clearTimeout(dt);
});
/**
* @todo 弹幕层和播放器控制层css有抵触待解决
*/
$('#danmu').danmu({
left: 20,
top: 20,
width: 760,
height: 380
});
initDanmu();
form.on('switch(danmu.status)', function (data) {
if (data.elem.checked) {
$('#danmu').danmu('setOpacity', 1);
} else {
$('#danmu').danmu('setOpacity', 0);
}
});
form.on('radio(danmu.opacity)', function (data) {
$('#danmu').danmu('setOpacity', parseFloat(data.value));
});
form.on('submit(danmu.send)', function (data) {
var setFormData = form.val('danmu.form.set');
var formData = form.val('danmu.form');
$.ajax({
type: 'POST',
url: data.form.action,
data: {
text: formData['danmu.text'],
color: setFormData['danmu.color'],
size: setFormData['danmu.size'],
position: setFormData['danmu.position'],
time: player.currentTime(),
chapter_id: chapterId
},
success: function (res) {
$('#danmu').danmu('addDanmu', {
text: res.danmu.text,
color: res.danmu.color,
size: res.danmu.size,
time: (res.danmu.time + 1) * 10, //十分之一秒
position: res.danmu.position,
isnew: 1
});
$danmuText.val('');
}
});
return false;
});
function clearLearningInterval() {
if (interval != null) {
clearInterval(interval);
@ -154,19 +64,11 @@ layui.use(['jquery', 'form', 'layer', 'helper'], function () {
}
function play() {
startDanmu();
clearLearningInterval();
setLearningInterval();
}
function pause() {
/**
* 视频结束也会触发暂停事件此时弹幕可能尚未结束
* 时间差区分暂停是手动还是结束触发
*/
if (player.currentTime() < player.duration() - 5) {
pauseDanmu();
}
clearLearningInterval();
}
@ -191,35 +93,4 @@ layui.use(['jquery', 'form', 'layer', 'helper'], function () {
}
}
function startDanmu() {
$('#danmu').danmu('danmuResume');
}
function pauseDanmu() {
$('#danmu').danmu('danmuPause');
}
/**
* 一次性获取弹幕待改进为根据时间轴区间获取
*/
function initDanmu() {
$.ajax({
type: 'GET',
url: danmuListUrl,
success: function (res) {
var items = [];
layui.each(res.items, function (index, item) {
items.push({
text: item.text,
color: item.color,
size: item.size,
time: (item.time + 1) * 10,
position: item.position
});
});
$('#danmu').danmu('addDanmu', items);
}
});
}
});

View File

@ -72,6 +72,19 @@ layui.use(['jquery', 'layer', 'helper'], function () {
});
});
/**
* 咨询详情
*/
$('body').on('click', '.consult-details', function () {
var url = $(this).data('url');
layer.open({
type: 2,
title: '咨询详情',
content: [url, 'no'],
area: ['720px', '320px']
});
});
/**
* 点赞咨询|评价
*/

View File

@ -12,8 +12,8 @@ layui.use(['jquery', 'layer', 'helper'], function () {
layer.open({
type: 2,
title: '咨询详情',
content: url,
area: ['720px', '480px']
content: [url, 'no'],
area: ['720px', '320px']
});
});

View File

@ -11,8 +11,8 @@ layui.use(['jquery', 'layer'], function () {
layer.open({
type: 2,
title: '咨询详情',
content: url,
area: ['720px', '480px']
content: [url, 'no'],
area: ['720px', '320px']
});
});
@ -25,7 +25,7 @@ layui.use(['jquery', 'layer'], function () {
type: 2,
title: '回复咨询',
content: [url, 'no'],
area: ['720px', '400px'],
area: ['720px', '300px'],
cancel: function () {
parent.location.reload();
}