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

Merge branch 'develop'

This commit is contained in:
koogua 2022-02-17 11:09:57 +08:00
commit d736b5ac61
95 changed files with 732 additions and 671 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
/.git
/.idea /.idea
/vendor /vendor
/config/config.php /config/config.php

View File

@ -1,3 +1,17 @@
### [v1.5.0](https://gitee.com/koogua/course-tencent-cloud/releases/v1.5.0)(2022-02-17)
- 调整对内部人员通知任务类型的前缀
- 调整微信和短信通知发送判断逻辑
- 清理后台实用工具的无用文件内容
- 支付后解除秒杀商品锁定
- 加强支付流程数据验证
- 加强退款流程数据验证
- 优化账户创建数据流
- 优化课程创建数据流
- 优化章节创建数据流
- 优化积分商品兑换
- 优化发货逻辑
### [v1.4.9](https://gitee.com/koogua/course-tencent-cloud/releases/v1.4.9)(2022-01-01) ### [v1.4.9](https://gitee.com/koogua/course-tencent-cloud/releases/v1.4.9)(2022-01-01)
- 修正订单消费未奖励积分问题 - 修正订单消费未奖励积分问题

View File

@ -1,15 +1,15 @@
## 酷瓜云课堂 ## 酷瓜云课堂
![酷瓜云网课GPL协议开源](https://portal-1255691183.file.myqcloud.com/img/content/60e7aea40966f.png) ![酷瓜云课堂](https://portal-1255691183.file.myqcloud.com/img/content/61dd395c053e5.png)
### 系统介绍 ### 系统介绍
酷瓜云课堂依托腾讯云基础服务架构采用C扩展框架Phalcon开发GPL-2.0开源协议,致力开源网课系统,开源网校系统,开源知识付费系统,开源在线教育系统。 酷瓜云课堂依托腾讯云基础服务架构采用C扩展框架Phalcon开发GPL-2.0开源协议,致力开源网课系统,开源网校系统,开源知识付费系统,开源在线教育系统。
![star](https://svg.hamm.cn/gitee.svg?user=koogua&project=course-tencent-cloud&type=star) ![star](https://koogua.com/gitee/badge?user=koogua&project=course-tencent-cloud&type=star)
![fork](https://svg.hamm.cn/gitee.svg?user=koogua&project=course-tencent-cloud&type=fork) ![fork](https://koogua.com/gitee/badge?user=koogua&project=course-tencent-cloud&type=fork)
![license](https://svg.hamm.cn/gitee.svg?user=koogua&project=course-tencent-cloud&type=license) ![license](https://koogua.com/gitee/badge?user=koogua&project=course-tencent-cloud&type=license)
![release](https://svg.hamm.cn/gitee.svg?user=koogua&project=course-tencent-cloud&type=release) ![release](https://koogua.com/gitee/badge?user=koogua&project=course-tencent-cloud&type=release)
### 系统功能 ### 系统功能

View File

@ -35,7 +35,7 @@ class SiteTodayStat extends Cache
$saleAmount = $statRepo->sumDailySales($date); $saleAmount = $statRepo->sumDailySales($date);
$refundAmount = $statRepo->sumDailyRefunds($date); $refundAmount = $statRepo->sumDailyRefunds($date);
$registerCount = $statRepo->countDailyRegisteredUsers($date); $registerCount = $statRepo->countDailyRegisteredUsers($date);
$pointRedeemCount = $statRepo->countDailyPointRedeems($date); $pointRedeemCount = $statRepo->countDailyPointGiftRedeems($date);
return [ return [
'sale_count' => $saleCount, 'sale_count' => $saleCount,

View File

@ -7,19 +7,18 @@
namespace App\Console\Tasks; namespace App\Console\Tasks;
use App\Models\Course as CourseModel;
use App\Models\CourseUser as CourseUserModel;
use App\Models\ImGroupUser as ImGroupUserModel;
use App\Models\Order as OrderModel; use App\Models\Order as OrderModel;
use App\Models\Refund as RefundModel; use App\Models\Refund as RefundModel;
use App\Models\Task as TaskModel; use App\Models\Task as TaskModel;
use App\Models\Trade as TradeModel; use App\Models\Trade as TradeModel;
use App\Repos\Course as CourseRepo; use App\Repos\Course as CourseRepo;
use App\Repos\ImGroup as ImGroupRepo;
use App\Repos\ImGroupUser as ImGroupUserRepo;
use App\Repos\ImUser as ImUserRepo;
use App\Repos\Order as OrderRepo; use App\Repos\Order as OrderRepo;
use App\Repos\Package as PackageRepo;
use App\Repos\User as UserRepo; 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\PackageDeliver as PackageDeliverService;
use App\Services\Logic\Deliver\VipDeliver as VipDeliverService;
use App\Services\Logic\Notice\OrderFinish as OrderFinishNotice; use App\Services\Logic\Notice\OrderFinish as OrderFinishNotice;
use App\Services\Logic\Point\History\OrderConsume as OrderConsumePointHistory; use App\Services\Logic\Point\History\OrderConsume as OrderConsumePointHistory;
use Phalcon\Mvc\Model; use Phalcon\Mvc\Model;
@ -31,8 +30,6 @@ class DeliverTask extends Task
public function mainAction() public function mainAction()
{ {
$logger = $this->getLogger('order');
$tasks = $this->findTasks(30); $tasks = $this->findTasks(30);
echo sprintf('pending tasks: %s', $tasks->count()) . PHP_EOL; echo sprintf('pending tasks: %s', $tasks->count()) . PHP_EOL;
@ -45,15 +42,7 @@ class DeliverTask extends Task
foreach ($tasks as $task) { foreach ($tasks as $task) {
$orderId = $task->item_info['order']['id'] ?? 0; $order = $orderRepo->findById($task->item_id);
$order = $orderRepo->findById($orderId);
if (!$order) {
$task->status = TaskModel::STATUS_FAILED;
$task->update();
continue;
}
try { try {
@ -72,16 +61,10 @@ class DeliverTask extends Task
} }
$order->status = OrderModel::STATUS_FINISHED; $order->status = OrderModel::STATUS_FINISHED;
$order->update();
if ($order->update() === false) {
throw new \RuntimeException('Update Order Status Failed');
}
$task->status = TaskModel::STATUS_FINISHED; $task->status = TaskModel::STATUS_FINISHED;
$task->update();
if ($task->update() === false) {
throw new \RuntimeException('Update Task Status Failed');
}
$this->db->commit(); $this->db->commit();
@ -98,7 +81,9 @@ class DeliverTask extends Task
$task->update(); $task->update();
$logger->error('Order Process Exception ' . kg_json_encode([ $logger = $this->getLogger('deliver');
$logger->error('Deliver Task Exception ' . kg_json_encode([
'file' => $e->getFile(), 'file' => $e->getFile(),
'line' => $e->getLine(), 'line' => $e->getLine(),
'message' => $e->getMessage(), 'message' => $e->getMessage(),
@ -119,126 +104,47 @@ class DeliverTask extends Task
protected function handleCourseOrder(OrderModel $order) protected function handleCourseOrder(OrderModel $order)
{ {
$course = $order->item_info['course'];
if ($course['model'] == CourseModel::MODEL_OFFLINE) {
$expiryTime = strtotime($course['attrs']['end_date']);
} else {
$expiryTime = $course['study_expiry_time'];
}
$courseUser = new CourseUserModel();
$courseUser->user_id = $order->owner_id;
$courseUser->course_id = $order->item_id;
$courseUser->expiry_time = $expiryTime;
$courseUser->role_type = CourseUserModel::ROLE_STUDENT;
$courseUser->source_type = CourseUserModel::SOURCE_CHARGE;
$courseUser->create();
$courseRepo = new CourseRepo(); $courseRepo = new CourseRepo();
$course = $courseRepo->findById($course['id']); $course = $courseRepo->findById($order->item_id);
$course->user_count += 1;
$course->update();
$groupRepo = new ImGroupRepo();
$group = $groupRepo->findByCourseId($course->id);
$imUserRepo = new ImUserRepo();
$imUser = $imUserRepo->findById($order->owner_id);
$groupUserRepo = new ImGroupUserRepo();
$groupUser = $groupUserRepo->findGroupUser($group->id, $order->owner_id);
if (!$groupUser) {
$groupUser = new ImGroupUserModel();
$groupUser->group_id = $group->id;
$groupUser->user_id = $order->owner_id;
$groupUser->create();
$imUser->group_count += 1;
$imUser->update();
$group->user_count += 1;
$group->update();
}
}
protected function handlePackageOrder(OrderModel $order)
{
$itemInfo = $order->item_info;
foreach ($itemInfo['courses'] as $course) {
$courseUser = new CourseUserModel();
$courseUser->user_id = $order->owner_id;
$courseUser->course_id = $course['id'];
$courseUser->expiry_time = $course['study_expiry_time'];
$courseUser->role_type = CourseUserModel::ROLE_STUDENT;
$courseUser->source_type = CourseUserModel::SOURCE_CHARGE;
$courseUser->create();
$courseRepo = new CourseRepo();
$course = $courseRepo->findById($course['id']);
$course->user_count += 1;
$course->update();
$groupRepo = new ImGroupRepo();
$group = $groupRepo->findByCourseId($course->id);
$imUserRepo = new ImUserRepo();
$imUser = $imUserRepo->findById($order->owner_id);
$groupUserRepo = new ImGroupUserRepo();
$groupUser = $groupUserRepo->findGroupUser($group->id, $order->owner_id);
if (!$groupUser) {
$groupUser = new ImGroupUserModel();
$groupUser->group_id = $group->id;
$groupUser->user_id = $order->owner_id;
$groupUser->create();
$imUser->group_count += 1;
$imUser->update();
$group->user_count += 1;
$group->update();
}
}
}
protected function handleVipOrder(OrderModel $order)
{
$itemInfo = $order->item_info;
$userRepo = new UserRepo(); $userRepo = new UserRepo();
$user = $userRepo->findById($order->owner_id); $user = $userRepo->findById($order->owner_id);
$user->vip_expiry_time = $itemInfo['vip']['expiry_time']; $service = new CourseDeliverService();
$user->vip = 1; $service->handle($course, $user);
}
$user->update(); protected function handlePackageOrder(OrderModel $order)
{
$packageRepo = new PackageRepo();
$package = $packageRepo->findById($order->item_id);
$userRepo = new UserRepo();
$user = $userRepo->findById($order->owner_id);
$service = new PackageDeliverService();
$service->handle($package, $user);
}
protected function handleVipOrder(OrderModel $order)
{
$vipRepo = new VipRepo();
$vip = $vipRepo->findById($order->item_id);
$userRepo = new UserRepo();
$user = $userRepo->findById($order->owner_id);
$service = new VipDeliverService();
$service->handle($vip, $user);
} }
protected function handleOrderConsumePoint(OrderModel $order) protected function handleOrderConsumePoint(OrderModel $order)
@ -311,7 +217,7 @@ class DeliverTask extends Task
{ {
$itemType = TaskModel::TYPE_DELIVER; $itemType = TaskModel::TYPE_DELIVER;
$status = TaskModel::STATUS_PENDING; $status = TaskModel::STATUS_PENDING;
$createTime = strtotime('-1 days'); $createTime = strtotime('-7 days');
return TaskModel::query() return TaskModel::query()
->where('item_type = :item_type:', ['item_type' => $itemType]) ->where('item_type = :item_type:', ['item_type' => $itemType])

View File

@ -26,8 +26,6 @@ class NoticeTask extends Task
public function mainAction() public function mainAction()
{ {
$logger = $this->getLogger('notice');
$tasks = $this->findTasks(300); $tasks = $this->findTasks(300);
if ($tasks->count() == 0) return; if ($tasks->count() == 0) return;
@ -55,16 +53,16 @@ class NoticeTask extends Task
case TaskModel::TYPE_NOTICE_POINT_GOODS_DELIVER: case TaskModel::TYPE_NOTICE_POINT_GOODS_DELIVER:
$this->handlePointGoodsDeliverNotice($task); $this->handlePointGoodsDeliverNotice($task);
break; break;
case TaskModel::TYPE_NOTICE_CONSULT_CREATE: case TaskModel::TYPE_STAFF_NOTICE_CONSULT_CREATE:
$this->handleConsultCreateNotice($task); $this->handleConsultCreateNotice($task);
break; break;
case TaskModel::TYPE_NOTICE_TEACHER_LIVE: case TaskModel::TYPE_STAFF_NOTICE_TEACHER_LIVE:
$this->handleTeacherLiveNotice($task); $this->handleTeacherLiveNotice($task);
break; break;
case TaskModel::TYPE_NOTICE_SERVER_MONITOR: case TaskModel::TYPE_STAFF_NOTICE_SERVER_MONITOR:
$this->handleServerMonitorNotice($task); $this->handleServerMonitorNotice($task);
break; break;
case TaskModel::TYPE_NOTICE_CUSTOM_SERVICE: case TaskModel::TYPE_STAFF_NOTICE_CUSTOM_SERVICE:
$this->handleCustomServiceNotice($task); $this->handleCustomServiceNotice($task);
break; break;
} }
@ -84,6 +82,8 @@ class NoticeTask extends Task
$task->update(); $task->update();
$logger = $this->getLogger('notice');
$logger->error('Notice Process Exception ' . kg_json_encode([ $logger->error('Notice Process Exception ' . kg_json_encode([
'file' => $e->getFile(), 'file' => $e->getFile(),
'line' => $e->getLine(), 'line' => $e->getLine(),
@ -178,10 +178,10 @@ class NoticeTask extends Task
TaskModel::TYPE_NOTICE_CONSULT_REPLY, TaskModel::TYPE_NOTICE_CONSULT_REPLY,
TaskModel::TYPE_NOTICE_POINT_GOODS_DELIVER, TaskModel::TYPE_NOTICE_POINT_GOODS_DELIVER,
TaskModel::TYPE_NOTICE_LUCKY_GOODS_DELIVER, TaskModel::TYPE_NOTICE_LUCKY_GOODS_DELIVER,
TaskModel::TYPE_NOTICE_CONSULT_CREATE, TaskModel::TYPE_STAFF_NOTICE_CONSULT_CREATE,
TaskModel::TYPE_NOTICE_TEACHER_LIVE, TaskModel::TYPE_STAFF_NOTICE_TEACHER_LIVE,
TaskModel::TYPE_NOTICE_SERVER_MONITOR, TaskModel::TYPE_STAFF_NOTICE_SERVER_MONITOR,
TaskModel::TYPE_NOTICE_CUSTOM_SERVICE, TaskModel::TYPE_STAFF_NOTICE_CUSTOM_SERVICE,
]; ];
$status = TaskModel::STATUS_PENDING; $status = TaskModel::STATUS_PENDING;

View File

@ -10,15 +10,15 @@ namespace App\Console\Tasks;
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\PointGift as PointGiftModel; use App\Models\PointGift as PointGiftModel;
use App\Models\PointRedeem as PointRedeemModel; 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\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\PointGift as PointGiftRepo; use App\Repos\PointGift as PointGiftRepo;
use App\Repos\PointRedeem as PointRedeemRepo; use App\Repos\PointGiftRedeem as PointGiftRedeemRepo;
use App\Services\Logic\Notice\DingTalk\PointRedeem as PointRedeemNotice; use App\Services\Logic\Notice\DingTalk\PointGiftRedeem as PointGiftRedeemNotice;
use App\Services\Logic\Point\History\PointRefund as PointRefundPointHistory; use App\Services\Logic\Point\History\PointRefund as PointRefundPointHistory;
use Phalcon\Mvc\Model\Resultset; use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface; use Phalcon\Mvc\Model\ResultsetInterface;
@ -38,13 +38,11 @@ class PointGiftDeliverTask extends Task
echo '------ start deliver task ------' . PHP_EOL; echo '------ start deliver task ------' . PHP_EOL;
$redeemRepo = new PointRedeemRepo(); $redeemRepo = new PointGiftRedeemRepo();
foreach ($tasks as $task) { foreach ($tasks as $task) {
$redeemId = $task->item_info['point_redeem']['id'] ?? 0; $redeem = $redeemRepo->findById($task->item_id);
$redeem = $redeemRepo->findById($redeemId);
if (!$redeem) { if (!$redeem) {
$task->status = TaskModel::STATUS_FAILED; $task->status = TaskModel::STATUS_FAILED;
@ -102,7 +100,7 @@ class PointGiftDeliverTask extends Task
echo '------ end deliver task ------' . PHP_EOL; echo '------ end deliver task ------' . PHP_EOL;
} }
protected function handleCourseRedeem(PointRedeemModel $redeem) protected function handleCourseRedeem(PointGiftRedeemModel $redeem)
{ {
$giftRepo = new PointGiftRepo(); $giftRepo = new PointGiftRepo();
@ -163,21 +161,21 @@ class PointGiftDeliverTask extends Task
} }
} }
$redeem->status = PointRedeemModel::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 Redeem Status Failed');
} }
} }
protected function handleGoodsRedeem(PointRedeemModel $redeem) protected function handleGoodsRedeem(PointGiftRedeemModel $redeem)
{ {
$notice = new PointRedeemNotice(); $notice = new PointGiftRedeemNotice();
$notice->createTask($redeem); $notice->createTask($redeem);
} }
protected function handlePointRefund(PointRedeemModel $redeem) protected function handlePointRefund(PointGiftRedeemModel $redeem)
{ {
$service = new PointRefundPointHistory(); $service = new PointRefundPointHistory();

View File

@ -29,8 +29,6 @@ class RefundTask extends Task
public function mainAction() public function mainAction()
{ {
$logger = $this->getLogger('refund');
$tasks = $this->findTasks(30); $tasks = $this->findTasks(30);
echo sprintf('pending tasks: %s', $tasks->count()) . PHP_EOL; echo sprintf('pending tasks: %s', $tasks->count()) . PHP_EOL;
@ -45,14 +43,12 @@ class RefundTask extends Task
foreach ($tasks as $task) { foreach ($tasks as $task) {
$itemInfo = $task->item_info; $refund = $refundRepo->findById($task->item_id);
$refund = $refundRepo->findById($itemInfo['refund']['id']);
$trade = $tradeRepo->findById($refund->trade_id); $trade = $tradeRepo->findById($refund->trade_id);
$order = $orderRepo->findById($refund->order_id); $order = $orderRepo->findById($refund->order_id);
if (!$refund || !$trade || !$order) { if ($refund->status != RefundModel::STATUS_APPROVED) {
$task->status = TaskModel::STATUS_FAILED; $task->status = TaskModel::STATUS_CANCELED;
$task->update(); $task->update();
continue; continue;
} }
@ -62,32 +58,19 @@ class RefundTask extends Task
$this->db->begin(); $this->db->begin();
$this->handleTradeRefund($trade, $refund); $this->handleTradeRefund($trade, $refund);
$this->handleOrderRefund($order); $this->handleOrderRefund($order);
$refund->status = RefundModel::STATUS_FINISHED; $refund->status = RefundModel::STATUS_FINISHED;
$refund->update();
if ($refund->update() === false) {
throw new \RuntimeException('Update Refund Status Failed');
}
$trade->status = TradeModel::STATUS_REFUNDED; $trade->status = TradeModel::STATUS_REFUNDED;
$trade->update();
if ($trade->update() === false) {
throw new \RuntimeException('Update Trade Status Failed');
}
$order->status = OrderModel::STATUS_REFUNDED; $order->status = OrderModel::STATUS_REFUNDED;
$order->update();
if ($order->update() === false) {
throw new \RuntimeException('Update Order Status Failed');
}
$task->status = TaskModel::STATUS_FINISHED; $task->status = TaskModel::STATUS_FINISHED;
$task->update();
if ($task->update() === false) {
throw new \RuntimeException('Update Task Status Failed');
}
$this->db->commit(); $this->db->commit();
@ -106,7 +89,9 @@ class RefundTask extends Task
$task->update(); $task->update();
$logger->info('Refund Task Exception ' . kg_json_encode([ $logger = $this->getLogger('refund');
$logger->error('Refund Task Exception ' . kg_json_encode([
'file' => $e->getFile(), 'file' => $e->getFile(),
'line' => $e->getLine(), 'line' => $e->getLine(),
'message' => $e->getMessage(), 'message' => $e->getMessage(),

View File

@ -25,8 +25,6 @@ class ImGroupController extends Controller
$group = $service->getGroup($id); $group = $service->getGroup($id);
$pager = $service->getGroupUsers($id); $pager = $service->getGroupUsers($id);
$this->view->pick('im/group/users');
$this->view->setVar('group', $group); $this->view->setVar('group', $group);
$this->view->setVar('pager', $pager); $this->view->setVar('pager', $pager);
} }
@ -40,8 +38,6 @@ class ImGroupController extends Controller
$pager = $groupService->getGroups(); $pager = $groupService->getGroups();
$this->view->pick('im/group/list');
$this->view->setVar('pager', $pager); $this->view->setVar('pager', $pager);
} }
@ -54,8 +50,6 @@ class ImGroupController extends Controller
$types = $groupService->getGroupTypes(); $types = $groupService->getGroupTypes();
$this->view->pick('im/group/search');
$this->view->setVar('types', $types); $this->view->setVar('types', $types);
} }
@ -64,7 +58,7 @@ class ImGroupController extends Controller
*/ */
public function addAction() public function addAction()
{ {
$this->view->pick('im/group/add');
} }
/** /**
@ -76,8 +70,6 @@ class ImGroupController extends Controller
$group = $groupService->getGroup($id); $group = $groupService->getGroup($id);
$this->view->pick('im/group/edit');
$this->view->setVar('group', $group); $this->view->setVar('group', $group);
} }

View File

@ -24,8 +24,6 @@ class PointGiftController extends Controller
$pager = $service->getPointGifts(); $pager = $service->getPointGifts();
$this->view->pick('point/gift/list');
$this->view->setVar('pager', $pager); $this->view->setVar('pager', $pager);
} }
@ -38,8 +36,6 @@ class PointGiftController extends Controller
$types = $service->getTypes(); $types = $service->getTypes();
$this->view->pick('point/gift/search');
$this->view->setVar('types', $types); $this->view->setVar('types', $types);
} }
@ -53,8 +49,6 @@ class PointGiftController extends Controller
$xmCourses = $service->getXmCourses(); $xmCourses = $service->getXmCourses();
$types = $service->getTypes(); $types = $service->getTypes();
$this->view->pick('point/gift/add');
$this->view->setVar('xm_courses', $xmCourses); $this->view->setVar('xm_courses', $xmCourses);
$this->view->setVar('types', $types); $this->view->setVar('types', $types);
} }
@ -68,8 +62,6 @@ class PointGiftController extends Controller
$gift = $service->getPointGift($id); $gift = $service->getPointGift($id);
$this->view->pick('point/gift/edit');
$this->view->setVar('gift', $gift); $this->view->setVar('gift', $gift);
} }

View File

@ -7,42 +7,40 @@
namespace App\Http\Admin\Controllers; namespace App\Http\Admin\Controllers;
use App\Http\Admin\Services\PointRedeem as PointRedeemService; use App\Http\Admin\Services\PointGiftRedeem as PointGiftRedeemService;
/** /**
* @RoutePrefix("/admin/point/redeem") * @RoutePrefix("/admin/point/gift/redeem")
*/ */
class PointRedeemController extends Controller class PointGiftRedeemController extends Controller
{ {
/** /**
* @Get("/search", name="admin.point_redeem.search") * @Get("/search", name="admin.point_gift_redeem.search")
*/ */
public function searchAction() public function searchAction()
{ {
$this->view->pick('point/redeem/search');
} }
/** /**
* @Get("/list", name="admin.point_redeem.list") * @Get("/list", name="admin.point_gift_redeem.list")
*/ */
public function listAction() public function listAction()
{ {
$redeemService = new PointRedeemService(); $redeemService = new PointGiftRedeemService();
$pager = $redeemService->getRedeems(); $pager = $redeemService->getRedeems();
$this->view->pick('point/redeem/list');
$this->view->setVar('pager', $pager); $this->view->setVar('pager', $pager);
} }
/** /**
* @Post("/{id:[0-9]+}/deliver", name="admin.point_redeem.deliver") * @Post("/{id:[0-9]+}/deliver", name="admin.point_gift_redeem.deliver")
*/ */
public function deliverAction($id) public function deliverAction($id)
{ {
$redeemService = new PointRedeemService(); $redeemService = new PointGiftRedeemService();
$redeemService->deliver($id); $redeemService->deliver($id);

View File

@ -24,7 +24,6 @@ class PointHistoryController extends Controller
$eventTypes = $historyService->getEventTypes(); $eventTypes = $historyService->getEventTypes();
$this->view->pick('point/history/search');
$this->view->setVar('event_types', $eventTypes); $this->view->setVar('event_types', $eventTypes);
} }
@ -37,8 +36,6 @@ class PointHistoryController extends Controller
$pager = $historyService->getHistories(); $pager = $historyService->getHistories();
$this->view->pick('point/history/list');
$this->view->setVar('pager', $pager); $this->view->setVar('pager', $pager);
} }

View File

@ -871,7 +871,7 @@ class AuthNode extends Service
'id' => '2-20-2', 'id' => '2-20-2',
'title' => '兑换记录', 'title' => '兑换记录',
'type' => 'button', 'type' => 'button',
'route' => 'admin.point_redeem.list', 'route' => 'admin.point_gift_redeem.list',
], ],
[ [
'id' => '2-20-3', 'id' => '2-20-3',

View File

@ -11,10 +11,6 @@ use App\Builders\ResourceList as ResourceListBuilder;
use App\Caches\Chapter as ChapterCache; use App\Caches\Chapter as ChapterCache;
use App\Caches\CourseChapterList as CatalogCache; use App\Caches\CourseChapterList as CatalogCache;
use App\Models\Chapter as ChapterModel; use App\Models\Chapter as ChapterModel;
use App\Models\ChapterLive as ChapterLiveModel;
use App\Models\ChapterOffline as ChapterOfflineModel;
use App\Models\ChapterRead as ChapterReadModel;
use App\Models\ChapterVod as ChapterVodModel;
use App\Models\Course as CourseModel; use App\Models\Course as CourseModel;
use App\Repos\Chapter as ChapterRepo; use App\Repos\Chapter as ChapterRepo;
use App\Repos\Course as CourseRepo; use App\Repos\Course as CourseRepo;
@ -75,17 +71,14 @@ class Chapter extends Service
$chapterRepo = new ChapterRepo(); $chapterRepo = new ChapterRepo();
$parentId = 0;
if (isset($post['parent_id'])) { if (isset($post['parent_id'])) {
$parent = $validator->checkParent($post['parent_id']); $parent = $validator->checkParent($post['parent_id']);
$data['parent_id'] = $parent->id; $data['parent_id'] = $parent->id;
$data['free'] = $validator->checkFreeStatus($post['free']); $data['free'] = $validator->checkFreeStatus($post['free']);
$data['priority'] = $chapterRepo->maxLessonPriority($post['parent_id']); $data['priority'] = $chapterRepo->maxLessonPriority($post['parent_id']);
$parentId = $parent->id;
} else { } else {
$data['priority'] = $chapterRepo->maxChapterPriority($post['course_id']); $data['priority'] = $chapterRepo->maxChapterPriority($post['course_id']);
$data['parent_id'] = $parentId; $data['parent_id'] = 0;
} }
$data['priority'] += 1; $data['priority'] += 1;
@ -100,39 +93,6 @@ class Chapter extends Service
throw new \RuntimeException('Create Chapter Failed'); throw new \RuntimeException('Create Chapter Failed');
} }
$data = [
'course_id' => $course->id,
'chapter_id' => $chapter->id,
];
if ($parentId > 0) {
$attrs = false;
switch ($course->model) {
case CourseMOdel::MODEL_VOD:
$chapterVod = new ChapterVodModel();
$attrs = $chapterVod->create($data);
break;
case CourseModel::MODEL_LIVE:
$chapterLive = new ChapterLiveModel();
$attrs = $chapterLive->create($data);
break;
case CourseModel::MODEL_READ:
$chapterRead = new ChapterReadModel();
$attrs = $chapterRead->create($data);
break;
case CourseModel::MODEL_OFFLINE:
$chapterOffline = new ChapterOfflineModel();
$attrs = $chapterOffline->create($data);
break;
}
if ($attrs === false) {
throw new \RuntimeException("Create Chapter Related Attrs Failed");
}
}
$this->db->commit(); $this->db->commit();
$this->updateChapterStats($chapter); $this->updateChapterStats($chapter);

View File

@ -16,10 +16,8 @@ use App\Library\Paginator\Query as PagerQuery;
use App\Models\Category as CategoryModel; use App\Models\Category as CategoryModel;
use App\Models\Course as CourseModel; use App\Models\Course as CourseModel;
use App\Models\CourseCategory as CourseCategoryModel; use App\Models\CourseCategory as CourseCategoryModel;
use App\Models\CourseRating as CourseRatingModel;
use App\Models\CourseRelated as CourseRelatedModel; use App\Models\CourseRelated as CourseRelatedModel;
use App\Models\CourseUser as CourseUserModel; use App\Models\CourseUser as CourseUserModel;
use App\Models\ImGroup as ImGroupModel;
use App\Models\ImGroupUser as ImGroupUserModel; use App\Models\ImGroupUser as ImGroupUserModel;
use App\Repos\Category as CategoryRepo; use App\Repos\Category as CategoryRepo;
use App\Repos\Chapter as ChapterRepo; use App\Repos\Chapter as ChapterRepo;
@ -90,25 +88,6 @@ class Course extends Service
throw new \RuntimeException('Create Course Failed'); throw new \RuntimeException('Create Course Failed');
} }
$courseRating = new CourseRatingModel();
$courseRating->course_id = $course->id;
if ($courseRating->create() === false) {
throw new \RuntimeException('Create CourseRating Failed');
}
$imGroup = new ImGroupModel();
$imGroup->type = ImGroupModel::TYPE_COURSE;
$imGroup->course_id = $course->id;
$imGroup->name = $course->title;
$imGroup->about = $course->summary;
if ($imGroup->create() === false) {
throw new \RuntimeException('Create ImGroup Failed');
}
$this->db->commit(); $this->db->commit();
return $course; return $course;

View File

@ -9,12 +9,12 @@ namespace App\Http\Admin\Services;
use App\Library\Paginator\Query as PagerQuery; use App\Library\Paginator\Query as PagerQuery;
use App\Models\PointGift as PointGiftModel; use App\Models\PointGift as PointGiftModel;
use App\Models\PointRedeem as PointRedeemModel; use App\Models\PointGiftRedeem as PointGiftRedeemModel;
use App\Repos\PointRedeem as PointRedeemRepo; use App\Repos\PointGiftRedeem as PointGiftRedeemRepo;
use App\Services\Logic\Notice\PointGoodsDeliver as PointGoodsDeliverNotice; use App\Services\Logic\Notice\PointGoodsDeliver as PointGoodsDeliverNotice;
use App\Validators\PointRedeem as PointRedeemValidator; use App\Validators\PointGiftRedeem as PointGiftRedeemValidator;
class PointRedeem extends Service class PointGiftRedeem extends Service
{ {
public function getRedeems() public function getRedeems()
@ -27,7 +27,7 @@ class PointRedeem extends Service
$page = $pagerQuery->getPage(); $page = $pagerQuery->getPage();
$limit = $pagerQuery->getLimit(); $limit = $pagerQuery->getLimit();
$redeemRepo = new PointRedeemRepo(); $redeemRepo = new PointGiftRedeemRepo();
return $redeemRepo->paginate($params, $sort, $page, $limit); return $redeemRepo->paginate($params, $sort, $page, $limit);
} }
@ -45,7 +45,7 @@ class PointRedeem extends Service
return $redeem; return $redeem;
} }
$redeem->status = PointRedeemModel::STATUS_FINISHED; $redeem->status = PointGiftRedeemModel::STATUS_FINISHED;
$redeem->update(); $redeem->update();
@ -54,7 +54,7 @@ class PointRedeem extends Service
return $redeem; return $redeem;
} }
protected function handleGoodsDeliverNotice(PointRedeemModel $redeem) protected function handleGoodsDeliverNotice(PointGiftRedeemModel $redeem)
{ {
$notice = new PointGoodsDeliverNotice(); $notice = new PointGoodsDeliverNotice();
@ -63,7 +63,7 @@ class PointRedeem extends Service
protected function findOrFail($id) protected function findOrFail($id)
{ {
$validator = new PointRedeemValidator(); $validator = new PointGiftRedeemValidator();
return $validator->checkRedeem($id); return $validator->checkRedeem($id);
} }

View File

@ -12,7 +12,6 @@ use App\Caches\User as UserCache;
use App\Library\Paginator\Query as PaginateQuery; use App\Library\Paginator\Query as PaginateQuery;
use App\Library\Utils\Password as PasswordUtil; use App\Library\Utils\Password as PasswordUtil;
use App\Models\Account as AccountModel; use App\Models\Account as AccountModel;
use App\Models\ImUser as ImUserModel;
use App\Models\User as UserModel; use App\Models\User as UserModel;
use App\Repos\Account as AccountRepo; use App\Repos\Account as AccountRepo;
use App\Repos\Online as OnlineRepo; use App\Repos\Online as OnlineRepo;
@ -118,24 +117,13 @@ class User extends Service
throw new \RuntimeException('Create Account Failed'); throw new \RuntimeException('Create Account Failed');
} }
$user = new UserModel(); $user = $this->findOrFail($account->id);
$user->id = $account->id;
$user->name = "user_{$account->id}";
$user->edu_role = $eduRole;
$user->admin_role = $adminRole; $user->admin_role = $adminRole;
$user->edu_role = $eduRole;
if ($user->create() === false) { if ($user->update() === false) {
throw new \RuntimeException('Create User Failed'); throw new \RuntimeException('Update User Failed');
}
$imUser = new ImUserModel();
$imUser->id = $user->id;
$imUser->name = $user->name;
if ($imUser->create() === false) {
throw new \RuntimeException('Create Im User Failed');
} }
$this->db->commit(); $this->db->commit();
@ -148,6 +136,14 @@ class User extends Service
$this->db->rollback(); $this->db->rollback();
$logger = $this->getLogger('http');
$logger->error('Create User Error ' . kg_json_encode([
'file' => $e->getFile(),
'line' => $e->getLine(),
'message' => $e->getMessage(),
]));
throw new \RuntimeException('sys.trans_rollback'); throw new \RuntimeException('sys.trans_rollback');
} }
} }

View File

@ -77,10 +77,10 @@
{% if item.teacher.id is defined %} {% if item.teacher.id is defined %}
<span>讲师:{{ item.teacher.name }}</span> <span>讲师:{{ item.teacher.name }}</span>
{% endif %} {% endif %}
<span>难度:{{ level_info(item.level) }}</span> <span>难度:{{ level_type(item.level) }}</span>
</p> </p>
<p class="meta"> <p class="meta">
<span>类型:{{ model_info(item.model) }}</span> <span>类型:{{ model_type(item.model) }}</span>
<span>评分:{{ item.rating }}</span> <span>评分:{{ item.rating }}</span>
<span>创建:{{ date('Y-m-d',item.create_time) }}</span> <span>创建:{{ date('Y-m-d',item.create_time) }}</span>
</p> </p>

View File

@ -1,4 +1,4 @@
{%- macro model_info(value) %} {%- macro model_type(value) %}
{% if value == 1 %} {% if value == 1 %}
点播 点播
{% elseif value == 2 %} {% elseif value == 2 %}
@ -12,7 +12,7 @@
{% endif %} {% endif %}
{%- endmacro %} {%- endmacro %}
{%- macro level_info(value) %} {%- macro level_type(value) %}
{% if value == 1 %} {% if value == 1 %}
入门 入门
{% elseif value == 2 %} {% elseif value == 2 %}

View File

@ -0,0 +1,19 @@
{%- macro gift_type_info(value) %}
{% if value == 1 %}
课程
{% elseif value == 2 %}
商品
{% elseif value == 3 %}
现金
{% endif %}
{%- endmacro %}
{%- macro redeem_status_info(value) %}
{% if value == 1 %}
处理中
{% elseif value == 2 %}
已完成
{% elseif value == 3 %}
已失败
{% endif %}
{%- endmacro %}

View File

@ -1,23 +1,3 @@
{%- macro redeem_status_info(value) %}
{% if value == 1 %}
处理中
{% elseif value == 2 %}
已完成
{% elseif value == 3 %}
已失败
{% endif %}
{%- endmacro %}
{%- macro gift_type_info(value) %}
{% if value == 1 %}
课程
{% elseif value == 2 %}
商品
{% elseif value == 3 %}
现金
{% endif %}
{%- endmacro %}
{%- macro event_point_info(value) %} {%- macro event_point_info(value) %}
{% if value > 0 %} {% if value > 0 %}
<span class="layui-badge layui-bg-green">+{{ value }}</span> <span class="layui-badge layui-bg-green">+{{ value }}</span>
@ -51,9 +31,9 @@
{% if history.event_type == 1 %} {% if history.event_type == 1 %}
<p class="order">{{ event_info.order.subject }}</p> <p class="order">{{ event_info.order.subject }}</p>
{% elseif history.event_type == 2 %} {% elseif history.event_type == 2 %}
<p class="gift">{{ event_info.point_redeem.gift_name }}</p> <p class="gift">{{ event_info.point_gift_redeem.gift_name }}</p>
{% elseif history.event_type == 3 %} {% elseif history.event_type == 3 %}
<span class="none">{{ event_info.point_redeem.gift_name }}</span> <span class="none">{{ event_info.point_gift_redeem.gift_name }}</span>
{% elseif history.event_type == 4 %} {% elseif history.event_type == 4 %}
<span class="none">N/A</span> <span class="none">N/A</span>
{% elseif history.event_type == 5 %} {% elseif history.event_type == 5 %}

View File

@ -5,9 +5,9 @@
{% set update_url = url({'for':'admin.point_gift.update','id':gift.id}) %} {% set update_url = url({'for':'admin.point_gift.update','id':gift.id}) %}
{% if gift.type == 1 %} {% if gift.type == 1 %}
{{ partial('point/gift/edit_course') }} {{ partial('point_gift/edit_course') }}
{% elseif gift.type == 2 %} {% elseif gift.type == 2 %}
{{ partial('point/gift/edit_goods') }} {{ partial('point_gift/edit_goods') }}
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View File

@ -2,8 +2,9 @@
{% block content %} {% block content %}
{{ partial('macros/point') }} {{ partial('macros/point_gift') }}
{% set redeem_url = url({'for':'admin.point_gift_redeem.list'}) %}
{% set add_url = url({'for':'admin.point_gift.add'}) %} {% set add_url = url({'for':'admin.point_gift.add'}) %}
{% set search_url = url({'for':'admin.point_gift.search'}) %} {% set search_url = url({'for':'admin.point_gift.search'}) %}
@ -14,6 +15,9 @@
</span> </span>
</div> </div>
<div class="kg-nav-right"> <div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ redeem_url }}">
<i class="layui-icon layui-icon-log"></i>兑换记录
</a>
<a class="layui-btn layui-btn-sm" href="{{ add_url }}"> <a class="layui-btn layui-btn-sm" href="{{ add_url }}">
<i class="layui-icon layui-icon-add-1"></i>添加礼品 <i class="layui-icon layui-icon-add-1"></i>添加礼品
</a> </a>
@ -50,7 +54,7 @@
</thead> </thead>
<tbody> <tbody>
{% for item in pager.items %} {% for item in pager.items %}
{% set redeem_url = url({'for':'admin.point_redeem.list'},{'gift_id':item.id}) %} {% set redeem_url = url({'for':'admin.point_gift_redeem.list'},{'gift_id':item.id}) %}
{% set gift_url = url({'for':'home.point_gift.show','id':item.id}) %} {% set gift_url = url({'for':'home.point_gift.show','id':item.id}) %}
{% set edit_url = url({'for':'admin.point_gift.edit','id':item.id}) %} {% set edit_url = url({'for':'admin.point_gift.edit','id':item.id}) %}
{% set update_url = url({'for':'admin.point_gift.update','id':item.id}) %} {% set update_url = url({'for':'admin.point_gift.update','id':item.id}) %}

View File

@ -2,9 +2,9 @@
{% block content %} {% block content %}
{{ partial('macros/point') }} {{ partial('macros/point_gift') }}
{% set search_url = url({'for':'admin.point_redeem.search'}) %} {% set search_url = url({'for':'admin.point_gift_redeem.search'}) %}
<div class="kg-nav"> <div class="kg-nav">
<div class="kg-nav-left"> <div class="kg-nav-left">
@ -40,8 +40,8 @@
</thead> </thead>
<tbody> <tbody>
{% for item in pager.items %} {% for item in pager.items %}
{% set user_filter_url = url({'for':'admin.point_redeem.list'},{'user_id':item.user_id}) %} {% set user_filter_url = url({'for':'admin.point_gift_redeem.list'},{'user_id':item.user_id}) %}
{% set deliver_url = url({'for':'admin.point_redeem.deliver','id':item.id}) %} {% set deliver_url = url({'for':'admin.point_gift_redeem.deliver','id':item.id}) %}
{% set gift_url = url({'for':'home.point_gift.show','id':item.gift_id}) %} {% set gift_url = url({'for':'home.point_gift.show','id':item.gift_id}) %}
<tr> <tr>
<td> <td>

View File

@ -2,7 +2,7 @@
{% block content %} {% block content %}
<form class="layui-form kg-form" method="GET" action="{{ url({'for':'admin.point_redeem.list'}) }}"> <form class="layui-form kg-form" method="GET" action="{{ url({'for':'admin.point_gift_redeem.list'}) }}">
<fieldset class="layui-elem-field layui-field-title"> <fieldset class="layui-elem-field layui-field-title">
<legend>搜索兑换</legend> <legend>搜索兑换</legend>
</fieldset> </fieldset>

View File

@ -51,39 +51,3 @@
</form> </form>
{% endblock %} {% endblock %}
{% block inline_js %}
<script>
layui.use(['jquery', 'form', 'layer'], function () {
var $ = layui.jquery;
var form = layui.form;
var layer = layui.layer;
form.on('submit(back_verify)', function (data) {
$.ajax({
type: 'POST',
url: data.form.action,
data: data.field,
success: function (res) {
if (res.code === 0) {
$('#back-verify-btn').remove();
$('#back-verify-tips').removeClass('layui-hide');
}
layer.msg(res.msg, {icon: 1});
},
error: function (xhr) {
var json = JSON.parse(xhr.responseText);
layer.msg(json.msg, {icon: 2});
}
});
return false;
});
});
</script>
{% endblock %}

View File

@ -9,8 +9,8 @@ namespace App\Http\Home\Controllers;
use App\Services\Logic\Point\GiftInfo as GiftInfoService; use App\Services\Logic\Point\GiftInfo as GiftInfoService;
use App\Services\Logic\Point\GiftList as GiftListService; use App\Services\Logic\Point\GiftList as GiftListService;
use App\Services\Logic\Point\GiftRedeem as GiftRedeemService;
use App\Services\Logic\Point\HotGiftList as HotGiftListService; use App\Services\Logic\Point\HotGiftList as HotGiftListService;
use App\Services\Logic\Point\PointRedeem as GiftRedeemService;
use App\Services\Logic\User\Console\BalanceInfo as BalanceInfoService; use App\Services\Logic\User\Console\BalanceInfo as BalanceInfoService;
use Phalcon\Mvc\Dispatcher; use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\View; use Phalcon\Mvc\View;
@ -39,8 +39,6 @@ class PointGiftController extends Controller
public function listAction() public function listAction()
{ {
$this->seo->prependTitle('积分兑换'); $this->seo->prependTitle('积分兑换');
$this->view->pick('point/gift/list');
} }
/** /**
@ -55,7 +53,6 @@ class PointGiftController extends Controller
$pager->target = 'gift-list'; $pager->target = 'gift-list';
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW); $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
$this->view->pick('point/gift/pager');
$this->view->setVar('pager', $pager); $this->view->setVar('pager', $pager);
} }
@ -81,20 +78,19 @@ class PointGiftController extends Controller
$this->seo->prependTitle(['积分兑换', $gift['name']]); $this->seo->prependTitle(['积分兑换', $gift['name']]);
$this->view->pick('point/gift/show');
$this->view->setVar('gift', $gift); $this->view->setVar('gift', $gift);
$this->view->setVar('hot_gifts', $hotGifts); $this->view->setVar('hot_gifts', $hotGifts);
$this->view->setVar('user_balance', $userBalance); $this->view->setVar('user_balance', $userBalance);
} }
/** /**
* @Post("/redeem", name="home.point_gift.redeem") * @Post("/{id:[0-9]+}/redeem", name="home.point_gift.redeem")
*/ */
public function redeemAction() public function redeemAction($id)
{ {
$service = new GiftRedeemService(); $service = new GiftRedeemService();
$service->handle(); $service->handle($id);
return $this->jsonSuccess(['msg' => '兑换成功']); return $this->jsonSuccess(['msg' => '兑换成功']);
} }

View File

@ -1,30 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Http\Home\Controllers;
use App\Services\Logic\Point\PointRedeem as PointRedeemService;
/**
* @RoutePrefix("/point/redeem")
*/
class PointRedeemController extends Controller
{
/**
* @Post("/create", name="home.point_redeem.create")
*/
public function createAction()
{
$service = new PointRedeemService();
$service->handle();
return $this->jsonSuccess(['msg' => '兑换请求提交成功']);
}
}

View File

@ -26,8 +26,8 @@ use App\Services\Logic\User\Console\NotificationRead as NotificationReadService;
use App\Services\Logic\User\Console\NotifyStats as NotifyStatsService; use App\Services\Logic\User\Console\NotifyStats as NotifyStatsService;
use App\Services\Logic\User\Console\Online as OnlineService; use App\Services\Logic\User\Console\Online as OnlineService;
use App\Services\Logic\User\Console\OrderList as OrderListService; use App\Services\Logic\User\Console\OrderList as OrderListService;
use App\Services\Logic\User\Console\PointGiftRedeemList as PointGiftRedeemListService;
use App\Services\Logic\User\Console\PointHistory as PointHistoryService; use App\Services\Logic\User\Console\PointHistory as PointHistoryService;
use App\Services\Logic\User\Console\PointRedeemList as PointRedeemListService;
use App\Services\Logic\User\Console\ProfileInfo as ProfileInfoService; use App\Services\Logic\User\Console\ProfileInfo as ProfileInfoService;
use App\Services\Logic\User\Console\ProfileUpdate as ProfileUpdateService; use App\Services\Logic\User\Console\ProfileUpdate as ProfileUpdateService;
use App\Services\Logic\User\Console\QuestionList as QuestionListService; use App\Services\Logic\User\Console\QuestionList as QuestionListService;
@ -266,15 +266,15 @@ class UserConsoleController extends Controller
} }
/** /**
* @Get("/point/redeems", name="home.uc.point_redeems") * @Get("/point/gift/redeems", name="home.uc.point_gift_redeems")
*/ */
public function pointRedeemsAction() public function pointGiftRedeemsAction()
{ {
$service = new PointRedeemListService(); $service = new PointGiftRedeemListService();
$pager = $service->handle(); $pager = $service->handle();
$this->view->pick('user/console/point_redeems'); $this->view->pick('user/console/point_gift_redeems');
$this->view->setVar('pager', $pager); $this->view->setVar('pager', $pager);
} }

View File

@ -85,7 +85,7 @@
{%- macro meta_stats_info(course) %} {%- macro meta_stats_info(course) %}
<p class="item"> <p class="item">
<span class="key">难度级别</span> <span class="key">难度级别</span>
<span class="value">{{ level_info(course.level) }}</span> <span class="value">{{ level_type(course.level) }}</span>
<span class="key">学习人次</span> <span class="key">学习人次</span>
<span class="value">{{ course.user_count }}</span> <span class="value">{{ course.user_count }}</span>
<span class="key">综合评分</span> <span class="key">综合评分</span>
@ -95,6 +95,7 @@
<div class="course-meta wrap clearfix"> <div class="course-meta wrap clearfix">
<div class="cover"> <div class="cover">
<span class="model layui-badge layui-bg-green">{{ model_type(course.model) }}</span>
<img src="{{ course.cover }}!cover_270" alt="{{ course.title }}"> <img src="{{ course.cover }}!cover_270" alt="{{ course.title }}">
</div> </div>
<div class="info"> <div class="info">

View File

@ -1,4 +1,4 @@
{%- macro model_info(value) %} {%- macro model_type(value) %}
{% if value == 1 %} {% if value == 1 %}
点播 点播
{% elseif value == 2 %} {% elseif value == 2 %}
@ -10,7 +10,7 @@
{% endif %} {% endif %}
{%- endmacro %} {%- endmacro %}
{%- macro level_info(value) %} {%- macro level_type(value) %}
{% if value == 1 %} {% if value == 1 %}
入门 入门
{% elseif value == 2 %} {% elseif value == 2 %}
@ -32,7 +32,7 @@
{%- macro course_card(course) %} {%- macro course_card(course) %}
{% set course_url = url({'for':'home.course.show','id':course.id}) %} {% set course_url = url({'for':'home.course.show','id':course.id}) %}
<div class="course-card"> <div class="course-card">
<span class="model layui-badge layui-bg-green">{{ model_info(course.model) }}</span> <span class="model layui-badge layui-bg-green">{{ model_type(course.model) }}</span>
<div class="cover"> <div class="cover">
<a href="{{ course_url }}" target="_blank"> <a href="{{ course_url }}" target="_blank">
<img src="{{ course.cover }}!cover_270" alt="{{ course.title }}" title="{{ course.title }}"> <img src="{{ course.cover }}!cover_270" alt="{{ course.title }}" title="{{ course.title }}">
@ -50,16 +50,16 @@
{% else %} {% else %}
<span class="free">会员免费</span> <span class="free">会员免费</span>
{% endif %} {% endif %}
<span class="level">{{ level_info(course.level) }}</span> <span class="level">{{ level_type(course.level) }}</span>
<span class="user">{{ course.user_count }}人购买</span> <span class="user">{{ course.user_count }}人购买</span>
{% elseif course.market_price > 0 %} {% elseif course.market_price > 0 %}
<span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span> <span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span>
<span class="level">{{ level_info(course.level) }}</span> <span class="level">{{ level_type(course.level) }}</span>
<span class="lesson">{{ course.lesson_count }}节课</span> <span class="lesson">{{ course.lesson_count }}节课</span>
<span class="user">{{ course.user_count }}人购买</span> <span class="user">{{ course.user_count }}人购买</span>
{% else %} {% else %}
<span class="free">免费</span> <span class="free">免费</span>
<span class="level">{{ level_info(course.level) }}</span> <span class="level">{{ level_type(course.level) }}</span>
<span class="lesson">{{ course.lesson_count }}节课</span> <span class="lesson">{{ course.lesson_count }}节课</span>
<span class="user">{{ course.user_count }}人报名</span> <span class="user">{{ course.user_count }}人报名</span>
{% endif %} {% endif %}
@ -81,11 +81,11 @@
<div class="meta"> <div class="meta">
{% if course.market_price > 0 %} {% if course.market_price > 0 %}
<span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span> <span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span>
<span class="level">{{ level_info(course.level) }}</span> <span class="level">{{ level_type(course.level) }}</span>
<span class="user">{{ course.user_count }}人购买</span> <span class="user">{{ course.user_count }}人购买</span>
{% else %} {% else %}
<span class="free">免费</span> <span class="free">免费</span>
<span class="level">{{ level_info(course.level) }}</span> <span class="level">{{ level_type(course.level) }}</span>
<span class="user">{{ course.user_count }}人报名</span> <span class="user">{{ course.user_count }}人报名</span>
{% endif %} {% endif %}
</div> </div>
@ -97,7 +97,7 @@
{% set course_title = item.course.title %} {% set course_title = item.course.title %}
{% set course_url = url({'for':'home.course.show','id':item.course.id}) %} {% set course_url = url({'for':'home.course.show','id':item.course.id}) %}
<div class="course-card"> <div class="course-card">
<span class="model layui-badge layui-bg-green">{{ model_info(item.course.model) }}</span> <span class="model layui-badge layui-bg-green">{{ model_type(item.course.model) }}</span>
<div class="cover"> <div class="cover">
<a href="{{ course_url }}" title="{{ course_title }}" target="_blank"> <a href="{{ course_url }}" title="{{ course_title }}" target="_blank">
<img src="{{ item.course.cover }}!cover_270" alt="{{ course_title }}"> <img src="{{ item.course.cover }}!cover_270" alt="{{ course_title }}">

View File

@ -0,0 +1,19 @@
{%- macro gift_type_info(value) %}
{% if value == 1 %}
课程
{% elseif value == 2 %}
商品
{% elseif value == 3 %}
现金
{% endif %}
{%- endmacro %}
{%- macro redeem_status_info(value) %}
{% if value == 1 %}
处理中
{% elseif value == 2 %}
已完成
{% elseif value == 3 %}
已失败
{% endif %}
{%- endmacro %}

View File

@ -1,23 +1,3 @@
{%- macro redeem_status_info(value) %}
{% if value == 1 %}
<span class="status">处理中</span>
{% elseif value == 2 %}
<span class="status">已完成</span>
{% elseif value == 3 %}
<span class="status">已失败</span>
{% endif %}
{%- endmacro %}
{%- macro gift_type_info(value) %}
{% if value == 1 %}
<span class="layui-badge layui-bg-green type">课程</span>
{% elseif value == 2 %}
<span class="layui-badge layui-bg-blue type">商品</span>
{% elseif value == 3 %}
<span class="layui-badge layui-bg-cyan type">现金</span>
{% endif %}
{%- endmacro %}
{%- macro event_point_info(value) %} {%- macro event_point_info(value) %}
{% if value > 0 %} {% if value > 0 %}
<span class="layui-badge layui-bg-green point">+{{ value }}</span> <span class="layui-badge layui-bg-green point">+{{ value }}</span>
@ -64,11 +44,11 @@
{% if type == 1 %} {% if type == 1 %}
<p class="order">{{ info.order.subject }}</p> <p class="order">{{ info.order.subject }}</p>
{% elseif type == 2 %} {% elseif type == 2 %}
{% set gift_url = url({'for':'home.point_gift.show','id':info.point_redeem.gift_id}) %} {% set gift_url = url({'for':'home.point_gift.show','id':info.point_gift_redeem.gift_id}) %}
<p class="gift"><a href="{{ gift_url }}" target="_blank">{{ info.point_redeem.gift_name }}</a></p> <p class="gift"><a href="{{ gift_url }}" target="_blank">{{ info.point_gift_redeem.gift_name }}</a></p>
{% elseif type == 3 %} {% elseif type == 3 %}
{% set gift_url = url({'for':'home.point_gift.show','id':info.point_redeem.gift_id}) %} {% set gift_url = url({'for':'home.point_gift.show','id':info.point_gift_redeem.gift_id}) %}
<p class="gift"><a href="{{ gift_url }}" target="_blank">{{ info.point_redeem.gift_name }}</a></p> <p class="gift"><a href="{{ gift_url }}" target="_blank">{{ info.point_gift_redeem.gift_name }}</a></p>
{% elseif type == 4 %} {% elseif type == 4 %}
<span class="none">N/A</span> <span class="none">N/A</span>
{% elseif type == 5 %} {% elseif type == 5 %}

View File

@ -60,7 +60,7 @@
</p> </p>
<p> <p>
<span class="key">难度</span> <span class="key">难度</span>
<span class="value">{{ level_info(course.level) }}</span> <span class="value">{{ level_type(course.level) }}</span>
<span class="key">课时</span> <span class="key">课时</span>
<span class="value">{{ course.lesson_count }}</span> <span class="value">{{ course.lesson_count }}</span>
<span class="key">学员</span> <span class="key">学员</span>

View File

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

View File

@ -2,9 +2,9 @@
{% block content %} {% block content %}
{{ partial('macros/point') }} {{ partial('macros/point_gift') }}
{% set redeem_create_url = url({'for':'home.point_redeem.create'}) %} {% set gift_redeem_url = url({'for':'home.point_gift.redeem','id':gift.id}) %}
{% set gift_list_url = url({'for':'home.point_gift.list'}) %} {% set gift_list_url = url({'for':'home.point_gift.list'}) %}
<div class="breadcrumb"> <div class="breadcrumb">
@ -22,6 +22,7 @@
<div class="layui-card-body"> <div class="layui-card-body">
<div class="gift-meta clearfix"> <div class="gift-meta clearfix">
<div class="cover"> <div class="cover">
<span class="layui-badge layui-bg-green type">{{ gift_type_info(gift.type) }}</span>
<img src="{{ gift.cover }}!cover_270" alt="{{ gift.name }}"> <img src="{{ gift.cover }}!cover_270" alt="{{ gift.name }}">
</div> </div>
<div class="info"> <div class="info">
@ -29,27 +30,23 @@
{% set course_url = url({'for':'home.course.show','id':gift.attrs.id}) %} {% set course_url = url({'for':'home.course.show','id':gift.attrs.id}) %}
<p class="item"> <p class="item">
<a href="{{ course_url }}">{{ gift.name }}</a> <a href="{{ course_url }}">{{ gift.name }}</a>
{{ gift_type_info(gift.type) }}
</p> </p>
{% else %} {% else %}
<p class="item">{{ gift.name }} {{ gift_type_info(gift.type) }}</p> <p class="item">{{ gift.name }} }}</p>
{% endif %} {% endif %}
<p class="item stats"> <p class="item stats">
<span class="key">兑换库存</span>
<span class="value">{{ gift.stock }}</span>
<span class="key">兑换价格</span>
<span class="price">{{ gift.point }} 积分</span>
<span class="key">兑换限额</span>
<span class="value">{{ gift.redeem_limit }}</span>
<span class="key">兑换人次</span> <span class="key">兑换人次</span>
<span class="value">{{ gift.redeem_count }}</span> <span class="value">{{ gift.redeem_count }}</span>
<span class="key">兑换限额</span>
<span class="value">{{ gift.redeem_limit }}</span>
</p> </p>
<p class="item"> <p class="item stats">
{% if gift.stock > 0 and user_balance.point > gift.point %} <span class="key">兑换价格</span>
<button class="layui-btn layui-bg-red btn-redeem" data-id="{{ gift.id }}" data-url="{{ redeem_create_url }}">立即兑换</button> <span class="price">{{ gift.point }} 积分</span>
{% else %} </p>
<button class="layui-btn layui-btn-disabled">立即兑换</button> <p class="item stats">
{% endif %} <span class="key">库存数量</span>
<span class="value">{{ gift.stock }}</span>
</p> </p>
</div> </div>
</div> </div>
@ -79,6 +76,13 @@
</div> </div>
</div> </div>
</div> </div>
<div class="sidebar wrap">
{% if gift.me.allow_redeem == 1 %}
<button class="layui-btn layui-bg-red layui-btn-fluid btn-redeem" data-url="{{ gift_redeem_url }}">立即兑换</button>
{% else %}
<button class="layui-btn layui-btn-fluid layui-btn-disabled">立即兑换</button>
{% endif %}
</div>
<div class="sidebar"> <div class="sidebar">
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-header">热门兑换</div> <div class="layui-card-header">热门兑换</div>

View File

@ -16,7 +16,7 @@
<div class="summary">{{ item.summary }}</div> <div class="summary">{{ item.summary }}</div>
<div class="meta"> <div class="meta">
<span>讲师:<a href="{{ teacher_url }}" target="_blank">{{ item.teacher.name }}</a></span> <span>讲师:<a href="{{ teacher_url }}" target="_blank">{{ item.teacher.name }}</a></span>
<span>难度:{{ level_info(item.level) }}</span> <span>难度:{{ level_type(item.level) }}</span>
<span>课时:{{ item.lesson_count }}</span> <span>课时:{{ item.lesson_count }}</span>
<span>学员:{{ item.user_count }}</span> <span>学员:{{ item.user_count }}</span>
</div> </div>

View File

@ -33,7 +33,7 @@
{% for item in pager.items %} {% for item in pager.items %}
{% set course_url = url({'for':'home.course.show','id':item.id}) %} {% set course_url = url({'for':'home.course.show','id':item.id}) %}
<tr> <tr>
<td><a href="{{ course_url }}">{{ item.title }}</a> {{ model_info(item.model) }}</td> <td><a href="{{ course_url }}">{{ item.title }}</a> {{ model_type(item.model) }}</td>
<td>{{ item.lesson_count }}</td> <td>{{ item.lesson_count }}</td>
<td>{{ item.user_count }}</td> <td>{{ item.user_count }}</td>
<td>{{ item.favorite_count }}</td> <td>{{ item.favorite_count }}</td>

View File

@ -35,7 +35,7 @@
<td> <td>
<p>标题:<a href="{{ course_url }}" target="_blank">{{ item.course.title }}</a></p> <p>标题:<a href="{{ course_url }}" target="_blank">{{ item.course.title }}</a></p>
<p class="meta"> <p class="meta">
类型:<span class="layui-badge layui-bg-gray">{{ model_info(item.course.model) }}</span> 类型:<span class="layui-badge layui-bg-gray">{{ model_type(item.course.model) }}</span>
来源:<span class="layui-badge layui-bg-gray">{{ source_type_info(item.source_type) }}</span> 来源:<span class="layui-badge layui-bg-gray">{{ source_type_info(item.source_type) }}</span>
{% if item.expiry_time > 0 %} {% if item.expiry_time > 0 %}
期限:{{ date('Y-m-d',item.expiry_time) }} 期限:{{ date('Y-m-d',item.expiry_time) }}

View File

@ -56,7 +56,7 @@
<div class="layui-card-body"> <div class="layui-card-body">
<ul class="my-menu"> <ul class="my-menu">
<li><a href="{{ url({'for':'home.point_gift.list'}) }}">积分商城</a></li> <li><a href="{{ url({'for':'home.point_gift.list'}) }}">积分商城</a></li>
<li><a href="{{ url({'for':'home.uc.point_redeems'}) }}">兑换记录</a></li> <li><a href="{{ url({'for':'home.uc.point_gift_redeems'}) }}">兑换记录</a></li>
<li><a href="{{ url({'for':'home.uc.point_history'}) }}">积分记录</a></li> <li><a href="{{ url({'for':'home.uc.point_history'}) }}">积分记录</a></li>
</ul> </ul>
</div> </div>

View File

@ -2,7 +2,7 @@
{% block content %} {% block content %}
{{ partial('macros/point') }} {{ partial('macros/point_gift') }}
<div class="layout-main clearfix"> <div class="layout-main clearfix">
<div class="my-sidebar">{{ partial('user/console/menu') }}</div> <div class="my-sidebar">{{ partial('user/console/menu') }}</div>

View File

@ -2,7 +2,7 @@
{% block content %} {% block content %}
{{ partial('macros/point') }} {{ partial('macros/point_history') }}
<div class="layout-main clearfix"> <div class="layout-main clearfix">
<div class="my-sidebar">{{ partial('user/console/menu') }}</div> <div class="my-sidebar">{{ partial('user/console/menu') }}</div>

View File

@ -16,7 +16,7 @@ class AppInfo
protected $link = 'https://koogua.com'; protected $link = 'https://koogua.com';
protected $version = '1.4.9'; protected $version = '1.5.0';
public function __get($name) public function __get($name)
{ {

View File

@ -11,6 +11,7 @@ use App\Models\Order as OrderModel;
use App\Models\Task as TaskModel; use App\Models\Task as TaskModel;
use App\Models\Trade as TradeModel; use App\Models\Trade as TradeModel;
use App\Repos\Order as OrderRepo; use App\Repos\Order as OrderRepo;
use App\Services\Logic\FlashSale\UserOrderCache as FlashSaleLockCache;
use Phalcon\Events\Event as PhEvent; use Phalcon\Events\Event as PhEvent;
use Phalcon\Logger\Adapter\File as FileLogger; use Phalcon\Logger\Adapter\File as FileLogger;
@ -34,20 +35,13 @@ class Trade extends Listener
$this->db->begin(); $this->db->begin();
$trade->status = TradeModel::STATUS_FINISHED; $trade->status = TradeModel::STATUS_FINISHED;
$trade->update();
if ($trade->update() === false) {
throw new \RuntimeException('Update Trade Status Failed');
}
$orderRepo = new OrderRepo(); $orderRepo = new OrderRepo();
$order = $orderRepo->findById($trade->order_id); $order = $orderRepo->findById($trade->order_id);
$order->status = OrderModel::STATUS_DELIVERING; $order->status = OrderModel::STATUS_DELIVERING;
$order->update();
if ($order->update() === false) {
throw new \RuntimeException('Update Order Status Failed');
}
$task = new TaskModel(); $task = new TaskModel();
@ -58,13 +52,18 @@ class Trade extends Listener
$task->item_id = $order->id; $task->item_id = $order->id;
$task->item_info = $itemInfo; $task->item_info = $itemInfo;
$task->item_type = TaskModel::TYPE_DELIVER; $task->item_type = TaskModel::TYPE_DELIVER;
$task->create();
if ($task->create() === false) {
throw new \RuntimeException('Create Order Process Task Failed');
}
$this->db->commit(); $this->db->commit();
/**
* 解除秒杀锁定
*/
if ($order->promotion_type == OrderModel::PROMOTION_FLASH_SALE) {
$cache = new FlashSaleLockCache();
$cache->delete($order->owner_id, $order->promotion_id);
}
} catch (\Exception $e) { } catch (\Exception $e) {
$this->db->rollback(); $this->db->rollback();
@ -72,7 +71,6 @@ class Trade extends Listener
$this->logger->error('After Pay Event Error ' . kg_json_encode([ $this->logger->error('After Pay Event Error ' . kg_json_encode([
'file' => $e->getFile(), 'file' => $e->getFile(),
'line' => $e->getLine(), 'line' => $e->getLine(),
'code' => $e->getCode(),
'message' => $e->getMessage(), 'message' => $e->getMessage(),
])); ]));

View File

@ -95,4 +95,33 @@ class Account extends Model
$this->update_time = time(); $this->update_time = time();
} }
public function afterCreate()
{
$user = new User();
$user->id = $this->id;
$user->name = "user:{$this->id}";
if ($user->create() === false) {
throw new \RuntimeException('Create User Failed');
}
$userBalance = new UserBalance();
$userBalance->user_id = $user->id;
if ($userBalance->create() === false) {
throw new \RuntimeException('Create User Balance Failed');
}
$imUser = new ImUser();
$imUser->id = $user->id;
$imUser->name = $user->name;
if ($imUser->create() === false) {
throw new \RuntimeException('Create Im User Failed');
}
}
} }

View File

@ -261,6 +261,40 @@ class Chapter extends Model
$cache = new MaxChapterIdCache(); $cache = new MaxChapterIdCache();
$cache->rebuild(); $cache->rebuild();
if ($this->parent_id > 0) {
$data = [
'course_id' => $this->course_id,
'chapter_id' => $this->id,
'model' => $this->model,
];
$extend = false;
switch ($this->model) {
case Course::MODEL_VOD:
$vod = new ChapterVod();
$extend = $vod->create($data);
break;
case Course::MODEL_LIVE:
$live = new ChapterLive();
$extend = $live->create($data);
break;
case Course::MODEL_READ:
$read = new ChapterRead();
$extend = $read->create($data);
break;
case Course::MODEL_OFFLINE:
$offline = new ChapterOffline();
$extend = $offline->create($data);
break;
}
if ($extend === false) {
throw new \RuntimeException("Create Chapter Extend Failed");
}
}
} }
public function afterFetch() public function afterFetch()

View File

@ -382,6 +382,24 @@ class Course extends Model
$cache = new MaxCourseIdCache(); $cache = new MaxCourseIdCache();
$cache->rebuild(); $cache->rebuild();
$courseRating = new CourseRating();
$courseRating->course_id = $this->id;
if ($courseRating->create() === false) {
throw new \RuntimeException('Create Course Rating Failed');
}
$imGroup = new ImGroup();
$imGroup->course_id = $this->id;
$imGroup->name = $this->title;
$imGroup->type = ImGroup::TYPE_COURSE;
if ($imGroup->create() === false) {
throw new \RuntimeException('Create Im Group Failed');
}
} }
public function afterFetch() public function afterFetch()

View File

@ -7,7 +7,7 @@
namespace App\Models; namespace App\Models;
class PointRedeem extends Model class PointGiftRedeem extends Model
{ {
/** /**
@ -117,7 +117,7 @@ class PointRedeem extends Model
public function getSource(): string public function getSource(): string
{ {
return 'kg_point_redeem'; return 'kg_point_gift_redeem';
} }
public function beforeCreate() public function beforeCreate()

View File

@ -32,12 +32,12 @@ class Task extends Model
/** /**
* 针对内部人员 * 针对内部人员
*/ */
const TYPE_NOTICE_CONSULT_CREATE = 31; // 咨询创建通知 const TYPE_STAFF_NOTICE_CONSULT_CREATE = 31; // 咨询创建通知
const TYPE_NOTICE_TEACHER_LIVE = 32; // 直播讲师通知 const TYPE_STAFF_NOTICE_TEACHER_LIVE = 32; // 直播讲师通知
const TYPE_NOTICE_SERVER_MONITOR = 33; // 服务监控通知 const TYPE_STAFF_NOTICE_SERVER_MONITOR = 33; // 服务监控通知
const TYPE_NOTICE_CUSTOM_SERVICE = 34; // 客服消息通知 const TYPE_STAFF_NOTICE_CUSTOM_SERVICE = 34; // 客服消息通知
const TYPE_NOTICE_POINT_REDEEM = 35; // 积分兑换通知 const TYPE_STAFF_NOTICE_POINT_GIFT_REDEEM = 35; // 积分兑换通知
const TYPE_NOTICE_LUCKY_REDEEM = 36; // 抽奖兑换通知 const TYPE_STAFF_NOTICE_LUCKY_GIFT_REDEEM = 36; // 抽奖兑换通知
/** /**
* 优先级 * 优先级

View File

@ -33,6 +33,7 @@ class Annotation extends Provider
'host' => $config->path('redis.host'), 'host' => $config->path('redis.host'),
'port' => $config->path('redis.port'), 'port' => $config->path('redis.port'),
'auth' => $config->path('redis.auth'), 'auth' => $config->path('redis.auth'),
'index' => $config->path('redis.index') ?: 0,
'lifetime' => $config->path('annotation.lifetime') ?: 30 * 86400, 'lifetime' => $config->path('annotation.lifetime') ?: 30 * 86400,
'prefix' => $statsKey . ':', 'prefix' => $statsKey . ':',
'statsKey' => $statsKey, 'statsKey' => $statsKey,

View File

@ -33,6 +33,7 @@ class Cache extends Provider
'host' => $config->path('redis.host'), 'host' => $config->path('redis.host'),
'port' => $config->path('redis.port'), 'port' => $config->path('redis.port'),
'auth' => $config->path('redis.auth'), 'auth' => $config->path('redis.auth'),
'index' => $config->path('redis.index') ?: 0,
]); ]);
}); });
} }

View File

@ -33,6 +33,7 @@ class MetaData extends Provider
'host' => $config->path('redis.host'), 'host' => $config->path('redis.host'),
'port' => $config->path('redis.port'), 'port' => $config->path('redis.port'),
'auth' => $config->path('redis.auth'), 'auth' => $config->path('redis.auth'),
'index' => $config->path('redis.index') ?: 0,
'lifetime' => $config->path('metadata.lifetime') ?: 30 * 86400, 'lifetime' => $config->path('metadata.lifetime') ?: 30 * 86400,
'prefix' => $statsKey . ':', 'prefix' => $statsKey . ':',
'statsKey' => $statsKey, 'statsKey' => $statsKey,

View File

@ -28,6 +28,7 @@ class Session extends Provider
'host' => $config->path('redis.host'), 'host' => $config->path('redis.host'),
'port' => $config->path('redis.port'), 'port' => $config->path('redis.port'),
'auth' => $config->path('redis.auth'), 'auth' => $config->path('redis.auth'),
'index' => $config->path('redis.index') ?: 0,
'lifetime' => $config->path('session.lifetime') ?: 24 * 3600, 'lifetime' => $config->path('session.lifetime') ?: 24 * 3600,
'prefix' => '_SESSION_:', 'prefix' => '_SESSION_:',
]); ]);

View File

@ -8,17 +8,17 @@
namespace App\Repos; namespace App\Repos;
use App\Library\Paginator\Adapter\QueryBuilder as PagerQueryBuilder; use App\Library\Paginator\Adapter\QueryBuilder as PagerQueryBuilder;
use App\Models\PointRedeem as PointRedeemModel; use App\Models\PointGiftRedeem as PointGiftRedeemModel;
use Phalcon\Mvc\Model; use Phalcon\Mvc\Model;
class PointRedeem extends Repository class PointGiftRedeem extends Repository
{ {
public function paginate($where = [], $sort = 'latest', $page = 1, $limit = 15) public function paginate($where = [], $sort = 'latest', $page = 1, $limit = 15)
{ {
$builder = $this->modelsManager->createBuilder(); $builder = $this->modelsManager->createBuilder();
$builder->from(PointRedeemModel::class); $builder->from(PointGiftRedeemModel::class);
$builder->where('1 = 1'); $builder->where('1 = 1');
@ -57,11 +57,11 @@ class PointRedeem extends Repository
/** /**
* @param int $id * @param int $id
* @return PointRedeemModel|Model|bool * @return PointGiftRedeemModel|Model|bool
*/ */
public function findById($id) public function findById($id)
{ {
return PointRedeemModel::findFirst([ return PointGiftRedeemModel::findFirst([
'conditions' => 'id = :id:', 'conditions' => 'id = :id:',
'bind' => ['id' => $id], 'bind' => ['id' => $id],
]); ]);
@ -69,7 +69,7 @@ class PointRedeem extends Repository
public function countUserGiftRedeems($userId, $giftId) public function countUserGiftRedeems($userId, $giftId)
{ {
return (int)PointRedeemModel::count([ return (int)PointGiftRedeemModel::count([
'conditions' => 'user_id = :user_id: AND gift_id = :gift_id:', 'conditions' => 'user_id = :user_id: AND gift_id = :gift_id:',
'bind' => ['user_id' => $userId, 'gift_id' => $giftId], 'bind' => ['user_id' => $userId, 'gift_id' => $giftId],
]); ]);

View File

@ -14,7 +14,7 @@ use App\Models\Consult as ConsultModel;
use App\Models\Online as OnlineModel; use App\Models\Online as OnlineModel;
use App\Models\Order as OrderModel; use App\Models\Order as OrderModel;
use App\Models\OrderStatus as OrderStatusModel; use App\Models\OrderStatus as OrderStatusModel;
use App\Models\PointRedeem as PointRedeemModel; use App\Models\PointGiftRedeem as PointGiftRedeemModel;
use App\Models\Question as QuestionModel; use App\Models\Question as QuestionModel;
use App\Models\Refund as RefundModel; use App\Models\Refund as RefundModel;
use App\Models\Review as ReviewModel; use App\Models\Review as ReviewModel;
@ -162,16 +162,16 @@ class Stat extends Repository
]); ]);
} }
public function countDailyPointRedeems($date) public function countDailyPointGiftRedeems($date)
{ {
$startTime = strtotime($date); $startTime = strtotime($date);
$endTime = $startTime + 86400; $endTime = $startTime + 86400;
return (int)PointRedeemModel::count([ return (int)PointGiftRedeemModel::count([
'conditions' => 'status = ?1 AND create_time BETWEEN ?2 AND ?3', 'conditions' => 'status = ?1 AND create_time BETWEEN ?2 AND ?3',
'bind' => [ 'bind' => [
1 => PointRedeemModel::STATUS_PENDING, 1 => PointGiftRedeemModel::STATUS_PENDING,
2 => $startTime, 2 => $startTime,
3 => $endTime, 3 => $endTime,
], ],

View File

@ -10,8 +10,6 @@ namespace App\Services\Logic\Account;
use App\Library\Utils\Password as PasswordUtil; use App\Library\Utils\Password as PasswordUtil;
use App\Library\Validators\Common as CommonValidator; use App\Library\Validators\Common as CommonValidator;
use App\Models\Account as AccountModel; use App\Models\Account as AccountModel;
use App\Models\ImUser as ImUserModel;
use App\Models\User as UserModel;
use App\Services\Logic\Service as LogicService; use App\Services\Logic\Service as LogicService;
use App\Validators\Account as AccountValidator; use App\Validators\Account as AccountValidator;
use App\Validators\Verify as VerifyValidator; use App\Validators\Verify as VerifyValidator;
@ -62,24 +60,6 @@ class Register extends LogicService
throw new \RuntimeException('Create Account Failed'); throw new \RuntimeException('Create Account Failed');
} }
$user = new UserModel();
$user->id = $account->id;
$user->name = "user_{$account->id}";
if ($user->create() === false) {
throw new \RuntimeException('Create User Failed');
}
$imUser = new ImUserModel();
$imUser->id = $user->id;
$imUser->name = $user->name;
if ($imUser->create() === false) {
throw new \RuntimeException('Create Im User Failed');
}
$this->db->commit(); $this->db->commit();
return $account; return $account;

View File

@ -0,0 +1,70 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Deliver;
use App\Models\Course as CourseModel;
use App\Models\CourseUser as CourseUserModel;
use App\Models\ImGroupUser as ImGroupUserModel;
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\Services\Logic\Service as LogicService;
class CourseDeliver extends LogicService
{
public function handle(CourseModel $course, UserModel $user)
{
if ($course->model == CourseModel::MODEL_OFFLINE) {
$expiryTime = strtotime($course->attrs['end_date']);
} else {
$expiryTime = strtotime("+{$course->study_expiry} months");
}
$courseUser = new CourseUserModel();
$courseUser->user_id = $user->id;
$courseUser->course_id = $course->id;
$courseUser->expiry_time = $expiryTime;
$courseUser->role_type = CourseUserModel::ROLE_STUDENT;
$courseUser->source_type = CourseUserModel::SOURCE_CHARGE;
$courseUser->create();
$course->user_count += 1;
$course->update();
$groupRepo = new ImGroupRepo();
$group = $groupRepo->findByCourseId($course->id);
$imUserRepo = new ImUserRepo();
$imUser = $imUserRepo->findById($user->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();
}
}
}

View File

@ -0,0 +1,70 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
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\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\Services\Logic\Service as LogicService;
class PackageDeliver extends LogicService
{
public function handle(PackageModel $package, UserModel $user)
{
$packageRepo = new PackageRepo();
$courses = $packageRepo->findCourses($package->id);
foreach ($courses as $course) {
$courseUser = new CourseUserModel();
$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();
}
}
}
}

View File

@ -0,0 +1,28 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Deliver;
use App\Models\User as UserModel;
use App\Models\Vip as VipModel;
use App\Services\Logic\Service as LogicService;
class VipDeliver extends LogicService
{
public function handle(VipModel $vip, UserModel $user)
{
$baseTime = $user->vip_expiry_time > time() ? $user->vip_expiry_time : time();
$user->vip_expiry_time = strtotime("+{$vip->expiry} months", $baseTime);
$user->vip = 1;
$user->update();
}
}

View File

@ -28,11 +28,11 @@ class OrderCreate extends OrderCreateService
$sale = $this->checkFlashSale($id); $sale = $this->checkFlashSale($id);
$validator = new FlashSaleValidator; $saleValidator = new FlashSaleValidator();
$validator->checkIfExpired($sale->end_time); $saleValidator->checkIfExpired($sale->end_time);
$validator->checkIfOutSchedules($sale->schedules); $saleValidator->checkIfOutSchedules($sale->schedules);
$validator->checkIfNotPaid($user->id, $sale->id); $saleValidator->checkIfNotPaid($user->id, $sale->id);
$queue = new Queue(); $queue = new Queue();
@ -50,31 +50,33 @@ class OrderCreate extends OrderCreateService
] ]
]; ];
$orderValidator = new OrderValidator();
$orderValidator->checkAmount($this->amount);
try { try {
$order = new OrderModel(); $order = new OrderModel();
$validator = new OrderValidator();
if ($sale->item_type == FlashSaleModel::ITEM_COURSE) { if ($sale->item_type == FlashSaleModel::ITEM_COURSE) {
$course = $validator->checkCourse($sale->item_id); $course = $orderValidator->checkCourse($sale->item_id);
$validator->checkIfBoughtCourse($user->id, $course->id); $orderValidator->checkIfBoughtCourse($user->id, $course->id);
$order = $this->createCourseOrder($course, $user); $order = $this->createCourseOrder($course, $user);
} elseif ($sale->item_type == FlashSaleModel::ITEM_PACKAGE) { } elseif ($sale->item_type == FlashSaleModel::ITEM_PACKAGE) {
$package = $validator->checkPackage($sale->item_id); $package = $orderValidator->checkPackage($sale->item_id);
$validator->checkIfBoughtPackage($user->id, $package->id); $orderValidator->checkIfBoughtPackage($user->id, $package->id);
$order = $this->createPackageOrder($package, $user); $order = $this->createPackageOrder($package, $user);
} elseif ($sale->item_type == FlashSaleModel::ITEM_VIP) { } elseif ($sale->item_type == FlashSaleModel::ITEM_VIP) {
$vip = $validator->checkVip($sale->item_id); $vip = $orderValidator->checkVip($sale->item_id);
$order = $this->createVipOrder($vip, $user); $order = $this->createVipOrder($vip, $user);
} }

View File

@ -70,16 +70,13 @@ class ConsultReply extends LogicService
$subscribe = $subscribeRepo->findByUserId($consult->owner_id); $subscribe = $subscribeRepo->findByUserId($consult->owner_id);
if ($wechatNoticeEnabled && $subscribe) { if ($wechatNoticeEnabled && $subscribe) {
$notice = new WeChatConsultReplyNotice(); $notice = new WeChatConsultReplyNotice();
$notice->handle($subscribe, $params);
}
return $notice->handle($subscribe, $params); if ($smsNoticeEnabled) {
} elseif ($smsNoticeEnabled) {
$notice = new SmsConsultReplyNotice(); $notice = new SmsConsultReplyNotice();
$notice->handle($user, $params);
return $notice->handle($user, $params);
} }
} }

View File

@ -64,7 +64,7 @@ class ConsultCreate extends DingTalkNotice
$task->item_id = $consult->id; $task->item_id = $consult->id;
$task->item_info = $itemInfo; $task->item_info = $itemInfo;
$task->item_type = TaskModel::TYPE_NOTICE_CONSULT_CREATE; $task->item_type = TaskModel::TYPE_STAFF_NOTICE_CONSULT_CREATE;
$task->priority = TaskModel::PRIORITY_LOW; $task->priority = TaskModel::PRIORITY_LOW;
$task->status = TaskModel::STATUS_PENDING; $task->status = TaskModel::STATUS_PENDING;

View File

@ -58,7 +58,7 @@ class CustomService extends DingTalkNotice
$task->item_id = $message->id; $task->item_id = $message->id;
$task->item_info = $itemInfo; $task->item_info = $itemInfo;
$task->item_type = TaskModel::TYPE_NOTICE_CUSTOM_SERVICE; $task->item_type = TaskModel::TYPE_STAFF_NOTICE_CUSTOM_SERVICE;
$task->priority = TaskModel::PRIORITY_MIDDLE; $task->priority = TaskModel::PRIORITY_MIDDLE;
$task->status = TaskModel::STATUS_PENDING; $task->status = TaskModel::STATUS_PENDING;

View File

@ -8,19 +8,19 @@
namespace App\Services\Logic\Notice\DingTalk; namespace App\Services\Logic\Notice\DingTalk;
use App\Models\PointGift as PointGiftModel; use App\Models\PointGift as PointGiftModel;
use App\Models\PointRedeem as PointRedeemModel; use App\Models\PointGiftRedeem as PointGiftRedeemModel;
use App\Models\Task as TaskModel; use App\Models\Task as TaskModel;
use App\Repos\PointRedeem as PointRedeemRepo; use App\Repos\PointGiftRedeem as PointGiftRedeemRepo;
use App\Services\DingTalkNotice; use App\Services\DingTalkNotice;
class PointRedeem extends DingTalkNotice class PointGiftRedeem extends DingTalkNotice
{ {
public function handleTask(TaskModel $task) public function handleTask(TaskModel $task)
{ {
if (!$this->enabled) return; if (!$this->enabled) return;
$redeemRepo = new PointRedeemRepo(); $redeemRepo = new PointGiftRedeemRepo();
$redeem = $redeemRepo->findById($task->item_id); $redeem = $redeemRepo->findById($task->item_id);
@ -32,7 +32,7 @@ class PointRedeem extends DingTalkNotice
$this->atCustomService($content); $this->atCustomService($content);
} }
public function createTask(PointRedeemModel $redeem) public function createTask(PointGiftRedeemModel $redeem)
{ {
if (!$this->enabled) return; if (!$this->enabled) return;
@ -41,12 +41,12 @@ class PointRedeem extends DingTalkNotice
$task = new TaskModel(); $task = new TaskModel();
$itemInfo = [ $itemInfo = [
'point_redeem' => ['id' => $redeem->id], 'point_gift_redeem' => ['id' => $redeem->id],
]; ];
$task->item_id = $redeem->id; $task->item_id = $redeem->id;
$task->item_info = $itemInfo; $task->item_info = $itemInfo;
$task->item_type = TaskModel::TYPE_NOTICE_POINT_REDEEM; $task->item_type = TaskModel::TYPE_STAFF_NOTICE_POINT_GIFT_REDEEM;
$task->priority = TaskModel::PRIORITY_MIDDLE; $task->priority = TaskModel::PRIORITY_MIDDLE;
$task->status = TaskModel::STATUS_PENDING; $task->status = TaskModel::STATUS_PENDING;

View File

@ -34,7 +34,7 @@ class ServerMonitor extends DingTalkNotice
$task->item_id = time(); $task->item_id = time();
$task->item_info = $itemInfo; $task->item_info = $itemInfo;
$task->item_type = TaskModel::TYPE_NOTICE_SERVER_MONITOR; $task->item_type = TaskModel::TYPE_STAFF_NOTICE_SERVER_MONITOR;
$task->priority = TaskModel::PRIORITY_HIGH; $task->priority = TaskModel::PRIORITY_HIGH;
$task->status = TaskModel::STATUS_PENDING; $task->status = TaskModel::STATUS_PENDING;
$task->max_try_count = 1; $task->max_try_count = 1;

View File

@ -48,7 +48,7 @@ class TeacherLive extends DingTalkNotice
$task->item_id = $live->id; $task->item_id = $live->id;
$task->item_info = $itemInfo; $task->item_info = $itemInfo;
$task->item_type = TaskModel::TYPE_NOTICE_TEACHER_LIVE; $task->item_type = TaskModel::TYPE_STAFF_NOTICE_TEACHER_LIVE;
$task->priority = TaskModel::PRIORITY_LOW; $task->priority = TaskModel::PRIORITY_LOW;
$task->status = TaskModel::STATUS_PENDING; $task->status = TaskModel::STATUS_PENDING;

View File

@ -68,16 +68,13 @@ class LiveBegin extends LogicService
$subscribe = $subscribeRepo->findByUserId($user->id); $subscribe = $subscribeRepo->findByUserId($user->id);
if ($wechatNoticeEnabled && $subscribe) { if ($wechatNoticeEnabled && $subscribe) {
$notice = new WeChatLiveBeginNotice(); $notice = new WeChatLiveBeginNotice();
$notice->handle($subscribe, $params);
}
return $notice->handle($subscribe, $params); if ($smsNoticeEnabled) {
} elseif ($smsNoticeEnabled) {
$notice = new SmsLiveBeginNotice(); $notice = new SmsLiveBeginNotice();
$notice->handle($user, $params);
return $notice->handle($user, $params);
} }
} }

View File

@ -55,16 +55,13 @@ class OrderFinish extends LogicService
$subscribe = $subscribeRepo->findByUserId($order->owner_id); $subscribe = $subscribeRepo->findByUserId($order->owner_id);
if ($wechatNoticeEnabled && $subscribe) { if ($wechatNoticeEnabled && $subscribe) {
$notice = new WeChatOrderFinishNotice(); $notice = new WeChatOrderFinishNotice();
$notice->handle($subscribe, $params);
}
return $notice->handle($subscribe, $params); if ($smsNoticeEnabled) {
} elseif ($smsNoticeEnabled) {
$notice = new SmsOrderFinishNotice(); $notice = new SmsOrderFinishNotice();
$notice->handle($user, $params);
return $notice->handle($user, $params);
} }
} }

View File

@ -7,9 +7,9 @@
namespace App\Services\Logic\Notice; namespace App\Services\Logic\Notice;
use App\Models\PointRedeem as PointRedeemModel; use App\Models\PointGiftRedeem as PointGiftRedeemModel;
use App\Models\Task as TaskModel; use App\Models\Task as TaskModel;
use App\Repos\PointRedeem as PointRedeemRepo; use App\Repos\PointGiftRedeem as PointGiftRedeemRepo;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use App\Repos\WeChatSubscribe as WeChatSubscribeRepo; use App\Repos\WeChatSubscribe as WeChatSubscribeRepo;
use App\Services\Logic\Notice\Sms\GoodsDeliver as SmsGoodsDeliverNotice; use App\Services\Logic\Notice\Sms\GoodsDeliver as SmsGoodsDeliverNotice;
@ -28,7 +28,7 @@ class PointGoodsDeliver extends LogicService
$redeemId = $task->item_info['point_redeem']['id']; $redeemId = $task->item_info['point_redeem']['id'];
$redeemRepo = new PointRedeemRepo(); $redeemRepo = new PointGiftRedeemRepo();
$redeem = $redeemRepo->findById($redeemId); $redeem = $redeemRepo->findById($redeemId);
@ -51,20 +51,17 @@ class PointGoodsDeliver extends LogicService
$subscribe = $subscribeRepo->findByUserId($user->id); $subscribe = $subscribeRepo->findByUserId($user->id);
if ($wechatNoticeEnabled && $subscribe) { if ($wechatNoticeEnabled && $subscribe) {
$notice = new WeChatGoodsDeliverNotice(); $notice = new WeChatGoodsDeliverNotice();
$notice->handle($subscribe, $params);
}
return $notice->handle($subscribe, $params); if ($smsNoticeEnabled) {
} elseif ($smsNoticeEnabled) {
$notice = new SmsGoodsDeliverNotice(); $notice = new SmsGoodsDeliverNotice();
$notice->handle($user, $params);
return $notice->handle($user, $params);
} }
} }
public function createTask(PointRedeemModel $redeem) public function createTask(PointGiftRedeemModel $redeem)
{ {
$wechatNoticeEnabled = $this->wechatNoticeEnabled(); $wechatNoticeEnabled = $this->wechatNoticeEnabled();
$smsNoticeEnabled = $this->smsNoticeEnabled(); $smsNoticeEnabled = $this->smsNoticeEnabled();
@ -74,7 +71,7 @@ class PointGoodsDeliver extends LogicService
$task = new TaskModel(); $task = new TaskModel();
$itemInfo = [ $itemInfo = [
'point_redeem' => ['id' => $redeem->id], 'point_gift_redeem' => ['id' => $redeem->id],
]; ];
$task->item_id = $redeem->id; $task->item_id = $redeem->id;

View File

@ -55,16 +55,13 @@ class RefundFinish extends LogicService
$subscribe = $subscribeRepo->findByUserId($refund->owner_id); $subscribe = $subscribeRepo->findByUserId($refund->owner_id);
if ($wechatNoticeEnabled && $subscribe) { if ($wechatNoticeEnabled && $subscribe) {
$notice = new WeChatRefundFinishNotice(); $notice = new WeChatRefundFinishNotice();
$notice->handle($subscribe, $params);
}
return $notice->handle($subscribe, $params); if ($smsNoticeEnabled) {
} elseif ($smsNoticeEnabled) {
$notice = new SmsRefundFinishNotice(); $notice = new SmsRefundFinishNotice();
$notice->handle($user, $params);
return $notice->handle($user, $params);
} }
} }

View File

@ -55,9 +55,9 @@ class OrderCreate extends LogicService
$validator->checkDailyOrderLimit($user); $validator->checkDailyOrderLimit($user);
$validator = new OrderValidator(); $orderValidator = new OrderValidator();
$validator->checkItemType($post['item_type']); $orderValidator->checkItemType($post['item_type']);
$orderRepo = new OrderRepo(); $orderRepo = new OrderRepo();
@ -70,41 +70,49 @@ class OrderCreate extends LogicService
if ($post['item_type'] == OrderModel::ITEM_COURSE) { if ($post['item_type'] == OrderModel::ITEM_COURSE) {
$course = $validator->checkCourse($post['item_id']); $course = $orderValidator->checkCourse($post['item_id']);
$validator->checkIfBoughtCourse($user->id, $course->id); $orderValidator->checkIfBoughtCourse($user->id, $course->id);
$this->amount = $user->vip ? $course->vip_price : $course->market_price; $this->amount = $user->vip ? $course->vip_price : $course->market_price;
$orderValidator->checkAmount($this->amount);
$order = $this->createCourseOrder($course, $user); $order = $this->createCourseOrder($course, $user);
} elseif ($post['item_type'] == OrderModel::ITEM_PACKAGE) { } elseif ($post['item_type'] == OrderModel::ITEM_PACKAGE) {
$package = $validator->checkPackage($post['item_id']); $package = $orderValidator->checkPackage($post['item_id']);
$validator->checkIfBoughtPackage($user->id, $package->id); $orderValidator->checkIfBoughtPackage($user->id, $package->id);
$this->amount = $user->vip ? $package->vip_price : $package->market_price; $this->amount = $user->vip ? $package->vip_price : $package->market_price;
$orderValidator->checkAmount($this->amount);
$order = $this->createPackageOrder($package, $user); $order = $this->createPackageOrder($package, $user);
} elseif ($post['item_type'] == OrderModel::ITEM_REWARD) { } elseif ($post['item_type'] == OrderModel::ITEM_REWARD) {
list($courseId, $rewardId) = explode('-', $post['item_id']); list($courseId, $rewardId) = explode('-', $post['item_id']);
$course = $validator->checkCourse($courseId); $course = $orderValidator->checkCourse($courseId);
$reward = $validator->checkReward($rewardId); $reward = $orderValidator->checkReward($rewardId);
$this->amount = $reward->price; $this->amount = $reward->price;
$orderValidator->checkAmount($this->amount);
$order = $this->createRewardOrder($course, $reward, $user); $order = $this->createRewardOrder($course, $reward, $user);
} elseif ($post['item_type'] == OrderModel::ITEM_VIP) { } elseif ($post['item_type'] == OrderModel::ITEM_VIP) {
$vip = $validator->checkVip($post['item_id']); $vip = $orderValidator->checkVip($post['item_id']);
$this->amount = $vip->price; $this->amount = $vip->price;
$orderValidator->checkAmount($this->amount);
$order = $this->createVipOrder($vip, $user); $order = $this->createVipOrder($vip, $user);
} }

View File

@ -8,6 +8,7 @@
namespace App\Services\Logic\Point; namespace App\Services\Logic\Point;
use App\Models\PointGift; use App\Models\PointGift;
use App\Repos\User as UserRepo;
use App\Services\Logic\CourseTrait; use App\Services\Logic\CourseTrait;
use App\Services\Logic\PointGiftTrait; use App\Services\Logic\PointGiftTrait;
use App\Services\Logic\Service as LogicService; use App\Services\Logic\Service as LogicService;
@ -28,6 +29,8 @@ class GiftInfo extends LogicService
$gift->details = kg_parse_markdown($gift->details); $gift->details = kg_parse_markdown($gift->details);
$meInfo = $this->handleMeInfo($gift);
return [ return [
'id' => $gift->id, 'id' => $gift->id,
'name' => $gift->name, 'name' => $gift->name,
@ -43,6 +46,7 @@ class GiftInfo extends LogicService
'redeem_count' => $gift->redeem_count, 'redeem_count' => $gift->redeem_count,
'create_time' => $gift->create_time, 'create_time' => $gift->create_time,
'update_time' => $gift->update_time, 'update_time' => $gift->update_time,
'me' => $meInfo,
]; ];
} }
@ -64,4 +68,21 @@ class GiftInfo extends LogicService
return $gift; return $gift;
} }
protected function handleMeInfo(PointGift $gift)
{
$me = ['allow_redeem' => 0];
$user = $this->getLoginUser(true);
$userRepo = new UserRepo();
$balance = $userRepo->findUserBalance($user->id);
if ($gift->stock > 0 && $balance->point > $gift->point) {
$me['allow_redeem'] = 1;
}
return $me;
}
} }

View File

@ -9,40 +9,36 @@ namespace App\Services\Logic\Point;
use App\Library\Utils\Lock as LockUtil; use App\Library\Utils\Lock as LockUtil;
use App\Models\PointGift as PointGiftModel; use App\Models\PointGift as PointGiftModel;
use App\Models\PointRedeem as PointRedeemModel; use App\Models\PointGiftRedeem as PointGiftRedeemModel;
use App\Models\Task as TaskModel; use App\Models\Task as TaskModel;
use App\Models\User as UserModel; use App\Models\User as UserModel;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use App\Services\Logic\Point\History\PointRedeem as PointRedeemPointHistory; use App\Services\Logic\Point\History\PointGiftRedeem as PointGiftRedeemPointHistory;
use App\Services\Logic\PointGiftTrait; use App\Services\Logic\PointGiftTrait;
use App\Services\Logic\Service as LogicService; use App\Services\Logic\Service as LogicService;
use App\Validators\PointRedeem as PointRedeemValidator; use App\Validators\PointGiftRedeem as PointGiftRedeemValidator;
class PointRedeem extends LogicService class GiftRedeem extends LogicService
{ {
use PointGiftTrait; use PointGiftTrait;
public function handle() public function handle($id)
{ {
$giftId = $this->request->getPost('gift_id', ['trim', 'int']); $gift = $this->checkPointGift($id);
$gift = $this->checkPointGift($giftId);
$user = $this->getLoginUser(); $user = $this->getLoginUser();
$validator = new PointRedeemValidator(); $validator = new PointGiftRedeemValidator();
$validator->checkIfAllowRedeem($gift, $user); $validator->checkIfAllowRedeem($gift, $user);
$this->createPointRedeem($gift, $user); $this->createGiftRedeem($gift, $user);
} }
protected function createPointRedeem(PointGiftModel $gift, UserModel $user) protected function createGiftRedeem(PointGiftModel $gift, UserModel $user)
{ {
$logger = $this->getLogger('point'); $itemId = "point_gift_redeem:{$gift->id}";
$itemId = "point_redeem:{$gift->id}";
$lockId = LockUtil::addLock($itemId); $lockId = LockUtil::addLock($itemId);
@ -54,7 +50,7 @@ class PointRedeem extends LogicService
$this->db->begin(); $this->db->begin();
$redeem = new PointRedeemModel(); $redeem = new PointGiftRedeemModel();
$redeem->user_id = $user->id; $redeem->user_id = $user->id;
$redeem->user_name = $user->name; $redeem->user_name = $user->name;
@ -71,7 +67,7 @@ class PointRedeem extends LogicService
$redeem->contact_address = $contact->fullAddress(); $redeem->contact_address = $contact->fullAddress();
} }
$redeem->status = PointRedeemModel::STATUS_PENDING; $redeem->status = PointGiftRedeemModel::STATUS_PENDING;
$result = $redeem->create(); $result = $redeem->create();
@ -89,7 +85,7 @@ class PointRedeem extends LogicService
$task = new TaskModel(); $task = new TaskModel();
$itemInfo = [ $itemInfo = [
'point_redeem' => [ 'point_gift_redeem' => [
'id' => $redeem->id, 'id' => $redeem->id,
'user_id' => $redeem->user_id, 'user_id' => $redeem->user_id,
'gift_id' => $redeem->gift_id, 'gift_id' => $redeem->gift_id,
@ -114,7 +110,9 @@ class PointRedeem extends LogicService
$this->db->rollback(); $this->db->rollback();
$logger->error('Point Redeem Exception ' . kg_json_encode([ $logger = $this->getLogger('point');
$logger->error('Gift Redeem Exception ' . kg_json_encode([
'file' => $e->getFile(), 'file' => $e->getFile(),
'line' => $e->getLine(), 'line' => $e->getLine(),
'message' => $e->getMessage(), 'message' => $e->getMessage(),
@ -126,9 +124,9 @@ class PointRedeem extends LogicService
LockUtil::releaseLock($itemId, $lockId); LockUtil::releaseLock($itemId, $lockId);
} }
protected function handleRedeemPoint(PointRedeemModel $redeem) protected function handleRedeemPoint(PointGiftRedeemModel $redeem)
{ {
$service = new PointRedeemPointHistory(); $service = new PointGiftRedeemPointHistory();
$service->handle($redeem); $service->handle($redeem);
} }

View File

@ -7,16 +7,16 @@
namespace App\Services\Logic\Point\History; namespace App\Services\Logic\Point\History;
use App\Models\PointGiftRedeem as PointGiftRedeemModel;
use App\Models\PointHistory as PointHistoryModel; use App\Models\PointHistory as PointHistoryModel;
use App\Models\PointRedeem as PointRedeemModel;
use App\Repos\PointHistory as PointHistoryRepo; use App\Repos\PointHistory as PointHistoryRepo;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use App\Services\Logic\Point\PointHistory; use App\Services\Logic\Point\PointHistory;
class PointRedeem extends PointHistory class PointGiftRedeem extends PointHistory
{ {
public function handle(PointRedeemModel $redeem) public function handle(PointGiftRedeemModel $redeem)
{ {
$setting = $this->getSettings('point'); $setting = $this->getSettings('point');
@ -39,7 +39,7 @@ class PointRedeem extends PointHistory
$user = $userRepo->findById($redeem->user_id); $user = $userRepo->findById($redeem->user_id);
$eventInfo = [ $eventInfo = [
'point_redeem' => [ 'point_gift_redeem' => [
'id' => $redeem->id, 'id' => $redeem->id,
'gift_id' => $redeem->gift_id, 'gift_id' => $redeem->gift_id,
'gift_name' => $redeem->gift_name, 'gift_name' => $redeem->gift_name,

View File

@ -7,8 +7,8 @@
namespace App\Services\Logic\Point\History; namespace App\Services\Logic\Point\History;
use App\Models\PointGiftRedeem as PointGiftRedeemModel;
use App\Models\PointHistory as PointHistoryModel; use App\Models\PointHistory as PointHistoryModel;
use App\Models\PointRedeem as PointRedeemModel;
use App\Repos\PointHistory as PointHistoryRepo; use App\Repos\PointHistory as PointHistoryRepo;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use App\Services\Logic\Point\PointHistory; use App\Services\Logic\Point\PointHistory;
@ -16,7 +16,7 @@ use App\Services\Logic\Point\PointHistory;
class PointRefund extends PointHistory class PointRefund extends PointHistory
{ {
public function handle(PointRedeemModel $redeem) public function handle(PointGiftRedeemModel $redeem)
{ {
$eventId = $redeem->id; $eventId = $redeem->id;
$eventType = PointHistoryModel::EVENT_POINT_REFUND; $eventType = PointHistoryModel::EVENT_POINT_REFUND;
@ -33,7 +33,7 @@ class PointRefund extends PointHistory
$user = $userRepo->findById($redeem->user_id); $user = $userRepo->findById($redeem->user_id);
$eventInfo = [ $eventInfo = [
'point_redeem' => [ 'point_gift_redeem' => [
'id' => $redeem->id, 'id' => $redeem->id,
'gift_id' => $redeem->gift_id, 'gift_id' => $redeem->gift_id,
'gift_name' => $redeem->gift_name, 'gift_name' => $redeem->gift_name,

View File

@ -8,12 +8,12 @@
namespace App\Services\Logic\User\Console; namespace App\Services\Logic\User\Console;
use App\Library\Paginator\Query as PagerQuery; use App\Library\Paginator\Query as PagerQuery;
use App\Models\PointRedeem as PointRedeemModel; use App\Models\PointGiftRedeem as PointGiftRedeemModel;
use App\Repos\PointRedeem as PointRedeemRepo; use App\Repos\PointGiftRedeem as PointGiftRedeemRepo;
use App\Services\Logic\Service as LogicService; use App\Services\Logic\Service as LogicService;
use App\Services\Logic\UserTrait; use App\Services\Logic\UserTrait;
class PointRedeemList extends LogicService class PointGiftRedeemList extends LogicService
{ {
use UserTrait; use UserTrait;
@ -33,7 +33,7 @@ class PointRedeemList extends LogicService
$page = $pagerQuery->getPage(); $page = $pagerQuery->getPage();
$limit = $pagerQuery->getLimit(); $limit = $pagerQuery->getLimit();
$redeemRepo = new PointRedeemRepo(); $redeemRepo = new PointGiftRedeemRepo();
$pager = $redeemRepo->paginate($params, $sort, $page, $limit); $pager = $redeemRepo->paginate($params, $sort, $page, $limit);
@ -49,7 +49,7 @@ class PointRedeemList extends LogicService
$items = []; $items = [];
/** /**
* @var PointRedeemModel[] $redeems * @var PointGiftRedeemModel[] $redeems
*/ */
$redeems = $pager->items; $redeems = $pager->items;

View File

@ -79,7 +79,7 @@ class Article extends Validator
$length = kg_strlen($value); $length = kg_strlen($value);
if ($length < 5) { if ($length < 2) {
throw new BadRequestException('article.title_too_short'); throw new BadRequestException('article.title_too_short');
} }

View File

@ -12,21 +12,21 @@ use App\Models\Course as CourseModel;
use App\Models\PointGift as PointGiftModel; use App\Models\PointGift as PointGiftModel;
use App\Models\User as UserModel; use App\Models\User as UserModel;
use App\Repos\CourseUser as CourseUserRepo; use App\Repos\CourseUser as CourseUserRepo;
use App\Repos\PointRedeem as PointRedeemRepo; use App\Repos\PointGiftRedeem as PointGiftRedeemRepo;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
class PointRedeem extends Validator class PointGiftRedeem extends Validator
{ {
public function checkRedeem($id) public function checkRedeem($id)
{ {
$redeemRepo = new PointRedeemRepo(); $redeemRepo = new PointGiftRedeemRepo();
$redeem = $redeemRepo->findById($id); $redeem = $redeemRepo->findById($id);
if (!$redeem) { if (!$redeem) {
throw new BadRequestException('point_redeem.not_found'); throw new BadRequestException('point_gift_redeem.not_found');
} }
return $redeem; return $redeem;
@ -64,11 +64,11 @@ class PointRedeem extends Validator
protected function checkIfAllowRedeemCourse(CourseModel $course, UserModel $user) protected function checkIfAllowRedeemCourse(CourseModel $course, UserModel $user)
{ {
if ($course->published == 0) { if ($course->published == 0) {
throw new BadRequestException('point_redeem.course_not_published'); throw new BadRequestException('point_gift_redeem.course_not_published');
} }
if ($course->market_price == 0) { if ($course->market_price == 0) {
throw new BadRequestException('point_redeem.course_free'); throw new BadRequestException('point_gift_redeem.course_free');
} }
$courseUserRepo = new CourseUserRepo(); $courseUserRepo = new CourseUserRepo();
@ -76,7 +76,7 @@ class PointRedeem extends Validator
$courseUser = $courseUserRepo->findCourseUser($course->id, $user->id); $courseUser = $courseUserRepo->findCourseUser($course->id, $user->id);
if ($courseUser && $courseUser->expiry_time > time()) { if ($courseUser && $courseUser->expiry_time > time()) {
throw new BadRequestException('point_redeem.course_owned'); throw new BadRequestException('point_gift_redeem.course_owned');
} }
} }
@ -87,25 +87,25 @@ class PointRedeem extends Validator
$contact = $userRepo->findUserContact($user->id); $contact = $userRepo->findUserContact($user->id);
if (!$contact) { if (!$contact) {
throw new BadRequestException('point_redeem.no_user_contact'); throw new BadRequestException('point_gift_redeem.no_user_contact');
} }
} }
protected function checkStock(PointGiftModel $gift) protected function checkStock(PointGiftModel $gift)
{ {
if ($gift->stock < 1) { if ($gift->stock < 1) {
throw new BadRequestException('point_redeem.no_enough_stock'); throw new BadRequestException('point_gift_redeem.no_enough_stock');
} }
} }
protected function checkRedeemLimit(PointGiftModel $gift, UserModel $user) protected function checkRedeemLimit(PointGiftModel $gift, UserModel $user)
{ {
$redeemRepo = new PointRedeemRepo(); $redeemRepo = new PointGiftRedeemRepo();
$count = $redeemRepo->countUserGiftRedeems($user->id, $gift->id); $count = $redeemRepo->countUserGiftRedeems($user->id, $gift->id);
if ($count >= $gift->redeem_limit) { if ($count >= $gift->redeem_limit) {
throw new BadRequestException('point_redeem.reach_redeem_limit'); throw new BadRequestException('point_gift_redeem.reach_redeem_limit');
} }
} }
@ -116,7 +116,7 @@ class PointRedeem extends Validator
$balance = $userRepo->findUserBalance($user->id); $balance = $userRepo->findUserBalance($user->id);
if (!$balance || $balance->point < $gift->point) { if (!$balance || $balance->point < $gift->point) {
throw new BadRequestException('point_redeem.no_enough_point'); throw new BadRequestException('point_gift_redeem.no_enough_point');
} }
} }

View File

@ -82,6 +82,11 @@ $config['redis']['host'] = 'redis';
*/ */
$config['redis']['port'] = 6379; $config['redis']['port'] = 6379;
/**
* redis库编号
*/
$config['redis']['index'] = 0;
/** /**
* redis密码 * redis密码
*/ */

View File

@ -118,7 +118,7 @@ $error['nav.has_child_node'] = '不允许相关操作(存在子节点)';
* 文章相关 * 文章相关
*/ */
$error['article.not_found'] = '文章不存在'; $error['article.not_found'] = '文章不存在';
$error['article.title_too_short'] = '标题太短(少于5个字符)'; $error['article.title_too_short'] = '标题太短(少于2个字符)';
$error['article.title_too_long'] = '标题太长多于50个字符'; $error['article.title_too_long'] = '标题太长多于50个字符';
$error['article.content_too_short'] = '内容太短少于10个字符'; $error['article.content_too_short'] = '内容太短少于10个字符';
$error['article.content_too_long'] = '内容太长多于30000个字符'; $error['article.content_too_long'] = '内容太长多于30000个字符';
@ -505,14 +505,14 @@ $error['point_gift.invalid_stock'] = '无效的库存值范围1-999999'
$error['point_gift.invalid_redeem_limit'] = '无效的兑换限额范围1-10'; $error['point_gift.invalid_redeem_limit'] = '无效的兑换限额范围1-10';
$error['point_gift.invalid_publish_status'] = '无效的发布状态'; $error['point_gift.invalid_publish_status'] = '无效的发布状态';
$error['point_redeem.not_found'] = '兑换不存在'; $error['point_gift_redeem.not_found'] = '兑换不存在';
$error['point_redeem.course_not_published'] = '课程尚未发布'; $error['point_gift_redeem.course_not_published'] = '课程尚未发布';
$error['point_redeem.course_free'] = '课程当前免费,无需积分兑换'; $error['point_gift_redeem.course_free'] = '课程当前免费,无需积分兑换';
$error['point_redeem.course_owned'] = '您已经拥有课程,无需积分兑换'; $error['point_gift_redeem.course_owned'] = '您已经拥有课程,无需积分兑换';
$error['point_redeem.no_user_contact'] = '您尚未设置收货地址,请前往用户中心设置'; $error['point_gift_redeem.no_user_contact'] = '您尚未设置收货地址,请前往用户中心设置';
$error['point_redeem.reach_redeem_limit'] = '超出物品兑换限额'; $error['point_gift_redeem.reach_redeem_limit'] = '超出物品兑换限额';
$error['point_redeem.no_enough_point'] = '您的积分余额不足以抵扣此次兑换'; $error['point_gift_redeem.no_enough_point'] = '您的积分余额不足以抵扣此次兑换';
$error['point_redeem.no_enough_stock'] = '兑换物品库存不足'; $error['point_gift_redeem.no_enough_stock'] = '兑换物品库存不足';
/** /**
* 限时秒杀相关 * 限时秒杀相关

View File

@ -0,0 +1,46 @@
<?php
use Phinx\Migration\AbstractMigration;
final class V20220117122902 extends AbstractMigration
{
public function up()
{
$this->renameGiftRedeemTable();
$this->handlePointHistory();
}
protected function renameGiftRedeemTable()
{
if ($this->table('kg_point_redeem')->exists()) {
$this->table('kg_point_redeem')
->rename('kg_point_gift_redeem')
->save();
}
}
protected function handlePointHistory()
{
$rows = $this->getQueryBuilder()
->select('*')
->from('kg_point_history')
->whereInList('event_type', [2, 3])
->execute()->fetchAll(PDO::FETCH_ASSOC);
if (empty($rows)) return;
foreach ($rows as $row) {
$eventInfo = json_decode($row['event_info'], true);
$newEventInfo = json_encode([
'point_gift_redeem' => $eventInfo['point_redeem']
]);
$this->getQueryBuilder()
->update('kg_point_history')
->set('event_info', $newEventInfo)
->where(['id' => $row['id']])
->execute();
}
}
}

View File

@ -926,12 +926,14 @@
.course-meta .cover { .course-meta .cover {
float: left; float: left;
position: relative;
margin-right: 10px; margin-right: 10px;
} }
.course-meta .info { .course-meta .info {
float: left; float: left;
width: 560px; width: 560px;
padding-top: 5px;
} }
.course-meta .rating { .course-meta .rating {
@ -940,12 +942,18 @@
} }
.course-meta p { .course-meta p {
line-height: 30px; line-height: 35px;
} }
.course-meta .cover img { .course-meta .cover img {
width: 210px; width: 270px;
height: 118px; height: 150px;
}
.course-meta .cover .model {
position: absolute;
top: 15px;
right: 15px;
} }
.course-meta .info .key { .course-meta .info .key {
@ -2287,26 +2295,30 @@
.gift-meta .cover { .gift-meta .cover {
float: left; float: left;
position: relative;
margin-right: 10px; margin-right: 10px;
} }
.gift-meta .cover .type {
position: absolute;
top: 15px;
right: 15px;
}
.gift-meta .cover img { .gift-meta .cover img {
width: 210px; width: 270px;
height: 118px; height: 150px;
} }
.gift-meta .info { .gift-meta .info {
float: left; float: left;
padding-top: 5px;
} }
.gift-meta .info p { .gift-meta .info p {
line-height: 35px; line-height: 35px;
} }
.gift-meta .info .stats {
margin-bottom: 10px;
}
.gift-meta .info span { .gift-meta .info span {
margin-right: 5px; margin-right: 5px;
} }

View File

@ -5,16 +5,14 @@ layui.use(['jquery', 'layer'], function () {
$('.btn-redeem').on('click', function () { $('.btn-redeem').on('click', function () {
var url = $(this).data('url'); var url = $(this).data('url');
var data = {gift_id: $(this).data('id')};
layer.confirm('兑换不支持退换,确定要兑换该物品吗?', function () { layer.confirm('兑换不支持退换,确定要兑换该物品吗?', function () {
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: url, url: url,
data: data,
success: function (res) { success: function (res) {
layer.msg(res.msg, {icon: 1}); layer.msg(res.msg, {icon: 1});
setTimeout(function () { setTimeout(function () {
window.location.href = '/uc/point/redeems'; window.location.href = '/uc/point/gift/redeems';
}, 3000); }, 3000);
} }
}); });