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

完成直播回调

This commit is contained in:
xiaochong0302 2020-08-30 19:56:20 +08:00
parent 065b910b33
commit c22417913a
21 changed files with 217 additions and 101 deletions

View File

@ -66,7 +66,8 @@ class VodEventTask extends Task
*/ */
$attrs = $chapter->attrs; $attrs = $chapter->attrs;
$attrs['file_status'] = ChapterModel::FS_TRANSLATING; $attrs['file']['status'] = ChapterModel::FS_TRANSLATING;
$attrs['duration'] = (int)$duration; $attrs['duration'] = (int)$duration;
$chapter->update(['attrs' => $attrs]); $chapter->update(['attrs' => $attrs]);
@ -118,7 +119,7 @@ class VodEventTask extends Task
*/ */
$attrs = $chapter->attrs; $attrs = $chapter->attrs;
$attrs['file_status'] = $fileStatus; $attrs['file']['status'] = $fileStatus;
$chapter->update(['attrs' => $attrs]); $chapter->update(['attrs' => $attrs]);
} }

View File

@ -181,20 +181,6 @@ class TestController extends Controller
$this->view->setVar('qrcode', $qrcode); $this->view->setVar('qrcode', $qrcode);
} }
/**
* @Get("/alipay/status", name="admin.test.alipay_status")
*/
public function alipayStatusAction()
{
$sn = $this->request->getQuery('sn');
$alipayTestService = new AlipayTestService();
$status = $alipayTestService->status($sn);
return $this->jsonSuccess(['status' => $status]);
}
/** /**
* @Get("/wxpay", name="admin.test.wxpay") * @Get("/wxpay", name="admin.test.wxpay")
*/ */
@ -219,6 +205,20 @@ class TestController extends Controller
$this->view->setVar('qrcode', $qrcode); $this->view->setVar('qrcode', $qrcode);
} }
/**
* @Get("/alipay/status", name="admin.test.alipay_status")
*/
public function alipayStatusAction()
{
$sn = $this->request->getQuery('sn');
$alipayTestService = new AlipayTestService();
$status = $alipayTestService->status($sn);
return $this->jsonSuccess(['status' => $status]);
}
/** /**
* @Get("/wxpay/status", name="admin.test.wxpay_status") * @Get("/wxpay/status", name="admin.test.wxpay_status")
*/ */

View File

@ -92,8 +92,8 @@ class ChapterContent extends Service
$attrs = $chapter->attrs; $attrs = $chapter->attrs;
$attrs['duration'] = 0; $attrs['duration'] = 0;
$attrs['file_id'] = $fileId;
$attrs['file_status'] = ChapterModel::FS_UPLOADED; $attrs['file']['status'] = ChapterModel::FS_UPLOADED;
$chapter->update(['attrs' => $attrs]); $chapter->update(['attrs' => $attrs]);

View File

@ -92,7 +92,7 @@
layer.open({ layer.open({
type: 2, type: 2,
title: '推流测试', title: '推流测试',
area: ['680px', '450px'], area: ['720px', '500px'],
content: [url, 'no'] content: [url, 'no']
}); });
}); });

View File

@ -47,7 +47,7 @@
<span><a href="{{ edit_url }}">{{ item.title }}</a></span> <span><a href="{{ edit_url }}">{{ item.title }}</a></span>
<span class="layui-badge layui-bg-green">课</span> <span class="layui-badge layui-bg-green">课</span>
</td> </td>
<td>{{ file_status(item.attrs['file_status']) }}</td> <td>{{ file_status(item.attrs['file']['status']) }}</td>
<td>{{ item.attrs['duration']|duration }}</td> <td>{{ item.attrs['duration']|duration }}</td>
<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="free" value="1" lay-skin="switch" lay-text="是|否" lay-filter="free" data-url="{{ update_url }}" {% if item.free == 1 %}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{% endif %}></td>

View File

@ -65,7 +65,7 @@
layer.open({ layer.open({
type: 2, type: 2,
title: '推流测试', title: '推流测试',
area: ['680px', '450px'], area: ['720px', '500px'],
content: [url, 'no'] content: [url, 'no']
}); });
}); });

View File

@ -2,6 +2,7 @@
namespace App\Http\Desktop\Controllers; namespace App\Http\Desktop\Controllers;
use App\Models\Course as CourseModel;
use App\Services\Frontend\Chapter\ChapterInfo as ChapterInfoService; use App\Services\Frontend\Chapter\ChapterInfo as ChapterInfoService;
use App\Services\Frontend\Chapter\ChapterLike as ChapterLikeService; use App\Services\Frontend\Chapter\ChapterLike as ChapterLikeService;
use App\Services\Frontend\Chapter\DanmuList as ChapterDanmuListService; use App\Services\Frontend\Chapter\DanmuList as ChapterDanmuListService;
@ -39,11 +40,11 @@ class ChapterController extends Controller
$this->seo->prependTitle(['章节', $chapter['title'], $chapter['course']['title']]); $this->seo->prependTitle(['章节', $chapter['title'], $chapter['course']['title']]);
$this->seo->setDescription($chapter['summary']); $this->seo->setDescription($chapter['summary']);
if ($chapter['model'] == 'vod') { if ($chapter['model'] == CourseModel::MODEL_VOD) {
$this->view->pick('chapter/vod'); $this->view->pick('chapter/vod');
} elseif ($chapter['model'] == 'live') { } elseif ($chapter['model'] == CourseModel::MODEL_LIVE) {
$this->view->pick('chapter/live'); $this->view->pick('chapter/live');
} elseif ($chapter['model'] == 'read') { } elseif ($chapter['model'] == CourseModel::MODEL_READ) {
$this->view->pick('chapter/read'); $this->view->pick('chapter/read');
} }

View File

@ -51,9 +51,7 @@ class LiveController extends Controller
$stats = $service->getStats($id); $stats = $service->getStats($id);
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW); return $this->jsonSuccess($stats);
$this->view->pick('chapter/live_stats');
$this->view->setVar('stats', $stats);
} }
/** /**

View File

@ -20,7 +20,7 @@
</span> </span>
<span class="share"> <span class="share">
<a href="javascript:" title="点赞" data-url="{{ like_url }}"><i class="layui-icon layui-icon-praise icon-praise"></i><em class="like-count">{{ chapter.like_count }}</em></a> <a href="javascript:" title="点赞" data-url="{{ like_url }}"><i class="layui-icon layui-icon-praise icon-praise"></i><em class="like-count">{{ chapter.like_count }}</em></a>
<a href="javascript:" title="在线人数"><i class="layui-icon layui-icon-user"></i><em>15</em></a> <a href="javascript:" title="在线人数"><i class="layui-icon layui-icon-user"></i><em>0</em></a>
<a href="javascript:" title="分享到微信" data-url=""><i class="layui-icon layui-icon-login-wechat icon-wechat"></i></a> <a href="javascript:" title="分享到微信" data-url=""><i class="layui-icon layui-icon-login-wechat icon-wechat"></i></a>
<a href="javascript:" title="分享到QQ空间"><i class="layui-icon layui-icon-login-qq icon-qq"></i></a> <a href="javascript:" title="分享到QQ空间"><i class="layui-icon layui-icon-login-qq icon-qq"></i></a>
<a href="javascript:" title="分享到微博"><i class="layui-icon layui-icon-login-weibo icon-weibo"></i></a> <a href="javascript:" title="分享到微博"><i class="layui-icon layui-icon-login-weibo icon-weibo"></i></a>
@ -56,6 +56,7 @@
<input type="hidden" name="chapter.plan_id" value="{{ chapter.me.plan_id }}"> <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.learning_url" value="{{ learning_url }}">
<input type="hidden" name="chapter.play_urls" value='{{ chapter.play_urls|json_encode }}'> <input type="hidden" name="chapter.play_urls" value='{{ chapter.play_urls|json_encode }}'>
<input type="hidden" name="live_stats_url" value='{{ live_stats_url }}'>
<input type="hidden" name="bind_user_url" value='{{ bind_user_url }}'> <input type="hidden" name="bind_user_url" value='{{ bind_user_url }}'>
</div> </div>

View File

@ -9,7 +9,7 @@
</p> </p>
{% elseif course.model == '2' %} {% elseif course.model == '2' %}
<p class="item"> <p class="item">
<span class="key">直播时间</span><span>{{ course.attrs.start_date }} ~ {{ course.attrs.end_date }}</span> <span class="key">直播时间</span><span class="value">{{ course.attrs.start_date }} ~ {{ course.attrs.end_date }}</span>
</p> </p>
{% endif %} {% endif %}
{% if course.market_price > 0 %} {% if course.market_price > 0 %}

View File

@ -17,6 +17,13 @@ class Chapter extends Model
const FS_TRANSLATED = 'translated'; // 已转码 const FS_TRANSLATED = 'translated'; // 已转码
const FS_FAILED = 'failed'; // 已失败 const FS_FAILED = 'failed'; // 已失败
/**
* 推流状态
*/
const SS_ACTIVE = 'active'; // 活跃
const SS_INACTIVE = 'inactive'; // 非活跃
const SS_FORBID = 'forbid'; // 禁播
/** /**
* @var array * @var array
* *
@ -24,8 +31,7 @@ class Chapter extends Model
*/ */
protected $_vod_attrs = [ protected $_vod_attrs = [
'duration' => 0, 'duration' => 0,
'file_id' => '', 'file' => ['id' => '', 'status' => self::FS_PENDING],
'file_status' => 'pending',
]; ];
/** /**
@ -36,6 +42,7 @@ class Chapter extends Model
protected $_live_attrs = [ protected $_live_attrs = [
'start_time' => 0, 'start_time' => 0,
'end_time' => 0, 'end_time' => 0,
'stream' => ['status' => self::SS_INACTIVE],
]; ];
/** /**

View File

@ -5,6 +5,13 @@ namespace App\Models;
class ChapterLive extends Model class ChapterLive extends Model
{ {
/**
* 状态类型
*/
const STATUS_ACTIVE = 1; // 活跃
const STATUS_INACTIVE = 2; // 非活跃
const STATUS_FORBID = 3; // 禁播
/** /**
* 主键编号 * 主键编号
* *
@ -47,6 +54,13 @@ class ChapterLive extends Model
*/ */
public $user_limit; public $user_limit;
/**
* 直播状态
*
* @var int
*/
public $status;
/** /**
* 创建时间 * 创建时间
* *

View File

@ -67,7 +67,7 @@ trait BasicInfoTrait
$liveService = new LiveService(); $liveService = new LiveService();
$stream = $this->getLiveStreamName($chapter->id); $stream = $this->getStreamName($chapter->id);
$format = $browserParser->isType('desktop') ? 'flv' : 'hls'; $format = $browserParser->isType('desktop') ? 'flv' : 'hls';

View File

@ -5,7 +5,7 @@ namespace App\Services\Frontend\Chapter;
trait ChapterLiveTrait trait ChapterLiveTrait
{ {
protected function getLiveStreamName($id) protected function getStreamName($id)
{ {
return "chapter_{$id}"; return "chapter_{$id}";
} }

View File

@ -21,7 +21,7 @@ class LivePushUrl extends FrontendService
$service = new LiveService(); $service = new LiveService();
$steamName = $this->getLiveStreamName($chapter->id); $steamName = $this->getStreamName($chapter->id);
return $service->getPushUrl($steamName); return $service->getPushUrl($steamName);
} }

View File

@ -2,6 +2,10 @@
namespace App\Services; namespace App\Services;
use App\Models\Chapter as ChapterModel;
use App\Models\ChapterLive as ChapterLiveModel;
use App\Repos\Chapter as ChapterRepo;
class LiveNotify extends Service class LiveNotify extends Service
{ {
@ -11,28 +15,27 @@ class LiveNotify extends Service
$sign = $this->request->getPost('sign'); $sign = $this->request->getPost('sign');
$type = $this->request->getQuery('action'); $type = $this->request->getQuery('action');
if (!$this->checkSign($time, $sign)) { if (!$this->checkSign($sign, $time)) {
return false; return false;
} }
$result = false;
switch ($type) { switch ($type) {
case 'streamBegin': case 'streamBegin':
$result = $this->streamBegin(); $result = $this->handleStreamBegin();
break; break;
case 'streamEnd': case 'streamEnd':
$result = $this->streamEnd(); $result = $this->handleStreamEnd();
break; break;
case 'record': case 'record':
$result = $this->record(); $result = $this->handleRecord();
break; break;
case 'snapshot': case 'snapshot':
$result = $this->snapshot(); $result = $this->handleSnapshot();
break; break;
case 'porn': case 'porn':
$result = $this->porn(); $result = $this->handlePorn();
break;
default:
$result = false;
break; break;
} }
@ -42,45 +45,98 @@ class LiveNotify extends Service
/** /**
* 推流 * 推流
*/ */
protected function streamBegin() protected function handleStreamBegin()
{ {
$steamId = $this->request->getPost('stream_id');
$chapter = $this->getChapter($steamId);
if (!$chapter) return false;
$attrs = $chapter->attrs;
$attrs['stream']['status'] = ChapterModel::SS_ACTIVE;
$chapter->update(['attrs' => $attrs]);
$chapterLive = $this->getChapterLive($chapter->id);
$chapterLive->update(['status' => ChapterLiveModel::STATUS_ACTIVE]);
/**
* @todo 发送直播通知
*/
return true;
} }
/** /**
* 断流 * 断流
*/ */
protected function streamEnd() protected function handleStreamEnd()
{
$steamId = $this->request->getPost('stream_id');
$chapter = $this->getChapter($steamId);
if (!$chapter) return false;
$attrs = $chapter->attrs;
$attrs['stream']['status'] = ChapterModel::SS_INACTIVE;
$chapter->update(['attrs' => $attrs]);
$chapterLive = $this->getChapterLive($chapter->id);
$chapterLive->update(['status' => ChapterLiveModel::STATUS_INACTIVE]);
return true;
}
/**
* 录制
*/
protected function handleRecord()
{ {
} }
/** /**
* 断流 * 截图
*/ */
protected function record() protected function handleSnapshot()
{ {
} }
/** /**
* 断流 * 鉴黄
*/ */
protected function snapshot() protected function handlePorn()
{ {
} }
/** protected function getChapter($streamId)
* 断流
*/
protected function porn()
{ {
$id = (int)str_replace('chapter_', '', $streamId);
$chapterRepo = new ChapterRepo();
return $chapterRepo->findById($id);
}
protected function getChapterLive($chapterId)
{
$chapterRepo = new ChapterRepo();
return $chapterRepo->findChapterLive($chapterId);
} }
/** /**
* 检查签名 * 检查签名
*
* @param string $sign * @param string $sign
* @param int $time * @param int $time
* @return bool * @return bool
@ -91,7 +147,7 @@ class LiveNotify extends Service
return false; return false;
} }
if ($time < time() + 600) { if ($time < time()) {
return false; return false;
} }

View File

@ -2,7 +2,7 @@
use Phinx\Db\Adapter\MysqlAdapter; use Phinx\Db\Adapter\MysqlAdapter;
class InitTable extends Phinx\Migration\AbstractMigration class InitDb extends Phinx\Migration\AbstractMigration
{ {
public function change() public function change()
{ {
@ -643,19 +643,12 @@ class InitTable extends Phinx\Migration\AbstractMigration
'comment' => '章节编号', 'comment' => '章节编号',
'after' => 'course_id', 'after' => 'course_id',
]) ])
->addColumn('user_limit', 'integer', [
'null' => false,
'default' => '100',
'limit' => MysqlAdapter::INT_REGULAR,
'comment' => '用户限额',
'after' => 'chapter_id',
])
->addColumn('start_time', 'integer', [ ->addColumn('start_time', 'integer', [
'null' => false, 'null' => false,
'default' => '0', 'default' => '0',
'limit' => MysqlAdapter::INT_REGULAR, 'limit' => MysqlAdapter::INT_REGULAR,
'comment' => '开始时间', 'comment' => '开始时间',
'after' => 'user_limit', 'after' => 'chapter_id',
]) ])
->addColumn('end_time', 'integer', [ ->addColumn('end_time', 'integer', [
'null' => false, 'null' => false,
@ -664,12 +657,26 @@ class InitTable extends Phinx\Migration\AbstractMigration
'comment' => '结束时间', 'comment' => '结束时间',
'after' => 'start_time', 'after' => 'start_time',
]) ])
->addColumn('user_limit', 'integer', [
'null' => false,
'default' => '100',
'limit' => MysqlAdapter::INT_REGULAR,
'comment' => '用户限额',
'after' => 'end_time',
])
->addColumn('status', 'integer', [
'null' => false,
'default' => '0',
'limit' => MysqlAdapter::INT_REGULAR,
'comment' => '状态标识',
'after' => 'user_limit',
])
->addColumn('create_time', 'integer', [ ->addColumn('create_time', 'integer', [
'null' => false, 'null' => false,
'default' => '0', 'default' => '0',
'limit' => MysqlAdapter::INT_REGULAR, 'limit' => MysqlAdapter::INT_REGULAR,
'comment' => '创建时间', 'comment' => '创建时间',
'after' => 'end_time', 'after' => 'status',
]) ])
->addColumn('update_time', 'integer', [ ->addColumn('update_time', 'integer', [
'null' => false, 'null' => false,
@ -2251,7 +2258,7 @@ class InitTable extends Phinx\Migration\AbstractMigration
->addColumn('content', 'string', [ ->addColumn('content', 'string', [
'null' => false, 'null' => false,
'default' => '', 'default' => '',
'limit' => 1500, 'limit' => 3000,
'collation' => 'utf8mb4_general_ci', 'collation' => 'utf8mb4_general_ci',
'encoding' => 'utf8mb4', 'encoding' => 'utf8mb4',
'comment' => '内容', 'comment' => '内容',

View File

@ -2109,36 +2109,12 @@ return array(
'GENERATION_EXPRESSION' => '', 'GENERATION_EXPRESSION' => '',
'SRS_ID' => NULL, 'SRS_ID' => NULL,
), ),
'user_limit' =>
array(
'TABLE_CATALOG' => 'def',
'TABLE_NAME' => 'kg_chapter_live',
'COLUMN_NAME' => 'user_limit',
'ORDINAL_POSITION' => '4',
'COLUMN_DEFAULT' => '100',
'IS_NULLABLE' => 'NO',
'DATA_TYPE' => 'int',
'CHARACTER_MAXIMUM_LENGTH' => NULL,
'CHARACTER_OCTET_LENGTH' => NULL,
'NUMERIC_PRECISION' => '10',
'NUMERIC_SCALE' => '0',
'DATETIME_PRECISION' => NULL,
'CHARACTER_SET_NAME' => NULL,
'COLLATION_NAME' => NULL,
'COLUMN_TYPE' => 'int unsigned',
'COLUMN_KEY' => '',
'EXTRA' => '',
'PRIVILEGES' => 'select,insert,update,references',
'COLUMN_COMMENT' => '用户限额',
'GENERATION_EXPRESSION' => '',
'SRS_ID' => NULL,
),
'start_time' => 'start_time' =>
array( array(
'TABLE_CATALOG' => 'def', 'TABLE_CATALOG' => 'def',
'TABLE_NAME' => 'kg_chapter_live', 'TABLE_NAME' => 'kg_chapter_live',
'COLUMN_NAME' => 'start_time', 'COLUMN_NAME' => 'start_time',
'ORDINAL_POSITION' => '5', 'ORDINAL_POSITION' => '4',
'COLUMN_DEFAULT' => '0', 'COLUMN_DEFAULT' => '0',
'IS_NULLABLE' => 'NO', 'IS_NULLABLE' => 'NO',
'DATA_TYPE' => 'int', 'DATA_TYPE' => 'int',
@ -2162,7 +2138,7 @@ return array(
'TABLE_CATALOG' => 'def', 'TABLE_CATALOG' => 'def',
'TABLE_NAME' => 'kg_chapter_live', 'TABLE_NAME' => 'kg_chapter_live',
'COLUMN_NAME' => 'end_time', 'COLUMN_NAME' => 'end_time',
'ORDINAL_POSITION' => '6', 'ORDINAL_POSITION' => '5',
'COLUMN_DEFAULT' => '0', 'COLUMN_DEFAULT' => '0',
'IS_NULLABLE' => 'NO', 'IS_NULLABLE' => 'NO',
'DATA_TYPE' => 'int', 'DATA_TYPE' => 'int',
@ -2181,12 +2157,60 @@ return array(
'GENERATION_EXPRESSION' => '', 'GENERATION_EXPRESSION' => '',
'SRS_ID' => NULL, 'SRS_ID' => NULL,
), ),
'user_limit' =>
array(
'TABLE_CATALOG' => 'def',
'TABLE_NAME' => 'kg_chapter_live',
'COLUMN_NAME' => 'user_limit',
'ORDINAL_POSITION' => '6',
'COLUMN_DEFAULT' => '100',
'IS_NULLABLE' => 'NO',
'DATA_TYPE' => 'int',
'CHARACTER_MAXIMUM_LENGTH' => NULL,
'CHARACTER_OCTET_LENGTH' => NULL,
'NUMERIC_PRECISION' => '10',
'NUMERIC_SCALE' => '0',
'DATETIME_PRECISION' => NULL,
'CHARACTER_SET_NAME' => NULL,
'COLLATION_NAME' => NULL,
'COLUMN_TYPE' => 'int unsigned',
'COLUMN_KEY' => '',
'EXTRA' => '',
'PRIVILEGES' => 'select,insert,update,references',
'COLUMN_COMMENT' => '用户限额',
'GENERATION_EXPRESSION' => '',
'SRS_ID' => NULL,
),
'status' =>
array(
'TABLE_CATALOG' => 'def',
'TABLE_NAME' => 'kg_chapter_live',
'COLUMN_NAME' => 'status',
'ORDINAL_POSITION' => '7',
'COLUMN_DEFAULT' => '0',
'IS_NULLABLE' => 'NO',
'DATA_TYPE' => 'int',
'CHARACTER_MAXIMUM_LENGTH' => NULL,
'CHARACTER_OCTET_LENGTH' => NULL,
'NUMERIC_PRECISION' => '10',
'NUMERIC_SCALE' => '0',
'DATETIME_PRECISION' => NULL,
'CHARACTER_SET_NAME' => NULL,
'COLLATION_NAME' => NULL,
'COLUMN_TYPE' => 'int unsigned',
'COLUMN_KEY' => '',
'EXTRA' => '',
'PRIVILEGES' => 'select,insert,update,references',
'COLUMN_COMMENT' => '状态标识',
'GENERATION_EXPRESSION' => '',
'SRS_ID' => NULL,
),
'create_time' => 'create_time' =>
array( array(
'TABLE_CATALOG' => 'def', 'TABLE_CATALOG' => 'def',
'TABLE_NAME' => 'kg_chapter_live', 'TABLE_NAME' => 'kg_chapter_live',
'COLUMN_NAME' => 'create_time', 'COLUMN_NAME' => 'create_time',
'ORDINAL_POSITION' => '7', 'ORDINAL_POSITION' => '8',
'COLUMN_DEFAULT' => '0', 'COLUMN_DEFAULT' => '0',
'IS_NULLABLE' => 'NO', 'IS_NULLABLE' => 'NO',
'DATA_TYPE' => 'int', 'DATA_TYPE' => 'int',
@ -2210,7 +2234,7 @@ return array(
'TABLE_CATALOG' => 'def', 'TABLE_CATALOG' => 'def',
'TABLE_NAME' => 'kg_chapter_live', 'TABLE_NAME' => 'kg_chapter_live',
'COLUMN_NAME' => 'update_time', 'COLUMN_NAME' => 'update_time',
'ORDINAL_POSITION' => '8', 'ORDINAL_POSITION' => '9',
'COLUMN_DEFAULT' => '0', 'COLUMN_DEFAULT' => '0',
'IS_NULLABLE' => 'NO', 'IS_NULLABLE' => 'NO',
'DATA_TYPE' => 'int', 'DATA_TYPE' => 'int',
@ -7877,14 +7901,14 @@ return array(
'COLUMN_DEFAULT' => '', 'COLUMN_DEFAULT' => '',
'IS_NULLABLE' => 'NO', 'IS_NULLABLE' => 'NO',
'DATA_TYPE' => 'varchar', 'DATA_TYPE' => 'varchar',
'CHARACTER_MAXIMUM_LENGTH' => '1500', 'CHARACTER_MAXIMUM_LENGTH' => '3000',
'CHARACTER_OCTET_LENGTH' => '6000', 'CHARACTER_OCTET_LENGTH' => '12000',
'NUMERIC_PRECISION' => NULL, 'NUMERIC_PRECISION' => NULL,
'NUMERIC_SCALE' => NULL, 'NUMERIC_SCALE' => NULL,
'DATETIME_PRECISION' => NULL, 'DATETIME_PRECISION' => NULL,
'CHARACTER_SET_NAME' => 'utf8mb4', 'CHARACTER_SET_NAME' => 'utf8mb4',
'COLLATION_NAME' => 'utf8mb4_general_ci', 'COLLATION_NAME' => 'utf8mb4_general_ci',
'COLUMN_TYPE' => 'varchar(1500)', 'COLUMN_TYPE' => 'varchar(3000)',
'COLUMN_KEY' => '', 'COLUMN_KEY' => '',
'EXTRA' => '', 'EXTRA' => '',
'PRIVILEGES' => 'select,insert,update,references', 'PRIVILEGES' => 'select,insert,update,references',

View File

@ -138,6 +138,10 @@ body {
background: none; background: none;
} }
#header .layui-nav {
background: none;
}
#footer span, #footer a { #footer span, #footer a {
color: #999; color: #999;
} }

View File

@ -3,8 +3,9 @@ layui.use(['jquery', 'form', 'helper'], function () {
var $ = layui.jquery; var $ = layui.jquery;
var form = layui.form; var form = layui.form;
var helper = layui.helper; var helper = layui.helper;
var socket = new WebSocket(window.koogua.socketUrl); var socket = new WebSocket(window.im.websocket.url);
var bindUserUrl = $('input[name="bind_user_url"]').val(); var bindUserUrl = $('input[name="bind_user_url"]').val();
var liveStatsUrl = $('input[name="live_stats_url"]').val();
var $chatContent = $('input[name=content]'); var $chatContent = $('input[name=content]');
var $chatMsgList = $('#chat-msg-list'); var $chatMsgList = $('#chat-msg-list');
@ -53,7 +54,7 @@ layui.use(['jquery', 'form', 'helper'], function () {
setInterval(function () { setInterval(function () {
refreshLiveStats(); refreshLiveStats();
}, 300000); }, 30000);
function bindUser(clientId) { function bindUser(clientId) {
$.ajax({ $.ajax({
@ -92,8 +93,10 @@ layui.use(['jquery', 'form', 'helper'], function () {
} }
function refreshLiveStats() { function refreshLiveStats() {
var $tabStats = $('#tab-stats'); var $count = $('.layui-icon-user').next();
helper.ajaxLoadHtml($tabStats.data('url'), $tabStats.attr('id')); $.get(liveStatsUrl, function (res) {
$count.text(res.client_count);
});
} }
function loadRecentChats() { function loadRecentChats() {

View File

@ -5,7 +5,7 @@ layui.use(['jquery', 'helper'], function () {
var interval = null; var interval = null;
var intervalTime = 15000; var intervalTime = 15000;
var userId = window.koogua.user.id; var userId = window.user.id;
var chapterId = $('input[name="chapter.id"]').val(); var chapterId = $('input[name="chapter.id"]').val();
var planId = $('input[name="chapter.plan_id"]').val(); var planId = $('input[name="chapter.plan_id"]').val();
var learningUrl = $('input[name="chapter.learning_url"]').val(); var learningUrl = $('input[name="chapter.learning_url"]').val();