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

1.更改模块继承基类

2.升级layui到2.6.8
3.升级腾讯云播放器
4.点播增加外链支持
This commit is contained in:
koogua 2021-06-12 12:34:40 +08:00
parent 72c5b7e77c
commit 1d2f1dd266
196 changed files with 839 additions and 441 deletions

View File

@ -2,9 +2,9 @@
namespace App\Builders; namespace App\Builders;
use Phalcon\Mvc\User\Component; use Phalcon\Di\Injectable;
class Builder extends Component class Builder extends Injectable
{ {
public function objects(array $items) public function objects(array $items)

View File

@ -3,9 +3,9 @@
namespace App\Caches; namespace App\Caches;
use Phalcon\Cache\Backend\Redis as RedisCache; use Phalcon\Cache\Backend\Redis as RedisCache;
use Phalcon\Mvc\User\Component; use Phalcon\Di\Injectable;
abstract class Cache extends Component abstract class Cache extends Injectable
{ {
/** /**

View File

@ -3,9 +3,9 @@
namespace App\Caches; namespace App\Caches;
use App\Library\Cache\Backend\Redis as RedisCache; use App\Library\Cache\Backend\Redis as RedisCache;
use Phalcon\Mvc\User\Component; use Phalcon\Di\Injectable;
abstract class Counter extends Component abstract class Counter extends Injectable
{ {
/** /**

View File

@ -63,7 +63,6 @@ class VodEventTask extends Task
* 获取不到时长视为失败 * 获取不到时长视为失败
*/ */
if ($duration == 0) { if ($duration == 0) {
$attrs['file']['id'] = $fileId;
$attrs['file']['status'] = ChapterModel::FS_FAILED; $attrs['file']['status'] = ChapterModel::FS_FAILED;
$chapter->update(['attrs' => $attrs]); $chapter->update(['attrs' => $attrs]);
return; return;
@ -77,7 +76,6 @@ class VodEventTask extends Task
$vodService->createTransVideoTask($fileId); $vodService->createTransVideoTask($fileId);
} }
$attrs['file']['id'] = $fileId;
$attrs['file']['status'] = ChapterModel::FS_TRANSLATING; $attrs['file']['status'] = ChapterModel::FS_TRANSLATING;
$attrs['duration'] = (int)$duration; $attrs['duration'] = (int)$duration;
@ -106,7 +104,6 @@ class VodEventTask extends Task
* 获取不到处理结果视为失败 * 获取不到处理结果视为失败
*/ */
if (empty($processResult)) { if (empty($processResult)) {
$attrs['file']['id'] = $fileId;
$attrs['file']['status'] = ChapterModel::FS_FAILED; $attrs['file']['status'] = ChapterModel::FS_FAILED;
$chapter->update(['attrs' => $attrs]); $chapter->update(['attrs' => $attrs]);
return; return;

View File

@ -124,9 +124,13 @@ class ChapterController extends Controller
switch ($course->model) { switch ($course->model) {
case CourseModel::MODEL_VOD: case CourseModel::MODEL_VOD:
$vod = $contentService->getChapterVod($chapter->id); $vod = $contentService->getChapterVod($chapter->id);
$playUrls = $contentService->getPlayUrls($chapter->id); $cosPlayUrls = $contentService->getCosPlayUrls($chapter->id);
$remotePlayUrls = $contentService->getRemotePlayUrls($chapter->id);
$remoteDuration = $contentService->getRemoteDuration($chapter->id);
$this->view->setVar('vod', $vod); $this->view->setVar('vod', $vod);
$this->view->setVar('play_urls', $playUrls); $this->view->setVar('cos_play_urls', $cosPlayUrls);
$this->view->setVar('remote_play_urls', $remotePlayUrls);
$this->view->setVar('remote_duration', $remoteDuration);
break; break;
case CourseModel::MODEL_LIVE: case CourseModel::MODEL_LIVE:
$live = $contentService->getChapterLive($chapter->id); $live = $contentService->getChapterLive($chapter->id);

View File

@ -10,14 +10,14 @@ use Phalcon\Mvc\ModuleDefinitionInterface;
class Module implements ModuleDefinitionInterface class Module implements ModuleDefinitionInterface
{ {
public function registerAutoLoaders(DiInterface $di = null) public function registerAutoLoaders(DiInterface $dependencyInjector = null)
{ {
} }
public function registerServices(DiInterface $di) public function registerServices(DiInterface $dependencyInjector)
{ {
$di->setShared('view', function () { $dependencyInjector->setShared('view', function () {
$view = new MyView(); $view = new MyView();
$view->setViewsDir(__DIR__ . '/Views'); $view->setViewsDir(__DIR__ . '/Views');
$view->registerEngines([ $view->registerEngines([
@ -26,7 +26,7 @@ class Module implements ModuleDefinitionInterface
return $view; return $view;
}); });
$di->setShared('auth', function () { $dependencyInjector->setShared('auth', function () {
return new AdminAuth(); return new AdminAuth();
}); });
} }

View File

@ -3,9 +3,9 @@
namespace App\Http\Admin\Services; namespace App\Http\Admin\Services;
use App\Services\Auth\Admin as AdminAuth; use App\Services\Auth\Admin as AdminAuth;
use Phalcon\Mvc\User\Component; use Phalcon\Di\Injectable;
class AuthMenu extends Component class AuthMenu extends Injectable
{ {
protected $authInfo; protected $authInfo;

View File

@ -47,11 +47,37 @@ class ChapterContent extends Service
return $chapterRepo->findChapterOffline($chapterId); return $chapterRepo->findChapterOffline($chapterId);
} }
public function getPlayUrls($chapterId) public function getCosPlayUrls($chapterId)
{ {
$service = new ChapterVodService(); $service = new ChapterVodService();
return $service->getPlayUrls($chapterId); return $service->getCosPlayUrls($chapterId);
}
public function getRemotePlayUrls($chapterId)
{
$service = new ChapterVodService();
return $service->getRemotePlayUrls($chapterId);
}
public function getRemoteDuration($chapterId)
{
$chapterRepo = new ChapterRepo();
$chapter = $chapterRepo->findById($chapterId);
$duration = $chapter->attrs['duration'] ?? 0;
$result = ['hours' => 0, 'minutes' => 0, 'seconds' => 0];
if ($duration == 0) return $result;
$result['hours'] = floor($duration / 3600);
$result['minutes'] = floor(($duration - $result['hours'] * 3600) / 60);
$result['seconds'] = $duration % 60;
return $result;
} }
public function updateChapterContent($chapterId) public function updateChapterContent($chapterId)
@ -84,6 +110,17 @@ class ChapterContent extends Service
{ {
$post = $this->request->getPost(); $post = $this->request->getPost();
if (isset($post['file_id'])) {
$this->updateCosChapterVod($chapter);
} elseif (isset($post['file_remote'])) {
$this->updateRemoteChapterVod($chapter);
}
}
protected function updateCosChapterVod(ChapterModel $chapter)
{
$post = $this->request->getPost();
$validator = new ChapterVodValidator(); $validator = new ChapterVodValidator();
$fileId = $validator->checkFileId($post['file_id']); $fileId = $validator->checkFileId($post['file_id']);
@ -119,6 +156,54 @@ class ChapterContent extends Service
$this->updateCourseVodAttrs($vod->course_id); $this->updateCourseVodAttrs($vod->course_id);
} }
protected function updateRemoteChapterVod(ChapterModel $chapter)
{
$post = $this->request->getPost();
$validator = new ChapterVodValidator();
$hours = $post['file_remote']['duration']['hours'] ?? 0;
$minutes = $post['file_remote']['duration']['minutes'] ?? 0;
$seconds = $post['file_remote']['duration']['seconds'] ?? 0;
$duration = 3600 * $hours + 60 * $minutes + $seconds;
$validator->checkDuration($duration);
$odUrl = $post['file_remote']['od']['url'] ?? '';
$hdUrl = $post['file_remote']['hd']['url'] ?? '';
$sdUrl = $post['file_remote']['sd']['url'] ?? '';
$fileRemote = [];
$attrs = $chapter->attrs;
if (!empty($odUrl)) {
$fileRemote['od']['url'] = $validator->checkFileUrl($odUrl);
$attrs['file']['status'] = ChapterModel::FS_UPLOADED;
$attrs['duration'] = $duration;
}
if (!empty($hdUrl)) {
$fileRemote['hd']['url'] = $validator->checkFileUrl($hdUrl);
}
if (!empty($sdUrl)) {
$fileRemote['sd']['url'] = $validator->checkFileUrl($sdUrl);
}
$chapterRepo = new ChapterRepo();
$vod = $chapterRepo->findChapterVod($chapter->id);
$vod->file_remote = $fileRemote;
$vod->update();
$chapter->attrs = $attrs;
$chapter->update();
$this->updateCourseVodAttrs($vod->course_id);
}
protected function updateChapterLive(ChapterModel $chapter) protected function updateChapterLive(ChapterModel $chapter)
{ {
$post = $this->request->getPost(); $post = $this->request->getPost();

View File

@ -40,7 +40,7 @@
<td>{{ item.like_count }}</td> <td>{{ item.like_count }}</td>
<td>{{ publish_status(item.published) }}</td> <td>{{ publish_status(item.published) }}</td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ answer_url }}" target="_blank">预览回答</a></li> <li><a href="{{ answer_url }}" target="_blank">预览回答</a></li>

View File

@ -83,7 +83,7 @@
<td><input type="checkbox" name="featured" value="1" lay-skin="switch" lay-text="是|否" lay-filter="featured" data-url="{{ update_url }}" {% if item.featured == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="featured" value="1" lay-skin="switch" lay-text="是|否" lay-filter="featured" data-url="{{ update_url }}" {% if item.featured == 1 %}checked="checked"{% endif %}></td>
<td><input type="checkbox" name="comment" value="1" lay-skin="switch" lay-text="是|否" lay-filter="closed" data-url="{{ update_url }}" {% if item.closed == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="comment" value="1" lay-skin="switch" lay-text="是|否" lay-filter="closed" data-url="{{ update_url }}" {% if item.closed == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
{% if item.published == 1 %} {% if item.published == 1 %}

View File

@ -67,7 +67,7 @@
<td><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td> <td><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ edit_url }}">编辑</a></li> <li><a href="{{ edit_url }}">编辑</a></li>

View File

@ -1,66 +1,159 @@
{% set file_id = vod ? vod.file_id : '' %} {% set action_url = url({'for':'admin.chapter.content','id':chapter.id}) %}
{% if play_urls %} {% if vod.file_id is defined %}
<fieldset class="layui-elem-field layui-field-title"> {% set file_id = vod.file_id %}
<legend>视频信息</legend> {% else %}
</fieldset> {% set file_id = '' %}
<table class="kg-table layui-table">
<tr>
<th>格式</th>
<th>时长</th>
<th>分辨率</th>
<th>码率</th>
<th>大小</th>
<th width="16%">操作</th>
</tr>
{% for item in play_urls %}
<tr>
<td>{{ item.format }}</td>
<td>{{ item.duration|duration }}</td>
<td>{{ item.width }} x {{ item.height }}</td>
<td>{{ item.rate }}kbps</td>
<td>{{ item.size }}M</td>
<td>
<span class="layui-btn layui-btn-sm kg-preview" data-chapter-id="{{ chapter.id }}" data-play-url="{{ item.url|url_encode }}">预览</span>
<span class="layui-btn layui-btn-sm kg-copy" data-clipboard-text="{{ item.url }}">复制</span>
</td>
</tr>
{% endfor %}
</table>
<br>
{% endif %} {% endif %}
<fieldset class="layui-elem-field layui-field-title"> <div class="layui-tab layui-tab-brief">
<legend>上传视频</legend> <ul class="layui-tab-title kg-tab-title">
</fieldset> <li class="layui-this">腾讯云点播</li>
<li>外链云点播</li>
<form class="layui-form kg-form" id="vod-form" method="POST" action="{{ url({'for':'admin.chapter.content','id':chapter.id}) }}"> </ul>
<div class="layui-form-item" id="upload-block"> <div class="layui-tab-content">
<label class="layui-form-label">视频文件</label> <div class="layui-tab-item layui-show">
<div class="layui-input-block"> {% if cos_play_urls %}
<span class="layui-btn" id="upload-btn">选择视频</span> <fieldset class="layui-elem-field layui-field-title">
<input class="layui-hide" type="file" name="file" accept="video/*,audio/*"> <legend>视频信息</legend>
</fieldset>
<table class="kg-table layui-table">
<tr>
<th>格式</th>
<th>时长</th>
<th>分辨率</th>
<th>码率</th>
<th>大小</th>
<th width="16%">操作</th>
</tr>
{% for item in cos_play_urls %}
<tr>
<td>{{ item.format }}</td>
<td>{{ item.duration|duration }}</td>
<td>{{ item.width }} x {{ item.height }}</td>
<td>{{ item.rate }}kbps</td>
<td>{{ item.size }}M</td>
<td>
<span class="layui-btn kg-preview" data-chapter-id="{{ chapter.id }}" data-play-url="{{ item.url|url_encode }}">预览</span>
<span class="layui-btn layui-btn-primary kg-copy" data-clipboard-text="{{ item.url }}">复制</span>
</td>
</tr>
{% endfor %}
</table>
<br>
{% endif %}
<form class="layui-form kg-form" id="vod-form" method="POST" action="{{ action_url }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>上传视频</legend>
</fieldset>
<div class="layui-form-item" id="upload-block">
<label class="layui-form-label">视频文件</label>
<div class="layui-input-block">
<span class="layui-btn" id="upload-btn">选择视频</span>
<input class="layui-hide" type="file" name="file" accept="video/*,audio/*">
</div>
</div>
<div class="layui-form-item layui-hide" id="upload-progress-block">
<label class="layui-form-label">上传进度</label>
<div class="layui-input-block">
<div class="layui-progress layui-progress-big" lay-showpercent="yes" lay-filter="upload-progress" style="top:10px;">
<div class="layui-progress-bar" lay-percent="0%"></div>
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">文件编号</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="file_id" value="{{ file_id }}" readonly="readonly" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
</div>
</div>
</form>
</div>
<div class="layui-tab-item">
<form class="layui-form kg-form" method="POST" action="{{ action_url }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>外链视频</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">视频时长</label>
<div class="layui-input-block">
<div class="layui-inline">
<select name="file_remote[duration][hours]">
{% for value in 0..10 %}
{% set selected = value == remote_duration.hours ? 'selected="selected"' : '' %}
<option value="{{ value }}" {{ selected }}>{{ value }}小时</option>
{% endfor %}
</select>
</div>
<div class="layui-inline">
<select name="file_remote[duration][minutes]">
{% for value in 0..59 %}
{% set selected = value == remote_duration.minutes ? 'selected="selected"' : '' %}
<option value="{{ value }}" {{ selected }}>{{ value }}分钟</option>
{% endfor %}
</select>
</div>
<div class="layui-inline">
<select name="file_remote[duration][seconds]">
{% for value in 0..59 %}
{% set selected = value == remote_duration.seconds ? 'selected="selected"' : '' %}
<option value="{{ value }}" {{ selected }}>{{ value }}秒</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">原画地址</label>
<div class="layui-inline" style="width:55%;">
<input id="tc-od-url" class="layui-input" type="text" name="file_remote[od][url]" value="{{ remote_play_urls.od.url }}" lay-verify="required">
</div>
{% if remote_play_urls.od.url %}
<div class="layui-inline">
<span class="layui-btn kg-preview" data-chapter-id="{{ chapter.id }}" data-play-url="{{ remote_play_urls.hd.url }}">预览</span>
<span class="layui-btn layui-btn-primary kg-copy" data-clipboard-target="#tc-od-url">复制</span>
</div>
{% endif %}
</div>
<div class="layui-form-item">
<label class="layui-form-label">高清地址</label>
<div class="layui-inline" style="width:55%;">
<input id="tc-hd-url" class="layui-input" type="text" name="file_remote[hd][url]" value="{{ remote_play_urls.hd.url }}">
</div>
{% if remote_play_urls.hd.url %}
<div class="layui-inline">
<span class="layui-btn kg-preview" data-chapter-id="{{ chapter.id }}" data-play-url="{{ remote_play_urls.hd.url }}">预览</span>
<span class="layui-btn layui-btn-primary kg-copy" data-clipboard-target="#tc-hd-url">复制</span>
</div>
{% endif %}
</div>
<div class="layui-form-item">
<label class="layui-form-label">标清地址</label>
<div class="layui-inline" style="width:55%;">
<input id="tc-sd-url" class="layui-input" type="text" name="file_remote[sd][url]" value="{{ remote_play_urls.sd.url }}">
</div>
{% if remote_play_urls.hd.url %}
<div class="layui-inline">
<span class="layui-btn kg-preview" data-chapter-id="{{ chapter.id }}" data-play-url="{{ remote_play_urls.hd.url }}">预览</span>
<span class="layui-btn layui-btn-primary kg-copy" data-clipboard-target="#tc-sd-url">复制</span>
</div>
{% endif %}
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
</div>
</div>
</form>
</div> </div>
</div> </div>
<div class="layui-form-item layui-hide" id="upload-progress-block"> </div>
<label class="layui-form-label">上传进度</label>
<div class="layui-input-block">
<div class="layui-progress layui-progress-big" lay-showpercent="yes" lay-filter="upload-progress" style="top:10px;">
<div class="layui-progress-bar" lay-percent="0%"></div>
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">文件编号</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="file_id" value="{{ file_id }}" readonly="readonly" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
</div>
</div>
</form>

View File

@ -68,7 +68,7 @@
<td><input type="checkbox" name="free" value="1" lay-skin="switch" lay-text="是|否" lay-filter="free" data-url="{{ update_url }}" {% if item.free == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="free" value="1" lay-skin="switch" lay-text="是|否" lay-filter="free" data-url="{{ update_url }}" {% if item.free == 1 %}checked="checked"{% endif %}></td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ preview_url }}" target="_blank">预览</a></li> <li><a href="{{ preview_url }}" target="_blank">预览</a></li>

View File

@ -46,7 +46,7 @@
<td><input type="checkbox" name="free" value="1" lay-skin="switch" lay-text="是|否" lay-filter="free" data-url="{{ update_url }}" {% if item.free == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="free" value="1" lay-skin="switch" lay-text="是|否" lay-filter="free" data-url="{{ update_url }}" {% if item.free == 1 %}checked="checked"{% endif %}></td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ edit_url }}">编辑</a></li> <li><a href="{{ edit_url }}">编辑</a></li>

View File

@ -46,7 +46,7 @@
<td><input type="checkbox" name="free" value="1" lay-skin="switch" lay-text="是|否" lay-filter="free" data-url="{{ update_url }}" {% if item.free == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="free" value="1" lay-skin="switch" lay-text="是|否" lay-filter="free" data-url="{{ update_url }}" {% if item.free == 1 %}checked="checked"{% endif %}></td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ preview_url }}" target="_blank">预览</a></li> <li><a href="{{ preview_url }}" target="_blank">预览</a></li>

View File

@ -68,7 +68,7 @@
<td><input type="checkbox" name="free" value="1" lay-skin="switch" lay-text="是|否" lay-filter="free" data-url="{{ update_url }}" {% if item.free == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="free" value="1" lay-skin="switch" lay-text="是|否" lay-filter="free" data-url="{{ update_url }}" {% if item.free == 1 %}checked="checked"{% endif %}></td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ preview_url }}" target="_blank">预览</a></li> <li><a href="{{ preview_url }}" target="_blank">预览</a></li>

View File

@ -73,7 +73,7 @@
</td> </td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ edit_url }}">编辑</a></li> <li><a href="{{ edit_url }}">编辑</a></li>

View File

@ -65,7 +65,7 @@
<td>{{ item.comment_count }}</td> <td>{{ item.comment_count }}</td>
<td><input class="layui-input kg-priority" type="text" name="priority" value="{{ item.priority }}" data-url="{{ update_url }}"></td> <td><input class="layui-input kg-priority" type="text" name="priority" value="{{ item.priority }}" data-url="{{ update_url }}"></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ edit_url }}">编辑</a></li> <li><a href="{{ edit_url }}">编辑</a></li>

View File

@ -95,7 +95,7 @@
<td><input type="checkbox" name="featured" value="1" lay-skin="switch" lay-text="是|否" lay-filter="featured" data-url="{{ update_url }}" {% if item.featured == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="featured" value="1" lay-skin="switch" lay-text="是|否" lay-filter="featured" data-url="{{ update_url }}" {% if item.featured == 1 %}checked="checked"{% endif %}></td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ preview_url }}" target="_blank">预览课程</a></li> <li><a href="{{ preview_url }}" target="_blank">预览课程</a></li>

View File

@ -61,7 +61,7 @@
<td>{{ schedules_info(item.schedules) }}</td> <td>{{ schedules_info(item.schedules) }}</td>
<td><input type="checkbox" name="published" value="1" lay-filter="published" lay-skin="switch" lay-text="是|否" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="published" value="1" lay-filter="published" lay-skin="switch" lay-text="是|否" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ edit_url }}">编辑</a></li> <li><a href="{{ edit_url }}">编辑</a></li>

View File

@ -51,7 +51,7 @@
<td class="center"><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td> <td class="center"><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td>
<td class="center"><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td class="center"><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ preview_url }}" target="_blank">预览</a></li> <li><a href="{{ preview_url }}" target="_blank">预览</a></li>

View File

@ -74,7 +74,7 @@
<td><a href="{{ users_url }}" class="layui-badge layui-bg-green">{{ item.user_count }}</a></td> <td><a href="{{ users_url }}" class="layui-badge layui-bg-green">{{ item.user_count }}</a></td>
<td><input type="checkbox" name="published" value="1" lay-filter="published" lay-skin="switch" lay-text="是|否" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="published" value="1" lay-filter="published" lay-skin="switch" lay-text="是|否" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ preview_url }}" target="_blank">预览</a></li> <li><a href="{{ preview_url }}" target="_blank">预览</a></li>

View File

@ -84,7 +84,7 @@
<td><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td> <td><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <span class="layui-icon layui-icon-triangle-d"></span></button> <button class="layui-btn layui-btn-sm">操作 <span class="layui-icon layui-icon-triangle-d"></span></button>
<ul> <ul>
<li><a href="{{ edit_url }}">编辑</a></li> <li><a href="{{ edit_url }}">编辑</a></li>

View File

@ -56,7 +56,7 @@
<td>{{ '¥%0.2f'|format(item.vip_price) }}</td> <td>{{ '¥%0.2f'|format(item.vip_price) }}</td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ edit_url }}">编辑</a></li> <li><a href="{{ edit_url }}">编辑</a></li>

View File

@ -50,7 +50,7 @@
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}> <td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}>
</td> </td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ preview_url }}" target="_blank">预览</a></li> <li><a href="{{ preview_url }}" target="_blank">预览</a></li>

View File

@ -66,7 +66,7 @@
<td><a class="layui-badge layui-bg-green" href="{{ redeem_url }}">{{ item.redeem_count }}</a></td> <td><a class="layui-badge layui-bg-green" href="{{ redeem_url }}">{{ item.redeem_count }}</a></td>
<td><input type="checkbox" name="published" value="1" lay-filter="published" lay-skin="switch" lay-text="是|否" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="published" value="1" lay-filter="published" lay-skin="switch" lay-text="是|否" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ preview_url }}" target="_blank">前台预览</a></li> <li><a href="{{ preview_url }}" target="_blank">前台预览</a></li>

View File

@ -16,9 +16,13 @@
{% endblock %} {% endblock %}
{% block inline_js %} {% block include_js %}
<script src="https://imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.3.js"></script> {{ js_include('lib/tc-player-2.4.0.js') }}
{% endblock %}
{% block inline_js %}
<script> <script>

View File

@ -4,6 +4,10 @@
<div id="player"></div> <div id="player"></div>
<div class="layui-hide">
<input type="hidden" name="play_url" value="{{ play_url }}">
</div>
{% endblock %} {% endblock %}
{% block inline_css %} {% block inline_css %}
@ -16,16 +20,24 @@
{% endblock %} {% endblock %}
{% block inline_js %} {% block include_js %}
<script src="https://imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.3.js"></script> {{ js_include('lib/tc-player-2.4.0.js') }}
{% endblock %}
{% block inline_js %}
<script> <script>
layui.use(['jquery'], function () { layui.use(['jquery'], function () {
var $ = layui.jquery;
var playUrl = $('input[name=play_url]').val();
new TcPlayer('player', { new TcPlayer('player', {
m3u8: '{{ play_url }}', m3u8: playUrl,
autoplay: false, autoplay: false,
width: 720, width: 720,
height: 405 height: 405

View File

@ -80,7 +80,7 @@
<td>{{ publish_status(item.published) }}</td> <td>{{ publish_status(item.published) }}</td>
<td><input type="checkbox" name="closed" value="1" lay-skin="switch" lay-text="是|否" lay-filter="closed" data-url="{{ update_url }}" {% if item.closed == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="closed" value="1" lay-skin="switch" lay-text="是|否" lay-filter="closed" data-url="{{ update_url }}" {% if item.closed == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
{% if item.published == 1 %} {% if item.published == 1 %}

View File

@ -63,7 +63,7 @@
</td> </td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ edit_url }}">编辑</a></li> <li><a href="{{ edit_url }}">编辑</a></li>

View File

@ -62,7 +62,7 @@
</a> </a>
</td> </td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
{% if item.id == 1 %} {% if item.id == 1 %}

View File

@ -32,29 +32,21 @@
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-inline"> <label class="layui-form-label">Logo</label>
<label class="layui-form-label">Logo</label> <div class="layui-inline" style="width:40%;">
<div class="kg-input-inline"> <input class="layui-input" type="text" name="logo" placeholder="请确保存储已正确配置" value="{{ site.logo }}">
<input class="layui-input" type="text" name="logo" placeholder="请确保存储已正确配置" value="{{ site.logo }}">
</div>
</div> </div>
<div class="layui-inline"> <div class="layui-inline">
<div class="kg-input-inline"> <button class="layui-btn" type="button" id="upload-logo">上传文件</button>
<button class="layui-btn" type="button" id="upload-logo">上传文件</button>
</div>
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-inline"> <label class="layui-form-label">Favicon</label>
<label class="layui-form-label">Favicon</label> <div class="layui-inline" style="width:40%;">
<div class="kg-input-inline"> <input class="layui-input" type="text" name="favicon" placeholder="请确保存储已正确配置" value="{{ site.favicon }}">
<input class="layui-input" type="text" name="favicon" placeholder="请确保存储已正确配置" value="{{ site.favicon }}">
</div>
</div> </div>
<div class="layui-inline"> <div class="layui-inline">
<div class="kg-input-inline"> <button class="layui-btn" type="button" id="upload-favicon">上传文件</button>
<button class="layui-btn" type="button" id="upload-favicon">上传文件</button>
</div>
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
@ -96,7 +88,7 @@
</div> </div>
<div class="layui-inline"> <div class="layui-inline">
<label class="layui-form-label">备案链接</label> <label class="layui-form-label">备案链接</label>
<div class="kg-input-inline"> <div class="kg-input-inline" style="width:500px;">
<input class="layui-input" type="text" name="icp_link" value="{{ site.icp_link }}"> <input class="layui-input" type="text" name="icp_link" value="{{ site.icp_link }}">
</div> </div>
</div> </div>
@ -110,7 +102,7 @@
</div> </div>
<div class="layui-inline"> <div class="layui-inline">
<label class="layui-form-label">备案链接</label> <label class="layui-form-label">备案链接</label>
<div class="kg-input-inline"> <div class="kg-input-inline" style="width:500px;">
<input class="layui-input" type="text" name="police_link" value="{{ site.police_link }}"> <input class="layui-input" type="text" name="police_link" value="{{ site.police_link }}">
</div> </div>
</div> </div>

View File

@ -58,7 +58,7 @@
<td><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td> <td><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td>
<td><input type="checkbox" name="published" value="1" lay-filter="published" lay-skin="switch" lay-text="是|否" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="published" value="1" lay-filter="published" lay-skin="switch" lay-text="是|否" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm"> 操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm"> 操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ edit_url }}">编辑</a></li> <li><a href="{{ edit_url }}">编辑</a></li>

View File

@ -83,7 +83,7 @@
{% endif %} {% endif %}
</td> </td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ edit_url }}">编辑学员</a></li> <li><a href="{{ edit_url }}">编辑学员</a></li>

View File

@ -59,7 +59,7 @@
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}> <td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}>
</td> </td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ edit_url }}">编辑</a></li> <li><a href="{{ edit_url }}">编辑</a></li>

View File

@ -8,7 +8,7 @@
<title>管理后台</title> <title>管理后台</title>
{{ icon_link('favicon.ico') }} {{ icon_link('favicon.ico') }}
{{ css_link('lib/layui/css/layui.css') }} {{ css_link('lib/layui/css/layui.css') }}
{{ css_link('lib/layui/extends/dropdown.css') }} {{ css_link('lib/layui/extends/kg-dropdown.css') }}
{{ css_link('admin/css/common.css') }} {{ css_link('admin/css/common.css') }}
{% block link_css %}{% endblock %} {% block link_css %}{% endblock %}
{% block inline_css %}{% endblock %} {% block inline_css %}{% endblock %}

View File

@ -57,7 +57,7 @@
<td>{{ date('Y-m-d H:i',item.update_time) }}</td> <td>{{ date('Y-m-d H:i',item.update_time) }}</td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td> <td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ preview_url }}" target="_blank">预览</a></li> <li><a href="{{ preview_url }}" target="_blank">预览</a></li>

View File

@ -79,7 +79,7 @@
<td>{{ date('Y-m-d',item.active_time) }}</td> <td>{{ date('Y-m-d',item.active_time) }}</td>
<td>{{ date('Y-m-d',item.create_time) }}</td> <td>{{ date('Y-m-d',item.create_time) }}</td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ preview_url }}" target="_blank">用户主页</a></li> <li><a href="{{ preview_url }}" target="_blank">用户主页</a></li>

View File

@ -10,20 +10,20 @@ use Phalcon\Mvc\View;
class Module implements ModuleDefinitionInterface class Module implements ModuleDefinitionInterface
{ {
public function registerAutoLoaders(DiInterface $di = null) public function registerAutoLoaders(DiInterface $dependencyInjector = null)
{ {
} }
public function registerServices(DiInterface $di) public function registerServices(DiInterface $dependencyInjector)
{ {
$di->setShared('view', function () { $dependencyInjector->setShared('view', function () {
$view = new View(); $view = new View();
$view->disable(); $view->disable();
return $view; return $view;
}); });
$di->setShared('auth', function () { $dependencyInjector->setShared('auth', function () {
return new AppAuth(); return new AppAuth();
}); });
} }

View File

@ -10,14 +10,14 @@ use Phalcon\Mvc\ModuleDefinitionInterface;
class Module implements ModuleDefinitionInterface class Module implements ModuleDefinitionInterface
{ {
public function registerAutoLoaders(DiInterface $di = null) public function registerAutoLoaders(DiInterface $dependencyInjector = null)
{ {
} }
public function registerServices(DiInterface $di) public function registerServices(DiInterface $dependencyInjector)
{ {
$di->setShared('view', function () { $dependencyInjector->setShared('view', function () {
$view = new MyView(); $view = new MyView();
$view->setViewsDir(__DIR__ . '/Views'); $view->setViewsDir(__DIR__ . '/Views');
$view->registerEngines([ $view->registerEngines([
@ -26,7 +26,7 @@ class Module implements ModuleDefinitionInterface
return $view; return $view;
}); });
$di->setShared('auth', function () { $dependencyInjector->setShared('auth', function () {
return new HomeAuth(); return new HomeAuth();
}); });
} }

View File

@ -71,7 +71,7 @@
{% block include_js %} {% block include_js %}
{{ js_include('https://imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.3.js', false) }} {{ js_include('lib/tc-player-2.4.0.js') }}
{{ js_include('home/js/chapter.live.player.js') }} {{ js_include('home/js/chapter.live.player.js') }}
{{ js_include('home/js/chapter.live.chat.js') }} {{ js_include('home/js/chapter.live.chat.js') }}
{{ js_include('home/js/chapter.show.js') }} {{ js_include('home/js/chapter.show.js') }}

View File

@ -57,7 +57,7 @@
{% block include_js %} {% block include_js %}
{{ js_include('https://imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.3.js', false) }} {{ js_include('lib/tc-player-2.4.0.js') }}
{{ js_include('home/js/course.share.js') }} {{ js_include('home/js/course.share.js') }}
{{ js_include('home/js/chapter.show.js') }} {{ js_include('home/js/chapter.show.js') }}
{{ js_include('home/js/chapter.vod.player.js') }} {{ js_include('home/js/chapter.vod.player.js') }}

View File

@ -4,7 +4,8 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>聊天记录</title> <title>聊天记录</title>
<link rel="stylesheet" href="/static/lib/layui/css/layui.css"> {{ css_link('lib/layui/css/layui.css') }}
{{ css_link('lib/layui/extends/layim/assets/layim.css') }}
<style> <style>
body .layim-chat-main { body .layim-chat-main {
height: auto; height: auto;
@ -34,15 +35,15 @@
}); %> }); %>
</textarea> </textarea>
<script src="/static/lib/layui/layui.js"></script> {{ js_include('lib/layui/layui.js') }}
<script> <script>
layui.use(['jquery', 'layim', 'laytpl', 'laypage'], function () {
layui.use(['jquery', 'laypage'], function () {
var $ = layui.jquery; var $ = layui.jquery;
var layim = layui.layim;
var laytpl = layui.laytpl;
var laypage = layui.laypage; var laypage = layui.laypage;
var laytpl = parent.layui.laytpl;
laytpl.config({ laytpl.config({
open: '<%', open: '<%',
@ -97,6 +98,7 @@
} }
}); });
</script> </script>
</body> </body>

View File

@ -24,7 +24,7 @@
<colgroup> <colgroup>
<col> <col>
<col> <col>
<col width="20%"> <col width="15%">
</colgroup> </colgroup>
<thead> <thead>
<tr> <tr>

View File

@ -54,7 +54,7 @@
<td>{{ item.comment_count }}</td> <td>{{ item.comment_count }}</td>
<td>{{ item.view_count }}</td> <td>{{ item.view_count }}</td>
<td class="center"> <td class="center">
<a href="{{ edit_url }}" class="layui-btn layui-btn-xs">编辑</a> <a href="{{ edit_url }}" class="layui-btn layui-btn-xs layui-bg-blue">编辑</a>
<a href="javascript:" class="layui-btn layui-btn-xs layui-bg-red kg-delete" data-url="{{ delete_url }}">删除</a> <a href="javascript:" class="layui-btn layui-btn-xs layui-bg-red kg-delete" data-url="{{ delete_url }}">删除</a>
</td> </td>
</tr> </tr>

View File

@ -51,7 +51,7 @@
<td>{{ item.answer_count }}</td> <td>{{ item.answer_count }}</td>
<td>{{ item.view_count }}</td> <td>{{ item.view_count }}</td>
<td class="center"> <td class="center">
<a href="{{ edit_url }}" class="layui-btn layui-btn-xs">编辑</a> <a href="{{ edit_url }}" class="layui-btn layui-btn-xs layui-bg-blue">编辑</a>
<a href="javascript:" class="layui-btn layui-btn-xs layui-bg-red kg-delete" data-url="{{ delete_url }}">删除</a> <a href="javascript:" class="layui-btn layui-btn-xs layui-bg-red kg-delete" data-url="{{ delete_url }}">删除</a>
</td> </td>
</tr> </tr>

View File

@ -41,7 +41,7 @@
<p class="rating">逻辑清晰:{{ "%0.1f"|format(item.rating3) }}</p> <p class="rating">逻辑清晰:{{ "%0.1f"|format(item.rating3) }}</p>
</td> </td>
<td> <td>
<button class="layui-btn layui-btn-xs btn-edit-review" data-url="{{ edit_url }}">修改</button> <button class="layui-btn layui-btn-xs layui-bg-blue btn-edit-review" data-url="{{ edit_url }}">修改</button>
<button class="layui-btn layui-btn-xs layui-bg-red kg-delete" data-url="{{ delete_url }}">删除</button> <button class="layui-btn layui-btn-xs layui-bg-red kg-delete" data-url="{{ delete_url }}">删除</button>
</td> </td>
</tr> </tr>

View File

@ -31,7 +31,7 @@ class Chapter extends Model
*/ */
protected $_vod_attrs = [ protected $_vod_attrs = [
'duration' => 0, 'duration' => 0,
'file' => ['id' => '', 'status' => self::FS_PENDING], 'file' => ['status' => self::FS_PENDING],
]; ];
/** /**

View File

@ -42,6 +42,13 @@ class ChapterVod extends Model
*/ */
public $file_transcode = []; public $file_transcode = [];
/**
* 远程资源
*
* @var array|string
*/
public $file_remote = [];
/** /**
* 创建时间 * 创建时间
* *
@ -67,6 +74,10 @@ class ChapterVod extends Model
$this->file_transcode = kg_json_encode($this->file_transcode); $this->file_transcode = kg_json_encode($this->file_transcode);
} }
if (is_array($this->file_remote) || is_object($this->file_remote)) {
$this->file_remote = kg_json_encode($this->file_remote);
}
$this->create_time = time(); $this->create_time = time();
} }
@ -76,6 +87,10 @@ class ChapterVod extends Model
$this->file_transcode = kg_json_encode($this->file_transcode); $this->file_transcode = kg_json_encode($this->file_transcode);
} }
if (is_array($this->file_remote) || is_object($this->file_remote)) {
$this->file_remote = kg_json_encode($this->file_remote);
}
$this->update_time = time(); $this->update_time = time();
} }
@ -85,6 +100,10 @@ class ChapterVod extends Model
$this->file_transcode = json_decode($this->file_transcode, true); $this->file_transcode = json_decode($this->file_transcode, true);
} }
if (is_string($this->file_remote)) {
$this->file_remote = json_decode($this->file_remote, true);
}
if (!empty($this->file_id) && empty($this->file_transcode)) { if (!empty($this->file_id) && empty($this->file_transcode)) {
$this->file_transcode = $this->getFileTranscode($this->file_id); $this->file_transcode = $this->getFileTranscode($this->file_id);
} }

View File

@ -29,161 +29,161 @@ class User extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 名称 * 名称
* *
* @var string * @var string
*/ */
public $name; public $name = '';
/** /**
* 头像 * 头像
* *
* @var string * @var string
*/ */
public $avatar; public $avatar = '';
/** /**
* 头衔 * 头衔
* *
* @var string * @var string
*/ */
public $title; public $title = '';
/** /**
* 介绍 * 介绍
* *
* @var string * @var string
*/ */
public $about; public $about = '';
/** /**
* 地区 * 地区
* *
* @var string * @var string
*/ */
public $area; public $area = '';
/** /**
* 性别 * 性别
* *
* @var int * @var int
*/ */
public $gender; public $gender = self::GENDER_NONE;
/** /**
* 会员标识 * 会员标识
* *
* @var int * @var int
*/ */
public $vip; public $vip = 0;
/** /**
* 锁定标识 * 锁定标识
* *
* @var int * @var int
*/ */
public $locked; public $locked = 0;
/** /**
* 删除标识 * 删除标识
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 教学角色 * 教学角色
* *
* @var int * @var int
*/ */
public $edu_role; public $edu_role = self::EDU_ROLE_STUDENT;
/** /**
* 后台角色 * 后台角色
* *
* @var int * @var int
*/ */
public $admin_role; public $admin_role = 0;
/** /**
* 课程数 * 课程数
* *
* @var int * @var int
*/ */
public $course_count; public $course_count = 0;
/** /**
* 文章数 * 文章数
* *
* @var int * @var int
*/ */
public $article_count; public $article_count = 0;
/** /**
* 提问数 * 提问数
* *
* @var int * @var int
*/ */
public $question_count; public $question_count = 0;
/** /**
* 回答数 * 回答数
* *
* @var int * @var int
*/ */
public $answer_count; public $answer_count = 0;
/** /**
* 评论数 * 评论数
* *
* @var int * @var int
*/ */
public $comment_count; public $comment_count = 0;
/** /**
* 收藏数 * 收藏数
* *
* @var int * @var int
*/ */
public $favorite_count; public $favorite_count = 0;
/** /**
* 会员期限 * 会员期限
* *
* @var int * @var int
*/ */
public $vip_expiry_time; public $vip_expiry_time = 0;
/** /**
* 锁定期限 * 锁定期限
* *
* @var int * @var int
*/ */
public $lock_expiry_time; public $lock_expiry_time = 0;
/** /**
* 活跃时间 * 活跃时间
* *
* @var int * @var int
*/ */
public $active_time; public $active_time = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {

View File

@ -2,10 +2,10 @@
namespace App\Providers; namespace App\Providers;
use Phalcon\Di\Injectable;
use Phalcon\DiInterface; use Phalcon\DiInterface;
use Phalcon\Mvc\User\Component;
abstract class Provider extends Component implements ProviderInterface abstract class Provider extends Injectable implements ProviderInterface
{ {
/** /**

View File

@ -2,9 +2,9 @@
namespace App\Repos; namespace App\Repos;
use Phalcon\Mvc\User\Component; use Phalcon\Di\Injectable;
class Repository extends Component class Repository extends Injectable
{ {
} }

View File

@ -14,6 +14,24 @@ class ChapterVod extends Service
$vod = $chapterRepo->findChapterVod($chapterId); $vod = $chapterRepo->findChapterVod($chapterId);
/**
* 腾讯云点播优先
*/
if ($vod->file_id) {
$result = $this->getCosPlayUrls($chapterId);
} else {
$result = $this->getRemotePlayUrls($chapterId);
}
return $result;
}
public function getCosPlayUrls($chapterId)
{
$chapterRepo = new ChapterRepo();
$vod = $chapterRepo->findChapterVod($chapterId);
if (empty($vod->file_transcode)) return []; if (empty($vod->file_transcode)) return [];
$vodService = new VodService(); $vodService = new VodService();
@ -21,9 +39,28 @@ class ChapterVod extends Service
$result = []; $result = [];
foreach ($vod->file_transcode as $key => $file) { foreach ($vod->file_transcode as $key => $file) {
$file['url'] = $vodService->getPlayUrl($file['url']); $url = $vodService->getPlayUrl($file['url']);
$type = $this->getDefinitionType($file['height']); $type = $this->getDefinitionType($file['height']);
$result[$type] = $file; $result[$type] = ['url' => $url];
}
return $result;
}
public function getRemotePlayUrls($chapterId)
{
$chapterRepo = new ChapterRepo();
$vod = $chapterRepo->findChapterVod($chapterId);
$result = [
'od' => ['url' => ''],
'hd' => ['url' => ''],
'sd' => ['url' => ''],
];
if (!empty($vod->file_remote)) {
$result = $vod->file_remote;
} }
return $result; return $result;

View File

@ -5,9 +5,9 @@ namespace App\Services\Search;
use App\Models\Article as ArticleModel; use App\Models\Article as ArticleModel;
use App\Repos\Category as CategoryRepo; use App\Repos\Category as CategoryRepo;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use Phalcon\Mvc\User\Component; use Phalcon\Di\Injectable;
class ArticleDocument extends Component class ArticleDocument extends Injectable
{ {
/** /**

View File

@ -5,9 +5,9 @@ namespace App\Services\Search;
use App\Models\Category as CategoryModel; use App\Models\Category as CategoryModel;
use App\Models\Course as CourseModel; use App\Models\Course as CourseModel;
use App\Models\User as UserModel; use App\Models\User as UserModel;
use Phalcon\Mvc\User\Component; use Phalcon\Di\Injectable;
class CourseDocument extends Component class CourseDocument extends Injectable
{ {
/** /**

View File

@ -4,9 +4,9 @@ namespace App\Services\Search;
use App\Models\ImGroup as GroupModel; use App\Models\ImGroup as GroupModel;
use App\Models\User as UserModel; use App\Models\User as UserModel;
use Phalcon\Mvc\User\Component; use Phalcon\Di\Injectable;
class GroupDocument extends Component class GroupDocument extends Injectable
{ {
/** /**

View File

@ -6,9 +6,9 @@ use App\Models\Question as QuestionModel;
use App\Repos\Answer as AnswerRepo; use App\Repos\Answer as AnswerRepo;
use App\Repos\Category as CategoryRepo; use App\Repos\Category as CategoryRepo;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use Phalcon\Mvc\User\Component; use Phalcon\Di\Injectable;
class QuestionDocument extends Component class QuestionDocument extends Injectable
{ {
/** /**

View File

@ -2,9 +2,9 @@
namespace App\Services\Search; namespace App\Services\Search;
use Phalcon\Mvc\User\Component; use Phalcon\Di\Injectable;
abstract class Searcher extends Component abstract class Searcher extends Injectable
{ {
/** /**

View File

@ -3,9 +3,9 @@
namespace App\Services\Search; namespace App\Services\Search;
use App\Models\User as UserModel; use App\Models\User as UserModel;
use Phalcon\Mvc\User\Component; use Phalcon\Di\Injectable;
class UserDocument extends Component class UserDocument extends Injectable
{ {
/** /**

View File

@ -19,4 +19,35 @@ class ChapterVod extends Validator
return $value; return $value;
} }
public function checkDuration($duration)
{
$value = $value = $this->filter->sanitize($duration, ['trim', 'int']);
if ($value < 10 || $value > 10 * 3600) {
throw new BadRequestException('chapter_vod.invalid_duration');
}
return $value;
}
public function checkFileUrl($url)
{
$value = $this->filter->sanitize($url, ['trim', 'string']);
if (!CommonValidator::url($value)) {
throw new BadRequestException('chapter_vod.invalid_file_url');
}
$ext = strtolower(pathinfo($url, PATHINFO_EXTENSION));
/**
* 点播只支持mp4,m3u8格式
*/
if (!in_array($ext, ['mp4', 'm3u8'])) {
throw new BadRequestException('chapter_vod.invalid_file_ext');
}
return $value;
}
} }

View File

@ -4,9 +4,9 @@ namespace App\Validators;
use App\Exceptions\Forbidden as ForbiddenException; use App\Exceptions\Forbidden as ForbiddenException;
use App\Exceptions\Unauthorized as UnauthorizedException; use App\Exceptions\Unauthorized as UnauthorizedException;
use Phalcon\Mvc\User\Component; use Phalcon\Di\Injectable;
class Validator extends Component class Validator extends Injectable
{ {
public function checkAuthUser($userId) public function checkAuthUser($userId)

View File

@ -4,10 +4,10 @@ namespace Bootstrap;
use App\Library\Logger as AppLogger; use App\Library\Logger as AppLogger;
use Phalcon\Config as PhConfig; use Phalcon\Config as PhConfig;
use Phalcon\Di\Injectable;
use Phalcon\Logger\Adapter\File as PhLogger; use Phalcon\Logger\Adapter\File as PhLogger;
use Phalcon\Mvc\User\Component;
class ConsoleErrorHandler extends Component class ConsoleErrorHandler extends Injectable
{ {
public function __construct() public function __construct()

View File

@ -9,9 +9,9 @@ use App\Exceptions\ServiceUnavailable as ServiceUnavailableException;
use App\Exceptions\Unauthorized as UnauthorizedException; use App\Exceptions\Unauthorized as UnauthorizedException;
use App\Library\Logger as AppLogger; use App\Library\Logger as AppLogger;
use Phalcon\Config; use Phalcon\Config;
use Phalcon\Mvc\User\Component; use Phalcon\Di\Injectable;
class HttpErrorHandler extends Component class HttpErrorHandler extends Injectable
{ {
public function __construct() public function __construct()

76
composer.lock generated
View File

@ -15,16 +15,16 @@
"reference": "3e9d791b67d0a2912922b7b7c7312f4b37af41e4" "reference": "3e9d791b67d0a2912922b7b7c7312f4b37af41e4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/3e9d791b67d0a2912922b7b7c7312f4b37af41e4", "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/3e9d791b67d0a2912922b7b7c7312f4b37af41e4",
"reference": "3e9d791b67d0a2912922b7b7c7312f4b37af41e4", "reference": "3e9d791b67d0a2912922b7b7c7312f4b37af41e4",
"shasum": "", "shasum": "",
"mirrors": [ "mirrors": [
{ {
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true "preferred": true
} }
] ]
}, },
"require": { "require": {
"dasprid/enum": "^1.0.3", "dasprid/enum": "^1.0.3",
@ -1199,16 +1199,16 @@
"name": "Ashot Khanamiryan", "name": "Ashot Khanamiryan",
"email": "a.khanamiryan@gmail.com", "email": "a.khanamiryan@gmail.com",
"homepage": "https://github.com/khanamiryan", "homepage": "https://github.com/khanamiryan",
"role": "Developer" "role": "Developer"
} }
], ],
"description": "QR code decoder / reader", "description": "QR code decoder / reader",
"homepage": "https://github.com/khanamiryan/php-qrcode-detector-decoder/", "homepage": "https://github.com/khanamiryan/php-qrcode-detector-decoder/",
"keywords": [ "keywords": [
"barcode", "barcode",
"qr", "qr",
"zxing" "zxing"
], ],
"support": { "support": {
"issues": "https://github.com/khanamiryan/php-qrcode-detector-decoder/issues", "issues": "https://github.com/khanamiryan/php-qrcode-detector-decoder/issues",
"source": "https://github.com/khanamiryan/php-qrcode-detector-decoder/tree/1.0.4" "source": "https://github.com/khanamiryan/php-qrcode-detector-decoder/tree/1.0.4"
@ -1333,16 +1333,16 @@
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/1cb1cde8e8dd0f70cc0fe51354a59acad9302084", "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1cb1cde8e8dd0f70cc0fe51354a59acad9302084",
"reference": "1cb1cde8e8dd0f70cc0fe51354a59acad9302084", "reference": "1cb1cde8e8dd0f70cc0fe51354a59acad9302084",
"shasum": "", "shasum": "",
"mirrors": [ "mirrors": [
{ {
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true "preferred": true
} }
] ]
}, },
"require": { "require": {
"php": ">=7.2", "php": ">=7.2",
"psr/log": "^1.0.1" "psr/log": "^1.0.1"
}, },
@ -5348,15 +5348,15 @@
"homepage": "http://riimu.net" "homepage": "http://riimu.net"
} }
], ],
"description": "Highly customizable alternative to var_export for PHP code generation", "description": "Highly customizable alternative to var_export for PHP code generation",
"homepage": "http://kit.riimu.net", "homepage": "http://kit.riimu.net",
"keywords": [ "keywords": [
"code", "code",
"encoder", "encoder",
"export", "export",
"generator", "generator",
"variable" "variable"
], ],
"support": { "support": {
"issues": "https://github.com/Riimu/Kit-PHPEncoder/issues", "issues": "https://github.com/Riimu/Kit-PHPEncoder/issues",
"source": "https://github.com/Riimu/Kit-PHPEncoder/tree/v2.4.1" "source": "https://github.com/Riimu/Kit-PHPEncoder/tree/v2.4.1"
@ -5377,5 +5377,5 @@
"ext-fileinfo": "*" "ext-fileinfo": "*"
}, },
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "2.0.0" "plugin-api-version": "2.0.0"
} }

View File

@ -110,7 +110,7 @@ $error['nav.has_child_node'] = '不允许相关操作(存在子节点)';
/** /**
* 文章相关 * 文章相关
*/ */
$error['article.not_found'] = '课程不存在'; $error['article.not_found'] = '文章不存在';
$error['article.title_too_short'] = '标题太短少于5个字符'; $error['article.title_too_short'] = '标题太短少于5个字符';
$error['article.title_too_long'] = '标题太长多于50个字符'; $error['article.title_too_long'] = '标题太长多于50个字符';
$error['article.content_too_short'] = '内容太短少于10个字符'; $error['article.content_too_short'] = '内容太短少于10个字符';
@ -254,6 +254,8 @@ $error['chapter.child_existed'] = '不允许相关操作(存在子章节)';
*/ */
$error['chapter_vod.not_found'] = '点播资源不存在'; $error['chapter_vod.not_found'] = '点播资源不存在';
$error['chapter_vod.invalid_file_id'] = '无效的文件编号'; $error['chapter_vod.invalid_file_id'] = '无效的文件编号';
$error['chapter_vod.invalid_file_url'] = '无效的文件地址';
$error['chapter_vod.invalid_file_ext'] = '无效的文件格式目前只支持mp4m3u8';
/** /**
* 直播相关 * 直播相关

View File

@ -0,0 +1,44 @@
<?php
use Phinx\Migration\AbstractMigration;
final class V20210610034658 extends AbstractMigration
{
public function up()
{
$this->modifyChapterVodTable();
$this->handleVodFileRemote();
}
public function down()
{
$this->table('kg_chapter_vod')
->removeColumn('file_remote')
->save();
}
protected function modifyChapterVodTable()
{
$this->table('kg_chapter_vod')
->addColumn('file_remote', 'string', [
'null' => false,
'default' => '',
'limit' => 1500,
'collation' => 'utf8mb4_general_ci',
'encoding' => 'utf8mb4',
'comment' => '远程文件',
'after' => 'file_transcode',
])->save();
}
protected function handleVodFileRemote()
{
$this->getQueryBuilder()
->update('kg_chapter_vod')
->set('file_remote', '[]')
->where(['file_remote' => ''])
->execute();
}
}

View File

@ -1,10 +1,10 @@
layui.config({ layui.config({
base: '/static/lib/layui/extends/' base: '/static/lib/layui/extends/'
}).extend({ }).extend({
dropdown: 'dropdown' kgDropdown: 'kg-dropdown'
}); });
layui.use(['jquery', 'form', 'element', 'layer', 'dropdown'], function () { layui.use(['jquery', 'form', 'element', 'layer', 'kgDropdown'], function () {
var $ = layui.jquery; var $ = layui.jquery;
var form = layui.form; var form = layui.form;

View File

@ -1,7 +1,9 @@
layui.config({ layui.config({
base: '/static/lib/layui/extends/' base: '/static/lib/layui/extends/',
layimAssetsPath: '/static/lib/layui/extends/layim/assets/',
}).extend({ }).extend({
helper: 'helper' layim: 'layim/layim',
helper: 'helper',
}); });
layui.use(['jquery', 'form', 'element', 'layer', 'helper'], function () { layui.use(['jquery', 'form', 'element', 'layer', 'helper'], function () {

BIN
public/static/lib/layui.zip Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1 @@
/** layui-v2.5.6 MIT License By https://www.layui.com */ html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #eee;border-left-width:6px;background-color:#FAFAFA;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:40px;line-height:40px;border-bottom:1px solid #eee}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 10px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view .layui-code-ol li:first-child{padding-top:10px}.layui-code-view .layui-code-ol li:last-child{padding-bottom:10px}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none}.layui-code-demo .layui-code{visibility:visible!important;margin:-15px;border-top:none;border-right:none;border-bottom:none}.layui-code-demo .layui-tab-content{padding:15px;border-top:none}
html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #e2e2e2;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:32px;line-height:32px;border-bottom:1px solid #e2e2e2}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 5px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -1,11 +0,0 @@
/*dropdown*/
.layui-dropdown {display: inline-block;position: relative;font-size: 14px;}
.layui-dropdown>ul {position: absolute;display: none;top:100%;left:0px;padding: 5px 0;margin:5px 0;white-space: nowrap;line-height: 36px;box-shadow: 0 2px 4px rgba(0,0,0,.12);border: 1px solid #d2d2d2;background-color: #fff;border-radius: 2px;z-index: 900;}
.layui-dropdown>ul>h4 {color: #999;display: block;padding: 0 20px;font-size: 12px;}
.layui-dropdown>ul>li {position: relative;}
.layui-dropdown>ul>li>a {color: #333;display: block;padding: 0 20px;transition: all .3s;-webkit-transition: all .3s;}
.layui-dropdown>ul>li>a>i {font-size: 14px;margin-right:5px;}
.layui-dropdown>ul>li>a:hover {background-color: #f2f2f2;color: #000;}
.layui-dropdown.dropdown-right>ul {left:auto;right:0px;}
.layui-dropdown>ul>li.dropdown-item-disabled>a{color: #999;cursor:not-allowed;}
.layui-dropdown>ul>li.dropdown-item-disabled>a:hover{color: #999;background-color:transparent;}

View File

@ -0,0 +1,66 @@
/*dropdown*/
.kg-dropdown {
display: inline-block;
position: relative;
font-size: 14px;
}
.kg-dropdown > ul {
position: absolute;
display: none;
top: 100%;
left: 0px;
padding: 5px 0;
margin: 5px 0;
white-space: nowrap;
line-height: 36px;
box-shadow: 0 2px 4px rgba(0, 0, 0, .12);
border: 1px solid #d2d2d2;
background-color: #fff;
border-radius: 2px;
z-index: 900;
}
.kg-dropdown > ul > h4 {
color: #999;
display: block;
padding: 0 20px;
font-size: 12px;
}
.kg-dropdown > ul > li {
position: relative;
}
.kg-dropdown > ul > li > a {
color: #333;
display: block;
padding: 0 20px;
transition: all .3s;
-webkit-transition: all .3s;
}
.kg-dropdown > ul > li > a > i {
font-size: 14px;
margin-right: 5px;
}
.kg-dropdown > ul > li > a:hover {
background-color: #f2f2f2;
color: #000;
}
.kg-dropdown.dropdown-right > ul {
left: auto;
right: 0px;
}
.kg-dropdown > ul > li.dropdown-item-disabled > a {
color: #999;
cursor: not-allowed;
}
.kg-dropdown > ul > li.dropdown-item-disabled > a:hover {
color: #999;
background-color: transparent;
}

View File

@ -4,8 +4,8 @@
layui.define(['jquery'], function (exports) { layui.define(['jquery'], function (exports) {
var MOD_NAME = 'dropdown', var MOD_NAME = 'kgDropdown',
CLASS_NAME = '.layui-dropdown', CLASS_NAME = '.kg-dropdown',
$ = layui.jquery; $ = layui.jquery;
var dropdown = { var dropdown = {
@ -58,4 +58,4 @@ layui.define(['jquery'], function (exports) {
//输出接口 //输出接口
exports(MOD_NAME, dropdown); exports(MOD_NAME, dropdown);
}); });

View File

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>聊天记录</title> <title>聊天记录</title>
<link rel="stylesheet" href="http://local.res.layui.com/layui/src/css/layui.css"> <link rel="stylesheet" href="//unpkg.com/layui/dist/css/layui.css">
<style> <style>
body .layim-chat-main { body .layim-chat-main {
height: auto; height: auto;
@ -23,7 +23,7 @@
<textarea title="消息模版" id="LAY_tpl" style="display:none;"> <textarea title="消息模版" id="LAY_tpl" style="display:none;">
{{# layui.each(d.data, function(index, item){ {{# layui.each(d.data, function(index, item){
if(item.id == parent.layui.layim.cache().mine.id){ }} if(item.id == layui.layim.cache().mine.id){ }}
<li class="layim-chat-mine"><div class="layim-chat-user"><img src="{{ item.avatar }}"><cite><i>{{ layui.data.date(item.timestamp) }}</i>{{ item.username }}</cite></div><div class="layim-chat-text">{{ layui.layim.content(item.content) }}</div></li> <li class="layim-chat-mine"><div class="layim-chat-user"><img src="{{ item.avatar }}"><cite><i>{{ layui.data.date(item.timestamp) }}</i>{{ item.username }}</cite></div><div class="layim-chat-text">{{ layui.layim.content(item.content) }}</div></li>
{{# } else { }} {{# } else { }}
<li><div class="layim-chat-user"><img src="{{ item.avatar }}"><cite>{{ item.username }}<i>{{ layui.data.date(item.timestamp) }}</i></cite></div><div class="layim-chat-text">{{ layui.layim.content(item.content) }}</div></li> <li><div class="layim-chat-user"><img src="{{ item.avatar }}"><cite>{{ item.username }}<i>{{ layui.data.date(item.timestamp) }}</i></cite></div><div class="layim-chat-text">{{ layui.layim.content(item.content) }}</div></li>
@ -32,22 +32,24 @@
</textarea> </textarea>
<!-- <!--
上述模版采用了 laytpl 语法不了解的同学可以去看下文档http://www.layui.com/doc/modules/laytpl.html 上述模版采用了 laytpl 语法
--> -->
<script src="http://local.res.layui.com/layui/src/layui.js"></script> <script src="//unpkg.com/layui/dist/layui.js"></script>
<script> <script>
layui.use(['layim', 'laypage'], function () { layui.link('../layim.css', 'skinlayimcss') //加载 css
var layim = layui.layim layui.config({
, layer = layui.layer layimPath: '../../' //配置 layim.js 所在目录
, laytpl = layui.laytpl , layimAssetsPath: '../../layim-assets/' //layim 资源文件所在目录
}).use(['jquery'], function () {
var layim = parent.layui.layim
, laytpl = parent.layui.laytpl
, $ = layui.jquery , $ = layui.jquery
, laypage = layui.laypage; , laypage = parent.layui.laypage;
//聊天记录的分页此处不做演示你可以采用laypage不了解的同学见文档http://www.layui.com/doc/modules/laypage.html
//聊天记录的分页此处不做演示,你可以采用 laypage
//开始请求聊天记录 //开始请求聊天记录
var param = location.search //获得URL参数。该窗口url会携带会话id和type他们是你请求聊天记录的重要凭据 var param = location.search //获得URL参数。该窗口url会携带会话id和type他们是你请求聊天记录的重要凭据
@ -59,27 +61,27 @@
, data: [{ , data: [{
username: '纸飞机' username: '纸飞机'
, id: 100000 , id: 100000
, avatar: 'http://tva3.sinaimg.cn/crop.0.0.512.512.180/8693225ajw8f2rt20ptykj20e80e8weu.jpg' , avatar: '' || layui.cache.layimAssetsPath + 'images/default.png'
, timestamp: 1480897882000 , timestamp: 1480897882000
, content: 'face[抱抱] face[心] 你好啊小美女' , content: '我方模拟记录111'
}, { }, {
username: 'Z_子晴' username: 'test123'
, id: 108101 , id: 108101
, avatar: 'http://tva3.sinaimg.cn/crop.0.0.512.512.180/8693225ajw8f2rt20ptykj20e80e8weu.jpg' , avatar: '' || layui.cache.layimAssetsPath + 'images/default.png'
, timestamp: 1480897892000 , timestamp: 1480897892000
, content: '你没发错吧face[微笑]' , content: '对方模拟记录111'
}, { }, {
username: 'Z_子晴' username: 'test123'
, id: 108101 , id: 108101
, avatar: 'http://tva3.sinaimg.cn/crop.0.0.512.512.180/8693225ajw8f2rt20ptykj20e80e8weu.jpg' , avatar: '' || layui.cache.layimAssetsPath + 'images/default.png'
, timestamp: 1480897898000 , timestamp: 1480897898000
, content: '你是谁呀亲。。我爱的是贤心!我爱的是贤心!我爱的是贤心!重要的事情要说三遍~' , content: '对方模拟记录222'
}, { }, {
username: 'Z_子晴' username: 'test123'
, id: 108101 , id: 108101
, avatar: 'http://tva3.sinaimg.cn/crop.0.0.512.512.180/8693225ajw8f2rt20ptykj20e80e8weu.jpg' , avatar: '' || layui.cache.layimAssetsPath + 'images/default.png'
, timestamp: 1480897908000 , timestamp: 1480897908000
, content: '注意:这些都是模拟数据,实际使用时,需将其中的模拟接口改为你的项目真实接口。\n该模版文件所在目录相对于layui.js\n/css/modules/layim/html/chatlog.html' , content: '注意:这些都是模拟数据,实际使用时,需将其中的模拟接口改为你的项目真实接口。\n该模版文件所在目录相对于layim.js\n/layim-assets/html/chatlog.html'
}] }]
} }

View File

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>发现</title> <title>发现</title>
<link rel="stylesheet" href="http://local.res.layui.com/layui/src/css/layui.css"> <link rel="stylesheet" href="//unpkg.com/layui/dist/css/layui.css">
<style> <style>
</style> </style>
@ -14,14 +14,19 @@
<div style="margin: 15px;"> <div style="margin: 15px;">
<blockquote class="layui-elem-quote">此为自定义的【查找】页面,因需求不一,所以官方暂不提供该模版结构与样式,实际使用时,可移至该文件到你的项目中,对页面自行把控。 <blockquote class="layui-elem-quote">此为自定义的【查找】页面,因需求不一,所以官方暂不提供该模版结构与样式,实际使用时,可移至该文件到你的项目中,对页面自行把控。
<br>文件所在目录相对于layui.js/css/modules/layim/html/find.html <br>文件所在目录相对于layui.js/layim-assets/html/find.html
</blockquote> </blockquote>
</div> </div>
<script src="http://local.res.layui.com/layui/src/layui.js"></script> <script src="//unpkg.com/layui/dist/layui.js"></script>
<script> <script>
layui.use(['layim', 'laypage'], function () { layui.config({
layimPath: '../../' //配置 layim.js 所在目录
, layimAssetsPath: '../../layim-assets/' //layim 资源文件所在目录
}).extend({
layim: layui.cache.layimPath + 'layim' //配置 layim 组件所在的路径
}).use(['layim', 'laypage'], function () {
var layim = layui.layim var layim = layui.layim
, layer = layui.layer , layer = layui.layer
, laytpl = layui.laytpl , laytpl = layui.laytpl

View File

@ -9,14 +9,14 @@
"from": 166488, "from": 166488,
"from_group": 0, "from_group": 0,
"type": 1, "type": 1,
"remark": "有问题要问", "remark": "test1",
"href": null, "href": null,
"read": 1, "read": 1,
"time": "刚刚", "time": "刚刚",
"user": { "user": {
"id": 166488, "id": 166488,
"avatar": "http://q.qlogo.cn/qqapp/101235792/B704597964F9BD0DB648292D1B09F7E8/100", "avatar": "http://q.qlogo.cn/qqapp/101235792/B704597964F9BD0DB648292D1B09F7E8/100",
"username": "李彦宏", "username": "测试111",
"sign": null "sign": null
} }
}, },
@ -27,20 +27,20 @@
"from": 347592, "from": 347592,
"from_group": 0, "from_group": 0,
"type": 1, "type": 1,
"remark": "你好啊!", "remark": "test2",
"href": null, "href": null,
"read": 1, "read": 1,
"time": "刚刚", "time": "刚刚",
"user": { "user": {
"id": 347592, "id": 347592,
"avatar": "http://q.qlogo.cn/qqapp/101235792/B78751375E0531675B1272AD994BA875/100", "avatar": "http://q.qlogo.cn/qqapp/101235792/B78751375E0531675B1272AD994BA875/100",
"username": "麻花疼", "username": "测试222",
"sign": null "sign": null
} }
}, },
{ {
"id": 62, "id": 62,
"content": "雷军 拒绝了你的好友申请", "content": "测试333 拒绝了你的好友申请",
"uid": 168, "uid": 168,
"from": null, "from": null,
"from_group": null, "from_group": null,
@ -55,22 +55,7 @@
}, },
{ {
"id": 60, "id": 60,
"content": "马小云 已经同意你的好友申请", "content": "测试666 已经同意你的好友申请",
"uid": 168,
"from": null,
"from_group": null,
"type": 1,
"remark": null,
"href": null,
"read": 1,
"time": "10天前",
"user": {
"id": null
}
},
{
"id": 61,
"content": "贤心 已经同意你的好友申请",
"uid": 168, "uid": 168,
"from": null, "from": null,
"from_group": null, "from_group": null,

View File

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>消息盒子</title> <title>消息盒子</title>
<link rel="stylesheet" href="../../../layui.css?v=1"> <link rel="stylesheet" href="//unpkg.com/layui/dist/css/layui.css">
<style> <style>
.layim-msgbox { .layim-msgbox {
margin: 15px; margin: 15px;
@ -15,6 +15,7 @@
position: relative; position: relative;
margin-bottom: 10px; margin-bottom: 10px;
padding: 0 130px 10px 60px; padding: 0 130px 10px 60px;
padding-bottom: 10px;
line-height: 22px; line-height: 22px;
border-bottom: 1px dotted #e2e2e2; border-bottom: 1px dotted #e2e2e2;
} }
@ -76,7 +77,7 @@
<div style="margin: 0 15px;"> <div style="margin: 0 15px;">
<blockquote class="layui-elem-quote">注意:这些都是模拟数据,实际使用时,需将其中的模拟接口改为你的项目真实接口。 <blockquote class="layui-elem-quote">注意:这些都是模拟数据,实际使用时,需将其中的模拟接口改为你的项目真实接口。
<br>该模版文件所在目录相对于layui.js/css/modules/layim/html/msgbox.html <br>该模版文件所在目录(相对于 layim.js/html/msgbox.html
</blockquote> </blockquote>
</div> </div>
@ -109,13 +110,18 @@
</textarea> </textarea>
<!-- <!--
上述模版采用了 laytpl 语法不了解的同学可以去看下文档http://www.layui.com/doc/modules/laytpl.html 上述模版采用了 laytpl 语法
--> -->
<script src="../../../../layui.js?v=1"></script> <script src="//unpkg.com/layui/dist/layui.js"></script>
<script> <script>
layui.use(['layim', 'flow'], function () { layui.config({
layimPath: '../../' //配置 layim.js 所在目录
, layimAssetsPath: '../../layim-assets/' //layim 资源文件所在目录
}).extend({
layim: layui.cache.layimPath + 'layim' //配置 layim 组件所在的路径
}).use(['layim', 'flow'], function () {
var layim = layui.layim var layim = layui.layim
, layer = layui.layer , layer = layui.layer
, laytpl = layui.laytpl , laytpl = layui.laytpl
@ -233,15 +239,20 @@
, uid = li.data('uid'); , uid = li.data('uid');
layer.confirm('确定拒绝吗?', function (index) { layer.confirm('确定拒绝吗?', function (index) {
layer.close(index);
othis.parent().html('<em>已拒绝</em>');
/*
$.post('/im/refuseFriend', { $.post('/im/refuseFriend', {
uid: uid //对方用户ID uid: uid //对方用户ID
}, function (res) { }, function(res){
if (res.code != 0) { if(res.code != 0){
return layer.msg(res.msg); return layer.msg(res.msg);
} }
layer.close(index); layer.close(index);
othis.parent().html('<em>已拒绝</em>'); othis.parent().html('<em>已拒绝</em>');
}); });
*/
}); });
} }
}; };

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Some files were not shown because too many files have changed in this diff Show More