1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-06-28 05:11:39 +08:00

统一了状态类型,修复一些改字段名带来的错误

This commit is contained in:
xiaochong0302 2020-08-31 19:34:32 +08:00
parent c22417913a
commit 477a9f1c42
53 changed files with 14176 additions and 14240 deletions

View File

@ -109,7 +109,7 @@ class CloseTradeTask extends Task
* @param int $limit
* @return ResultsetInterface|Resultset|TradeModel[]
*/
protected function findTrades($limit = 15)
protected function findTrades($limit = 50)
{
$status = TradeModel::STATUS_PENDING;

View File

@ -14,7 +14,7 @@ use Phalcon\Mvc\Model;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;
class OrderTask extends Task
class DeliverTask extends Task
{
const TRY_COUNT = 3;
@ -178,11 +178,11 @@ class OrderTask extends Task
$refund = new RefundModel();
$refund->subject = $order->subject;
$refund->amount = $order->amount;
$refund->user_id = $order->user_id;
$refund->owner_id = $order->owner_id;
$refund->order_id = $order->id;
$refund->trade_id = $trade->id;
$refund->subject = $order->subject;
$refund->amount = $order->amount;
$refund->apply_note = '开通服务失败,自动退款';
$refund->review_note = '自动操作';
@ -210,7 +210,7 @@ class OrderTask extends Task
*/
protected function findTasks($limit = 100)
{
$itemType = TaskModel::TYPE_ORDER;
$itemType = TaskModel::TYPE_DELIVER;
$status = TaskModel::STATUS_PENDING;
$tryCount = self::TRY_COUNT;

View File

@ -1,70 +0,0 @@
<?php
namespace App\Console\Tasks;
use App\Library\Cache\Backend\Redis as RedisCache;
use App\Services\Smser\Live as LiveSmser;
use Phalcon\Cli\Task;
class LiveNoticeConsumerTask extends Task
{
/**
* @var RedisCache
*/
protected $cache;
/**
* @var \Redis
*/
protected $redis;
public function mainAction()
{
$hour = date('h');
/**
* 限定合理的时间范围
*/
if ($hour < 7 || $hour > 23) {
return;
}
$this->cache = $this->getDI()->get('cache');
$this->redis = $this->cache->getRedis();
$providerTask = new LiveNoticeProviderTask();
$cacheKey = $providerTask->getCacheKey();
$members = $this->redis->sMembers($cacheKey);
if (!$members) return;
$smser = new LiveSmser();
$now = time();
$removeList = [];
foreach ($members as $member) {
list($chapterId, $userId, $startTime) = explode(':', $member);
if ($now - $startTime < 3600) {
$smser->handle($chapterId, $userId, $startTime);
$removeList[] = $member;
}
if ($now > $startTime) {
$removeList[] = $member;
}
}
if (count($removeList) > 0) {
$this->redis->sRem($cacheKey, ...$removeList);
}
}
}

View File

@ -1,92 +0,0 @@
<?php
namespace App\Console\Tasks;
use App\Library\Cache\Backend\Redis as RedisCache;
use App\Models\ChapterLive as ChapterLiveModel;
use App\Models\CourseUser as CourseUserModel;
use Phalcon\Cli\Task;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;
class LiveNoticeProviderTask extends Task
{
/**
* @var RedisCache
*/
protected $cache;
/**
* @var \Redis
*/
protected $redis;
public function mainAction()
{
$this->cache = $this->getDI()->get('cache');
$this->redis = $this->cache->getRedis();
$tasks = $this->findTasks();
if ($tasks->count() == 0) {
return;
}
$values = [];
foreach ($tasks as $task) {
$items = [$task->chapter_id, $task->user_id, $task->start_time];
$values[] = implode(':', $items);
}
$key = $this->getCacheKey();
$lifetime = $this->getLifetime();
$this->redis->sAdd($key, ...$values);
$this->redis->expire($key, $lifetime);
}
/**
* @return ResultsetInterface|Resultset
*/
protected function findTasks()
{
$beginTime = strtotime('today');
$endTime = strtotime('tomorrow');
/**
* 过滤付费和导入用户,减少发送量
*/
$sourceTypes = [
CourseUserModel::SOURCE_CHARGE,
CourseUserModel::SOURCE_IMPORT,
];
return $this->modelsManager->createBuilder()
->columns(['cu.course_id', 'cu.user_id', 'cl.chapter_id', 'cl.start_time'])
->addFrom(ChapterLiveModel::class, 'cl')
->join(CourseUserModel::class, 'cl.course_id = cu.course_id', 'cu')
->inWhere('cu.source_type', $sourceTypes)
->betweenWhere('start_time', $beginTime, $endTime)
->getQuery()->execute();
}
public function getLifetime()
{
$tomorrow = strtotime('tomorrow');
return $tomorrow - time();
}
public function getCacheKey()
{
return 'live_notice';
}
}

View File

@ -0,0 +1,98 @@
<?php
namespace App\Console\Tasks;
use App\Library\Cache\Backend\Redis as RedisCache;
use App\Models\CourseUser as CourseUserModel;
use App\Repos\Chapter as ChapterRepo;
use App\Services\LiveNotify as LiveNotifyService;
use App\Services\Smser\Live as LiveSmser;
use Phalcon\Cli\Task;
class LiveNotifyTask extends Task
{
/**
* @var RedisCache
*/
protected $cache;
/**
* @var \Redis
*/
protected $redis;
public function mainAction()
{
$this->cache = $this->getDI()->get('cache');
$this->redis = $this->cache->getRedis();
$service = new LiveNotifyService();
$key = $service->getNotifyKey();
$chapterIds = $this->redis->sMembers($key);
if (!$chapterIds) return;
$sentKey = $service->getSentNotifyKey();
$sentChapterIds = $this->redis->sMembers($sentKey);
foreach ($chapterIds as $chapterId) {
if (!in_array($chapterId, $sentChapterIds)) {
$this->sendNotification($chapterId);
} else {
$this->redis->sAdd($sentKey, $chapterId);
}
}
if ($this->redis->sCard($sentKey) == 1) {
$this->redis->expire($sentKey, 86400);
}
}
protected function sendNotification($chapterId)
{
$chapterRepo = new ChapterRepo();
$chapterLive = $chapterRepo->findChapterLive($chapterId);
if (!$chapterLive) return;
$targetUserIds = $this->findTargetUserIds($chapterLive->course_id);
if (!$targetUserIds) return;
$smser = new LiveSmser();
foreach ($targetUserIds as $userId) {
$smser->handle($chapterId, $userId, $chapterLive->start_time);
}
}
protected function findTargetUserIds($courseId)
{
/**
* 只给付费和vip用户发通知
*/
$sourceTypes = [
CourseUserModel::SOURCE_CHARGE,
CourseUserModel::SOURCE_VIP,
];
$rows = CourseUserModel::query()
->where('course_id = :course_id:', ['course_id' => $courseId])
->andWhere('role_type = :role_type:', ['role_type' => CourseUserModel::ROLE_STUDENT])
->inWhere('source_type', $sourceTypes)
->execute();
if ($rows->count() > 0) {
return kg_array_column($rows->toArray(), 'user_id');
}
return [];
}
}

View File

@ -188,7 +188,7 @@ class RefundTask extends Task
{
$courseUserRepo = new CourseUserRepo();
$courseUser = $courseUserRepo->findCourseStudent($order->item_id, $order->user_id);
$courseUser = $courseUserRepo->findCourseStudent($order->item_id, $order->owner_id);
if ($courseUser) {
@ -216,7 +216,7 @@ class RefundTask extends Task
foreach ($itemInfo['courses'] as $course) {
$courseUser = $courseUserRepo->findCourseStudent($course['id'], $order->user_id);
$courseUser = $courseUserRepo->findCourseStudent($course['id'], $order->owner_id);
if ($courseUser) {
@ -238,7 +238,7 @@ class RefundTask extends Task
{
$userRepo = new UserRepo();
$user = $userRepo->findById($order->user_id);
$user = $userRepo->findById($order->owner_id);
/**
* @var array $itemInfo
@ -293,7 +293,7 @@ class RefundTask extends Task
* @param int $limit
* @return ResultsetInterface|Resultset|TaskModel[]
*/
protected function findTasks($limit = 5)
protected function findTasks($limit = 30)
{
$itemType = TaskModel::TYPE_REFUND;
$status = TaskModel::STATUS_PENDING;

View File

@ -17,7 +17,7 @@ class CategoryController extends Controller
public function listAction()
{
$parentId = $this->request->get('parent_id', 'int', 0);
$type = $this->request->get('type', 'string', CategoryModel::TYPE_COURSE);
$type = $this->request->get('type', 'int', CategoryModel::TYPE_COURSE);
$categoryService = new CategoryService();
@ -41,7 +41,7 @@ class CategoryController extends Controller
public function addAction()
{
$parentId = $this->request->get('parent_id', 'int', 0);
$type = $this->request->get('type', 'string', 'course');
$type = $this->request->get('type', 'int', CategoryModel::TYPE_COURSE);
$categoryService = new CategoryService();
@ -69,7 +69,7 @@ class CategoryController extends Controller
$location = $this->url->get(
['for' => 'admin.category.list'],
['type' => $category->type, 'parent_id' => $category->parent_id],
['type' => $category->type, 'parent_id' => $category->parent_id]
);
$content = [
@ -105,7 +105,7 @@ class CategoryController extends Controller
$location = $this->url->get(
['for' => 'admin.category.list'],
['type' => $category->type, 'parent_id' => $category->parent_id],
['type' => $category->type, 'parent_id' => $category->parent_id]
);
$content = [

View File

@ -133,10 +133,7 @@ class SettingController extends Controller
$live = $settingService->getLiveSettings();
$ptt = json_decode($live->pull_trans_template);
$this->view->setVar('live', $live);
$this->view->setVar('ptt', $ptt);
}
}

View File

@ -33,8 +33,8 @@ class Nav extends Service
$navRepo = new NavRepo();
return $navRepo->findAll([
'position' => NavModel::POS_TOP,
'parent_id' => 0,
'position' => 'top',
'published' => 1,
]);
}

View File

@ -7,6 +7,12 @@
{% endif %}
{%- endmacro %}
{%- macro live_status_info(attrs) %}
{% if attrs['stream']['status'] != 'active' %}
<span class="layui-badge layui-bg-blue">直播中</span>
{% endif %}
{%- endmacro %}
<table class="layui-table kg-table layui-form">
<colgroup>
<col>
@ -21,7 +27,7 @@
<tr>
<th>编号</th>
<th>名称</th>
<th>直播时间</th>
<th>时间</th>
<th>排序</th>
<th>免费</th>
<th>发布</th>
@ -30,6 +36,7 @@
</thead>
<tbody>
{% for item in lessons %}
{% set preview_url = url({'for':'desktop.chapter.show','id':item.id}) %}
{% set edit_url = url({'for':'admin.chapter.edit','id':item.id}) %}
{% set update_url = url({'for':'admin.chapter.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.chapter.delete','id':item.id}) %}
@ -39,6 +46,7 @@
<td>
<span><a href="{{ edit_url }}">{{ item.title }}</a></span>
<span class="layui-badge layui-bg-green">课</span>
{{ live_status_info(item.attrs) }}
</td>
<td>{{ live_time_info(item.attrs) }}</td>
<td><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td>
@ -48,6 +56,7 @@
<div class="layui-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul>
<li><a href="{{ preview_url }}" target="_blank">预览</a></li>
<li><a href="{{ edit_url }}">编辑</a></li>
{% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>

View File

@ -21,6 +21,7 @@
</thead>
<tbody>
{% for item in lessons %}
{% set preview_url = url({'for':'desktop.chapter.show','id':item.id}) %}
{% set edit_url = url({'for':'admin.chapter.edit','id':item.id}) %}
{% set update_url = url({'for':'admin.chapter.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.chapter.delete','id':item.id}) %}
@ -39,6 +40,7 @@
<div class="layui-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul>
<li><a href="{{ preview_url }}" target="_blank">预览</a></li>
<li><a href="{{ edit_url }}">编辑</a></li>
{% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>

View File

@ -37,6 +37,7 @@
</thead>
<tbody>
{% for item in lessons %}
{% set show_url = url({'for':'desktop.chapter.show','id':item.id}) %}
{% set edit_url = url({'for':'admin.chapter.edit','id':item.id}) %}
{% set update_url = url({'for':'admin.chapter.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.chapter.delete','id':item.id}) %}
@ -56,6 +57,7 @@
<div class="layui-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul>
<li><a href="{{ preview_url }}" target="_blank">预览</a></li>
<li><a href="{{ edit_url }}">编辑</a></li>
{% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>

View File

@ -69,6 +69,7 @@
</thead>
<tbody>
{% for item in pager.items %}
{% set preview_url = url({'for':'desktop.course.show','id':item.id}) %}
{% set edit_url = url({'for':'admin.course.edit','id':item.id}) %}
{% set update_url = url({'for':'admin.course.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.course.delete','id':item.id}) %}
@ -101,6 +102,7 @@
<div class="layui-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul>
<li><a href="{{ preview_url }}" target="_blank">预览课程</a></li>
<li><a href="{{ edit_url }}">编辑课程</a></li>
{% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除课程</a></li>

View File

@ -32,13 +32,14 @@
<tbody>
{% for item in helps %}
{% set list_url = url({'for':'admin.help.list'},{'category_id':item.category.id}) %}
{% set preview_url = url({'for':'desktop.help.show','id':item.id}) %}
{% set edit_url = url({'for':'admin.help.edit','id':item.id}) %}
{% set update_url = url({'for':'admin.help.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.help.delete','id':item.id}) %}
{% set restore_url = url({'for':'admin.help.restore','id':item.id}) %}
<tr>
<td>{{ item.id }}</td>
<td>{{ item.title }}</td>
<td><a href="{{ edit_url }}">{{ item.title }}</a></td>
<td><a href="{{ list_url }}">{{ item.category.name }}</a></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{% endif %}></td>
@ -46,6 +47,7 @@
<div class="layui-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul>
<li><a href="{{ preview_url }}" target="_blank">预览</a></li>
<li><a href="{{ edit_url }}">编辑</a></li>
{% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>

View File

@ -40,8 +40,8 @@
<div class="layui-form-item">
<label class="layui-form-label">位置</label>
<div class="layui-input-block">
<input type="radio" name="position" value="top" title="顶部" checked="checked">
<input type="radio" name="position" value="bottom" title="底部">
<input type="radio" name="position" value="1" title="顶部" checked="checked">
<input type="radio" name="position" value="2" title="底部">
</div>
</div>
<div class="layui-form-item">

View File

@ -27,8 +27,8 @@
<div class="layui-form-item">
<label class="layui-form-label">位置</label>
<div class="layui-input-block">
<input type="radio" name="position" value="top" title="顶部" {% if nav.position == 'top' %}checked{% endif %}>
<input type="radio" name="position" value="bottom" title="底部" {% if nav.position == 'bottom' %}checked{% endif %}>
<input type="radio" name="position" value="top" title="顶部" {% if nav.position == 1 %}checked{% endif %}>
<input type="radio" name="position" value="bottom" title="底部" {% if nav.position == 2 %}checked{% endif %}>
</div>
</div>
<div class="layui-form-item">

View File

@ -3,9 +3,9 @@
{% block content %}
{%- macro position_info(value) %}
{% if value == 'top' %}
{% if value == 1 %}
<span class="layui-badge layui-bg-green">顶部</span>
{% elseif value == 'bottom' %}
{% elseif value == 2 %}
<span class="layui-badge layui-bg-blue">底部</span>
{% endif %}
{%- endmacro %}

View File

@ -31,13 +31,13 @@
</thead>
<tbody>
{% for item in pager.items %}
{% set show_url = url({'for':'desktop.page.show','id':item.id}) %}
{% set preview_url = url({'for':'desktop.page.show','id':item.id}) %}
{% set edit_url = url({'for':'admin.page.edit','id':item.id}) %}
{% set update_url = url({'for':'admin.page.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.page.delete','id':item.id}) %}
<tr>
<td>{{ item.id }}</td>
<td><a href="{{ show_url }}" target="_blank">{{ item.title }}</a></td>
<td><a href="{{ edit_url }}">{{ item.title }}</a></td>
<td>{{ date('Y-m-d H:i',item.create_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{% endif %}>
@ -46,6 +46,7 @@
<div class="layui-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul>
<li><a href="{{ preview_url }}" target="_blank">预览</a></li>
<li><a href="{{ edit_url }}">编辑</a></li>
{% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>

View File

@ -16,7 +16,7 @@
{{ partial('setting/live_pull') }}
</div>
<div class="layui-tab-item">
{{ partial('setting/live_callback') }}
{{ partial('setting/live_notify') }}
</div>
</div>
</div>

View File

@ -52,42 +52,45 @@
<input type="radio" name="pull_trans_enabled" value="0" title="否" lay-filter="pull_trans_enabled" {% if live.pull_trans_enabled == 0 %}checked{% endif %}>
</div>
</div>
<table class="layui-table kg-table layui-form" id="ptt-block" {{ ppt_display }}>
<colgroup>
<col>
<col>
<col>
<col>
</colgroup>
<thead>
<tr>
<th>模板名称</th>
<th>模板描述</th>
<th>视频码率kbps</th>
<th>视频高度px</th>
</tr>
</thead>
<tbody>
<tr>
<td><input class="layui-input" type="text" name="ptt[id][fd]" value="{{ ptt.fd.id }}" readonly="readonly"></td>
<td><input class="layui-input" type="text" name="ptt[summary][fd]" value="{{ ptt.fd.summary }}" readonly="readonly"></td>
<td><input class="layui-input" type="text" name="ptt[bit_rate][fd]" value="{{ ptt.fd.bit_rate }}" readonly="readonly"></td>
<td><input class="layui-input" type="text" name="ptt[height][fd]" value="{{ ptt.fd.height }}" readonly="readonly"></td>
</tr>
<tr>
<td><input class="layui-input" type="text" name="ptt[id][sd]" value="{{ ptt.sd.id }}" readonly="readonly"></td>
<td><input class="layui-input" type="text" name="ptt[summary][sd]" value="{{ ptt.sd.summary }}" readonly="readonly"></td>
<td><input class="layui-input" type="text" name="ptt[bit_rate][sd]" value="{{ ptt.sd.bit_rate }}" readonly="readonly"></td>
<td><input class="layui-input" type="text" name="ptt[height][sd]" value="{{ ptt.sd.height }}" readonly="readonly"></td>
</tr>
<tr>
<td><input class="layui-input" type="text" name="ptt[id][hd]" value="{{ ptt.hd.id }}" readonly="readonly"></td>
<td><input class="layui-input" type="text" name="ptt[summary][hd]" value="{{ ptt.hd.summary }}" readonly="readonly"></td>
<td><input class="layui-input" type="text" name="ptt[bit_rate][hd]" value="{{ ptt.hd.bit_rate }}" readonly="readonly"></td>
<td><input class="layui-input" type="text" name="ptt[height][hd]" value="{{ ptt.hd.height }}" readonly="readonly"></td>
</tr>
</tbody>
</table>
<div id="ptt-block" {{ ppt_display }}>
<table class="layui-table kg-table layui-form">
<colgroup>
<col>
<col>
<col>
<col>
</colgroup>
<thead>
<tr>
<th>模板名称</th>
<th>模板描述</th>
<th>视频码率kbps</th>
<th>视频高度px</th>
</tr>
</thead>
<tbody>
<tr>
<td>fd</td>
<td>流畅</td>
<td>500</td>
<td>540</td>
</tr>
<tr>
<td>sd</td>
<td>标清</td>
<td>1000</td>
<td>720</td>
</tr>
<tr>
<td>hd</td>
<td>高清</td>
<td>2000</td>
<td>1080</td>
</tr>
</tbody>
</table>
<br>
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">

View File

@ -35,12 +35,6 @@
<input type="radio" name="video_format" value="mp4" title="MP4" disabled="disabled" lay-filter="video_format" {% if vod.video_format == "mp4" %}checked{% endif %}>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">视频模板ID</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="video_template" readonly="readonly" layui-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">音频格式</label>
<div class="layui-input-block">
@ -48,12 +42,6 @@
<input type="radio" name="audio_format" value="m4a" title="M4A" disabled="disabled" lay-filter="audio_format" {% if vod.audio_format == "m4a" %}checked{% endif %}>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">音频模板ID</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="audio_template" readonly="readonly" layui-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">开启水印</label>
<div class="layui-input-block">
@ -148,24 +136,6 @@
var $ = layui.jquery;
var form = layui.form;
var changeVideoTemplate = function (format) {
var template = $('input[name=video_template]');
if (format === 'mp4') {
template.val('100010,100020,100030');
} else {
template.val('100210,100220,100230');
}
};
var changeAudioTemplate = function (format) {
var template = $('input[name=audio_template]');
if (format === 'mp3') {
template.val('1010');
} else {
template.val('1110');
}
};
form.on('radio(storage_type)', function (data) {
var block = $('#storage-region-block');
if (data.value === 'fixed') {
@ -193,20 +163,6 @@
}
});
form.on('radio(video_format)', function (data) {
changeVideoTemplate(data.value);
});
form.on('radio(audio_format)', function (data) {
changeAudioTemplate(data.value);
});
var videoFormat = $('input[name=video_format]:checked').val();
var audioFormat = $('input[name=audio_format]:checked').val();
changeVideoTemplate(videoFormat);
changeAudioTemplate(audioFormat);
});
</script>

View File

@ -33,6 +33,7 @@
</thead>
<tbody>
{% for item in pager.items %}
{% set preview_url = url({'for':'desktop.topic.show','id':item.id}) %}
{% set edit_url = url({'for':'admin.topic.edit','id':item.id}) %}
{% set update_url = url({'for':'admin.topic.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.topic.delete','id':item.id}) %}
@ -48,6 +49,7 @@
<div class="layui-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul>
<li><a href="{{ preview_url }}" target="_blank">预览</a></li>
<li><a href="{{ edit_url }}">编辑</a></li>
{% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>

View File

@ -68,10 +68,11 @@
</thead>
<tbody>
{% for item in pager.items %}
{% set preview_url = url({'for':'desktop.user.show','id':item.id}) %}
{% set edit_url = url({'for':'admin.user.edit','id':item.id}) %}
<tr>
<td>{{ item.id }}</td>
<td><span title="{{ item.about }}">{{ item.name }}</span>{{ status_info(item) }}</td>
<td><a href="{{ edit_url }}" title="{{ item.about }}">{{ item.name }}</a>{{ status_info(item) }}</td>
<td>{{ gender_info(item.gender) }}</td>
<td>{{ edu_role_info(item) }}</td>
<td>{{ admin_role_info(item) }}</td>
@ -81,6 +82,7 @@
<div class="layui-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul>
<li><a href="{{ preview_url }}" target="_blank">预览</a></li>
<li><a href="{{ edit_url }}">编辑</a></li>
</ul>
</div>

View File

@ -19,7 +19,7 @@ class PageController extends Controller
$page = $service->handle($id);
$this->seo->prependTitle($page['title']);
$this->seo->prependTitle(['单页', $page['title']]);
$this->view->setVar('page', $page);
}

View File

@ -5,6 +5,7 @@
<div class="breadcrumb">
<span class="layui-breadcrumb">
<a href="/">首页</a>
<a><cite>单页</cite></a>
<a><cite>{{ page.title }}</cite></a>
</span>
</div>

View File

@ -42,8 +42,8 @@
<tr>
<td>
<p>课程:<a href="{{ course_url }}" target="_blank">{{ item.course.title }}</a></p>
<p class="question layui-elip" title="{{ item.question }}">提问:{{ item.question }}</p>
<p class="answer layui-elip" title="{{ item.answer }}">回复:{{ answer }}</p>
<p class="content layui-elip" title="{{ item.question }}">提问:{{ item.question }}</p>
<p class="content layui-elip" title="{{ item.answer }}">回复:{{ answer }}</p>
</td>
<td>{{ item.priority }}</td>
<td>{{ date('Y-m-d',item.create_time) }}</td>

View File

@ -12,7 +12,7 @@
{{ vip_info(item.vip) }}
<div class="avatar">
<a href="{{ user_url }}" title="{{ item.about }}">
<img src="{{ item.avatar }}" alt="{{ item.name }}">
<img src="{{ item.avatar }}!avatar_160" alt="{{ item.name }}">
</a>
</div>
<div class="name layui-elip">

View File

@ -11,7 +11,7 @@
{{ type_info(item.type) }}
<div class="avatar">
<a href="{{ group_url }}" title="{{ item.about }}">
<img src="{{ item.avatar }}" alt="{{ item.name }}">
<img src="{{ item.avatar }}!avatar_160" alt="{{ item.name }}">
</a>
</div>
<div class="name layui-elip">

View File

@ -50,7 +50,9 @@
<div class="tab-wrap">
<div class="layui-tab layui-tab-brief user-tab">
<ul class="layui-tab-title">
<li class="layui-this">课程<span class="tab-count">{{ user.course_count }}</span></li>
{% if show_tab_courses %}
<li class="layui-this">课程<span class="tab-count">{{ user.course_count }}</span></li>
{% endif %}
{% if show_tab_favorites %}
<li>收藏<span class="tab-count">{{ user.favorite_count }}</span></li>
{% endif %}
@ -62,7 +64,9 @@
{% endif %}
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show" id="tab-courses" data-url="{{ courses_url }}"></div>
{% if show_tab_courses %}
<div class="layui-tab-item layui-show" id="tab-courses" data-url="{{ courses_url }}"></div>
{% endif %}
{% if show_tab_favorites %}
<div class="layui-tab-item" id="tab-favorites" data-url="{{ favorites_url }}"></div>
{% endif %}

View File

@ -6,11 +6,15 @@ use App\Models\Order as OrderModel;
use App\Models\Task as TaskModel;
use App\Models\Trade as TradeModel;
use App\Repos\Order as OrderRepo;
use Phalcon\Events\Event;
use Phalcon\Events\Event as PhEvent;
use Phalcon\Logger\Adapter\File as FileLogger;
class Pay extends Listener
{
/**
* @var FileLogger
*/
protected $logger;
public function __construct()
@ -18,7 +22,7 @@ class Pay extends Listener
$this->logger = $this->getLogger();
}
public function afterPay(Event $event, $source, TradeModel $trade)
public function afterPay(PhEvent $event, $source, TradeModel $trade)
{
try {
@ -34,7 +38,7 @@ class Pay extends Listener
$order = $orderRepo->findById($trade->order_id);
$order->status = OrderModel::STATUS_SHIPPING;
$order->status = OrderModel::STATUS_DELIVERING;
if ($order->update() === false) {
throw new \RuntimeException('Update Order Status Failed');
@ -52,7 +56,7 @@ class Pay extends Listener
$task->item_id = $order->id;
$task->item_info = $itemInfo;
$task->item_type = TaskModel::TYPE_ORDER;
$task->item_type = TaskModel::TYPE_DELIVER;
if ($task->create() === false) {
throw new \RuntimeException('Create Order Process Task Failed');
@ -69,15 +73,15 @@ class Pay extends Listener
'code' => $e->getCode(),
'message' => $e->getMessage(),
]));
$this->logger->debug('Event: {event}, Source: {source}, Data: {data}', [
'event' => $event->getType(),
'source' => get_class($source),
'data' => kg_json_encode($trade),
]);
throw new \RuntimeException('sys.trans_rollback');
}
$this->logger->debug('Event: {event}, Source: {source}, Data: {data}', [
'event' => $event->getType(),
'source' => get_class($source),
'data' => kg_json_encode($trade),
]);
throw new \RuntimeException('sys.trans_rollback');
}
}

View File

@ -2,14 +2,22 @@
namespace App\Listeners;
use Phalcon\Db\Adapter as DbAdapter;
use Phalcon\Db\Profiler as DbProfiler;
use Phalcon\Events\Event;
use Phalcon\Events\Event as PhEvent;
use Phalcon\Logger\Adapter\File as FileLogger;
class Profiler extends Listener
{
/**
* @var FileLogger
*/
protected $logger;
/**
* @var DbProfiler
*/
protected $profiler;
public function __construct()
@ -19,12 +27,20 @@ class Profiler extends Listener
$this->profiler = new DbProfiler();
}
public function beforeQuery(Event $event, $connection)
/**
* @param PhEvent $event
* @param DbAdapter $connection
*/
public function beforeQuery(PhEvent $event, $connection)
{
$this->profiler->startProfile($connection->getSQLStatement(), $connection->getSQLVariables());
$this->profiler->startProfile($connection->getSqlStatement(), $connection->getSqlVariables());
}
public function afterQuery(Event $event, $connection)
/**
* @param PhEvent $event
* @param DbAdapter $connection
*/
public function afterQuery(PhEvent $event, $connection)
{
$this->profiler->stopProfile();

View File

@ -11,8 +11,8 @@ class Category extends Model
/**
* 类型
*/
const TYPE_COURSE = 'course'; // 课程
const TYPE_HELP = 'help'; // 帮助
const TYPE_COURSE = 1; // 课程
const TYPE_HELP = 2; // 帮助
/**
* 主键编号
@ -38,7 +38,7 @@ class Category extends Model
/**
* 类型
*
* @var string
* @var int
*/
public $type;

View File

@ -18,7 +18,8 @@ class CourseUser extends Model
*/
const SOURCE_FREE = 1; // 免费
const SOURCE_CHARGE = 2; // 付费
const SOURCE_IMPORT = 3; // 导入
const SOURCE_VIP = 3; // 会员
const SOURCE_IMPORT = 4; // 导入
/**
* 主键编号
@ -153,6 +154,7 @@ class CourseUser extends Model
return [
self::SOURCE_FREE => '免费',
self::SOURCE_CHARGE => '付费',
self::SOURCE_VIP => '会员',
self::SOURCE_IMPORT => '导入',
];
}

View File

@ -10,8 +10,8 @@ class Nav extends Model
/**
* 位置类型
*/
const POS_TOP = 'top';
const POS_BOTTOM = 'bottom';
const POS_TOP = 1; // 顶部
const POS_BOTTOM = 2; // 底部
/**
* 打开方式
@ -54,13 +54,6 @@ class Nav extends Model
*/
public $path;
/**
* 位置
*
* @var string
*/
public $position;
/**
* 打开方式
*
@ -75,6 +68,13 @@ class Nav extends Model
*/
public $url;
/**
* 位置
*
* @var int
*/
public $position;
/**
* 优先级
*

View File

@ -20,7 +20,7 @@ class Order extends Model
* 状态类型
*/
const STATUS_PENDING = 1; // 待支付
const STATUS_SHIPPING = 2; // 发货中
const STATUS_DELIVERING = 2; // 发货中
const STATUS_FINISHED = 3; // 已完成
const STATUS_CLOSED = 4; // 已关闭
const STATUS_REFUNDED = 5; // 已退款
@ -198,7 +198,7 @@ class Order extends Model
{
return [
self::STATUS_PENDING => '待支付',
self::STATUS_SHIPPING => '发货中',
self::STATUS_DELIVERING => '发货中',
self::STATUS_FINISHED => '已完成',
self::STATUS_CLOSED => '已关闭',
self::STATUS_REFUNDED => '已退款',

View File

@ -10,8 +10,8 @@ class Role extends Model
/**
* 角色类型
*/
const TYPE_SYSTEM = 'system'; // 内置
const TYPE_CUSTOM = 'custom'; // 自定
const TYPE_SYSTEM = 1; // 内置
const TYPE_CUSTOM = 2; // 自定
/**
* 内置角色

View File

@ -8,7 +8,7 @@ class Task extends Model
/**
* 任务类型
*/
const TYPE_ORDER = 1; // 下单
const TYPE_DELIVER = 1; // 发货
const TYPE_REFUND = 2; // 退款
/**

View File

@ -2,6 +2,7 @@
namespace App\Services;
use App\Library\Cache\Backend\Redis as RedisCache;
use App\Models\Chapter as ChapterModel;
use App\Models\ChapterLive as ChapterLiveModel;
use App\Repos\Chapter as ChapterRepo;
@ -13,7 +14,7 @@ class LiveNotify extends Service
{
$time = $this->request->getPost('t');
$sign = $this->request->getPost('sign');
$type = $this->request->getQuery('action');
$action = $this->request->getQuery('action');
if (!$this->checkSign($sign, $time)) {
return false;
@ -21,7 +22,7 @@ class LiveNotify extends Service
$result = false;
switch ($type) {
switch ($action) {
case 'streamBegin':
$result = $this->handleStreamBegin();
break;
@ -42,14 +43,24 @@ class LiveNotify extends Service
return $result;
}
public function getNotifyKey()
{
return 'live_notify';
}
public function getSentNotifyKey()
{
return 'live_notify_sent';
}
/**
* 推流
*/
protected function handleStreamBegin()
{
$steamId = $this->request->getPost('stream_id');
$streamId = $this->request->getPost('stream_id');
$chapter = $this->getChapter($steamId);
$chapter = $this->getChapter($streamId);
if (!$chapter) return false;
@ -63,9 +74,7 @@ class LiveNotify extends Service
$chapterLive->update(['status' => ChapterLiveModel::STATUS_ACTIVE]);
/**
* @todo 发送直播通知
*/
$this->sendBeginNotify($chapter);
return true;
}
@ -75,9 +84,9 @@ class LiveNotify extends Service
*/
protected function handleStreamEnd()
{
$steamId = $this->request->getPost('stream_id');
$streamId = $this->request->getPost('stream_id');
$chapter = $this->getChapter($steamId);
$chapter = $this->getChapter($streamId);
if (!$chapter) return false;
@ -118,6 +127,22 @@ class LiveNotify extends Service
}
protected function sendBeginNotify(ChapterModel $chapter)
{
/**
* @var RedisCache $cache
*/
$cache = $this->getDI()->get('cache');
$redis = $cache->getRedis();
$keyName = $this->getNotifyKeyName();
$redis->sAdd($keyName, $chapter->id);
$redis->expire($keyName, 86400);
}
protected function getChapter($streamId)
{
$id = (int)str_replace('chapter_', '', $streamId);

View File

@ -38,7 +38,7 @@ class Refund extends Service
$refundAmount = 0.00;
if ($itemInfo['course']['refund_expiry_time'] > time()) {
$refundPercent = $this->getCourseRefundPercent($order->item_id, $order->user_id);
$refundPercent = $this->getCourseRefundPercent($order->item_id, $order->owner_id);
$refundAmount = $order->amount * $refundPercent;
}
@ -79,7 +79,7 @@ class Refund extends Service
if ($course['refund_expiry_time'] > time()) {
$pricePercent = round($course['market_price'] / $totalMarketPrice, 4);
$refundPercent = $this->getCourseRefundPercent($order->user_id, $course['id']);
$refundPercent = $this->getCourseRefundPercent($course['id'], $order->owner_id);
$refundAmount = round($order->amount * $pricePercent * $refundPercent, 2);
$totalRefundAmount += $refundAmount;
}

View File

@ -24,7 +24,7 @@ class Live extends Smser
$account = $accountRepo->findById($userId);
if (!$account->phone) {
if (empty($account->phone)) {
return false;
}

View File

@ -19,9 +19,9 @@ class Order extends Smser
{
$accountRepo = new AccountRepo();
$account = $accountRepo->findById($order->user_id);
$account = $accountRepo->findById($order->owner_id);
if (!$account->phone) {
if (empty($account->phone)) {
return false;
}

View File

@ -19,9 +19,9 @@ class Refund extends Smser
{
$accountRepo = new AccountRepo();
$account = $accountRepo->findById($refund->user_id);
$account = $accountRepo->findById($refund->owner_id);
if (!$account->phone) {
if (empty($account->phone)) {
return false;
}

View File

@ -36,7 +36,9 @@ class CourseIndex extends Service
$this->redis->sAdd($key, $courseId);
$this->redis->expire($key, $this->lifetime);
if ($this->redis->sCard($key) == 1) {
$this->redis->expire($key, $this->lifetime);
}
}
public function getSyncKey()

View File

@ -36,7 +36,9 @@ class GroupIndex extends Service
$this->redis->sAdd($key, $groupId);
$this->redis->expire($key, $this->lifetime);
if ($this->redis->sCard($key) == 1) {
$this->redis->expire($key, $this->lifetime);
}
}
public function getSyncKey()

View File

@ -65,11 +65,13 @@ class Learning extends Service
$this->cache->save($itemKey, $cacheLearning, $this->lifetime);
}
$syncKey = $this->getSyncKey();
$key = $this->getSyncKey();
$this->redis->sAdd($syncKey, $learning->request_id);
$this->redis->sAdd($key, $learning->request_id);
$this->redis->expire($syncKey, $this->lifetime);
if ($this->redis->sCard($key) == 1) {
$this->redis->expire($key, $this->lifetime);
}
}
public function getItemKey($id)

View File

@ -36,7 +36,9 @@ class UserIndex extends Service
$this->redis->sAdd($key, $userId);
$this->redis->expire($key, $this->lifetime);
if ($this->redis->sCard($key) == 1) {
$this->redis->expire($key, $this->lifetime);
}
}
public function getSyncKey()

File diff suppressed because it is too large Load Diff

View File

@ -80,11 +80,6 @@ final class InsertSettingData extends AbstractMigration
'item_key' => 'push_domain',
'item_value' => 'push.abc.com',
],
[
'section' => 'live',
'item_key' => 'pull_trans_template',
'item_value' => '{"fd":{"id":"fd","bit_rate":"500","summary":"流畅","height":"540"},"sd":{"id":"sd","bit_rate":"1000","summary":"标清","height":"720"},"hd":{"id":"hd","bit_rate":"2000","summary":"高清","height":"1080"}}',
],
[
'section' => 'live',
'item_key' => 'pull_trans_enabled',
@ -125,11 +120,6 @@ final class InsertSettingData extends AbstractMigration
'item_key' => 'pull_domain',
'item_value' => 'play.abc.com',
],
[
'section' => 'live',
'item_key' => 'push_template',
'item_value' => '',
],
[
'section' => 'live',
'item_key' => 'push_auth_key',
@ -375,11 +365,6 @@ final class InsertSettingData extends AbstractMigration
'item_key' => 'watermark_template',
'item_value' => '462027',
],
[
'section' => 'vod',
'item_key' => 'video_template',
'item_value' => '100210,100220,100230',
],
[
'section' => 'vod',
'item_key' => 'audio_format',
@ -400,11 +385,6 @@ final class InsertSettingData extends AbstractMigration
'item_key' => 'storage_region',
'item_value' => '',
],
[
'section' => 'vod',
'item_key' => 'template',
'item_value' => '',
],
[
'section' => 'vod',
'item_key' => 'key_anti_ip_limit',
@ -415,11 +395,6 @@ final class InsertSettingData extends AbstractMigration
'item_key' => 'dist_domain',
'item_value' => '',
],
[
'section' => 'vod',
'item_key' => 'audio_template',
'item_value' => '1110',
],
[
'section' => 'vod',
'item_key' => 'key_anti_key',

View File

@ -16,9 +16,9 @@ final class InsertNavData extends AbstractMigration
'level' => 1,
'name' => '首页',
'path' => ',1,',
'position' => 'top',
'target' => '_self',
'url' => '/',
'position' => 1,
'priority' => 1,
'published' => 1,
],
@ -28,9 +28,9 @@ final class InsertNavData extends AbstractMigration
'level' => 1,
'name' => '录播',
'path' => ',2,',
'position' => 'top',
'target' => '_self',
'url' => '/course/list?model=1',
'position' => 1,
'priority' => 2,
'published' => 1,
],
@ -40,9 +40,9 @@ final class InsertNavData extends AbstractMigration
'level' => 1,
'name' => '直播',
'path' => ',3,',
'position' => 'top',
'target' => '_self',
'url' => '/course/list?model=2',
'position' => 1,
'priority' => 3,
'published' => 1,
],
@ -52,9 +52,9 @@ final class InsertNavData extends AbstractMigration
'level' => 1,
'name' => '专栏',
'path' => ',4,',
'position' => 'top',
'target' => '_self',
'url' => '/course/list?model=3',
'position' => 1,
'priority' => 4,
'published' => 1,
],
@ -64,9 +64,9 @@ final class InsertNavData extends AbstractMigration
'level' => 1,
'name' => '名师',
'path' => ',5,',
'position' => 'top',
'target' => '_self',
'url' => '/teacher/list',
'position' => 1,
'priority' => 5,
'published' => 1,
],
@ -76,9 +76,9 @@ final class InsertNavData extends AbstractMigration
'level' => 1,
'name' => '群组',
'path' => ',6,',
'position' => 'top',
'target' => '_self',
'url' => '/im/group/list',
'position' => 1,
'priority' => 6,
'published' => 1,
],
@ -88,9 +88,9 @@ final class InsertNavData extends AbstractMigration
'level' => 1,
'name' => '关于我们',
'path' => ',7,',
'position' => 'bottom',
'target' => '_blank',
'url' => '#',
'position' => 2,
'priority' => 1,
'published' => 1,
],
@ -100,9 +100,9 @@ final class InsertNavData extends AbstractMigration
'level' => 1,
'name' => '联系我们',
'path' => ',8,',
'position' => 'bottom',
'target' => '_blank',
'url' => '#',
'position' => 2,
'priority' => 2,
'published' => 1,
],
@ -112,9 +112,9 @@ final class InsertNavData extends AbstractMigration
'level' => 1,
'name' => '人才招聘',
'path' => ',9,',
'position' => 'bottom',
'target' => '_blank',
'url' => '#',
'position' => 2,
'priority' => 3,
'published' => 1,
],
@ -124,9 +124,9 @@ final class InsertNavData extends AbstractMigration
'level' => 1,
'name' => '帮助中心',
'path' => ',10,',
'position' => 'bottom',
'target' => '_blank',
'url' => '/help',
'position' => 2,
'priority' => 4,
'published' => 1,
],
@ -136,9 +136,9 @@ final class InsertNavData extends AbstractMigration
'level' => 1,
'name' => '友情链接',
'path' => ',11,',
'position' => 'bottom',
'target' => '_blank',
'url' => '#',
'position' => 2,
'priority' => 5,
'published' => 1,
],

File diff suppressed because it is too large Load Diff

View File

@ -1465,15 +1465,11 @@ body {
text-align: center;
}
.consult-table .item-elip {
width: 450px;
}
.review-table .title {
width: 400px;
}
.review-table .content {
.review-table .content, .consult-table .content {
width: 400px;
color: #666;
}

View File

@ -10,20 +10,20 @@ $script = __DIR__ . '/console.php';
$bin = '/usr/bin/php';
$scheduler->php($script, $bin, ['--task' => 'sync_learning', '--action' => 'main'])
$scheduler->php($script, $bin, ['--task' => 'deliver', '--action' => 'main'])
->at('*/3 * * * *');
$scheduler->php($script, $bin, ['--task' => 'order', '--action' => 'main'])
$scheduler->php($script, $bin, ['--task' => 'live_notify', '--action' => 'main'])
->at('*/5 * * * *');
$scheduler->php($script, $bin, ['--task' => 'sync_learning', '--action' => 'main'])
->at('*/7 * * * *');
$scheduler->php($script, $bin, ['--task' => 'vod_event', '--action' => 'main'])
->at('*/5 * * * *');
->at('*/9 * * * *');
$scheduler->php($script, $bin, ['--task' => 'close_trade', '--action' => 'main'])
->at('*/10 * * * *');
$scheduler->php($script, $bin, ['--task' => 'live_notice_consumer', '--action' => 'main'])
->at('*/15 * * * *');
->at('*/13 * * * *');
$scheduler->php($script, $bin, ['--task' => 'close_order', '--action' => 'main'])
->hourly(3);
@ -43,11 +43,8 @@ $scheduler->php($script, $bin, ['--task' => 'unlock_user', '--action' => 'main']
$scheduler->php($script, $bin, ['--task' => 'revoke_vip', '--action' => 'main'])
->daily(3, 11);
$scheduler->php($script, $bin, ['--task' => 'live_notice_provider', '--action' => 'main'])
->daily(3, 17);
$scheduler->php($script, $bin, ['--task' => 'clean_token', '--action' => 'main'])
->daily(3, 23);
->daily(3, 17);
$scheduler->php($script, $bin, ['--task' => 'site_map', '--action' => 'main'])
->daily(4, 3);