mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-06-25 12:09:09 +08:00
Merge branch 'koogua/v1.5.4' into demo
# Conflicts: # app/Library/AppInfo.php
This commit is contained in:
commit
582c6bdb58
@ -1,3 +1,7 @@
|
|||||||
|
### [v1.5.4](https://gitee.com/koogua/course-tencent-cloud/releases/v1.5.4)(2022-06-30)
|
||||||
|
|
||||||
|
- 优化章节排序初始值和步长
|
||||||
|
|
||||||
### [v1.5.3](https://gitee.com/koogua/course-tencent-cloud/releases/v1.5.3)(2022-05-30)
|
### [v1.5.3](https://gitee.com/koogua/course-tencent-cloud/releases/v1.5.3)(2022-05-30)
|
||||||
|
|
||||||
- 优化章节排序初始值和步长
|
- 优化章节排序初始值和步长
|
||||||
|
@ -84,9 +84,9 @@ class CategoryTreeList extends Builder
|
|||||||
{
|
{
|
||||||
$query = CategoryModel::query();
|
$query = CategoryModel::query();
|
||||||
|
|
||||||
$query->where('published = 1');
|
$query->where('parent_id = :parent_id:', ['parent_id' => $parentId]);
|
||||||
$query->where('deleted = 0');
|
$query->andWhere('published = 1');
|
||||||
$query->andWhere('parent_id = :parent_id:', ['parent_id' => $parentId]);
|
$query->andWhere('deleted = 0');
|
||||||
$query->orderBy('priority ASC');
|
$query->orderBy('priority ASC');
|
||||||
|
|
||||||
return $query->execute();
|
return $query->execute();
|
||||||
|
@ -7,17 +7,16 @@
|
|||||||
|
|
||||||
namespace App\Console\Tasks;
|
namespace App\Console\Tasks;
|
||||||
|
|
||||||
use App\Models\CourseUser as CourseUserModel;
|
|
||||||
use App\Models\ImGroupUser as ImGroupUserModel;
|
|
||||||
use App\Models\PointGift as PointGiftModel;
|
use App\Models\PointGift as PointGiftModel;
|
||||||
use App\Models\PointGiftRedeem as PointGiftRedeemModel;
|
use App\Models\PointGiftRedeem as PointGiftRedeemModel;
|
||||||
use App\Models\Task as TaskModel;
|
use App\Models\Task as TaskModel;
|
||||||
use App\Repos\Course as CourseRepo;
|
use App\Repos\Course as CourseRepo;
|
||||||
use App\Repos\CourseUser as CourseUserRepo;
|
|
||||||
use App\Repos\ImGroup as ImGroupRepo;
|
|
||||||
use App\Repos\ImGroupUser as ImGroupUserRepo;
|
|
||||||
use App\Repos\PointGift as PointGiftRepo;
|
use App\Repos\PointGift as PointGiftRepo;
|
||||||
use App\Repos\PointGiftRedeem as PointGiftRedeemRepo;
|
use App\Repos\PointGiftRedeem as PointGiftRedeemRepo;
|
||||||
|
use App\Repos\User as UserRepo;
|
||||||
|
use App\Repos\Vip as VipRepo;
|
||||||
|
use App\Services\Logic\Deliver\CourseDeliver as CourseDeliverService;
|
||||||
|
use App\Services\Logic\Deliver\VipDeliver as VipDeliverService;
|
||||||
use App\Services\Logic\Notice\DingTalk\PointGiftRedeem as PointGiftRedeemNotice;
|
use App\Services\Logic\Notice\DingTalk\PointGiftRedeem as PointGiftRedeemNotice;
|
||||||
use App\Services\Logic\Point\History\PointGiftRefund as PointGiftRefundPointHistory;
|
use App\Services\Logic\Point\History\PointGiftRefund as PointGiftRefundPointHistory;
|
||||||
use Phalcon\Mvc\Model\Resultset;
|
use Phalcon\Mvc\Model\Resultset;
|
||||||
@ -52,6 +51,9 @@ class PointGiftDeliverTask extends Task
|
|||||||
case PointGiftModel::TYPE_COURSE:
|
case PointGiftModel::TYPE_COURSE:
|
||||||
$this->handleCourseRedeem($redeem);
|
$this->handleCourseRedeem($redeem);
|
||||||
break;
|
break;
|
||||||
|
case PointGiftModel::TYPE_VIP:
|
||||||
|
$this->handleVipRedeem($redeem);
|
||||||
|
break;
|
||||||
case PointGiftModel::TYPE_GOODS:
|
case PointGiftModel::TYPE_GOODS:
|
||||||
$this->handleGoodsRedeem($redeem);
|
$this->handleGoodsRedeem($redeem);
|
||||||
break;
|
break;
|
||||||
@ -112,54 +114,52 @@ class PointGiftDeliverTask extends Task
|
|||||||
throw new \RuntimeException('Course Not Found');
|
throw new \RuntimeException('Course Not Found');
|
||||||
}
|
}
|
||||||
|
|
||||||
$groupRepo = new ImGroupRepo();
|
$redeem->status = PointGiftRedeemModel::STATUS_FINISHED;
|
||||||
|
|
||||||
$group = $groupRepo->findByCourseId($course->id);
|
if ($redeem->update() === false) {
|
||||||
|
throw new \RuntimeException('Update Point Redeem Status Failed');
|
||||||
if (!$group) {
|
|
||||||
throw new \RuntimeException('Im Group Not Found');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$courseUserRepo = new CourseUserRepo();
|
$userRepo = new UserRepo();
|
||||||
|
|
||||||
$courseUser = $courseUserRepo->findCourseUser($course->id, $redeem->user_id);
|
$user = $userRepo->findById($redeem->user_id);
|
||||||
|
|
||||||
if (!$courseUser) {
|
$deliverService = new CourseDeliverService();
|
||||||
|
|
||||||
$courseUser = new CourseUserModel();
|
$deliverService->handle($course, $user);
|
||||||
|
}
|
||||||
|
|
||||||
$courseUser->user_id = $redeem->user_id;
|
protected function handleVipRedeem(PointGiftRedeemModel $redeem)
|
||||||
$courseUser->course_id = $course->id;
|
{
|
||||||
$courseUser->expiry_time = strtotime("+{$course->study_expiry} months");
|
$giftRepo = new PointGiftRepo();
|
||||||
$courseUser->role_type = CourseUserModel::ROLE_STUDENT;
|
|
||||||
$courseUser->source_type = CourseUserModel::SOURCE_POINT_REDEEM;
|
|
||||||
|
|
||||||
if ($courseUser->create() === false) {
|
$gift = $giftRepo->findById($redeem->gift_id);
|
||||||
throw new \RuntimeException('Create Course User Failed');
|
|
||||||
}
|
if (!$gift) {
|
||||||
|
throw new \RuntimeException('Gift Not Found');
|
||||||
}
|
}
|
||||||
|
|
||||||
$groupUserRepo = new ImGroupUserRepo();
|
$vipRepo = new VipRepo();
|
||||||
|
|
||||||
$groupUser = $groupUserRepo->findGroupUser($group->id, $redeem->user_id);
|
$vip = $vipRepo->findById($gift->attrs['id']);
|
||||||
|
|
||||||
if (!$groupUser) {
|
if (!$vip) {
|
||||||
|
throw new \RuntimeException('Vip Not Found');
|
||||||
$groupUser = new ImGroupUserModel();
|
|
||||||
|
|
||||||
$groupUser->group_id = $group->id;
|
|
||||||
$groupUser->user_id = $redeem->user_id;
|
|
||||||
|
|
||||||
if ($groupUser->create() === false) {
|
|
||||||
throw new \RuntimeException('Create Group User Failed');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$redeem->status = PointGiftRedeemModel::STATUS_FINISHED;
|
$redeem->status = PointGiftRedeemModel::STATUS_FINISHED;
|
||||||
|
|
||||||
if ($redeem->update() === false) {
|
if ($redeem->update() === false) {
|
||||||
throw new \RuntimeException('Update Redeem Status Failed');
|
throw new \RuntimeException('Update Point Redeem Status Failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$userRepo = new UserRepo();
|
||||||
|
|
||||||
|
$user = $userRepo->findById($redeem->user_id);
|
||||||
|
|
||||||
|
$deliverService = new VipDeliverService();
|
||||||
|
|
||||||
|
$deliverService->handle($vip, $user);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleGoodsRedeem(PointGiftRedeemModel $redeem)
|
protected function handleGoodsRedeem(PointGiftRedeemModel $redeem)
|
||||||
|
@ -56,11 +56,19 @@ class VodEventTask extends Task
|
|||||||
|
|
||||||
$attrs = $chapter->attrs;
|
$attrs = $chapter->attrs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取不到时长,尝试通过主动查询获取
|
||||||
|
*/
|
||||||
|
if ($duration == 0) {
|
||||||
|
$duration = $this->getFileDuration($fileId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取不到时长视为失败
|
* 获取不到时长视为失败
|
||||||
*/
|
*/
|
||||||
if ($duration == 0) {
|
if ($duration == 0) {
|
||||||
$attrs['file']['status'] = ChapterModel::FS_FAILED;
|
$attrs['file']['status'] = ChapterModel::FS_FAILED;
|
||||||
|
$attrs['duration'] = 0;
|
||||||
$chapter->update(['attrs' => $attrs]);
|
$chapter->update(['attrs' => $attrs]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -78,7 +86,7 @@ class VodEventTask extends Task
|
|||||||
|
|
||||||
$chapter->update(['attrs' => $attrs]);
|
$chapter->update(['attrs' => $attrs]);
|
||||||
|
|
||||||
$this->updateVodAttrs($chapter);
|
$this->updateCourseVodAttrs($chapter->course_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleProcedureStateChangedEvent($event)
|
protected function handleProcedureStateChangedEvent($event)
|
||||||
@ -95,6 +103,13 @@ class VodEventTask extends Task
|
|||||||
|
|
||||||
$attrs = $chapter->attrs;
|
$attrs = $chapter->attrs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取不到时长,尝试通过接口获得
|
||||||
|
*/
|
||||||
|
if ($attrs['duration'] == 0) {
|
||||||
|
$attrs['duration'] = $this->getFileDuration($fileId);
|
||||||
|
}
|
||||||
|
|
||||||
$processResult = $event['ProcedureStateChangeEvent']['MediaProcessResultSet'] ?? [];
|
$processResult = $event['ProcedureStateChangeEvent']['MediaProcessResultSet'] ?? [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -156,11 +171,20 @@ class VodEventTask extends Task
|
|||||||
return $vodService->confirmEvents($handles);
|
return $vodService->confirmEvents($handles);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function updateVodAttrs(ChapterModel $chapter)
|
protected function updateCourseVodAttrs($courseId)
|
||||||
{
|
{
|
||||||
$courseStats = new CourseStatService();
|
$courseStats = new CourseStatService();
|
||||||
|
|
||||||
$courseStats->updateVodAttrs($chapter->course_id);
|
$courseStats->updateVodAttrs($courseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getFileDuration($fileId)
|
||||||
|
{
|
||||||
|
$service = new VodService();
|
||||||
|
|
||||||
|
$metaInfo = $service->getOriginVideoInfo($fileId);
|
||||||
|
|
||||||
|
return $metaInfo['duration'] ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -47,9 +47,11 @@ class PointGiftController extends Controller
|
|||||||
$service = new PointGiftService();
|
$service = new PointGiftService();
|
||||||
|
|
||||||
$xmCourses = $service->getXmCourses();
|
$xmCourses = $service->getXmCourses();
|
||||||
|
$xmVips = $service->getXmVips();
|
||||||
$types = $service->getTypes();
|
$types = $service->getTypes();
|
||||||
|
|
||||||
$this->view->setVar('xm_courses', $xmCourses);
|
$this->view->setVar('xm_courses', $xmCourses);
|
||||||
|
$this->view->setVar('xm_vips', $xmVips);
|
||||||
$this->view->setVar('types', $types);
|
$this->view->setVar('types', $types);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,14 +133,19 @@ class ChapterContent extends Service
|
|||||||
|
|
||||||
$vod = $chapterRepo->findChapterVod($chapter->id);
|
$vod = $chapterRepo->findChapterVod($chapter->id);
|
||||||
|
|
||||||
$vod->file_id = $fileId;
|
|
||||||
$vod->file_transcode = [];
|
|
||||||
$vod->update();
|
|
||||||
|
|
||||||
$attrs = $chapter->attrs;
|
$attrs = $chapter->attrs;
|
||||||
$attrs['duration'] = 0;
|
|
||||||
$attrs['file']['status'] = ChapterModel::FS_UPLOADED;
|
if ($fileId != $vod->file_id) {
|
||||||
|
$vod->file_id = $fileId;
|
||||||
|
$vod->file_transcode = [];
|
||||||
|
$vod->update();
|
||||||
|
|
||||||
|
$attrs['file']['status'] = ChapterModel::FS_UPLOADED;
|
||||||
|
$attrs['duration'] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
$chapter->attrs = $attrs;
|
$chapter->attrs = $attrs;
|
||||||
|
|
||||||
$chapter->update();
|
$chapter->update();
|
||||||
|
|
||||||
$this->updateCourseVodAttrs($vod->course_id);
|
$this->updateCourseVodAttrs($vod->course_id);
|
||||||
|
@ -274,6 +274,7 @@ class Course extends Service
|
|||||||
$allCategories = $categoryRepo->findAll([
|
$allCategories = $categoryRepo->findAll([
|
||||||
'type' => CategoryModel::TYPE_COURSE,
|
'type' => CategoryModel::TYPE_COURSE,
|
||||||
'published' => 1,
|
'published' => 1,
|
||||||
|
'deleted' => 0,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($allCategories->count() == 0) return [];
|
if ($allCategories->count() == 0) return [];
|
||||||
|
@ -50,7 +50,11 @@ class FlashSale extends Service
|
|||||||
{
|
{
|
||||||
$courseRepo = new CourseRepo();
|
$courseRepo = new CourseRepo();
|
||||||
|
|
||||||
$items = $courseRepo->findAll(['free' => 0, 'published' => 1]);
|
$items = $courseRepo->findAll([
|
||||||
|
'free' => 0,
|
||||||
|
'published' => 1,
|
||||||
|
'deleted' => 0,
|
||||||
|
]);
|
||||||
|
|
||||||
if ($items->count() == 0) return [];
|
if ($items->count() == 0) return [];
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ use App\Library\Paginator\Query as PagerQuery;
|
|||||||
use App\Models\PointGift as PointGiftModel;
|
use App\Models\PointGift as PointGiftModel;
|
||||||
use App\Repos\Course as CourseRepo;
|
use App\Repos\Course as CourseRepo;
|
||||||
use App\Repos\PointGift as PointGiftRepo;
|
use App\Repos\PointGift as PointGiftRepo;
|
||||||
|
use App\Repos\Vip as VipRepo;
|
||||||
use App\Validators\PointGift as PointGiftValidator;
|
use App\Validators\PointGift as PointGiftValidator;
|
||||||
|
|
||||||
class PointGift extends Service
|
class PointGift extends Service
|
||||||
@ -47,6 +48,29 @@ class PointGift extends Service
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getXmVips()
|
||||||
|
{
|
||||||
|
$vipRepo = new VipRepo();
|
||||||
|
|
||||||
|
$items = $vipRepo->findAll([
|
||||||
|
'published' => 1,
|
||||||
|
'deleted' => 0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($items->count() == 0) return [];
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$result[] = [
|
||||||
|
'name' => sprintf('%s(¥%0.2f)', $item->title, $item->price),
|
||||||
|
'value' => $item->id,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
public function getPointGifts()
|
public function getPointGifts()
|
||||||
{
|
{
|
||||||
$pagerQuery = new PagerQuery();
|
$pagerQuery = new PagerQuery();
|
||||||
@ -83,6 +107,9 @@ class PointGift extends Service
|
|||||||
case PointGiftModel::TYPE_COURSE:
|
case PointGiftModel::TYPE_COURSE:
|
||||||
$gift = $this->createCoursePointGift($post);
|
$gift = $this->createCoursePointGift($post);
|
||||||
break;
|
break;
|
||||||
|
case PointGiftModel::TYPE_VIP:
|
||||||
|
$gift = $this->createVipPointGift($post);
|
||||||
|
break;
|
||||||
case PointGiftModel::TYPE_GOODS:
|
case PointGiftModel::TYPE_GOODS:
|
||||||
$gift = $this->createGoodsPointGift($post);
|
$gift = $this->createGoodsPointGift($post);
|
||||||
break;
|
break;
|
||||||
@ -168,7 +195,7 @@ class PointGift extends Service
|
|||||||
|
|
||||||
$giftRepo = new PointGiftRepo();
|
$giftRepo = new PointGiftRepo();
|
||||||
|
|
||||||
$gift = $giftRepo->findByCourseId($course->id);
|
$gift = $giftRepo->findItemGift($course->id, PointGiftModel::TYPE_COURSE);
|
||||||
|
|
||||||
if ($gift) return $gift;
|
if ($gift) return $gift;
|
||||||
|
|
||||||
@ -188,6 +215,34 @@ class PointGift extends Service
|
|||||||
return $gift;
|
return $gift;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function createVipPointGift($post)
|
||||||
|
{
|
||||||
|
$validator = new PointGiftValidator();
|
||||||
|
|
||||||
|
$vip = $validator->checkVip($post['xm_vip_id']);
|
||||||
|
|
||||||
|
$giftRepo = new PointGiftRepo();
|
||||||
|
|
||||||
|
$gift = $giftRepo->findItemGift($vip->id, PointGiftModel::TYPE_VIP);
|
||||||
|
|
||||||
|
if ($gift) return $gift;
|
||||||
|
|
||||||
|
$gift = new PointGiftModel();
|
||||||
|
|
||||||
|
$gift->type = PointGiftModel::TYPE_VIP;
|
||||||
|
$gift->name = sprintf('会员服务(%s个月)', $vip->expiry);
|
||||||
|
$gift->cover = $vip->cover;
|
||||||
|
$gift->attrs = [
|
||||||
|
'id' => $vip->id,
|
||||||
|
'title' => $vip->title,
|
||||||
|
'price' => $vip->price,
|
||||||
|
];
|
||||||
|
|
||||||
|
$gift->create();
|
||||||
|
|
||||||
|
return $gift;
|
||||||
|
}
|
||||||
|
|
||||||
protected function createGoodsPointGift($post)
|
protected function createGoodsPointGift($post)
|
||||||
{
|
{
|
||||||
$validator = new PointGiftValidator();
|
$validator = new PointGiftValidator();
|
||||||
|
@ -70,7 +70,7 @@
|
|||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<label class="layui-form-label"></label>
|
<label class="layui-form-label"></label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
|
<button id="vod-submit" class="layui-btn layui-btn-disabled" disabled="disabled" lay-submit="true" lay-filter="go">提交</button>
|
||||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
{% elseif value == 2 %}
|
{% elseif value == 2 %}
|
||||||
商品
|
商品
|
||||||
{% elseif value == 3 %}
|
{% elseif value == 3 %}
|
||||||
现金
|
会员
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
|
@ -22,6 +22,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="block-3" class="block" style="display:none;">
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">会员选择</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<div id="xm-vip-id"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="block-2" class="block" style="display:none;">
|
<div id="block-2" class="block" style="display:none;">
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<label class="layui-form-label">商品名称</label>
|
<label class="layui-form-label">商品名称</label>
|
||||||
@ -67,6 +75,13 @@
|
|||||||
data: {{ xm_courses|json_encode }}
|
data: {{ xm_courses|json_encode }}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
xmSelect.render({
|
||||||
|
el: '#xm-vip-id',
|
||||||
|
name: 'xm_vip_id',
|
||||||
|
radio: true,
|
||||||
|
data: {{ xm_vips|json_encode }}
|
||||||
|
});
|
||||||
|
|
||||||
form.on('radio(type)', function (data) {
|
form.on('radio(type)', function (data) {
|
||||||
$('.block').hide();
|
$('.block').hide();
|
||||||
$('#block-' + data.value).show();
|
$('#block-' + data.value).show();
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
{% if gift.type == 1 %}
|
{% if gift.type == 1 %}
|
||||||
{{ partial('point_gift/edit_course') }}
|
{{ partial('point_gift/edit_course') }}
|
||||||
|
{% elseif gift.type == 3 %}
|
||||||
|
{{ partial('point_gift/edit_vip') }}
|
||||||
{% elseif gift.type == 2 %}
|
{% elseif gift.type == 2 %}
|
||||||
{{ partial('point_gift/edit_goods') }}
|
{{ partial('point_gift/edit_goods') }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
41
app/Http/Admin/Views/point_gift/edit_vip.volt
Normal file
41
app/Http/Admin/Views/point_gift/edit_vip.volt
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<form class="layui-form kg-form" method="POST" action="{{ update_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-inline">
|
||||||
|
<img id="img-cover" class="kg-cover" src="{{ gift.cover }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">礼品名称</label>
|
||||||
|
<div class="layui-form-mid layui-word-aux">{{ gift.name }}({{ '¥%0.2f'|format(gift.attrs['price']) }})</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="point" value="{{ gift.point }}" lay-verify="number">
|
||||||
|
</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="stock" value="{{ gift.stock }}" lay-verify="number">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">发布</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<input type="radio" name="published" value="1" title="是" {% if gift.published == 1 %}checked="checked"{% endif %}>
|
||||||
|
<input type="radio" name="published" value="0" title="否" {% if gift.published == 0 %}checked="checked"{% endif %}>
|
||||||
|
</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>
|
@ -93,6 +93,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<div class="layui-inline">
|
||||||
|
<label class="layui-form-label">ISP备案号</label>
|
||||||
|
<div class="kg-input-inline">
|
||||||
|
<input class="layui-input" type="text" name="isp_sn" value="{{ site.isp_sn }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-inline">
|
||||||
|
<label class="layui-form-label">备案链接</label>
|
||||||
|
<div class="kg-input-inline" style="width:500px;">
|
||||||
|
<input class="layui-input" type="text" name="isp_link" value="{{ site.isp_link }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<div class="layui-inline">
|
<div class="layui-inline">
|
||||||
<label class="layui-form-label">公安备案号</label>
|
<label class="layui-form-label">公安备案号</label>
|
||||||
@ -107,6 +121,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<div class="layui-inline">
|
||||||
|
<label class="layui-form-label">企业信用代码</label>
|
||||||
|
<div class="kg-input-inline">
|
||||||
|
<input class="layui-input" type="text" name="company_sn" value="{{ site.company_sn }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-inline">
|
||||||
|
<label class="layui-form-label">电子执照链接</label>
|
||||||
|
<div class="kg-input-inline" style="width:500px;">
|
||||||
|
<input class="layui-input" type="text" name="company_sn_link" value="{{ site.company_sn_link }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<label class="layui-form-label">开启统计</label>
|
<label class="layui-form-label">开启统计</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
{% elseif value == 2 %}
|
{% elseif value == 2 %}
|
||||||
商品
|
商品
|
||||||
{% elseif value == 3 %}
|
{% elseif value == 3 %}
|
||||||
现金
|
会员
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
|
@ -12,9 +12,15 @@
|
|||||||
{% if site_info.icp_sn %}
|
{% if site_info.icp_sn %}
|
||||||
<a href="{{ site_info.icp_link }}" target="_blank">{{ site_info.icp_sn }}</a>
|
<a href="{{ site_info.icp_link }}" target="_blank">{{ site_info.icp_sn }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if site_info.isp_sn %}
|
||||||
|
<a href="{{ site_info.isp_link }}" target="_blank">{{ site_info.isp_sn }}</a>
|
||||||
|
{% endif %}
|
||||||
{% if site_info.police_sn %}
|
{% if site_info.police_sn %}
|
||||||
<a href="{{ site_info.police_link }}" target="_blank">{{ site_info.police_sn }}</a>
|
<a href="{{ site_info.police_link }}" target="_blank">{{ site_info.police_sn }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if site_info.company_sn %}
|
||||||
|
<a href="{{ site_info.company_sn_link }}" title="企业信用代码:{{ site_info.company_sn }}" target="_blank">工商网监电子标识</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if contact_info.enabled == 1 %}
|
{% if contact_info.enabled == 1 %}
|
||||||
<div class="row contact">
|
<div class="row contact">
|
||||||
|
@ -16,7 +16,7 @@ class AppInfo
|
|||||||
|
|
||||||
protected $link = 'https://koogua.com';
|
protected $link = 'https://koogua.com';
|
||||||
|
|
||||||
protected $version = '1.5.3';
|
protected $version = '1.5.4';
|
||||||
|
|
||||||
public function __get($name)
|
public function __get($name)
|
||||||
{
|
{
|
||||||
|
@ -19,6 +19,7 @@ class PointGift extends Model
|
|||||||
*/
|
*/
|
||||||
const TYPE_COURSE = 1; // 课程
|
const TYPE_COURSE = 1; // 课程
|
||||||
const TYPE_GOODS = 2; // 商品
|
const TYPE_GOODS = 2; // 商品
|
||||||
|
const TYPE_VIP = 3; // 会员
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 课程扩展属性
|
* 课程扩展属性
|
||||||
@ -31,6 +32,17 @@ class PointGift extends Model
|
|||||||
'price' => 0,
|
'price' => 0,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员扩展属性
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $_vip_attrs = [
|
||||||
|
'id' => 0,
|
||||||
|
'title' => '',
|
||||||
|
'price' => 0,
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品扩展属性
|
* 商品扩展属性
|
||||||
*
|
*
|
||||||
@ -162,6 +174,8 @@ class PointGift extends Model
|
|||||||
if (empty($this->attrs)) {
|
if (empty($this->attrs)) {
|
||||||
if ($this->type == self::TYPE_COURSE) {
|
if ($this->type == self::TYPE_COURSE) {
|
||||||
$this->attrs = $this->_course_attrs;
|
$this->attrs = $this->_course_attrs;
|
||||||
|
} elseif ($this->type == self::TYPE_VIP) {
|
||||||
|
$this->attrs = $this->_vip_attrs;
|
||||||
} elseif ($this->type == self::TYPE_GOODS) {
|
} elseif ($this->type == self::TYPE_GOODS) {
|
||||||
$this->attrs = $this->_goods_attrs;
|
$this->attrs = $this->_goods_attrs;
|
||||||
}
|
}
|
||||||
@ -224,6 +238,7 @@ class PointGift extends Model
|
|||||||
return [
|
return [
|
||||||
self::TYPE_COURSE => '课程',
|
self::TYPE_COURSE => '课程',
|
||||||
self::TYPE_GOODS => '商品',
|
self::TYPE_GOODS => '商品',
|
||||||
|
self::TYPE_VIP => '会员',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,4 +163,17 @@ class CourseUser extends Repository
|
|||||||
->execute();
|
->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $courseId
|
||||||
|
* @param int $userId
|
||||||
|
* @return ResultsetInterface|Resultset|CourseUserModel[]
|
||||||
|
*/
|
||||||
|
public function findByCourseAndUserId($courseId, $userId)
|
||||||
|
{
|
||||||
|
return CourseUserModel::query()
|
||||||
|
->where('course_id = :course_id:', ['course_id' => $courseId])
|
||||||
|
->andWhere('user_id = :user_id:', ['user_id' => $userId])
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -77,10 +77,11 @@ class PointGift extends Repository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $courseId
|
* @param int $itemId
|
||||||
|
* @param int $itemType
|
||||||
* @return PointGiftModel|Model|bool
|
* @return PointGiftModel|Model|bool
|
||||||
*/
|
*/
|
||||||
public function findByCourseId($courseId)
|
public function findItemGift($itemId, $itemType)
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @todo 重新设计表结构
|
* @todo 重新设计表结构
|
||||||
@ -88,13 +89,13 @@ class PointGift extends Repository
|
|||||||
* 没有预留独立的条目编号,先这么将就实现吧
|
* 没有预留独立的条目编号,先这么将就实现吧
|
||||||
*/
|
*/
|
||||||
$records = PointGiftModel::query()
|
$records = PointGiftModel::query()
|
||||||
->where('type = :type:', ['type' => PointGiftModel::TYPE_COURSE])
|
->where('type = :type:', ['type' => $itemType])
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
if ($records->count() == 0) return false;
|
if ($records->count() == 0) return false;
|
||||||
|
|
||||||
foreach ($records as $record) {
|
foreach ($records as $record) {
|
||||||
if ($record->attrs['id'] == $courseId) {
|
if ($record->attrs['id'] == $itemId) {
|
||||||
return $record;
|
return $record;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ use App\Models\Course as CourseModel;
|
|||||||
use App\Models\CourseUser as CourseUserModel;
|
use App\Models\CourseUser as CourseUserModel;
|
||||||
use App\Models\ImGroupUser as ImGroupUserModel;
|
use App\Models\ImGroupUser as ImGroupUserModel;
|
||||||
use App\Models\User as UserModel;
|
use App\Models\User as UserModel;
|
||||||
|
use App\Repos\CourseUser as CourseUserRepo;
|
||||||
use App\Repos\ImGroup as ImGroupRepo;
|
use App\Repos\ImGroup as ImGroupRepo;
|
||||||
use App\Repos\ImGroupUser as ImGroupUserRepo;
|
use App\Repos\ImGroupUser as ImGroupUserRepo;
|
||||||
use App\Repos\ImUser as ImUserRepo;
|
use App\Repos\ImUser as ImUserRepo;
|
||||||
@ -20,6 +21,13 @@ class CourseDeliver extends LogicService
|
|||||||
{
|
{
|
||||||
|
|
||||||
public function handle(CourseModel $course, UserModel $user)
|
public function handle(CourseModel $course, UserModel $user)
|
||||||
|
{
|
||||||
|
$this->revokeCourseUser($course, $user);
|
||||||
|
$this->handleCourseUser($course, $user);
|
||||||
|
$this->handleImGroupUser($course, $user);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function handleCourseUser(CourseModel $course, UserModel $user)
|
||||||
{
|
{
|
||||||
if ($course->model == CourseModel::MODEL_OFFLINE) {
|
if ($course->model == CourseModel::MODEL_OFFLINE) {
|
||||||
$expiryTime = strtotime($course->attrs['end_date']);
|
$expiryTime = strtotime($course->attrs['end_date']);
|
||||||
@ -28,7 +36,6 @@ class CourseDeliver extends LogicService
|
|||||||
}
|
}
|
||||||
|
|
||||||
$courseUser = new CourseUserModel();
|
$courseUser = new CourseUserModel();
|
||||||
|
|
||||||
$courseUser->user_id = $user->id;
|
$courseUser->user_id = $user->id;
|
||||||
$courseUser->course_id = $course->id;
|
$courseUser->course_id = $course->id;
|
||||||
$courseUser->expiry_time = $expiryTime;
|
$courseUser->expiry_time = $expiryTime;
|
||||||
@ -39,6 +46,12 @@ class CourseDeliver extends LogicService
|
|||||||
$course->user_count += 1;
|
$course->user_count += 1;
|
||||||
$course->update();
|
$course->update();
|
||||||
|
|
||||||
|
$user->course_count += 1;
|
||||||
|
$user->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function handleImGroupUser(CourseModel $course, UserModel $user)
|
||||||
|
{
|
||||||
$groupRepo = new ImGroupRepo();
|
$groupRepo = new ImGroupRepo();
|
||||||
|
|
||||||
$group = $groupRepo->findByCourseId($course->id);
|
$group = $groupRepo->findByCourseId($course->id);
|
||||||
@ -52,9 +65,7 @@ class CourseDeliver extends LogicService
|
|||||||
$groupUser = $groupUserRepo->findGroupUser($group->id, $user->id);
|
$groupUser = $groupUserRepo->findGroupUser($group->id, $user->id);
|
||||||
|
|
||||||
if (!$groupUser) {
|
if (!$groupUser) {
|
||||||
|
|
||||||
$groupUser = new ImGroupUserModel();
|
$groupUser = new ImGroupUserModel();
|
||||||
|
|
||||||
$groupUser->group_id = $group->id;
|
$groupUser->group_id = $group->id;
|
||||||
$groupUser->user_id = $user->id;
|
$groupUser->user_id = $user->id;
|
||||||
$groupUser->create();
|
$groupUser->create();
|
||||||
@ -67,4 +78,20 @@ class CourseDeliver extends LogicService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function revokeCourseUser(CourseModel $course, UserModel $user)
|
||||||
|
{
|
||||||
|
$courseUserRepo = new CourseUserRepo();
|
||||||
|
|
||||||
|
$relations = $courseUserRepo->findByCourseAndUserId($course->id, $user->id);
|
||||||
|
|
||||||
|
if ($relations->count() == 0) return;
|
||||||
|
|
||||||
|
foreach ($relations as $relation) {
|
||||||
|
if ($relation->deleted == 0) {
|
||||||
|
$relation->deleted = 1;
|
||||||
|
$relation->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,8 @@
|
|||||||
|
|
||||||
namespace App\Services\Logic\Deliver;
|
namespace App\Services\Logic\Deliver;
|
||||||
|
|
||||||
use App\Models\CourseUser as CourseUserModel;
|
|
||||||
use App\Models\ImGroupUser as ImGroupUserModel;
|
|
||||||
use App\Models\Package as PackageModel;
|
use App\Models\Package as PackageModel;
|
||||||
use App\Models\User as UserModel;
|
use App\Models\User as UserModel;
|
||||||
use App\Repos\ImGroup as ImGroupRepo;
|
|
||||||
use App\Repos\ImGroupUser as ImGroupUserRepo;
|
|
||||||
use App\Repos\ImUser as ImUserRepo;
|
|
||||||
use App\Repos\Package as PackageRepo;
|
use App\Repos\Package as PackageRepo;
|
||||||
use App\Services\Logic\Service as LogicService;
|
use App\Services\Logic\Service as LogicService;
|
||||||
|
|
||||||
@ -27,43 +22,8 @@ class PackageDeliver extends LogicService
|
|||||||
$courses = $packageRepo->findCourses($package->id);
|
$courses = $packageRepo->findCourses($package->id);
|
||||||
|
|
||||||
foreach ($courses as $course) {
|
foreach ($courses as $course) {
|
||||||
|
$deliver = new CourseDeliver();
|
||||||
$courseUser = new CourseUserModel();
|
$deliver->handle($course, $user);
|
||||||
|
|
||||||
$courseUser->user_id = $user->id;
|
|
||||||
$courseUser->course_id = $course->id;
|
|
||||||
$courseUser->expiry_time = strtotime("+{$course->study_expiry} months");
|
|
||||||
$courseUser->role_type = CourseUserModel::ROLE_STUDENT;
|
|
||||||
$courseUser->source_type = CourseUserModel::SOURCE_CHARGE;
|
|
||||||
$courseUser->create();
|
|
||||||
|
|
||||||
$course->user_count += 1;
|
|
||||||
$course->update();
|
|
||||||
|
|
||||||
$imUserRepo = new ImUserRepo();
|
|
||||||
|
|
||||||
$imUser = $imUserRepo->findById($user->id);
|
|
||||||
|
|
||||||
$groupRepo = new ImGroupRepo();
|
|
||||||
|
|
||||||
$group = $groupRepo->findByCourseId($course->id);
|
|
||||||
|
|
||||||
$groupUserRepo = new ImGroupUserRepo();
|
|
||||||
|
|
||||||
$groupUser = $groupUserRepo->findGroupUser($group->id, $user->id);
|
|
||||||
|
|
||||||
if (!$groupUser) {
|
|
||||||
$groupUser = new ImGroupUserModel();
|
|
||||||
$groupUser->group_id = $group->id;
|
|
||||||
$groupUser->user_id = $user->id;
|
|
||||||
$groupUser->create();
|
|
||||||
|
|
||||||
$imUser->group_count += 1;
|
|
||||||
$imUser->update();
|
|
||||||
|
|
||||||
$group->user_count += 1;
|
|
||||||
$group->update();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,4 +177,11 @@ class PointGift extends Validator
|
|||||||
return $validator->checkCourse($id);
|
return $validator->checkCourse($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function checkVip($id)
|
||||||
|
{
|
||||||
|
$validator = new Vip();
|
||||||
|
|
||||||
|
return $validator->checkVip($id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
51
db/migrations/20220607014823.php
Normal file
51
db/migrations/20220607014823.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2022 深圳市酷瓜软件有限公司
|
||||||
|
* @license https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* @link https://www.koogua.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once 'SettingTrait.php';
|
||||||
|
|
||||||
|
use Phinx\Migration\AbstractMigration;
|
||||||
|
|
||||||
|
final class V20220607014823 extends AbstractMigration
|
||||||
|
{
|
||||||
|
|
||||||
|
use SettingTrait;
|
||||||
|
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
$this->handleSiteSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function handleSiteSettings()
|
||||||
|
{
|
||||||
|
$rows =
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'section' => 'site',
|
||||||
|
'item_key' => 'isp_sn',
|
||||||
|
'item_value' => '',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'section' => 'site',
|
||||||
|
'item_key' => 'isp_link',
|
||||||
|
'item_value' => 'https://dxzhgl.miit.gov.cn',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'section' => 'site',
|
||||||
|
'item_key' => 'company_sn',
|
||||||
|
'item_value' => '',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'section' => 'site',
|
||||||
|
'item_key' => 'company_sn_link',
|
||||||
|
'item_value' => '',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->insertSettings($rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
34
db/migrations/SettingTrait.php
Normal file
34
db/migrations/SettingTrait.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2022 深圳市酷瓜软件有限公司
|
||||||
|
* @license https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* @link https://www.koogua.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
trait SettingTrait
|
||||||
|
{
|
||||||
|
|
||||||
|
protected function insertSettings(array $rows)
|
||||||
|
{
|
||||||
|
foreach ($rows as $key => $row) {
|
||||||
|
$exists = $this->settingExits($row['section'], $row['item_key']);
|
||||||
|
if ($exists) unset($rows[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($rows) == 0) return;
|
||||||
|
|
||||||
|
$this->table('kg_setting')->insert($rows)->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function settingExits($section, $itemKey)
|
||||||
|
{
|
||||||
|
$row = $this->getQueryBuilder()
|
||||||
|
->select('*')
|
||||||
|
->from('kg_setting')
|
||||||
|
->where(['section' => $section, 'item_key' => $itemKey])
|
||||||
|
->execute()->fetch();
|
||||||
|
|
||||||
|
return $row ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -46,6 +46,7 @@ layui.use(['jquery', 'element'], function () {
|
|||||||
|
|
||||||
uploader.done().then(function (result) {
|
uploader.done().then(function (result) {
|
||||||
$('input[name=file_id]').val(result.fileId);
|
$('input[name=file_id]').val(result.fileId);
|
||||||
|
$('#vod-submit').removeAttr('disabled').removeClass('layui-btn-disabled');
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: $('#vod-form').attr('action'),
|
url: $('#vod-form').attr('action'),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user