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

Merge branch 'develop'

# Conflicts:
#	app/Models/Course.php
#	db/migrations/schema.php
This commit is contained in:
koogua 2021-02-18 21:24:31 +08:00
commit c4f1adb27f
184 changed files with 6513 additions and 17234 deletions

1
.gitignore vendored
View File

@ -6,6 +6,7 @@
/config/xs.user.ini /config/xs.user.ini
/config/alipay/*.crt /config/alipay/*.crt
/config/wxpay/*.pem /config/wxpay/*.pem
/db/migrations/schema.php
/public/robots.txt /public/robots.txt
/public/sitemap.xml /public/sitemap.xml
/public/h5 /public/h5

View File

@ -1,3 +1,24 @@
### [v1.2.6](https://gitee.com/koogua/course-tencent-cloud/releases/v1.2.6)(2021-02-20)
### 新增
- 积分兑换机制
- 课程增加原价属性
- gitee提交webhooks自动化部署脚本
### 更新
- course和chapter数据迁移文件中遗漏了recourse_count字段
- app/Caches/TopicCourseList不存在
- Model文件属性定义默认值
- 隐藏非付费课程的咨询服务
- 教学中心教师直播推流按钮无反应
- 用户中心部分样式调整
- 播放器清晰度标签和实际的清晰度不对应
- CNZZ统计代码会显示出站长统计图标
- 自动安装后访问站点500错误
- 自动更新脚本可更新css和js版本号
### [v1.2.5](https://gitee.com/koogua/course-tencent-cloud/releases/v1.2.5)(2021-01-20) ### [v1.2.5](https://gitee.com/koogua/course-tencent-cloud/releases/v1.2.5)(2021-01-20)
### 新增 ### 新增

View File

@ -0,0 +1,29 @@
<?php
namespace App\Caches;
use App\Models\PointGift as PointGiftModel;
class MaxPointGiftId extends Cache
{
protected $lifetime = 365 * 86400;
public function getLifetime()
{
return $this->lifetime;
}
public function getKey($id = null)
{
return 'max_point_gift_id';
}
public function getContent($id = null)
{
$gift = PointGiftModel::findFirst(['order' => 'id DESC']);
return $gift->id ?? 0;
}
}

31
app/Caches/PointGift.php Normal file
View File

@ -0,0 +1,31 @@
<?php
namespace App\Caches;
use App\Repos\PointGift as PointGiftRepo;
class PointGift extends Cache
{
protected $lifetime = 365 * 86400;
public function getLifetime()
{
return $this->lifetime;
}
public function getKey($id = null)
{
return "point_gift:{$id}";
}
public function getContent($id = null)
{
$giftRepo = new PointGiftRepo();
$gift = $giftRepo->findById($id);
return $gift ?: null;
}
}

View File

@ -0,0 +1,79 @@
<?php
namespace App\Caches;
use App\Models\PointGift as PointGiftModel;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;
class PointHotGiftList extends Cache
{
/**
* 过期时间
*
* @var int
*/
protected $lifetime = 1 * 86400;
/**
* 显示个数
*
* @var int
*/
protected $limit = 5;
public function setLimit($limit)
{
$this->limit = $limit;
}
public function getLifetime()
{
return $this->lifetime;
}
public function getKey($id = null)
{
return 'point_hot_gift_list';
}
public function getContent($id = null)
{
$gifts = $this->findGifts($this->limit);
if (count($gifts) == 0) {
return [];
}
$result = [];
foreach ($gifts as $gift) {
$result[] = [
'id' => $gift->id,
'name' => $gift->name,
'cover' => $gift->cover,
'details' => $gift->details,
'type' => $gift->type,
'point' => $gift->point,
'redeem_count' => $gift->redeem_count,
];
}
return $result;
}
/**
* @param int $limit
* @return ResultsetInterface|Resultset|PointGiftModel[]
*/
protected function findGifts($limit = 5)
{
return PointGiftModel::query()
->where('published = 1')
->orderBy('redeem_count DESC')
->limit($limit)
->execute();
}
}

View File

@ -25,6 +25,7 @@ class CleanLogTask extends Task
$this->cleanWxpayLog(); $this->cleanWxpayLog();
$this->cleanOrderLog(); $this->cleanOrderLog();
$this->cleanRefundLog(); $this->cleanRefundLog();
$this->cleanPointLog();
$this->cleanNoticeLog(); $this->cleanNoticeLog();
$this->cleanOtherLog(); $this->cleanOtherLog();
} }
@ -221,6 +222,18 @@ class CleanLogTask extends Task
$this->whitelist[] = $type; $this->whitelist[] = $type;
} }
/**
* 清理积分日志
*/
protected function cleanPointLog()
{
$type = 'point';
$this->cleanLog($type, 7);
$this->whitelist[] = $type;
}
/** /**
* 清理通知日志 * 清理通知日志
*/ */

View File

@ -48,7 +48,7 @@ class CloseTradeTask extends Task
*/ */
if ($alipayTrade->trade_status == 'TRADE_SUCCESS') { if ($alipayTrade->trade_status == 'TRADE_SUCCESS') {
$this->eventsManager->fire('pay:afterPay', $this, $trade); $this->eventsManager->fire('Trade:afterPay', $this, $trade);
$allowClosed = false; $allowClosed = false;
@ -85,7 +85,7 @@ class CloseTradeTask extends Task
*/ */
if ($wxpayTrade->trade_state == 'SUCCESS') { if ($wxpayTrade->trade_state == 'SUCCESS') {
$this->eventsManager->fire('pay:afterPay', $this, $trade); $this->eventsManager->fire('Trade:afterPay', $this, $trade);
$allowClosed = false; $allowClosed = false;

View File

@ -13,6 +13,7 @@ use App\Repos\ImGroupUser as ImGroupUserRepo;
use App\Repos\Order as OrderRepo; use App\Repos\Order as OrderRepo;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use App\Services\Logic\Notice\OrderFinish as OrderFinishNotice; use App\Services\Logic\Notice\OrderFinish as OrderFinishNotice;
use App\Services\Logic\Point\PointHistory as PointHistoryService;
use Phalcon\Mvc\Model; use Phalcon\Mvc\Model;
use Phalcon\Mvc\Model\Resultset; use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface; use Phalcon\Mvc\Model\ResultsetInterface;
@ -36,17 +37,20 @@ class DeliverTask extends Task
foreach ($tasks as $task) { foreach ($tasks as $task) {
/** $orderId = $task->item_info['order']['id'] ?? 0;
* @var array $itemInfo
*/
$itemInfo = $task->item_info;
$order = $orderRepo->findById($itemInfo['order']['id']); $order = $orderRepo->findById($orderId);
if (!$order) continue; if (!$order) {
$task->status = TaskModel::STATUS_FAILED;
$task->update();
continue;
}
try { try {
$this->db->begin();
switch ($order->item_type) { switch ($order->item_type) {
case OrderModel::ITEM_COURSE: case OrderModel::ITEM_COURSE:
$this->handleCourseOrder($order); $this->handleCourseOrder($order);
@ -59,14 +63,24 @@ class DeliverTask extends Task
break; break;
} }
$this->finishOrder($order); $order->status = OrderModel::STATUS_FINISHED;
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();
} catch (\Exception $e) { } catch (\Exception $e) {
$this->db->rollback();
$task->try_count += 1; $task->try_count += 1;
$task->priority += 1; $task->priority += 1;
@ -76,14 +90,16 @@ class DeliverTask extends Task
$task->update(); $task->update();
$logger->info('Order Process Exception ' . kg_json_encode([ $logger->error('Order Process Exception ' . kg_json_encode([
'code' => $e->getCode(), 'file' => $e->getFile(),
'line' => $e->getLine(),
'message' => $e->getMessage(), 'message' => $e->getMessage(),
'task' => $task->toArray(), 'task' => $task->toArray(),
])); ]));
} }
if ($task->status == TaskModel::STATUS_FINISHED) { if ($task->status == TaskModel::STATUS_FINISHED) {
$this->handleOrderConsumePoint($order);
$this->handleOrderFinishNotice($order); $this->handleOrderFinishNotice($order);
} elseif ($task->status == TaskModel::STATUS_FAILED) { } elseif ($task->status == TaskModel::STATUS_FAILED) {
$this->handleOrderRefund($order); $this->handleOrderRefund($order);
@ -91,20 +107,8 @@ class DeliverTask extends Task
} }
} }
protected function finishOrder(OrderModel $order)
{
$order->status = OrderModel::STATUS_FINISHED;
if ($order->update() === false) {
throw new \RuntimeException('Finish Order Failed');
}
}
protected function handleCourseOrder(OrderModel $order) protected function handleCourseOrder(OrderModel $order)
{ {
/**
* @var array $itemInfo
*/
$itemInfo = $order->item_info; $itemInfo = $order->item_info;
$courseUser = new CourseUserModel(); $courseUser = new CourseUserModel();
@ -127,23 +131,21 @@ class DeliverTask extends Task
$groupUser = $groupUserRepo->findGroupUser($group->id, $order->owner_id); $groupUser = $groupUserRepo->findGroupUser($group->id, $order->owner_id);
if ($groupUser) return; if (!$groupUser) {
$groupUser = new ImGroupUserModel(); $groupUser = new ImGroupUserModel();
$groupUser->group_id = $group->id; $groupUser->group_id = $group->id;
$groupUser->user_id = $order->owner_id; $groupUser->user_id = $order->owner_id;
if ($groupUser->create() === false) { if ($groupUser->create() === false) {
throw new \RuntimeException('Create Group User Failed'); throw new \RuntimeException('Create Group User Failed');
}
} }
} }
protected function handlePackageOrder(OrderModel $order) protected function handlePackageOrder(OrderModel $order)
{ {
/**
* @var array $itemInfo
*/
$itemInfo = $order->item_info; $itemInfo = $order->item_info;
foreach ($itemInfo['courses'] as $course) { foreach ($itemInfo['courses'] as $course) {
@ -168,24 +170,24 @@ class DeliverTask extends Task
$groupUser = $groupUserRepo->findGroupUser($group->id, $order->owner_id); $groupUser = $groupUserRepo->findGroupUser($group->id, $order->owner_id);
if ($groupUser) continue; if (!$groupUser) {
$groupUser = new ImGroupUserModel(); $groupUser = new ImGroupUserModel();
$groupUser->group_id = $group->id; $groupUser->group_id = $group->id;
$groupUser->user_id = $order->owner_id; $groupUser->user_id = $order->owner_id;
if ($groupUser->create() === false) { if ($groupUser->create() === false) {
throw new \RuntimeException('Create Group User Failed'); throw new \RuntimeException('Create Group User Failed');
}
continue;
} }
} }
} }
protected function handleVipOrder(OrderModel $order) protected function handleVipOrder(OrderModel $order)
{ {
/**
* @var array $itemInfo
*/
$itemInfo = $order->item_info; $itemInfo = $order->item_info;
$userRepo = new UserRepo(); $userRepo = new UserRepo();
@ -199,6 +201,13 @@ class DeliverTask extends Task
} }
} }
protected function handleOrderConsumePoint(OrderModel $order)
{
$service = new PointHistoryService();
$service->handleOrderConsume($order);
}
protected function handleOrderFinishNotice(OrderModel $order) protected function handleOrderFinishNotice(OrderModel $order)
{ {
$notice = new OrderFinishNotice(); $notice = new OrderFinishNotice();

View File

@ -66,7 +66,6 @@ class NoticeTask extends Task
$logger->info('Notice Process Exception ' . kg_json_encode([ $logger->info('Notice Process Exception ' . kg_json_encode([
'file' => $e->getFile(), 'file' => $e->getFile(),
'line' => $e->getLine(), 'line' => $e->getLine(),
'code' => $e->getCode(),
'message' => $e->getMessage(), 'message' => $e->getMessage(),
'task' => $task->toArray(), 'task' => $task->toArray(),
])); ]));

View File

@ -0,0 +1,209 @@
<?php
namespace App\Console\Tasks;
use App\Models\CourseUser as CourseUserModel;
use App\Models\ImGroupUser as ImGroupUserModel;
use App\Models\PointGift as PointGiftModel;
use App\Models\PointRedeem as PointRedeemModel;
use App\Models\Task as TaskModel;
use App\Repos\Course as CourseRepo;
use App\Repos\CourseUser as CourseUserRepo;
use App\Repos\ImGroup as ImGroupRepo;
use App\Repos\ImGroupUser as ImGroupUserRepo;
use App\Repos\PointGift as PointGiftRepo;
use App\Repos\PointRedeem as PointRedeemRepo;
use App\Services\Logic\Point\PointHistory as PointHistoryService;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;
class PointGiftDeliverTask extends Task
{
const TRY_COUNT = 3;
public function mainAction()
{
$logger = $this->getLogger('point');
$tasks = $this->findTasks(30);
if ($tasks->count() == 0) {
return;
}
$redeemRepo = new PointRedeemRepo();
foreach ($tasks as $task) {
$redeemId = $task->item_info['point_redeem']['id'] ?? 0;
$redeem = $redeemRepo->findById($redeemId);
if (!$redeem) {
$task->status = TaskModel::STATUS_FAILED;
$task->update();
break;
}
try {
$this->db->begin();
switch ($redeem->gift_type) {
case PointGiftModel::TYPE_COURSE:
$this->handleCourseRedeem($redeem);
break;
case PointGiftModel::TYPE_GOODS:
$this->handleGoodsRedeem($redeem);
break;
case PointGiftModel::TYPE_CASH:
$this->handleCashRedeem($redeem);
break;
}
$task->status = TaskModel::STATUS_FINISHED;
if ($task->update() === false) {
throw new \RuntimeException('Update Task Status Failed');
}
$this->db->commit();
} catch (\Exception $e) {
$this->db->rollback();
$task->try_count += 1;
$task->priority += 1;
if ($task->try_count > self::TRY_COUNT) {
$task->status = TaskModel::STATUS_FAILED;
}
$task->update();
$logger->error('Point Gift Deliver Exception ' . kg_json_encode([
'file' => $e->getFile(),
'line' => $e->getLine(),
'message' => $e->getMessage(),
'task' => $task->toArray(),
]));
}
if ($task->status == TaskModel::STATUS_FAILED) {
$this->handlePointRefund($redeem);
}
}
}
protected function handleCourseRedeem(PointRedeemModel $redeem)
{
$giftRepo = new PointGiftRepo();
$gift = $giftRepo->findById($redeem->gift_id);
if (!$gift) {
throw new \RuntimeException('Gift Not Found');
}
$courseRepo = new CourseRepo();
$course = $courseRepo->findById($gift->attrs['id']);
if (!$course) {
throw new \RuntimeException('Course Not Found');
}
$groupRepo = new ImGroupRepo();
$group = $groupRepo->findByCourseId($course->id);
if (!$group) {
throw new \RuntimeException('Im Group Not Found');
}
$courseUserRepo = new CourseUserRepo();
$courseUser = $courseUserRepo->findCourseUser($course->id, $redeem->user_id);
if (!$courseUser) {
$courseUser = new CourseUserModel();
$courseUser->user_id = $redeem->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_POINT_REDEEM;
if ($courseUser->create() === false) {
throw new \RuntimeException('Create Course User Failed');
}
}
$groupUserRepo = new ImGroupUserRepo();
$groupUser = $groupUserRepo->findGroupUser($group->id, $redeem->user_id);
if (!$groupUser) {
$groupUser = new ImGroupUserModel();
$groupUser->group_id = $group->id;
$groupUser->user_id = $redeem->user_id;
if ($groupUser->create() === false) {
throw new \RuntimeException('Create Group User Failed');
}
}
$redeem->status = PointRedeemModel::STATUS_FINISHED;
if ($redeem->update() === false) {
throw new \RuntimeException('Update Redeem Status Failed');
}
}
protected function handleGoodsRedeem(PointRedeemModel $redeem)
{
}
protected function handleCashRedeem(PointRedeemModel $redeem)
{
}
protected function handlePointRefund(PointRedeemModel $redeem)
{
$service = new PointHistoryService();
$service->handlePointRefund($redeem);
}
protected function handleRedeemFinishNotice(PointRedeemModel $redeem)
{
}
/**
* @param int $limit
* @return ResultsetInterface|Resultset|TaskModel[]
*/
protected function findTasks($limit = 30)
{
$itemType = TaskModel::TYPE_POINT_GIFT_DELIVER;
$status = TaskModel::STATUS_PENDING;
$createTime = strtotime('-3 days');
return TaskModel::query()
->where('item_type = :item_type:', ['item_type' => $itemType])
->andWhere('status = :status:', ['status' => $status])
->andWhere('create_time > :create_time:', ['create_time' => $createTime])
->orderBy('priority ASC')
->limit($limit)
->execute();
}
}

View File

@ -41,9 +41,6 @@ class RefundTask extends Task
foreach ($tasks as $task) { foreach ($tasks as $task) {
/**
* @var array $itemInfo
*/
$itemInfo = $task->item_info; $itemInfo = $task->item_info;
$refund = $refundRepo->findById($itemInfo['refund']['id']); $refund = $refundRepo->findById($itemInfo['refund']['id']);
@ -51,13 +48,8 @@ class RefundTask extends Task
$order = $orderRepo->findById($itemInfo['refund']['order_id']); $order = $orderRepo->findById($itemInfo['refund']['order_id']);
if (!$refund || !$trade || !$order) { if (!$refund || !$trade || !$order) {
continue; $task->status = TaskModel::STATUS_FAILED;
} $task->update();
/**
* 退款存在延迟,给取消退款调解机会
*/
if (isset($itemInfo['deadline']) && $itemInfo['deadline'] > time()) {
continue; continue;
} }
@ -111,7 +103,8 @@ class RefundTask extends Task
$task->update(); $task->update();
$logger->info('Refund Task Exception ' . kg_json_encode([ $logger->info('Refund Task Exception ' . kg_json_encode([
'code' => $e->getCode(), 'file' => $e->getFile(),
'line' => $e->getLine(),
'message' => $e->getMessage(), 'message' => $e->getMessage(),
'task' => $task->toArray(), 'task' => $task->toArray(),
])); ]));
@ -148,7 +141,7 @@ class RefundTask extends Task
} }
if (!$response) { if (!$response) {
throw new \RuntimeException('Pay Refund Failed'); throw new \RuntimeException('Trade Refund Failed');
} }
} }
@ -208,9 +201,6 @@ class RefundTask extends Task
{ {
$courseUserRepo = new CourseUserRepo(); $courseUserRepo = new CourseUserRepo();
/**
* @var array $itemInfo
*/
$itemInfo = $order->item_info; $itemInfo = $order->item_info;
foreach ($itemInfo['courses'] as $course) { foreach ($itemInfo['courses'] as $course) {
@ -239,9 +229,6 @@ class RefundTask extends Task
$user = $userRepo->findById($order->owner_id); $user = $userRepo->findById($order->owner_id);
/**
* @var array $itemInfo
*/
$itemInfo = $order->item_info; $itemInfo = $order->item_info;
$diffTime = "-{$itemInfo['vip']['expiry']} months"; $diffTime = "-{$itemInfo['vip']['expiry']} months";

View File

@ -2,6 +2,7 @@
namespace App\Console\Tasks; namespace App\Console\Tasks;
use App\Models\ChapterUser as ChapterUserModel;
use App\Models\Course as CourseModel; use App\Models\Course as CourseModel;
use App\Models\Learning as LearningModel; use App\Models\Learning as LearningModel;
use App\Repos\Chapter as ChapterRepo; use App\Repos\Chapter as ChapterRepo;
@ -9,7 +10,8 @@ use App\Repos\ChapterUser as ChapterUserRepo;
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\Learning as LearningRepo; use App\Repos\Learning as LearningRepo;
use App\Services\Sync\Learning as LearningSync; use App\Services\Logic\Point\PointHistory as PointHistoryService;
use App\Services\Sync\Learning as LearningSyncService;
class SyncLearningTask extends Task class SyncLearningTask extends Task
{ {
@ -18,7 +20,7 @@ class SyncLearningTask extends Task
{ {
$redis = $this->getRedis(); $redis = $this->getRedis();
$sync = new LearningSync(); $sync = new LearningSyncService();
$syncKey = $sync->getSyncKey(); $syncKey = $sync->getSyncKey();
@ -120,7 +122,10 @@ class SyncLearningTask extends Task
$chapterUser->update(); $chapterUser->update();
if ($chapterUser->consumed == 1) { if ($chapterUser->consumed == 1) {
$this->updateCourseUser($learning); $this->updateCourseUser($learning);
$this->handleStudyPoint($chapterUser);
} }
} }
@ -174,4 +179,14 @@ class SyncLearningTask extends Task
$courseUser->update(); $courseUser->update();
} }
/**
* @param ChapterUserModel $chapterUser
*/
protected function handleStudyPoint(ChapterUserModel $chapterUser)
{
$service = new PointHistoryService();
$service->handleChapterStudy($chapterUser);
}
} }

View File

@ -26,8 +26,6 @@ class Controller extends \Phalcon\Mvc\Controller
$this->checkCsrfToken(); $this->checkCsrfToken();
} }
$this->checkRateLimit();
$this->authInfo = $this->getAuthInfo(); $this->authInfo = $this->getAuthInfo();
if (!$this->authInfo) { if (!$this->authInfo) {

View File

@ -0,0 +1,136 @@
<?php
namespace App\Http\Admin\Controllers;
use App\Http\Admin\Services\PointGift as PointGiftService;
/**
* @RoutePrefix("/admin/point/gift")
*/
class PointGiftController extends Controller
{
/**
* @Get("/list", name="admin.point_gift.list")
*/
public function listAction()
{
$giftService = new PointGiftService();
$pager = $giftService->getGifts();
$this->view->pick('point/gift/list');
$this->view->setVar('pager', $pager);
}
/**
* @Get("/search", name="admin.point_gift.search")
*/
public function searchAction()
{
$this->view->pick('point/gift/search');
}
/**
* @Get("/add", name="admin.point_gift.add")
*/
public function addAction()
{
$this->view->pick('point/gift/add');
}
/**
* @Get("/{id:[0-9]+}/edit", name="admin.point_gift.edit")
*/
public function editAction($id)
{
$giftService = new PointGiftService();
$gift = $giftService->getGift($id);
$this->view->pick('point/gift/edit');
$this->view->setVar('gift', $gift);
}
/**
* @Post("/create", name="admin.point_gift.create")
*/
public function createAction()
{
$giftService = new PointGiftService();
$gift = $giftService->createGift();
$location = $this->url->get([
'for' => 'admin.point_gift.edit',
'id' => $gift->id,
]);
$content = [
'location' => $location,
'msg' => '添加礼品成功',
];
return $this->jsonSuccess($content);
}
/**
* @Post("/{id:[0-9]+}/update", name="admin.point_gift.update")
*/
public function updateAction($id)
{
$giftService = new PointGiftService();
$giftService->updateGift($id);
$location = $this->url->get(['for' => 'admin.point_gift.list']);
$content = [
'location' => $location,
'msg' => '更新礼品成功',
];
return $this->jsonSuccess($content);
}
/**
* @Post("/{id:[0-9]+}/delete", name="admin.point_gift.delete")
*/
public function deleteAction($id)
{
$giftService = new PointGiftService();
$giftService->deleteGift($id);
$location = $this->request->getHTTPReferer();
$content = [
'location' => $location,
'msg' => '删除礼品成功',
];
return $this->jsonSuccess($content);
}
/**
* @Post("/{id:[0-9]+}/restore", name="admin.point_gift.restore")
*/
public function restoreAction($id)
{
$giftService = new PointGiftService();
$giftService->restoreGift($id);
$location = $this->request->getHTTPReferer();
$content = [
'location' => $location,
'msg' => '还原礼品成功',
];
return $this->jsonSuccess($content);
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace App\Http\Admin\Controllers;
use App\Http\Admin\Services\PointRedeem as PointRedeemService;
/**
* @RoutePrefix("/admin/point/redeem")
*/
class PointRedeemController extends Controller
{
/**
* @Get("/search", name="admin.point_redeem.search")
*/
public function searchAction()
{
$this->view->pick('point/redeem/search');
}
/**
* @Get("/list", name="admin.point_redeem.list")
*/
public function listAction()
{
$redeemService = new PointRedeemService();
$pager = $redeemService->getRedeems();
$this->view->pick('point/redeem/list');
$this->view->setVar('pager', $pager);
}
/**
* @Post("/{id:[0-9]+}/deliver", name="admin.point_redeem.deliver")
*/
public function deliverAction($id)
{
$redeemService = new PointRedeemService();
$redeemService->deliver($id);
return $this->jsonSuccess(['msg' => '发货成功']);
}
}

View File

@ -50,7 +50,7 @@ class SettingController extends Controller
$data = $this->request->getPost(); $data = $this->request->getPost();
$settingService->updateStorageSettings($section, $data); $settingService->updateSettings($section, $data);
return $this->jsonSuccess(['msg' => '更新配置成功']); return $this->jsonSuccess(['msg' => '更新配置成功']);
@ -248,6 +248,31 @@ class SettingController extends Controller
} }
} }
/**
* @Route("/point", name="admin.setting.point")
*/
public function pointAction()
{
$section = 'point';
$settingService = new SettingService();
if ($this->request->isPost()) {
$data = $this->request->getPost();
$settingService->updatePointSettings($section, $data);
return $this->jsonSuccess(['msg' => '更新配置成功']);
} else {
$point = $settingService->getSettings($section);
$this->view->setVar('point', $point);
}
}
/** /**
* @Route("/vip", name="admin.setting.vip") * @Route("/vip", name="admin.setting.vip")
*/ */

View File

@ -476,6 +476,43 @@ class AuthNode extends Service
], ],
], ],
], ],
[
'id' => '2-8',
'title' => '积分商城',
'type' => 'menu',
'children' => [
[
'id' => '2-8-2',
'title' => '礼品列表',
'type' => 'menu',
'route' => 'admin.point_gift.list',
],
[
'id' => '2-8-1',
'title' => '兑换记录',
'type' => 'menu',
'route' => 'admin.point_redeem.list',
],
[
'id' => '2-8-3',
'title' => '添加礼品',
'type' => 'button',
'route' => 'admin.point_gift.add',
],
[
'id' => '2-8-4',
'title' => '编辑礼品',
'type' => 'button',
'route' => 'admin.point_gift.edit',
],
[
'id' => '2-8-5',
'title' => '删除礼品',
'type' => 'button',
'route' => 'admin.point_gift.delete',
],
],
],
], ],
]; ];
} }
@ -763,6 +800,12 @@ class AuthNode extends Service
'type' => 'menu', 'type' => 'menu',
'route' => 'admin.setting.wechat_oa', 'route' => 'admin.setting.wechat_oa',
], ],
[
'id' => '5-1-14',
'title' => '积分设置',
'type' => 'menu',
'route' => 'admin.setting.point',
],
], ],
], ],
], ],

View File

@ -0,0 +1,163 @@
<?php
namespace App\Http\Admin\Services;
use App\Library\Paginator\Query as PagerQuery;
use App\Models\PointGift as PointGiftModel;
use App\Repos\PointGift as PointGiftRepo;
use App\Validators\PointGift as PointGiftValidator;
class PointGift extends Service
{
public function getGifts()
{
$pagerQuery = new PagerQuery();
$params = $pagerQuery->getParams();
$params['deleted'] = $params['deleted'] ?? 0;
$sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage();
$limit = $pagerQuery->getLimit();
$giftRepo = new PointGiftRepo();
return $giftRepo->paginate($params, $sort, $page, $limit);
}
public function getGift($id)
{
return $this->findOrFail($id);
}
public function createGift()
{
$post = $this->request->getPost();
$validator = new PointGiftValidator();
$post['type'] = $validator->checkType($post['type']);
$gift = new PointGiftModel();
switch ($post['type']) {
case PointGiftModel::TYPE_COURSE:
$gift = $this->createCourseGift($post);
break;
case PointGiftModel::TYPE_GOODS:
$gift = $this->createCommodityGift($post);
break;
}
return $gift;
}
public function updateGift($id)
{
$gift = $this->findOrFail($id);
$post = $this->request->getPost();
$validator = new PointGiftValidator();
$data = [];
if (isset($post['cover'])) {
$data['cover'] = $validator->checkCover($post['cover']);
}
if (isset($post['name'])) {
$data['name'] = $validator->checkName($post['name']);
}
if (isset($post['details'])) {
$data['details'] = $validator->checkDetails($post['details']);
}
if (isset($post['attrs'])) {
$data['attrs'] = $validator->checkAttrs($gift, $post['attrs']);
}
if (isset($post['point'])) {
$data['point'] = $validator->checkPoint($post['point']);
}
if (isset($post['stock'])) {
$data['stock'] = $validator->checkStock($post['stock']);
}
if (isset($post['redeem_limit'])) {
$data['redeem_limit'] = $validator->checkRedeemLimit($post['redeem_limit']);
}
if (isset($post['published'])) {
$data['published'] = $validator->checkPublishStatus($post['published']);
}
$gift->update($data);
return $gift;
}
public function deleteGift($id)
{
$gift = $this->findOrFail($id);
$gift->deleted = 1;
$gift->update();
return $gift;
}
public function restoreGift($id)
{
$gift = $this->findOrFail($id);
$gift->deleted = 0;
$gift->update();
return $gift;
}
protected function createCourseGift($post)
{
$validator = new PointGiftValidator();
$course = $validator->checkCourse($post['course_id']);
$gift = new PointGiftModel();
$gift->type = PointGiftModel::TYPE_COURSE;
$gift->name = $course->title;
$gift->create();
return $gift;
}
protected function createCommodityGift($post)
{
$validator = new PointGiftValidator();
$gift = new PointGiftModel();
$gift->type = PointGiftModel::TYPE_GOODS;
$gift->name = $validator->checkName($post['name']);
$gift->create();
return $gift;
}
protected function findOrFail($id)
{
$validator = new PointGiftValidator();
return $validator->checkGift($id);
}
}

View File

@ -0,0 +1,58 @@
<?php
namespace App\Http\Admin\Services;
use App\Library\Paginator\Query as PagerQuery;
use App\Models\PointGift as PointGiftModel;
use App\Models\PointRedeem as PointRedeemModel;
use App\Repos\PointRedeem as PointRedeemRepo;
use App\Validators\PointRedeem as PointRedeemValidator;
class PointRedeem extends Service
{
public function getRedeems()
{
$pagerQuery = new PagerQuery();
$params = $pagerQuery->getParams();
$params['deleted'] = $params['deleted'] ?? 0;
$sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage();
$limit = $pagerQuery->getLimit();
$redeemRepo = new PointRedeemRepo();
return $redeemRepo->paginate($params, $sort, $page, $limit);
}
public function getRedeem($id)
{
return $this->findOrFail($id);
}
public function deliver($id)
{
$redeem = $this->findOrFail($id);
if ($redeem->gift_type != PointGiftModel::TYPE_GOODS) {
return $redeem;
}
$redeem->status = PointRedeemModel::STATUS_FINISHED;
$redeem->update();
return $redeem;
}
protected function findOrFail($id)
{
$validator = new PointRedeemValidator();
return $validator->checkRedeem($id);
}
}

View File

@ -103,9 +103,17 @@ class Refund extends Service
$task = new TaskModel(); $task = new TaskModel();
$itemInfo = [
'refund' => [
'id' => $refund->id,
'order_id' => $refund->order_id,
'trade_id' => $refund->trade_id,
],
];
$task->item_id = $refund->id; $task->item_id = $refund->id;
$task->item_type = TaskModel::TYPE_REFUND; $task->item_type = TaskModel::TYPE_REFUND;
$task->item_info = ['refund' => $refund->toArray()]; $task->item_info = $itemInfo;
$task->priority = TaskModel::PRIORITY_HIGH; $task->priority = TaskModel::PRIORITY_HIGH;
$task->status = TaskModel::STATUS_PENDING; $task->status = TaskModel::STATUS_PENDING;

View File

@ -2,9 +2,7 @@
namespace App\Http\Admin\Services; namespace App\Http\Admin\Services;
use App\Models\User as UserModel;
use App\Services\Auth\Admin as AdminAuth; use App\Services\Auth\Admin as AdminAuth;
use App\Services\Logic\Notice\AccountLogin as AccountLoginNoticeService;
use App\Validators\Account as AccountValidator; use App\Validators\Account as AccountValidator;
use App\Validators\Captcha as CaptchaValidator; use App\Validators\Captcha as CaptchaValidator;
@ -47,21 +45,18 @@ class Session extends Service
$captchaValidator->checkCode($post['ticket'], $post['rand']); $captchaValidator->checkCode($post['ticket'], $post['rand']);
} }
$this->handleLoginNotice($user);
$this->auth->saveAuthInfo($user); $this->auth->saveAuthInfo($user);
$this->eventsManager->fire('Account:afterLogin', $this, $user);
} }
public function logout() public function logout()
{ {
$user = $this->getLoginUser();
$this->auth->clearAuthInfo(); $this->auth->clearAuthInfo();
}
protected function handleLoginNotice(UserModel $user) $this->eventsManager->fire('Account:afterLogout', $this, $user);
{
$service = new AccountLoginNoticeService();
$service->createTask($user);
} }
} }

View File

@ -181,6 +181,19 @@ class Setting extends Service
$this->updateSettings($section, $settings); $this->updateSettings($section, $settings);
} }
public function updatePointSettings($section, $settings)
{
if (isset($settings['event_rule'])) {
$settings['event_rule'] = kg_json_encode($settings['event_rule']);
}
if (isset($settings['consume_rule'])) {
$settings['consume_rule'] = kg_json_encode($settings['consume_rule']);
}
$this->updateSettings($section, $settings);
}
public function updateVipSettings($items) public function updateVipSettings($items)
{ {
$vipRepo = new VipRepo(); $vipRepo = new VipRepo();

View File

@ -3,7 +3,6 @@
namespace App\Http\Admin\Services; namespace App\Http\Admin\Services;
use App\Caches\Topic as TopicCache; use App\Caches\Topic as TopicCache;
use App\Caches\TopicCourseList as TopicCourseListCache;
use App\Library\Paginator\Query as PagerQuery; use App\Library\Paginator\Query as PagerQuery;
use App\Models\CourseTopic as CourseTopicModel; use App\Models\CourseTopic as CourseTopicModel;
use App\Models\Topic as TopicModel; use App\Models\Topic as TopicModel;
@ -66,8 +65,8 @@ class Topic extends Service
$data = []; $data = [];
if (isset($post['name'])) { if (isset($post['title'])) {
$data['name'] = $validator->checkName($post['name']); $data['title'] = $validator->checkTitle($post['title']);
} }
if (isset($post['summary'])) { if (isset($post['summary'])) {
@ -194,10 +193,6 @@ class Topic extends Service
$cache = new TopicCache(); $cache = new TopicCache();
$cache->rebuild($topic->id); $cache->rebuild($topic->id);
$cache = new TopicCourseListCache();
$cache->rebuild($topic->id);
} }
protected function findOrFail($id) protected function findOrFail($id)

View File

@ -0,0 +1,61 @@
{%- 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_type_info(value) %}
{% if value == 1 %}
<span class="type">订单消费</span>
{% elseif value == 2 %}
<span class="type">积分兑换</span>
{% elseif value == 3 %}
<span class="type">积分退款</span>
{% elseif value == 4 %}
<span class="type">帐号注册</span>
{% elseif value == 5 %}
<span class="type">站点访问</span>
{% elseif value == 6 %}
<span class="type">课时学习</span>
{% elseif value == 7 %}
<span class="type">课程评价</span>
{% elseif value == 8 %}
<span class="type">微聊讨论</span>
{% endif %}
{%- endmacro %}
{%- macro event_detail_info(history) %}
{% set event_info = history.event_info %}
{% if history.event_type == 1 %}
<p class="order">{{ event_info.order.subject }}</p>
{% elseif history.event_type == 2 %}
<p class="gift">{{ event_info.point_redeem.gift_name }}</p>
{% elseif history.event_type == 3 %}
<span class="none">{{ event_info.point_redeem.gift_name }}</span>
{% elseif history.event_type == 4 %}
<span class="none">N/A</span>
{% elseif history.event_type == 5 %}
<span class="none">N/A</span>
{% elseif history.event_type == 6 %}
<p class="course">课程:{{ event_info.course.title }}</p>
<p class="chapter">章节:{{ event_info.chapter.title }}</p>
{% elseif history.event_type == 7 %}
<p class="course">{{ event_info.course.title }}</p>
{% elseif history.event_type == 8 %}
<span class="none">N/A</span>
{% endif %}
{%- endmacro %}

View File

@ -0,0 +1,62 @@
{% extends 'templates/main.volt' %}
{% block content %}
<form id="form-1" class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.point_gift.create'}) }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>添加礼品</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">礼品类型</label>
<div class="layui-input-block">
<input type="radio" name="type" value="1" title="课程" lay-filter="type">
<input type="radio" name="type" value="2" title="商品" lay-filter="type">
</div>
</div>
<div id="block-1" class="block" style="display:none;">
<div class="layui-form-item">
<label class="layui-form-label">课程编号</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="item_id" value="">
</div>
</div>
</div>
<div id="block-2" class="block" style="display:none;">
<div class="layui-form-item">
<label class="layui-form-label">商品名称</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="name" value="">
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
</div>
</div>
</form>
{% endblock %}
{% block inline_js %}
<script>
layui.use(['jquery', 'form'], function () {
var $ = layui.jquery;
var form = layui.form;
form.on('radio(type)', function (data) {
var block = $('#block-' + data.value);
$('.block').hide();
block.show();
});
});
</script>
{% endblock %}

View File

@ -0,0 +1,27 @@
{% extends 'templates/main.volt' %}
{% block content %}
{% set update_url = url({'for':'admin.point_gift.update','id':gift.id}) %}
{% if gift.type == 1 %}
{{ partial('point/gift/edit_course') }}
{% elseif gift.type == 2 %}
{{ partial('point/gift/edit_goods') }}
{% endif %}
{% endblock %}
{% block link_css %}
{{ css_link('https://cdn.jsdelivr.net/npm/vditor/dist/index.css', false) }}
{% endblock %}
{% block include_js %}
{{ js_include('https://cdn.jsdelivr.net/npm/vditor/dist/index.min.js', false) }}
{{ js_include('admin/js/cover.upload.js') }}
{{ js_include('admin/js/vditor.js') }}
{% endblock %}

View File

@ -0,0 +1,34 @@
<form class="layui-form kg-form" method="POST" action="{{ update_url }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>编辑礼品</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">课程封面</label>
<div class="layui-input-inline">
<img id="img-cover" class="kg-cover" src="{{ gift.cover }}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">课程名称</label>
<div class="layui-form-mid layui-word-aux">{{ gift.name }}</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">所需积分</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="point" value="{{ gift.point }}" lay-verify="number">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">库存数量</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="stock" value="{{ gift.stock }}" lay-verify="number">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
</div>
</div>
</form>

View File

@ -0,0 +1,59 @@
<form class="layui-form kg-form" method="POST" action="{{ update_url }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>编辑礼品</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">商品封面</label>
<div class="layui-input-inline">
<img id="img-cover" class="kg-cover" src="{{ gift.cover }}">
<input type="hidden" name="cover" value="{{ gift.cover }}">
</div>
<div class="layui-input-inline" style="padding-top:35px;">
<button id="change-cover" class="layui-btn layui-btn-sm" type="button">更换</button>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">商品名称</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="name" value="{{ gift.name }}" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">采购地址</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="attrs[url]" value="{{ gift.attrs['url'] }}" placeholder="淘宝或京东等平台商品链接地址" lay-verify="url">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">商品详情</label>
<div class="layui-input-block">
<div id="vditor"></div>
<textarea name="details" class="layui-hide" id="vditor-textarea">{{ gift.details }}</textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">所需积分</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="point" value="{{ gift.point }}" lay-verify="number">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">库存数量</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="stock" value="{{ gift.stock }}" lay-verify="number">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">兑换限额</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="redeem_limit" value="{{ gift.redeem_limit }}" lay-verify="number">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="kg-submit layui-btn" lay-submit="true" lay-filter="go">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
</div>
</div>
</form>

View File

@ -0,0 +1,87 @@
{% extends 'templates/main.volt' %}
{% block content %}
{{ partial('macros/point') }}
{% set add_url = url({'for':'admin.point_gift.add'}) %}
{% set search_url = url({'for':'admin.point_gift.search'}) %}
<div class="kg-nav">
<div class="kg-nav-left">
<span class="layui-breadcrumb">
<a><cite>礼品管理</cite></a>
</span>
</div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ add_url }}">
<i class="layui-icon layui-icon-add-1"></i>添加礼品
</a>
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
<i class="layui-icon layui-icon-search"></i>搜索礼品
</a>
</div>
</div>
<table class="kg-table layui-table layui-form">
<group>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col width="12%">
</group>
<thead>
<tr>
<th>编号</th>
<th>物品名称</th>
<th>所需积分</th>
<th>库存数量</th>
<th>兑换限额</th>
<th>兑换人次</th>
<th>发布</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for item in pager.items %}
{% set redeem_url = url({'for':'admin.point_redeem.list'},{'gift_id':item.id}) %}
{% set preview_url = url({'for':'home.point_gift.show','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 delete_url = url({'for':'admin.point_gift.delete','id':item.id}) %}
{% set restore_url = url({'for':'admin.point_gift.restore','id':item.id}) %}
<tr>
<td>{{ item.id }}</td>
<td><a href="{{ edit_url }}">{{ item.name }}</a> {{ gift_type_info(item.type) }}</td>
<td>{{ item.point }}</td>
<td>{{ item.stock }}</td>
<td>{{ item.redeem_limit }}</td>
<td><a class="layui-badge layui-bg-green" href="{{ redeem_url }}">{{ item.redeem_count }}</a></td>
<td><input type="checkbox" name="published" value="1" lay-filter="published" lay-skin="switch" lay-text="是|否" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center">
<div class="layui-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul>
<li><a href="{{ preview_url }}" target="_blank">前台预览</a></li>
<li><a href="{{ redeem_url }}">兑换记录</a></li>
<li><a href="{{ edit_url }}">编辑</a></li>
{% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>
{% else %}
<li><a href="javascript:" class="kg-restore" data-url="{{ restore_url }}">还原</a></li>
{% endif %}
</ul>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ partial('partials/pager') }}
{% endblock %}

View File

@ -0,0 +1,51 @@
{% extends 'templates/main.volt' %}
{% block content %}
<form class="layui-form kg-form" method="GET" action="{{ url({'for':'admin.point_gift.list'}) }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>搜索礼品</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">礼品编号</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="id" placeholder="礼品编号精确匹配">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">礼品名称</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="name" placeholder="礼品名称模糊匹配">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">类型</label>
<div class="layui-input-block">
<input type="radio" name="type" value="1" title="课程">
<input type="radio" name="type" value="2" title="商品">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">发布</label>
<div class="layui-input-block">
<input type="radio" name="published" value="1" title="是">
<input type="radio" name="published" value="0" title="否">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">删除</label>
<div class="layui-input-block">
<input type="radio" name="deleted" value="1" title="是">
<input type="radio" name="deleted" value="0" title="否">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn" lay-submit="true">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,100 @@
{% extends 'templates/main.volt' %}
{% block content %}
{{ partial('macros/point') }}
{% set search_url = url({'for':'admin.point_redeem.search'}) %}
<div class="kg-nav">
<div class="kg-nav-left">
<span class="layui-breadcrumb">
<a><cite>兑换记录</cite></a>
</span>
</div>
<div class="kg-nav-right">
<a class="layui-btn layui-btn-sm" href="{{ search_url }}">
<i class="layui-icon layui-icon-search"></i>搜索兑换
</a>
</div>
</div>
<table class="kg-table layui-table">
<colgroup>
<col>
<col>
<col>
<col>
<col width="12%">
</colgroup>
<thead>
<tr>
<th>物品名称</th>
<th>消耗积分</th>
<th>兑换状态</th>
<th>兑换时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for item in pager.items %}
{% set user_filter_url = url({'for':'admin.point_redeem.list'},{'user_id':item.user_id}) %}
{% set deliver_url = url({'for':'admin.point_redeem.deliver','id':item.id}) %}
{% set gift_url = url({'for':'home.point_gift.show','id':item.gift_id}) %}
<tr>
<td>
<p><a href="{{ gift_url }}" target="_blank">{{ item.gift_name }}{{ item.gift_id }}</a>{{ gift_type_info(item.gift_type) }}</p>
<p>用户名称:<a href="{{ user_filter_url }}">{{ item.user_name }}</a> {{ item.user_id }} 联系方式:
<button class="layui-btn layui-btn-xs kg-contact" data-name="{{ item.contact_name }}" data-phone="{{ item.contact_phone }}" data-address="{{ item.contact_address }}">查看</button>
</p>
</td>
<td>{{ item.gift_point }}</td>
<td>{{ redeem_status_info(item.status) }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td class="center">
{% if item.gift_type == 2 %}
<button class="layui-btn layui-btn-sm kg-deliver" data-url="{{ deliver_url }}">发货</button>
{% else %}
N/A
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ partial('partials/pager') }}
{% endblock %}
{% block inline_js %}
<script>
layui.use(['jquery', 'layer'], function () {
var $ = layui.jquery;
var layer = layui.layer;
$('.kg-deliver').on('click', function () {
var url = $(this).data('url');
layer.confirm('确定要发货吗?', function () {
$.post(url, function (res) {
layer.msg(res.msg, {icon: 1});
setTimeout(function () {
window.location.reload();
}, 1500);
});
});
});
});
</script>
{% endblock %}
{% block include_js %}
{{ js_include('admin/js/contact.js') }}
{% endblock %}

View File

@ -0,0 +1,46 @@
{% extends 'templates/main.volt' %}
{% block content %}
<form class="layui-form kg-form" method="GET" action="{{ url({'for':'admin.point_redeem.list'}) }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>搜索兑换</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">用户编号</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="user_id" placeholder="用户编号精确匹配">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">礼物编号</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="gift_id" placeholder="礼物编号精确匹配">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">礼物类型</label>
<div class="layui-input-block">
<input type="radio" name="gift_type" value="1" title="课程">
<input type="radio" name="gift_type" value="2" title="商品">
<input type="radio" name="gift_type" value="3" title="现金">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">兑换状态</label>
<div class="layui-input-block">
<input type="radio" name="status" value="1" title="处理中">
<input type="radio" name="status" value="2" title="已完成">
<input type="radio" name="status" value="3" title="已失败">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn" lay-submit="true">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,112 @@
{% extends 'templates/main.volt' %}
{% block content %}
{% set consume_rule = point.consume_rule|json_decode %}
{% set event_rule = point.event_rule|json_decode %}
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.setting.point'}) }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>积分设置</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">启用积分</label>
<div class="layui-input-block">
<input type="radio" name="enabled" value="1" title="是" {% if point.enabled == "1" %}checked="checked"{% endif %}>
<input type="radio" name="enabled" value="0" title="否" {% if point.enabled == "0" %}checked="checked"{% endif %}>
</div>
</div>
<fieldset class="layui-elem-field layui-field-title">
<legend>消费奖励规则</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">启用规则</label>
<div class="layui-input-block">
<input type="radio" name="consume_rule[enabled]" value="1" title="是" {% if consume_rule.enabled == "1" %}checked="checked"{% endif %}>
<input type="radio" name="consume_rule[enabled]" value="0" title="否" {% if consume_rule.enabled == "0" %}checked="checked"{% endif %}>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">奖励倍率</label>
<div class="layui-input-inline">
<input class="layui-input" type="text" name="consume_rule[rate]" value="{{ consume_rule.rate }}" lay-verify="number">
</div>
<div class="layui-form-mid layui-word-aux">奖励积分 消费金额 X 奖励倍率</div>
</div>
<fieldset class="layui-elem-field layui-field-title">
<legend>行为奖励规则</legend>
</fieldset>
<table class="layui-table kg-table layui-form" style="width:60%;">
<colgroup>
<col width="15%">
<col>
<col>
<col>
</colgroup>
<thead>
<tr>
<th>行为类型</th>
<th>奖励积分</th>
<th>每日上限</th>
<th>启用规则</th>
</tr>
</thead>
<tbody>
<tr>
<td>帐号注册</td>
<td><input class="layui-input" type="text" name="event_rule[account_register][point]" value="{{ event_rule.account_register.point }}" lay-verify="required"></td>
<td>N/A</td>
<td>
<input type="radio" name="event_rule[account_register][enabled]" value="1" title="是" {% if event_rule.account_register.enabled == "1" %}checked="checked"{% endif %}>
<input type="radio" name="event_rule[account_register][enabled]" value="0" title="否" {% if event_rule.account_register.enabled == "0" %}checked="checked"{% endif %}>
</td>
</tr>
<tr>
<td>站点访问</td>
<td><input class="layui-input" type="text" name="event_rule[site_visit][point]" value="{{ event_rule.site_visit.point }}" lay-verify="required"></td>
<td>N/A</td>
<td>
<input type="radio" name="event_rule[site_visit][enabled]" value="1" title="是" {% if event_rule.site_visit.enabled == "1" %}checked="checked"{% endif %}>
<input type="radio" name="event_rule[site_visit][enabled]" value="0" title="否" {% if event_rule.site_visit.enabled == "0" %}checked="checked"{% endif %}>
</td>
</tr>
<tr>
<td>课程评价</td>
<td><input class="layui-input" type="text" name="event_rule[course_review][point]" value="{{ event_rule.course_review.point }}" lay-verify="required"></td>
<td>N/A</td>
<td>
<input type="radio" name="event_rule[course_review][enabled]" value="1" title="是" {% if event_rule.course_review.enabled == "1" %}checked="checked"{% endif %}>
<input type="radio" name="event_rule[course_review][enabled]" value="0" title="否" {% if event_rule.course_review.enabled == "0" %}checked="checked"{% endif %}>
</td>
</tr>
<tr>
<td>课时学习</td>
<td><input class="layui-input" type="text" name="event_rule[chapter_study][point]" value="{{ event_rule.chapter_study.point }}" lay-verify="required"></td>
<td>N/A</td>
<td>
<input type="radio" name="event_rule[chapter_study][enabled]" value="1" title="是" {% if event_rule.chapter_study.enabled == "1" %}checked="checked"{% endif %}>
<input type="radio" name="event_rule[chapter_study][enabled]" value="0" title="否" {% if event_rule.chapter_study.enabled == "0" %}checked="checked"{% endif %}>
</td>
</tr>
<tr>
<td>微聊讨论</td>
<td><input class="layui-input" type="text" name="event_rule[im_discuss][point]" value="{{ event_rule.im_discuss.point }}" lay-verify="required"></td>
<td>N/A</td>
<td>
<input type="radio" name="event_rule[im_discuss][enabled]" value="1" title="是" {% if event_rule.im_discuss.enabled == "1" %}checked="checked"{% endif %}>
<input type="radio" name="event_rule[im_discuss][enabled]" value="0" title="否" {% if event_rule.im_discuss.enabled == "0" %}checked="checked"{% endif %}>
</td>
</tr>
</tbody>
</table>
<br>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
</div>
</div>
</form>
{% endblock %}

View File

@ -6,9 +6,15 @@
{% if value == 1 %} {% if value == 1 %}
免费 免费
{% elseif value == 2 %} {% elseif value == 2 %}
<span class="layui-badge layui-bg-orange">付费</span> 付费
{% elseif value == 3 %} {% elseif value == 3 %}
导入 导入
{% elseif value == 4 %}
会员
{% elseif value == 5 %}
积分
{% elseif value == 6 %}
抽奖
{% endif %} {% endif %}
{%- endmacro %} {%- endmacro %}
@ -58,8 +64,8 @@
</td> </td>
<td>{{ source_type_info(item.source_type) }}</td> <td>{{ source_type_info(item.source_type) }}</td>
<td> <td>
<p>开始:{{ date('Y-m-d H:i:s',item.create_time) }}</p> <p>开始:{{ date('Y-m-d H:i',item.create_time) }}</p>
<p>结束:{{ date('Y-m-d H:i:s',item.expiry_time) }}</p> <p>结束:{{ date('Y-m-d H:i',item.expiry_time) }}</p>
</td> </td>
<td class="center"> <td class="center">
<div class="layui-dropdown"> <div class="layui-dropdown">

View File

@ -2,7 +2,8 @@
namespace App\Http\Api\Controllers; namespace App\Http\Api\Controllers;
use App\Services\Auth\Api as AppAuth; use App\Models\User as UserModel;
use App\Services\Auth\Api as ApiAuth;
use App\Traits\Response as ResponseTrait; use App\Traits\Response as ResponseTrait;
use App\Traits\Security as SecurityTrait; use App\Traits\Security as SecurityTrait;
use Phalcon\Mvc\Dispatcher; use Phalcon\Mvc\Dispatcher;
@ -10,6 +11,11 @@ use Phalcon\Mvc\Dispatcher;
class Controller extends \Phalcon\Mvc\Controller class Controller extends \Phalcon\Mvc\Controller
{ {
/**
* @var UserModel
*/
protected $authUser;
use ResponseTrait; use ResponseTrait;
use SecurityTrait; use SecurityTrait;
@ -19,17 +25,22 @@ class Controller extends \Phalcon\Mvc\Controller
$this->setCors(); $this->setCors();
} }
if (!$this->request->isOptions()) { $this->checkRateLimit();
$this->checkRateLimit();
}
return true; return true;
} }
public function initialize()
{
$this->authUser = $this->getAuthUser();
$this->eventsManager->fire('Site:afterView', $this, $this->authUser);
}
protected function getAuthUser() protected function getAuthUser()
{ {
/** /**
* @var AppAuth $auth * @var ApiAuth $auth
*/ */
$auth = $this->getDI()->get('auth'); $auth = $this->getDI()->get('auth');

View File

@ -2,11 +2,9 @@
namespace App\Http\Api\Services; namespace App\Http\Api\Services;
use App\Models\User as UserModel;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use App\Services\Auth\Api as AuthService; use App\Services\Auth\Api as AuthService;
use App\Services\Logic\Account\Register as RegisterService; use App\Services\Logic\Account\Register as RegisterService;
use App\Services\Logic\Notice\AccountLogin as AccountLoginNoticeService;
use App\Validators\Account as AccountValidator; use App\Validators\Account as AccountValidator;
class Account extends Service class Account extends Service
@ -32,7 +30,11 @@ class Account extends Service
$user = $userRepo->findById($account->id); $user = $userRepo->findById($account->id);
return $this->auth->saveAuthInfo($user); $token = $this->auth->saveAuthInfo($user);
$this->eventsManager->fire('Account:afterRegister', $this, $user);
return $token;
} }
public function loginByPassword() public function loginByPassword()
@ -52,9 +54,11 @@ class Account extends Service
$user = $validator->checkUserLogin($post['account'], $post['password']); $user = $validator->checkUserLogin($post['account'], $post['password']);
$this->handleLoginNotice($user); $token = $this->auth->saveAuthInfo($user);
return $this->auth->saveAuthInfo($user); $this->eventsManager->fire('Account:afterLogin', $this, $user);
return $token;
} }
public function loginByVerify() public function loginByVerify()
@ -74,21 +78,20 @@ class Account extends Service
$user = $validator->checkVerifyLogin($post['account'], $post['verify_code']); $user = $validator->checkVerifyLogin($post['account'], $post['verify_code']);
$this->handleLoginNotice($user); $token = $this->auth->saveAuthInfo($user);
return $this->auth->saveAuthInfo($user); $this->eventsManager->fire('Account:afterLogin', $this, $user);
return $token;
} }
public function logout() public function logout()
{ {
$user = $this->getLoginUser();
$this->auth->clearAuthInfo(); $this->auth->clearAuthInfo();
}
protected function handleLoginNotice(UserModel $user) $this->eventsManager->fire('Account:afterLogout', $this, $user);
{
$service = new AccountLoginNoticeService();
$service->createTask($user);
} }
} }

View File

@ -9,6 +9,7 @@ use App\Services\Logic\Chapter\ChapterLike as ChapterLikeService;
use App\Services\Logic\Chapter\DanmuList as ChapterDanmuListService; use App\Services\Logic\Chapter\DanmuList as ChapterDanmuListService;
use App\Services\Logic\Chapter\Learning as ChapterLearningService; use App\Services\Logic\Chapter\Learning as ChapterLearningService;
use App\Services\Logic\Chapter\ResourceList as ChapterResourceListService; use App\Services\Logic\Chapter\ResourceList as ChapterResourceListService;
use App\Services\Logic\Course\BasicInfo as CourseInfoService;
use App\Services\Logic\Course\ChapterList as CourseChapterListService; use App\Services\Logic\Course\ChapterList as CourseChapterListService;
/** /**
@ -50,20 +51,24 @@ class ChapterController extends Controller
$chapter = $service->handle($id); $chapter = $service->handle($id);
$service = new CourseInfoService();
$course = $service->handle($chapter['course']['id']);
$owned = $chapter['me']['owned'] ?? false; $owned = $chapter['me']['owned'] ?? false;
if (!$owned) { if (!$owned) {
$this->response->redirect([ $this->response->redirect([
'for' => 'home.course.show', 'for' => 'home.course.show',
'id' => $chapter['course']['id'], 'id' => $course['id'],
]); ]);
} }
$service = new CourseChapterListService(); $service = new CourseChapterListService();
$catalog = $service->handle($chapter['course']['id']); $catalog = $service->handle($course['id']);
$this->seo->prependTitle(['章节', $chapter['title'], $chapter['course']['title']]); $this->seo->prependTitle(['章节', $chapter['title'], $course['title']]);
if (!empty($chapter['summary'])) { if (!empty($chapter['summary'])) {
$this->seo->setDescription($chapter['summary']); $this->seo->setDescription($chapter['summary']);
@ -83,6 +88,7 @@ class ChapterController extends Controller
} }
} }
$this->view->setVar('course', $course);
$this->view->setVar('chapter', $chapter); $this->view->setVar('chapter', $chapter);
$this->view->setVar('catalog', $catalog); $this->view->setVar('catalog', $catalog);
} }

View File

@ -66,17 +66,15 @@ class Controller extends \Phalcon\Mvc\Controller
$this->checkCsrfToken(); $this->checkCsrfToken();
} }
$config = $this->getConfig(); $this->checkRateLimit();
if ($config->path('throttle.enabled')) {
$this->checkRateLimit();
}
return true; return true;
} }
public function initialize() public function initialize()
{ {
$this->eventsManager->fire('Site:afterView', $this, $this->authUser);
$this->seo = $this->getSeo(); $this->seo = $this->getSeo();
$this->navs = $this->getNavs(); $this->navs = $this->getNavs();
$this->appInfo = $this->getAppInfo(); $this->appInfo = $this->getAppInfo();

View File

@ -0,0 +1,103 @@
<?php
namespace App\Http\Home\Controllers;
use App\Services\Logic\Point\GiftInfo as GiftInfoService;
use App\Services\Logic\Point\GiftList as GiftListService;
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 Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\View;
/**
* @RoutePrefix("/point/gift")
*/
class PointGiftController extends Controller
{
public function beforeExecuteRoute(Dispatcher $dispatcher)
{
parent::beforeExecuteRoute($dispatcher);
if ($this->authUser->id == 0) {
$this->response->redirect(['for' => 'home.account.login']);
return false;
}
return true;
}
/**
* @Get("/list", name="home.point_gift.list")
*/
public function listAction()
{
$this->seo->prependTitle('积分兑换');
$this->view->pick('point/gift/list');
}
/**
* @Get("/pager", name="home.point_gift.pager")
*/
public function pagerAction()
{
$service = new GiftListService();
$pager = $service->handle();
$pager->target = 'gift-list';
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
$this->view->pick('point/gift/pager');
$this->view->setVar('pager', $pager);
}
/**
* @Get("/{id:[0-9]+}", name="home.point_gift.show")
*/
public function showAction($id)
{
$service = new GiftInfoService();
$gift = $service->handle($id);
$hotGifts = $this->getHotGifts();
$userBalance = $this->getUserBalance();
$this->seo->prependTitle(['积分兑换', $gift['name']]);
$this->view->pick('point/gift/show');
$this->view->setVar('gift', $gift);
$this->view->setVar('hot_gifts', $hotGifts);
$this->view->setVar('user_balance', $userBalance);
}
/**
* @Post("/redeem", name="home.point_gift.redeem")
*/
public function redeemAction()
{
$service = new GiftRedeemService();
$service->handle();
return $this->jsonSuccess(['msg' => '兑换成功']);
}
protected function getHotGifts()
{
$service = new HotGiftListService();
return $service->handle();
}
protected function getUserBalance()
{
$service = new BalanceInfoService();
return $service->handle();
}
}

View File

@ -0,0 +1,25 @@
<?php
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

@ -8,11 +8,15 @@ use App\Services\Logic\User\Console\AccountInfo as AccountInfoService;
use App\Services\Logic\User\Console\ConnectDelete as ConnectDeleteService; use App\Services\Logic\User\Console\ConnectDelete as ConnectDeleteService;
use App\Services\Logic\User\Console\ConnectList as ConnectListService; use App\Services\Logic\User\Console\ConnectList as ConnectListService;
use App\Services\Logic\User\Console\ConsultList as ConsultListService; use App\Services\Logic\User\Console\ConsultList as ConsultListService;
use App\Services\Logic\User\Console\ContactInfo as ContactInfoService;
use App\Services\Logic\User\Console\ContactUpdate as ContactUpdateService;
use App\Services\Logic\User\Console\CourseList as CourseListService; use App\Services\Logic\User\Console\CourseList as CourseListService;
use App\Services\Logic\User\Console\FavoriteList as FavoriteListService; use App\Services\Logic\User\Console\FavoriteList as FavoriteListService;
use App\Services\Logic\User\Console\FriendList as FriendListService; use App\Services\Logic\User\Console\FriendList as FriendListService;
use App\Services\Logic\User\Console\GroupList as GroupListService; use App\Services\Logic\User\Console\GroupList as GroupListService;
use App\Services\Logic\User\Console\OrderList as OrderListService; use App\Services\Logic\User\Console\OrderList as OrderListService;
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\RefundList as RefundListService; use App\Services\Logic\User\Console\RefundList as RefundListService;
@ -67,6 +71,19 @@ class UserConsoleController extends Controller
$this->view->setVar('user', $user); $this->view->setVar('user', $user);
} }
/**
* @Get("/contact", name="home.uc.contact")
*/
public function contactAction()
{
$service = new ContactInfoService();
$contact = $service->handle();
$this->view->pick('user/console/contact');
$this->view->setVar('contact', $contact);
}
/** /**
* @Get("/account", name="home.uc.account") * @Get("/account", name="home.uc.account")
*/ */
@ -182,6 +199,32 @@ class UserConsoleController extends Controller
$this->view->setVar('pager', $pager); $this->view->setVar('pager', $pager);
} }
/**
* @Get("/point/history", name="home.uc.point_history")
*/
public function pointHistoryAction()
{
$service = new PointHistoryService();
$pager = $service->handle();
$this->view->pick('user/console/point_history');
$this->view->setVar('pager', $pager);
}
/**
* @Get("/point/redeems", name="home.uc.point_redeems")
*/
public function pointRedeemsAction()
{
$service = new PointRedeemListService();
$pager = $service->handle();
$this->view->pick('user/console/point_redeems');
$this->view->setVar('pager', $pager);
}
/** /**
* @Get("/friends", name="home.uc.friends") * @Get("/friends", name="home.uc.friends")
*/ */
@ -249,6 +292,20 @@ class UserConsoleController extends Controller
return $this->jsonSuccess($content); return $this->jsonSuccess($content);
} }
/**
* @Post("/contact/update", name="home.uc.update_contact")
*/
public function updateContactAction()
{
$service = new ContactUpdateService();
$service->handle();
$content = ['msg' => '更新收货信息成功'];
return $this->jsonSuccess($content);
}
/** /**
* @Post("/connect/{id:[0-9]+}/delete", name="home.uc.unconnect") * @Post("/connect/{id:[0-9]+}/delete", name="home.uc.unconnect")
*/ */

View File

@ -2,11 +2,9 @@
namespace App\Http\Home\Services; namespace App\Http\Home\Services;
use App\Models\User as UserModel;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use App\Services\Auth\Home as AuthService; use App\Services\Auth\Home as AuthService;
use App\Services\Logic\Account\Register as RegisterService; use App\Services\Logic\Account\Register as RegisterService;
use App\Services\Logic\Notice\AccountLogin as AccountLoginNoticeService;
use App\Validators\Account as AccountValidator; use App\Validators\Account as AccountValidator;
use App\Validators\Captcha as CaptchaValidator; use App\Validators\Captcha as CaptchaValidator;
@ -35,6 +33,8 @@ class Account extends Service
$this->auth->saveAuthInfo($user); $this->auth->saveAuthInfo($user);
$this->eventsManager->fire('Account:afterRegister', $this, $user);
return $user; return $user;
} }
@ -50,9 +50,9 @@ class Account extends Service
$validator->checkCode($post['ticket'], $post['rand']); $validator->checkCode($post['ticket'], $post['rand']);
$this->handleLoginNotice($user);
$this->auth->saveAuthInfo($user); $this->auth->saveAuthInfo($user);
$this->eventsManager->fire('Account:afterLogin', $this, $user);
} }
public function loginByVerify() public function loginByVerify()
@ -63,21 +63,18 @@ class Account extends Service
$user = $validator->checkVerifyLogin($post['account'], $post['verify_code']); $user = $validator->checkVerifyLogin($post['account'], $post['verify_code']);
$this->handleLoginNotice($user);
$this->auth->saveAuthInfo($user); $this->auth->saveAuthInfo($user);
$this->eventsManager->fire('Account:afterLogin', $this, $user);
} }
public function logout() public function logout()
{ {
$user = $this->getLoginUser();
$this->auth->clearAuthInfo(); $this->auth->clearAuthInfo();
}
protected function handleLoginNotice(UserModel $user) $this->eventsManager->fire('Account:afterLogout', $this, $user);
{
$service = new AccountLoginNoticeService();
$service->createTask($user);
} }
} }

View File

@ -98,6 +98,8 @@ Trait ImMessageTrait
Gateway::$registerAddress = $this->getRegisterAddress(); Gateway::$registerAddress = $this->getRegisterAddress();
$imMessage = new ImMessageModel();
if ($to['type'] == 'friend') { if ($to['type'] == 'friend') {
$validator = new ImFriendUserValidator(); $validator = new ImFriendUserValidator();
@ -106,9 +108,9 @@ Trait ImMessageTrait
$online = Gateway::isUidOnline($to['id']); $online = Gateway::isUidOnline($to['id']);
$messageModel = new ImMessageModel(); $imMessage = new ImMessageModel();
$messageModel->create([ $imMessage->create([
'sender_id' => $from['id'], 'sender_id' => $from['id'],
'receiver_id' => $to['id'], 'receiver_id' => $to['id'],
'receiver_type' => ImMessageModel::TYPE_FRIEND, 'receiver_type' => ImMessageModel::TYPE_FRIEND,
@ -136,9 +138,9 @@ Trait ImMessageTrait
$relation = $validator->checkGroupUser($group->id, $user->id); $relation = $validator->checkGroupUser($group->id, $user->id);
$messageModel = new ImMessageModel(); $imMessage = new ImMessageModel();
$messageModel->create([ $imMessage->create([
'sender_id' => $from['id'], 'sender_id' => $from['id'],
'receiver_id' => $to['id'], 'receiver_id' => $to['id'],
'receiver_type' => ImMessageModel::TYPE_GROUP, 'receiver_type' => ImMessageModel::TYPE_GROUP,
@ -162,6 +164,8 @@ Trait ImMessageTrait
Gateway::sendToGroup($groupName, $content, $excludeClientId); Gateway::sendToGroup($groupName, $content, $excludeClientId);
} }
$this->eventsManager->fire('ImMessage:afterCreate', $this, $imMessage);
} }
public function sendCsMessage($from, $to) public function sendCsMessage($from, $to)

View File

@ -18,7 +18,9 @@
<span class="share"> <span class="share">
<a href="javascript:" title="我要点赞" data-url="{{ like_url }}"><i class="layui-icon layui-icon-praise icon-praise"></i><em class="like-count">{{ chapter.like_count }}</em></a> <a href="javascript:" title="我要点赞" data-url="{{ like_url }}"><i class="layui-icon layui-icon-praise icon-praise"></i><em class="like-count">{{ chapter.like_count }}</em></a>
<a href="javascript:" title="学习人次"><i class="layui-icon layui-icon-user"></i><em>{{ chapter.user_count }}</em></a> <a href="javascript:" title="学习人次"><i class="layui-icon layui-icon-user"></i><em>{{ chapter.user_count }}</em></a>
<a href="javascript:" title="我要提问" data-url="{{ consult_url }}"><i class="layui-icon layui-icon-help icon-help"></i></a> {% if course.market_price > 0 %}
<a href="javascript:" title="我要提问" data-url="{{ consult_url }}"><i class="layui-icon layui-icon-help icon-help"></i></a>
{% endif %}
{% if chapter.resource_count > 0 and chapter.me.owned == 1 %} {% if chapter.resource_count > 0 and chapter.me.owned == 1 %}
<a href="javascript:" title="资料下载" data-url="{{ resources_url }}"><i class="layui-icon layui-icon-download-circle icon-resource"></i></a> <a href="javascript:" title="资料下载" data-url="{{ resources_url }}"><i class="layui-icon layui-icon-download-circle icon-resource"></i></a>
{% endif %} {% endif %}

View File

@ -19,7 +19,9 @@
<span class="share"> <span class="share">
<a href="javascript:" title="我要点赞" data-url="{{ like_url }}"><i class="layui-icon layui-icon-praise icon-praise {{ liked_class }}"></i><em class="like-count">{{ chapter.like_count }}</em></a> <a href="javascript:" title="我要点赞" data-url="{{ like_url }}"><i class="layui-icon layui-icon-praise icon-praise {{ liked_class }}"></i><em class="like-count">{{ chapter.like_count }}</em></a>
<a href="javascript:" title="学习人次"><i class="layui-icon layui-icon-user"></i><em>{{ chapter.user_count }}</em></a> <a href="javascript:" title="学习人次"><i class="layui-icon layui-icon-user"></i><em>{{ chapter.user_count }}</em></a>
<a href="javascript:" title="我要提问" data-url="{{ consult_url }}"><i class="layui-icon layui-icon-help icon-help"></i></a> {% if course.market_price > 0 %}
<a href="javascript:" title="我要提问" data-url="{{ consult_url }}"><i class="layui-icon layui-icon-help icon-help"></i></a>
{% endif %}
{% if chapter.resource_count > 0 and chapter.me.owned == 1 %} {% if chapter.resource_count > 0 and chapter.me.owned == 1 %}
<a href="javascript:" title="资料下载" data-url="{{ resources_url }}"><i class="layui-icon layui-icon-download-circle icon-resource"></i></a> <a href="javascript:" title="资料下载" data-url="{{ resources_url }}"><i class="layui-icon layui-icon-download-circle icon-resource"></i></a>
{% endif %} {% endif %}

View File

@ -6,7 +6,7 @@
{% for teacher in course.teachers %} {% for teacher in course.teachers %}
{% set teacher_url = url({'for':'home.user.show','id':teacher.id}) %} {% set teacher_url = url({'for':'home.user.show','id':teacher.id}) %}
{% set teacher.title = teacher.title ? teacher.title : '小小教书匠' %} {% set teacher.title = teacher.title ? teacher.title : '小小教书匠' %}
<div class="sidebar-teacher-card clearfix"> <div class="sidebar-user-card clearfix">
<div class="avatar"> <div class="avatar">
<img src="{{ teacher.avatar }}!avatar_160" alt="{{ teacher.name }}"> <img src="{{ teacher.avatar }}!avatar_160" alt="{{ teacher.name }}">
</div> </div>

View File

@ -0,0 +1,74 @@
{%- 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) %}
{% if value > 0 %}
<span class="layui-badge layui-bg-green point">+{{ value }}</span>
{% else %}
<span class="layui-badge layui-bg-red point">{{ value }}</span>
{% endif %}
{%- endmacro %}
{%- macro event_type_info(value) %}
{% if value == 1 %}
<span class="type">订单消费</span>
{% elseif value == 2 %}
<span class="type">积分兑换</span>
{% elseif value == 3 %}
<span class="type">积分退款</span>
{% elseif value == 4 %}
<span class="type">帐号注册</span>
{% elseif value == 5 %}
<span class="type">站点访问</span>
{% elseif value == 6 %}
<span class="type">课时学习</span>
{% elseif value == 7 %}
<span class="type">课程评价</span>
{% elseif value == 8 %}
<span class="type">微聊讨论</span>
{% endif %}
{%- endmacro %}
{%- macro event_detail_info(history) %}
{% set event_info = history.event_info %}
{% if history.event_type == 1 %}
<p class="order">{{ event_info.order.subject }}</p>
{% elseif history.event_type == 2 %}
{% set gift_url = url({'for':'home.point_gift.show','id':event_info.point_redeem.gift_id}) %}
<p class="gift"><a href="{{ gift_url }}">{{ event_info.point_redeem.gift_name }}</a></p>
{% elseif history.event_type == 3 %}
{% set gift_url = url({'for':'home.point_gift.show','id':event_info.point_redeem.gift_id}) %}
<p class="gift"><a href="{{ gift_url }}">{{ event_info.point_redeem.gift_name }}</a></p>
{% elseif history.event_type == 4 %}
<span class="none">N/A</span>
{% elseif history.event_type == 5 %}
<span class="none">N/A</span>
{% elseif history.event_type == 6 %}
{% set course_url = url({'for':'home.course.show','id':event_info.course.id}) %}
{% set chapter_url = url({'for':'home.chapter.show','id':event_info.chapter.id}) %}
<p class="course">课程:<a href="{{ course_url }}">{{ event_info.course.title }}</a></p>
<p class="chapter">章节:<a href="{{ chapter_url }}">{{ event_info.chapter.title }}</a></p>
{% elseif history.event_type == 7 %}
{% set course_url = url({'for':'home.course.show','id':event_info.course.id}) %}
<p class="course"><a href="{{ course_url }}">{{ event_info.course.title }}</a></p>
{% elseif history.event_type == 8 %}
<span class="none">N/A</span>
{% endif %}
{%- endmacro %}

View File

@ -32,6 +32,9 @@
<li class="layui-nav-item"> <li class="layui-nav-item">
<a href="javascript:" class="nav-search" data-type="{{ s_type }}" data-query="{{ s_query }}" data-url="{{ s_url }}"><i class="layui-icon layui-icon-search"></i> 搜索</a> <a href="javascript:" class="nav-search" data-type="{{ s_type }}" data-query="{{ s_query }}" data-url="{{ s_url }}"><i class="layui-icon layui-icon-search"></i> 搜索</a>
</li> </li>
<li class="layui-nav-item">
<a href="{{ url({'for':'home.point_gift.list'}) }}" class="nav-point-gift"><i class="layui-icon layui-icon-gift"></i> 积分</a>
</li>
<li class="layui-nav-item"> <li class="layui-nav-item">
<a href="{{ url({'for':'home.vip.index'}) }}" class="nav-vip"><i class="layui-icon layui-icon-diamond"></i> 会员</a> <a href="{{ url({'for':'home.vip.index'}) }}" class="nav-vip"><i class="layui-icon layui-icon-diamond"></i> 会员</a>
</li> </li>

View File

@ -0,0 +1,20 @@
{% extends 'templates/main.volt' %}
{% block content %}
{% set pager_url = url({'for':'home.point_gift.pager'}) %}
<div class="layui-breadcrumb breadcrumb">
<a href="/">首页</a>
<a><cite>积分兑换</cite></a>
</div>
<div id="gift-list" data-url="{{ pager_url }}"></div>
{% endblock %}
{% block include_js %}
{{ js_include('home/js/point.gift.list.js') }}
{% endblock %}

View File

@ -0,0 +1,31 @@
{{ partial('macros/point') }}
{% if pager.total_pages > 0 %}
<div class="course-list clearfix">
<div class="layui-row layui-col-space20">
{% for item in pager.items %}
{% set gift_url = url({'for':'home.point_gift.show','id':item.id}) %}
<div class="layui-col-md3">
<div class="course-card">
<div class="cover">
<a href="{{ gift_url }}">
<img src="{{ item.cover }}" alt="item.name">
</a>
</div>
<div class="info">
<div class="title layui-elip">
<a href="{{ gift_url }}">{{ item.name }}</a>
</div>
<div class="meta">
{{ gift_type_info(item.type) }}
<span class="price">{{ item.point }} 积分</span>
<span>{{ item.redeem_count }} 人兑换</span>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{{ partial('partials/pager_ajax') }}
{% endif %}

View File

@ -0,0 +1,123 @@
{% extends 'templates/main.volt' %}
{% block content %}
{{ partial('macros/point') }}
{% set redeem_create_url = url({'for':'home.point_redeem.create'}) %}
{% set gift_list_url = url({'for':'home.point_gift.list'}) %}
<div class="breadcrumb">
<span class="layui-breadcrumb">
<a href="/">首页</a>
<a href="{{ gift_list_url }}">积分兑换</a>
<a><cite>{{ gift.name }}</cite></a>
</span>
</div>
<div class="layout-main clearfix">
<div class="layout-content">
<div class="layui-card">
<div class="layui-card-header">物品信息</div>
<div class="layui-card-body">
<div class="gift-meta clearfix">
<div class="cover">
<img src="{{ gift.cover }}!cover_270" alt="{{ gift.name }}">
</div>
<div class="info">
{% if gift.type == 1 %}
{% set course_url = url({'for':'home.course.show','id':gift.attrs.id}) %}
<p class="item">
<a href="{{ course_url }}">{{ gift.name }}</a>
{{ gift_type_info(gift.type) }}
</p>
{% else %}
<p class="item">{{ gift.name }} {{ gift_type_info(gift.type) }}</p>
{% endif %}
<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="value">{{ gift.redeem_count }}</span>
</p>
<p class="item">
{% if gift.stock > 0 and user_balance.point > gift.point %}
<button class="layui-btn layui-bg-red btn-redeem" data-id="{{ gift.id }}" data-url="{{ redeem_create_url }}">立即兑换</button>
{% else %}
<button class="layui-btn layui-btn-disabled">立即兑换</button>
{% endif %}
</p>
</div>
</div>
</div>
</div>
<div class="layui-card">
<div class="layui-card-header">物品详情</div>
<div class="layui-card-body">
<div class="gift-details markdown-body">{{ gift.details }}</div>
</div>
</div>
</div>
<div class="layout-sidebar">
<div class="sidebar">
<div class="layui-card">
<div class="layui-card-header">我的信息</div>
<div class="layui-card-body">
<div class="sidebar-user-card clearfix">
<div class="avatar">
<img src="{{ auth_user.avatar }}!avatar_160" alt="{{ auth_user.name }}">
</div>
<div class="info">
<div class="name">{{ auth_user.name }}</div>
<div class="meta"><span>当前积分</span><span class="point">{{ user_balance.point }}</span></div>
</div>
</div>
</div>
</div>
</div>
<div class="sidebar">
<div class="layui-card">
<div class="layui-card-header">热门兑换</div>
<div class="layui-card-body">
{% for gift in hot_gifts %}
{% set gift_url = url({'for':'home.point_gift.show','id':gift.id}) %}
<div class="sidebar-course-card clearfix">
<div class="cover">
<a href="{{ gift_url }}" title="{{ gift.name }}">
<img src="{{ gift.cover }}!cover_270" alt="{{ gift.name }}">
</a>
</div>
<div class="info">
<div class="title layui-elip">
<a href="{{ gift_url }}" title="{{ gift.name }}">{{ gift.name }}</a>
</div>
<div class="meta">
<span class="price">{{ gift.point }} 积分</span>
<span class="count">{{ gift.redeem_count }} 人兑换</span>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block link_css %}
{{ css_link('home/css/markdown.css') }}
{% endblock %}
{% block include_js %}
{{ js_include('home/js/point.gift.show.js') }}
{% endblock %}

View File

@ -34,7 +34,7 @@
<div class="layui-input-block"> <div class="layui-input-block">
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button> <button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button> <button type="reset" class="layui-btn layui-btn-primary">重置</button>
<input type="hidden" name="course_id" value="{{ request.get('course.id') }}"> <input type="hidden" name="course_id" value="{{ request.get('course_id') }}">
<input type="hidden" name="rating1" value="5"> <input type="hidden" name="rating1" value="5">
<input type="hidden" name="rating2" value="5"> <input type="hidden" name="rating2" value="5">
<input type="hidden" name="rating3" value="5"> <input type="hidden" name="rating3" value="5">

View File

@ -41,7 +41,9 @@
{% block inline_js %}{% endblock %} {% block inline_js %}{% endblock %}
{% if site_info.analytics_enabled == 1 %} {% if site_info.analytics_enabled == 1 %}
{{ site_info.analytics_script }} <div class="layui-hide">
{{ site_info.analytics_script }}
</div>
{% endif %} {% endif %}
</body> </body>

View File

@ -0,0 +1,69 @@
{% extends 'templates/main.volt' %}
{% block content %}
{% set update_url = url({'for':'home.uc.update_contact'}) %}
<div class="layout-main clearfix">
<div class="my-sidebar">{{ partial('user/console/menu') }}</div>
<div class="my-content">
<div class="wrap">
<div class="my-nav">
<span class="title">收货信息</span>
</div>
<form class="layui-form profile-form" method="post" action="{{ update_url }}">
<div class="layui-form-item">
<label class="layui-form-label">真实姓名</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="name" value="{{ contact.name }}" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">手机号码</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="phone" value="{{ contact.phone }}" lay-verify="phone">
</div>
</div>
<div class="layui-form-item" id="area-picker" style="margin-bottom: 25px;">
<div class="layui-form-label">所在地区</div>
<div class="layui-input-inline" style="width: 200px;">
<select name="address[province]" class="province-selector" data-value="{{ contact.add_province }}" lay-verify="required">
<option value="">请选择省</option>
</select>
</div>
<div class="layui-input-inline" style="width: 200px;">
<select name="address[city]" class="city-selector" data-value="{{ contact.add_city }}" lay-verify="required">
<option value="">请选择市</option>
</select>
</div>
<div class="layui-input-inline" style="width: 200px;">
<select name="address[county]" class="county-selector" data-value="{{ contact.add_county }}">
<option value="">请选择区</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">详细地址</label>
<div class="layui-input-block">
<textarea class="layui-textarea" name="address[other]" lay-verify="required">{{ contact.add_other }}</textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
<button class="layui-btn layui-btn-primary" type="reset">重置</button>
</div>
</div>
</form>
</div>
</div>
</div>
{% endblock %}
{% block include_js %}
{{ js_include('home/js/user.console.contact.js') }}
{% endblock %}

View File

@ -28,7 +28,7 @@
<tbody> <tbody>
{% for item in pager.items %} {% for item in pager.items %}
{% set course_url = url({'for':'home.course.show','id':item.course.id}) %} {% set course_url = url({'for':'home.course.show','id':item.course.id}) %}
{% set review_url = url({'for':'home.review.add'},{'id':item.course.id}) %} {% set review_url = url({'for':'home.review.add'},{'course_id':item.course.id}) %}
{% set allow_review = item.progress > 30 and item.reviewed == 0 %} {% set allow_review = item.progress > 30 and item.reviewed == 0 %}
<tr> <tr>
<td> <td>

View File

@ -12,13 +12,13 @@
<span class="title">我的好友</span> <span class="title">我的好友</span>
</div> </div>
{% if pager.total_pages > 0 %} {% if pager.total_pages > 0 %}
<table class="layui-table" lay-size="lg"> <table class="layui-table">
<colgroup> <colgroup>
<col> <col>
<col> <col>
<col> <col>
<col> <col>
<col width="15%"> <col width="10%">
</colgroup> </colgroup>
<thead> <thead>
<tr> <tr>

View File

@ -12,17 +12,19 @@
<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>
<div class="my-content"> <div class="my-content">
<div class="my-nav"> <div class="wrap">
<span class="title">我的群组</span> <div class="my-nav">
<a class="{{ joined_class }}" href="{{ joined_url }}">参加的</a> <span class="title">我的群组</span>
<a class="{{ owned_class }}" href="{{ owned_url }}">管理的</a> <a class="{{ joined_class }}" href="{{ joined_url }}">参加的</a>
</div> <a class="{{ owned_class }}" href="{{ owned_url }}">管理的</a>
<div class="my-group-wrap wrap"> </div>
{% if scope == 'owned' %} <div class="my-group-wrap">
{{ partial('user/console/groups_owned') }} {% if scope == 'owned' %}
{% else %} {{ partial('user/console/groups_owned') }}
{{ partial('user/console/groups_joined') }} {% else %}
{% endif %} {{ partial('user/console/groups_joined') }}
{% endif %}
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -36,6 +36,17 @@
</div> </div>
</div> </div>
<div class="layui-card">
<div class="layui-card-header">积分中心</div>
<div class="layui-card-body">
<ul class="my-menu">
<li><a href="{{ url({'for':'home.point_gift.list'}) }}">积分商城</a></li>
<li><a href="{{ url({'for':'home.uc.point_history'}) }}">积分记录</a></li>
<li><a href="{{ url({'for':'home.uc.point_redeems'}) }}">兑换记录</a></li>
</ul>
</div>
</div>
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-header">聊天设置</div> <div class="layui-card-header">聊天设置</div>
<div class="layui-card-body"> <div class="layui-card-body">
@ -51,6 +62,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.uc.profile'}) }}">个人信息</a></li> <li><a href="{{ url({'for':'home.uc.profile'}) }}">个人信息</a></li>
<li><a href="{{ url({'for':'home.uc.contact'}) }}">收货地址</a></li>
<li><a href="{{ url({'for':'home.uc.account'}) }}">帐号安全</a></li> <li><a href="{{ url({'for':'home.uc.account'}) }}">帐号安全</a></li>
{% if wechat_oa.enabled == 1 %} {% if wechat_oa.enabled == 1 %}
<li><a href="{{ url({'for':'home.uc.subscribe'}) }}">关注订阅</a></li> <li><a href="{{ url({'for':'home.uc.subscribe'}) }}">关注订阅</a></li>

View File

@ -10,36 +10,38 @@
<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>
<div class="my-content"> <div class="my-content">
<div class="my-nav"> <div class="wrap">
<span class="title">我的订单</span> <div class="my-nav">
{% for key,value in status_types %} <span class="title">我的订单</span>
{% set class = (status == key) ? 'layui-btn layui-btn-xs' : 'none' %} {% for key,value in status_types %}
{% set url = (key == '0') ? url({'for':'home.uc.orders'}) : url({'for':'home.uc.orders'},{'status':key}) %} {% set class = (status == key) ? 'layui-btn layui-btn-xs' : 'none' %}
<a class="{{ class }}" href="{{ url }}">{{ value }}</a> {% set url = (key == '0') ? url({'for':'home.uc.orders'}) : url({'for':'home.uc.orders'},{'status':key}) %}
{% endfor %} <a class="{{ class }}" href="{{ url }}">{{ value }}</a>
</div>
{% if pager.total_pages > 0 %}
<div class="order-list">
{% for item in pager.items %}
{% set order_info_url = url({'for':'home.order.info'},{'sn':item.sn}) %}
<div class="order-card">
<div class="header">
<span class="sn">编号:{{ item.sn }}</span>
<span class="time">时间:{{ date('Y-m-d H:i:s',item.create_time) }}</span>
</div>
<div class="body clearfix">
<div class="column subject">{{ item.subject }}</div>
<div class="column price">{{ '¥%0.2f'|format(item.amount) }}</div>
<div class="column status">{{ order_status(item.status) }}</div>
<div class="column action">
<button class="layui-btn layui-btn-sm btn-order-info" data-url="{{ order_info_url }}">详情</button>
</div>
</div>
</div>
{% endfor %} {% endfor %}
</div> </div>
{{ partial('partials/pager') }} {% if pager.total_pages > 0 %}
{% endif %} <div class="order-list">
{% for item in pager.items %}
{% set order_info_url = url({'for':'home.order.info'},{'sn':item.sn}) %}
<div class="order-card">
<div class="header">
<span class="sn">编号:{{ item.sn }}</span>
<span class="time">时间:{{ date('Y-m-d H:i:s',item.create_time) }}</span>
</div>
<div class="body clearfix">
<div class="column subject">{{ item.subject }}</div>
<div class="column price">{{ '¥%0.2f'|format(item.amount) }}</div>
<div class="column status">{{ order_status(item.status) }}</div>
<div class="column action">
<button class="layui-btn layui-btn-sm btn-order-info" data-url="{{ order_info_url }}">详情</button>
</div>
</div>
</div>
{% endfor %}
</div>
{{ partial('partials/pager') }}
{% endif %}
</div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,47 @@
{% extends 'templates/main.volt' %}
{% block content %}
{{ partial('macros/point') }}
<div class="layout-main clearfix">
<div class="my-sidebar">{{ partial('user/console/menu') }}</div>
<div class="my-content">
<div class="wrap">
<div class="my-nav">
<span class="title">积分记录</span>
</div>
{% if pager.total_pages > 0 %}
<table class="layui-table history-table" lay-size="lg">
<colgroup>
<col>
<col>
<col>
<col>
</colgroup>
<thead>
<tr>
<th>来源</th>
<th>积分</th>
<th>详情</th>
<th>时间</th>
</tr>
</thead>
<tbody>
{% for item in pager.items %}
<tr>
<td>{{ event_type_info(item.event_type) }}</td>
<td>{{ event_point_info(item.event_point) }}</td>
<td>{{ event_detail_info(item) }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ partial('partials/pager') }}
{% endif %}
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,48 @@
{% extends 'templates/main.volt' %}
{% block content %}
{{ partial('macros/point') }}
<div class="layout-main clearfix">
<div class="my-sidebar">{{ partial('user/console/menu') }}</div>
<div class="my-content">
<div class="wrap">
<div class="my-nav">
<span class="title">兑换记录</span>
</div>
{% if pager.total_pages > 0 %}
<table class="layui-table" lay-size="lg">
<colgroup>
<col>
<col>
<col>
<col>
</colgroup>
<thead>
<tr>
<th>物品名称</th>
<th>消耗积分</th>
<th>兑换状态</th>
<th>兑换时间</th>
</tr>
</thead>
<tbody>
{% for item in pager.items %}
{% set gift_url = url({'for':'home.point_gift.show','id':item.gift.id}) %}
<tr>
<td><a href="{{ gift_url }}">{{ item.gift.name }}</a> {{ gift_type_info(item.gift.type) }}</td>
<td>{{ item.gift.point }}</td>
<td>{{ redeem_status_info(item.status) }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ partial('partials/pager') }}
{% endif %}
</div>
</div>
</div>
{% endblock %}

View File

@ -10,36 +10,38 @@
<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>
<div class="my-content"> <div class="my-content">
<div class="my-nav"> <div class="wrap">
<span class="title">我的退款</span> <div class="my-nav">
{% for key,value in status_types %} <span class="title">我的退款</span>
{% set class = (status == key) ? 'layui-btn layui-btn-xs' : 'none' %} {% for key,value in status_types %}
{% set url = (key == 'all') ? url({'for':'home.uc.refunds'}) : url({'for':'home.uc.refunds'},{'status':key}) %} {% set class = (status == key) ? 'layui-btn layui-btn-xs' : 'none' %}
<a class="{{ class }}" href="{{ url }}">{{ value }}</a> {% set url = (key == 'all') ? url({'for':'home.uc.refunds'}) : url({'for':'home.uc.refunds'},{'status':key}) %}
{% endfor %} <a class="{{ class }}" href="{{ url }}">{{ value }}</a>
</div>
{% if pager.total_pages > 0 %}
<div class="order-list">
{% for item in pager.items %}
{% set refund_info_url = url({'for':'home.refund.info'},{'sn':item.sn}) %}
<div class="order-card">
<div class="header">
<span class="sn">编号:{{ item.sn }}</span>
<span class="time">时间:{{ date('Y-m-d H:i:s',item.create_time) }}</span>
</div>
<div class="body clearfix">
<div class="column subject">{{ item.subject }}</div>
<div class="column price">{{ '¥%0.2f'|format(item.amount) }}</div>
<div class="column status">{{ refund_status(item.status) }}</div>
<div class="column action">
<button class="layui-btn layui-btn-sm btn-refund-info" data-url="{{ refund_info_url }}">详情</button>
</div>
</div>
</div>
{% endfor %} {% endfor %}
</div> </div>
{{ partial('partials/pager') }} {% if pager.total_pages > 0 %}
{% endif %} <div class="order-list">
{% for item in pager.items %}
{% set refund_info_url = url({'for':'home.refund.info'},{'sn':item.sn}) %}
<div class="order-card">
<div class="header">
<span class="sn">编号:{{ item.sn }}</span>
<span class="time">时间:{{ date('Y-m-d H:i:s',item.create_time) }}</span>
</div>
<div class="body clearfix">
<div class="column subject">{{ item.subject }}</div>
<div class="column price">{{ '¥%0.2f'|format(item.amount) }}</div>
<div class="column status">{{ refund_status(item.status) }}</div>
<div class="column action">
<button class="layui-btn layui-btn-sm btn-refund-info" data-url="{{ refund_info_url }}">详情</button>
</div>
</div>
</div>
{% endfor %}
</div>
{{ partial('partials/pager') }}
{% endif %}
</div>
</div> </div>
</div> </div>

View File

@ -11,11 +11,13 @@ class AppInfo
protected $link = 'https://koogua.com'; protected $link = 'https://koogua.com';
protected $version = '1.2.5'; protected $version = '1.2.6';
public function __get($name) public function __get($name)
{ {
return $this->{$name} ?? null; if (isset($this->{$name})) {
return $this->{$name};
}
} }
} }

View File

@ -186,6 +186,23 @@ class Redis extends \Phalcon\Cache\Backend\Redis
return (bool)$redis->exists($lastKey); return (bool)$redis->exists($lastKey);
} }
/**
* @param string $keyName
* @return int|bool
*/
public function ttl($keyName = null)
{
$redis = $this->getRedis();
if ($keyName === null) {
$lastKey = $this->_lastKey;
} else {
$lastKey = $this->getKeyName($keyName);
}
return $redis->ttl($lastKey);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
* *

View File

@ -16,7 +16,7 @@ class Lock
*/ */
public static function addLock($itemId, $expire = 600) public static function addLock($itemId, $expire = 600)
{ {
if (!$itemId || $expire <= 0) { if (empty($itemId) || $expire <= 0) {
return false; return false;
} }
@ -43,7 +43,7 @@ class Lock
*/ */
public static function releaseLock($itemId, $lockId) public static function releaseLock($itemId, $lockId)
{ {
if (!$itemId || !$lockId) { if (empty($itemId) || empty($lockId)) {
return false; return false;
} }
@ -73,7 +73,7 @@ class Lock
public static function getLockKey($itemId) public static function getLockKey($itemId)
{ {
return sprintf('kg_lock:%s', $itemId); return sprintf('_LOCK_:%s', $itemId);
} }
} }

42
app/Listeners/Account.php Normal file
View File

@ -0,0 +1,42 @@
<?php
namespace App\Listeners;
use App\Models\User as UserModel;
use App\Services\Logic\Notice\AccountLogin as AccountLoginNoticeService;
use App\Services\Logic\Point\PointHistory as PointHistoryService;
use Phalcon\Events\Event as PhEvent;
class Account extends Listener
{
public function afterRegister(PhEvent $event, $source, UserModel $user)
{
$this->handleRegisterPoint($user);
}
public function afterLogin(PhEvent $event, $source, UserModel $user)
{
$this->handleLoginNotice($user);
}
public function afterLogout(PhEvent $event, $source, UserModel $user)
{
}
protected function handleRegisterPoint(UserModel $user)
{
$service = new PointHistoryService();
$service->handleAccountRegister($user);
}
protected function handleLoginNotice(UserModel $user)
{
$service = new AccountLoginNoticeService();
$service->createTask($user);
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace App\Listeners;
use App\Models\ImMessage as ImMessageModel;
use App\Services\Logic\Point\PointHistory as PointHistoryService;
use Phalcon\Events\Event as PhEvent;
class ImMessage extends Listener
{
public function afterCreate(PhEvent $event, $source, ImMessageModel $message)
{
$this->handleDiscussPoint($message);
}
protected function handleDiscussPoint(ImMessageModel $message)
{
$todayDate = date('Ymd');
$keyName = sprintf('im_discuss:%s:%s', $message->sender_id, $todayDate);
$cache = $this->getCache();
$content = $cache->get($keyName);
if ($content) return;
$service = new PointHistoryService();
$service->handleImDiscuss($message);
$tomorrow = strtotime($todayDate) + 86400;
$lifetime = $tomorrow - time();
$cache->save($keyName, 1, $lifetime);
}
}

View File

@ -8,6 +8,28 @@ use Phalcon\Mvc\User\Plugin as UserPlugin;
class Listener extends UserPlugin class Listener extends UserPlugin
{ {
public function getConfig()
{
$appService = new AppService();
return $appService->getConfig();
}
public function getCache()
{
$appService = new AppService();
return $appService->getCache();
}
public function getRedis()
{
$appService = new AppService();
return $appService->getRedis();
}
public function getLogger($channel = null) public function getLogger($channel = null)
{ {
$appService = new AppService(); $appService = new AppService();

24
app/Listeners/Review.php Normal file
View File

@ -0,0 +1,24 @@
<?php
namespace App\Listeners;
use App\Models\Review as ReviewModel;
use App\Services\Logic\Point\PointHistory as PointHistoryService;
use Phalcon\Events\Event as PhEvent;
class Review extends Listener
{
public function afterCreate(PhEvent $event, $source, ReviewModel $review)
{
$this->handleReviewPoint($review);
}
protected function handleReviewPoint(ReviewModel $review)
{
$service = new PointHistoryService();
$service->handleCourseReview($review);
}
}

118
app/Listeners/Site.php Normal file
View File

@ -0,0 +1,118 @@
<?php
namespace App\Listeners;
use App\Library\Utils\Lock as LockUtil;
use App\Models\Online as OnlineModel;
use App\Models\User as UserModel;
use App\Repos\Online as OnlineRepo;
use App\Services\Logic\Point\PointHistory as PointHistoryService;
use App\Traits\Client as ClientTrait;
use Phalcon\Events\Event as PhEvent;
class Site extends Listener
{
use ClientTrait;
public function afterView(PhEvent $event, $source, UserModel $user)
{
if ($user->id > 0) {
$this->handleOnline($user);
$this->handleVisitPoint($user);
/**
* 更新会重置afterFetch重新执行
*/
$user->afterFetch();
}
}
protected function handleOnline(UserModel $user)
{
$now = time();
if ($now - $user->active_time < 900) {
return;
}
$itemId = "user_online:{$user->id}";
$clientType = $this->getClientType();
$clientIp = $this->getClientIp();
$lockId = LockUtil::addLock($itemId);
if ($lockId === false) return;
$user->active_time = $now;
$user->update();
$onlineRepo = new OnlineRepo();
$records = $onlineRepo->findByUserDate($user->id, date('Ymd'));
if ($records->count() > 0) {
$online = null;
foreach ($records as $record) {
$case1 = $record->client_type == $clientType;
$case2 = $record->client_ip == $clientIp;
if ($case1 && $case2) {
$online = $record;
break;
}
}
if ($online) {
$online->active_time = $now;
$online->update();
} else {
$this->createOnline($user->id, $clientType, $clientIp);
}
} else {
$this->createOnline($user->id, $clientType, $clientIp);
}
LockUtil::releaseLock($itemId, $lockId);
}
protected function createOnline($userId, $clientType, $clientIp)
{
$online = new OnlineModel();
$online->user_id = $userId;
$online->client_type = $clientType;
$online->client_ip = $clientIp;
$online->active_time = time();
$online->create();
return $online;
}
protected function handleVisitPoint(UserModel $user)
{
$todayDate = date('Ymd');
$keyName = sprintf('site_visit:%s:%s', $user->id, $todayDate);
$cache = $this->getCache();
$content = $cache->get($keyName);
if ($content) return;
$service = new PointHistoryService();
$service->handleSiteVisit($user);
$tomorrow = strtotime($todayDate) + 86400;
$lifetime = $tomorrow - time();
$cache->save($keyName, 1, $lifetime);
}
}

View File

@ -9,7 +9,7 @@ use App\Repos\Order as OrderRepo;
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;
class Pay extends Listener class Trade extends Listener
{ {
/** /**
@ -73,12 +73,6 @@ class Pay extends Listener
'message' => $e->getMessage(), 'message' => $e->getMessage(),
])); ]));
$this->logger->debug('After Pay Event Info ' . kg_json_encode([
'event' => $event->getType(),
'source' => get_class($source),
'data' => kg_json_encode($trade),
]));
throw new \RuntimeException('sys.trans_rollback'); throw new \RuntimeException('sys.trans_rollback');
} }
} }

View File

@ -1,77 +0,0 @@
<?php
namespace App\Listeners;
use App\Library\Utils\Lock as LockUtil;
use App\Models\Online as OnlineModel;
use App\Models\User as UserModel;
use App\Repos\Online as OnlineRepo;
use App\Traits\Client as ClientTrait;
use Phalcon\Events\Event;
class User extends Listener
{
use ClientTrait;
public function online(Event $event, $source, UserModel $user)
{
$itemId = "user:{$user->id}";
$lockId = LockUtil::addLock($itemId);
$now = time();
$clientType = $this->getClientType();
$clientIp = $this->getClientIp();
if ($now - $user->active_time > 600) {
$user->active_time = $now;
$user->update();
$onlineRepo = new OnlineRepo();
$records = $onlineRepo->findByUserDate($user->id, date('Y-m-d'));
if ($records->count() > 0) {
$online = null;
foreach ($records as $record) {
if ($record->client_type == $clientType && $record->client_ip == $clientIp) {
$online = $record;
break;
}
}
if ($online) {
$online->active_time = $now;
$online->update();
} else {
$this->createOnline($user->id, $clientType, $clientIp);
}
} else {
$this->createOnline($user->id, $clientType, $clientIp);
}
}
LockUtil::releaseLock($itemId, $lockId);
}
protected function createOnline($userId, $clientType, $clientIp)
{
$online = new OnlineModel();
$online->user_id = $userId;
$online->client_type = $clientType;
$online->client_ip = $clientIp;
$online->active_time = time();
$online->create();
return $online;
}
}

View File

@ -4,7 +4,7 @@ namespace App\Listeners;
use App\Caches\UserDailyCounter as CacheUserDailyCounter; use App\Caches\UserDailyCounter as CacheUserDailyCounter;
use App\Models\User as UserModel; use App\Models\User as UserModel;
use Phalcon\Events\Event; use Phalcon\Events\Event as PhEvent;
class UserDailyCounter extends Listener class UserDailyCounter extends Listener
{ {
@ -16,42 +16,42 @@ class UserDailyCounter extends Listener
$this->counter = new CacheUserDailyCounter(); $this->counter = new CacheUserDailyCounter();
} }
public function incrFavoriteCount(Event $event, $source, UserModel $user) public function incrFavoriteCount(PhEvent $event, $source, UserModel $user)
{ {
$this->counter->hIncrBy($user->id, 'favorite_count'); $this->counter->hIncrBy($user->id, 'favorite_count');
} }
public function incrDanmuCount(Event $event, $source, UserModel $user) public function incrDanmuCount(PhEvent $event, $source, UserModel $user)
{ {
$this->counter->hIncrBy($user->id, 'danmu_count'); $this->counter->hIncrBy($user->id, 'danmu_count');
} }
public function incrConsultCount(Event $event, $source, UserModel $user) public function incrConsultCount(PhEvent $event, $source, UserModel $user)
{ {
$this->counter->hIncrBy($user->id, 'consult_count'); $this->counter->hIncrBy($user->id, 'consult_count');
} }
public function incrReviewCount(Event $event, $source, UserModel $user) public function incrReviewCount(PhEvent $event, $source, UserModel $user)
{ {
$this->counter->hIncrBy($user->id, 'review_count'); $this->counter->hIncrBy($user->id, 'review_count');
} }
public function incrOrderCount(Event $event, $source, UserModel $user) public function incrOrderCount(PhEvent $event, $source, UserModel $user)
{ {
$this->counter->hIncrBy($user->id, 'order_count'); $this->counter->hIncrBy($user->id, 'order_count');
} }
public function incrConsultLikeCount(Event $event, $source, UserModel $user) public function incrConsultLikeCount(PhEvent $event, $source, UserModel $user)
{ {
$this->counter->hIncrBy($user->id, 'consult_like_count'); $this->counter->hIncrBy($user->id, 'consult_like_count');
} }
public function incrChapterLikeCount(Event $event, $source, UserModel $user) public function incrChapterLikeCount(PhEvent $event, $source, UserModel $user)
{ {
$this->counter->hIncrBy($user->id, 'chapter_like_count'); $this->counter->hIncrBy($user->id, 'chapter_like_count');
} }
public function incrReviewLikeCount(Event $event, $source, UserModel $user) public function incrReviewLikeCount(PhEvent $event, $source, UserModel $user)
{ {
$this->counter->hIncrBy($user->id, 'review_like_count'); $this->counter->hIncrBy($user->id, 'review_like_count');
} }

View File

@ -12,56 +12,56 @@ class Account extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 邮箱 * 邮箱
* *
* @var string * @var string
*/ */
public $email; public $email = '';
/** /**
* 手机 * 手机
* *
* @var string * @var string
*/ */
public $phone; public $phone = '';
/** /**
* 密码 * 密码
* *
* @var string * @var string
*/ */
public $password; public $password = '';
/** /**
* 密盐 * 密盐
* *
* @var string * @var string
*/ */
public $salt; public $salt = '';
/** /**
* 删除标识 * 删除标识
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -90,4 +90,4 @@ class Account extends Model
$this->update_time = time(); $this->update_time = time();
} }
} }

View File

@ -17,32 +17,32 @@ class Area extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 类型 * 类型
* *
* @var int * @var int
*/ */
public $type; public $type = 0;
/** /**
* 编码 * 编码
* *
* @var string * @var string
*/ */
public $code; public $code = '';
/** /**
* 名称 * 名称
* *
* @var string * @var string
*/ */
public $name; public $name = '';
public function getSource(): string public function getSource(): string
{ {
return 'kg_area'; return 'kg_area';
} }
} }

View File

@ -10,49 +10,49 @@ class Audit extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 用户编号 * 用户编号
* *
* @var int * @var int
*/ */
public $user_id; public $user_id = 0;
/** /**
* 用户名称 * 用户名称
* *
* @var int * @var string
*/ */
public $user_name; public $user_name = '';
/** /**
* 用户IP * 用户IP
* *
* @var int * @var string
*/ */
public $user_ip; public $user_ip = '';
/** /**
* 请求路由 * 请求路由
* *
* @var string * @var string
*/ */
public $req_route; public $req_route = '';
/** /**
* 请求路径 * 请求路径
* *
* @var string * @var string
*/ */
public $req_path; public $req_path = '';
/** /**
* 请求参数 * 请求参数
* *
* @var string * @var array|string
*/ */
public $req_data; public $req_data = '';
/** /**
* 创建时间 * 创建时间
@ -68,8 +68,6 @@ class Audit extends Model
public function beforeCreate() public function beforeCreate()
{ {
$this->create_time = time();
if (is_array($this->req_data) && !empty($this->req_data)) { if (is_array($this->req_data) && !empty($this->req_data)) {
foreach ($this->req_data as $key => $value) { foreach ($this->req_data as $key => $value) {
if (!is_scalar($value)) { if (!is_scalar($value)) {
@ -83,6 +81,8 @@ class Audit extends Model
} else { } else {
$this->req_data = ''; $this->req_data = '';
} }
$this->create_time = time();
} }
} }

View File

@ -19,84 +19,84 @@ class Category extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 上级编号 * 上级编号
* *
* @var int * @var int
*/ */
public $parent_id; public $parent_id = 0;
/** /**
* 层级 * 层级
* *
* @var int * @var int
*/ */
public $level; public $level = 0;
/** /**
* 类型 * 类型
* *
* @var int * @var int
*/ */
public $type; public $type = 0;
/** /**
* 名称 * 名称
* *
* @var string * @var string
*/ */
public $name; public $name = '';
/** /**
* 路径 * 路径
* *
* @var string * @var string
*/ */
public $path; public $path = '';
/** /**
* 优先级 * 优先级
* *
* @var int * @var int
*/ */
public $priority; public $priority = 0;
/** /**
* 发布标识 * 发布标识
* *
* @var int * @var int
*/ */
public $published; public $published = 0;
/** /**
* 删除标识 * 删除标识
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 节点数 * 节点数
* *
* @var int * @var int
*/ */
public $child_count; public $child_count = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -144,4 +144,4 @@ class Category extends Model
]; ];
} }
} }

View File

@ -60,126 +60,126 @@ class Chapter extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 父级编号 * 父级编号
* *
* @var int * @var int
*/ */
public $parent_id; public $parent_id = 0;
/** /**
* 课程编号 * 课程编号
* *
* @var int * @var int
*/ */
public $course_id; public $course_id = 0;
/** /**
* 标题 * 标题
* *
* @var string * @var string
*/ */
public $title; public $title = '';
/** /**
* 摘要 * 摘要
* *
* @var string * @var string
*/ */
public $summary; public $summary = '';
/** /**
* 优先级 * 优先级
* *
* @var int * @var int
*/ */
public $priority; public $priority = 0;
/** /**
* 免费标识 * 免费标识
* *
* @var int * @var int
*/ */
public $free; public $free = 0;
/** /**
* 模式类型 * 模式类型
* *
* @var int * @var int
*/ */
public $model; public $model = 0;
/** /**
* 扩展属性 * 扩展属性
* *
* @var string|array * @var string|array
*/ */
public $attrs; public $attrs = '';
/** /**
* 发布标识 * 发布标识
* *
* @var int * @var int
*/ */
public $published; public $published = 0;
/** /**
* 删除标识 * 删除标识
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 资源数 * 资源数
* *
* @var int * @var int
*/ */
public $resource_count; public $resource_count = 0;
/** /**
* 课时数 * 课时数
* *
* @var int * @var int
*/ */
public $lesson_count; public $lesson_count = 0;
/** /**
* 学员数 * 学员数
* *
* @var int * @var int
*/ */
public $user_count; public $user_count = 0;
/** /**
* 咨询数 * 咨询数
* *
* @var int * @var int
*/ */
public $consult_count; public $consult_count = 0;
/** /**
* 点赞数 * 点赞数
* *
* @var int * @var int
*/ */
public $like_count; public $like_count = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -205,22 +205,18 @@ class Chapter extends Model
$this->model = $course->model; $this->model = $course->model;
if ($this->parent_id > 0) { if ($this->parent_id > 0) {
if (empty($this->attrs)) {
$attrs = []; if ($this->model == Course::MODEL_VOD) {
$this->attrs = $this->_vod_attrs;
switch ($course->model) { } elseif ($this->model == Course::MODEL_LIVE) {
case Course::MODEL_VOD: $this->attrs = $this->_live_attrs;
$attrs = $this->_vod_attrs; } elseif ($this->model == Course::MODEL_READ) {
break; $this->attrs = $this->_read_attrs;
case Course::MODEL_LIVE: }
$attrs = $this->_live_attrs; }
break; if (is_array($this->attrs) && !empty($this->attrs)) {
case Course::MODEL_READ: $this->attrs = kg_json_encode($this->attrs);
$attrs = $this->_read_attrs;
break;
} }
$this->attrs = kg_json_encode($attrs);
} }
$this->create_time = time(); $this->create_time = time();
@ -253,4 +249,4 @@ class Chapter extends Model
} }
} }
} }

View File

@ -12,42 +12,42 @@ class ChapterLike extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 章节编号 * 章节编号
* *
* @var int * @var int
*/ */
public $chapter_id; public $chapter_id = 0;
/** /**
* 用户编号 * 用户编号
* *
* @var int * @var int
*/ */
public $user_id; public $user_id = 0;
/** /**
* 删除标识 * 删除标识
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -76,4 +76,4 @@ class ChapterLike extends Model
$this->update_time = time(); $this->update_time = time();
} }
} }

View File

@ -17,63 +17,63 @@ class ChapterLive extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 课程编号 * 课程编号
* *
* @var int * @var int
*/ */
public $course_id; public $course_id = 0;
/** /**
* 章节编号 * 章节编号
* *
* @var int * @var int
*/ */
public $chapter_id; public $chapter_id = 0;
/** /**
* 开始时间 * 开始时间
* *
* @var int * @var int
*/ */
public $start_time; public $start_time = 0;
/** /**
* 结束时间 * 结束时间
* *
* @var int * @var int
*/ */
public $end_time; public $end_time = 0;
/** /**
* 用户限额 * 用户限额
* *
* @var int * @var int
*/ */
public $user_limit; public $user_limit = 0;
/** /**
* 直播状态 * 直播状态
* *
* @var int * @var int
*/ */
public $status; public $status = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -102,4 +102,4 @@ class ChapterLive extends Model
return str_replace('chapter_', '', $streamName); return str_replace('chapter_', '', $streamName);
} }
} }

View File

@ -10,42 +10,42 @@ class ChapterRead extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 课程编号 * 课程编号
* *
* @var int * @var int
*/ */
public $course_id; public $course_id = 0;
/** /**
* 章节编号 * 章节编号
* *
* @var int * @var int
*/ */
public $chapter_id; public $chapter_id = 0;
/** /**
* 内容 * 内容
* *
* @var string * @var string
*/ */
public $content; public $content = '';
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -55,13 +55,6 @@ class ChapterRead extends Model
public function beforeCreate() public function beforeCreate()
{ {
$this->create_time = time(); $this->create_time = time();
/**
* text类型不能自动填充默认值
*/
if (is_null($this->content)) {
$this->content = '';
}
} }
public function beforeUpdate() public function beforeUpdate()
@ -69,4 +62,4 @@ class ChapterRead extends Model
$this->update_time = time(); $this->update_time = time();
} }
} }

View File

@ -12,84 +12,84 @@ class ChapterUser extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 课程编号 * 课程编号
* *
* @var int * @var int
*/ */
public $course_id; public $course_id = 0;
/** /**
* 章节编号 * 章节编号
* *
* @var int * @var int
*/ */
public $chapter_id; public $chapter_id = 0;
/** /**
* 用户编号 * 用户编号
* *
* @var int * @var int
*/ */
public $user_id; public $user_id = 0;
/** /**
* 计划编号 * 计划编号
* *
* @var int * @var int
*/ */
public $plan_id; public $plan_id = 0;
/** /**
* 学习时长 * 学习时长(秒)
* *
* @var int * @var int
*/ */
public $duration; public $duration = 0;
/** /**
* 播放位置 * 播放位置(秒)
* *
* @var int * @var int
*/ */
public $position; public $position = 0;
/** /**
* 学习进度 * 学习进度
* *
* @var int * @var int
*/ */
public $progress; public $progress = 0;
/** /**
* 消费标识 * 消费标识
* *
* @var int * @var int
*/ */
public $consumed; public $consumed = 0;
/** /**
* 删除标识 * 删除标识
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -118,4 +118,4 @@ class ChapterUser extends Model
$this->update_time = time(); $this->update_time = time();
} }
} }

View File

@ -12,49 +12,49 @@ class ChapterVod extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 课程编号 * 课程编号
* *
* @var int * @var int
*/ */
public $course_id; public $course_id = 0;
/** /**
* 章节编号 * 章节编号
* *
* @var int * @var int
*/ */
public $chapter_id; public $chapter_id = 0;
/** /**
* 文件编号 * 文件编号
* *
* @var string * @var string
*/ */
public $file_id; public $file_id = '';
/** /**
* 文件转码 * 文件转码
* *
* @var string * @var array|string
*/ */
public $file_transcode; public $file_transcode = '';
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -104,4 +104,4 @@ class ChapterVod extends Model
return $transcode; return $transcode;
} }
} }

View File

@ -16,63 +16,63 @@ class Connect extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 用户编号 * 用户编号
* *
* @var int * @var int
*/ */
public $user_id; public $user_id = 0;
/** /**
* 开放ID * 开放ID
* *
* @var string * @var string
*/ */
public $open_id; public $open_id = '';
/** /**
* 开放名称 * 开放名称
* *
* @var string * @var string
*/ */
public $open_name; public $open_name = '';
/** /**
* 开放头像 * 开放头像
* *
* @var string * @var string
*/ */
public $open_avatar; public $open_avatar = '';
/** /**
* 提供商 * 提供商
* *
* @var int * @var int
*/ */
public $provider; public $provider = 0;
/** /**
* 删除标识 * 删除标识
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -101,4 +101,4 @@ class Connect extends Model
$this->update_time = time(); $this->update_time = time();
} }
} }

View File

@ -19,112 +19,112 @@ class Consult extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 课程编号 * 课程编号
* *
* @var int * @var int
*/ */
public $course_id; public $course_id = 0;
/** /**
* 章节编号 * 章节编号
* *
* @var int * @var int
*/ */
public $chapter_id; public $chapter_id = 0;
/** /**
* 提主编号 * 提主编号
* *
* @var int * @var int
*/ */
public $owner_id; public $owner_id = 0;
/** /**
* 答主编号 * 答主编号
* *
* @var int * @var int
*/ */
public $replier_id; public $replier_id = 0;
/** /**
* 提问 * 提问
* *
* @var string * @var string
*/ */
public $question; public $question = '';
/** /**
* 回答 * 回答
* *
* @var string * @var string
*/ */
public $answer; public $answer = '';
/** /**
* 评分 * 评分
* *
* @var int * @var int
*/ */
public $rating; public $rating = 0;
/** /**
* 优先级 * 优先级
* *
* @var int * @var int
*/ */
public $priority; public $priority = 0;
/** /**
* 私密标识 * 私密标识
* *
* @var int * @var int
*/ */
public $private; public $private = 0;
/** /**
* 发布标识 * 发布标识
* *
* @var int * @var int
*/ */
public $published; public $published = 0;
/** /**
* 删除标识 * 删除标识
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 赞成数 * 赞成数
* *
* @var int * @var int
*/ */
public $like_count; public $like_count = 0;
/** /**
* 回复时间 * 回复时间
* *
* @var int * @var int
*/ */
public $reply_time; public $reply_time = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -157,4 +157,4 @@ class Consult extends Model
$this->update_time = time(); $this->update_time = time();
} }
} }

View File

@ -12,42 +12,42 @@ class ConsultLike extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 咨询编号 * 咨询编号
* *
* @var int * @var int
*/ */
public $consult_id; public $consult_id = 0;
/** /**
* 用户编号 * 用户编号
* *
* @var int * @var int
*/ */
public $user_id; public $user_id = 0;
/** /**
* 删除标识 * 删除标识
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -76,4 +76,4 @@ class ConsultLike extends Model
$this->update_time = time(); $this->update_time = time();
} }
} }

View File

@ -52,56 +52,56 @@ class Course extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 标题 * 标题
* *
* @var string * @var string
*/ */
public $title; public $title = '';
/** /**
* 封面 * 封面
* *
* @var string * @var string
*/ */
public $cover; public $cover = '';
/** /**
* 简介 * 简介
* *
* @var string * @var string
*/ */
public $summary; public $summary = '';
/** /**
* 关键字 * 关键字
* *
* @var string * @var string
*/ */
public $keywords; public $keywords = '';
/** /**
* 详情 * 详情
* *
* @var string * @var string
*/ */
public $details; public $details = '';
/** /**
* 主分类编号 * 主分类编号
* *
* @var int * @var int
*/ */
public $category_id; public $category_id = 0;
/** /**
* 主教师编号 * 主教师编号
* *
* @var int * @var int
*/ */
public $teacher_id; public $teacher_id = 0;
/** /**
* 原始价格 * 原始价格
@ -115,147 +115,147 @@ class Course extends Model
* *
* @var float * @var float
*/ */
public $market_price; public $market_price = 0.00;
/** /**
* 会员价格 * 会员价格
* *
* @var float * @var float
*/ */
public $vip_price; public $vip_price = 0.00;
/** /**
* 学习期限(月) * 学习期限(月)
* *
* @var int * @var int
*/ */
public $study_expiry; public $study_expiry = 0;
/** /**
* 退款期限(天) * 退款期限(天)
* *
* @var int * @var int
*/ */
public $refund_expiry; public $refund_expiry = 0;
/** /**
* 用户评价 * 用户评价
* *
* @var float * @var float
*/ */
public $rating; public $rating = 0.00;
/** /**
* 综合得分 * 综合得分
* *
* @var float * @var float
*/ */
public $score; public $score = 0.00;
/** /**
* 模式类型 * 模式类型
* *
* @var int * @var int
*/ */
public $model; public $model = 0;
/** /**
* 难度级别 * 难度级别
* *
* @var int * @var int
*/ */
public $level; public $level = 0;
/** /**
* 扩展属性 * 扩展属性
* *
* @var string|array * @var string|array
*/ */
public $attrs; public $attrs = '';
/** /**
* 推荐标识 * 推荐标识
* *
* @var int * @var int
*/ */
public $featured; public $featured = 0;
/** /**
* 发布标识 * 发布标识
* *
* @var int * @var int
*/ */
public $published; public $published = 0;
/** /**
* 删除标识 * 删除标识
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 资源数 * 资源数
* *
* @var int * @var int
*/ */
public $resource_count; public $resource_count = 0;
/** /**
* 学员数 * 学员数
* *
* @var int * @var int
*/ */
public $user_count; public $user_count = 0;
/** /**
* 课时数 * 课时数
* *
* @var int * @var int
*/ */
public $lesson_count; public $lesson_count = 0;
/** /**
* 套餐数 * 套餐数
* *
* @var int * @var int
*/ */
public $package_count; public $package_count = 0;
/** /**
* 咨询数 * 咨询数
* *
* @var int * @var int
*/ */
public $consult_count; public $consult_count = 0;
/** /**
* 评价数 * 评价数
* *
* @var int * @var int
*/ */
public $review_count; public $review_count = 0;
/** /**
* 收藏数 * 收藏数
* *
* @var int * @var int
*/ */
public $favorite_count; public $favorite_count = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -278,18 +278,18 @@ class Course extends Model
public function beforeCreate() public function beforeCreate()
{ {
$attrs = []; if (empty($this->attrs)) {
if ($this->model == self::MODEL_VOD) {
$this->attrs = $this->_vod_attrs;
} elseif ($this->model == self::MODEL_LIVE) {
$this->attrs = $this->_live_attrs;
} elseif ($this->model == self::MODEL_READ) {
$this->attrs = $this->_read_attrs;
}
}
switch ($this->model) { if (is_array($this->attrs) && !empty($this->attrs)) {
case Course::MODEL_VOD: $this->attrs = kg_json_encode($this->attrs);
$attrs = $this->_vod_attrs;
break;
case Course::MODEL_LIVE:
$attrs = $this->_live_attrs;
break;
case Course::MODEL_READ:
$attrs = $this->_read_attrs;
break;
} }
if (empty($this->cover)) { if (empty($this->cover)) {
@ -298,17 +298,6 @@ class Course extends Model
$this->cover = self::getCoverPath($this->cover); $this->cover = self::getCoverPath($this->cover);
} }
/**
* text类型不会自动填充默认值
*/
if (is_null($this->details)) {
$this->details = '';
}
if (!empty($attrs)) {
$this->attrs = kg_json_encode($attrs);
}
$this->create_time = time(); $this->create_time = time();
} }
@ -427,4 +416,4 @@ class Course extends Model
]; ];
} }
} }

View File

@ -10,28 +10,28 @@ class CourseCategory extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 课程编号 * 课程编号
* *
* @var int * @var int
*/ */
public $course_id; public $course_id = 0;
/** /**
* 分类编号 * 分类编号
* *
* @var int * @var int
*/ */
public $category_id; public $category_id = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -43,4 +43,4 @@ class CourseCategory extends Model
$this->create_time = time(); $this->create_time = time();
} }
} }

View File

@ -12,42 +12,42 @@ class CourseFavorite extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 课程编号 * 课程编号
* *
* @var int * @var int
*/ */
public $course_id; public $course_id = 0;
/** /**
* 用户编号 * 用户编号
* *
* @var int * @var int
*/ */
public $user_id; public $user_id = 0;
/** /**
* 删除标识 * 删除标识
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -76,4 +76,4 @@ class CourseFavorite extends Model
$this->update_time = time(); $this->update_time = time();
} }
} }

View File

@ -10,28 +10,28 @@ class CoursePackage extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 课程编号 * 课程编号
* *
* @var int * @var int
*/ */
public $course_id; public $course_id = 0;
/** /**
* 套餐编号 * 套餐编号
* *
* @var int * @var int
*/ */
public $package_id; public $package_id = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -43,4 +43,4 @@ class CoursePackage extends Model
$this->create_time = time(); $this->create_time = time();
} }
} }

View File

@ -10,49 +10,49 @@ class CourseRating extends Model
* *
* @var int * @var int
*/ */
public $course_id; public $course_id = 0;
/** /**
* 综合评分 * 综合评分
* *
* @var float * @var float
*/ */
public $rating; public $rating = 0.00;
/** /**
* 维度1评分 * 维度1评分
* *
* @var float * @var float
*/ */
public $rating1; public $rating1 = 0.00;
/** /**
* 维度2评分 * 维度2评分
* *
* @var float * @var float
*/ */
public $rating2; public $rating2 = 0.00;
/** /**
* 维度3评分 * 维度3评分
* *
* @var float * @var float
*/ */
public $rating3; public $rating3 = 0.00;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -69,4 +69,4 @@ class CourseRating extends Model
$this->update_time = time(); $this->update_time = time();
} }
} }

View File

@ -10,28 +10,28 @@ class CourseRelated extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 课程编号 * 课程编号
* *
* @var int * @var int
*/ */
public $course_id; public $course_id = 0;
/** /**
* 相关编号 * 相关编号
* *
* @var int * @var int
*/ */
public $related_id; public $related_id = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -43,4 +43,4 @@ class CourseRelated extends Model
$this->create_time = time(); $this->create_time = time();
} }
} }

View File

@ -10,28 +10,28 @@ class CourseTopic extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 课程编号 * 课程编号
* *
* @var int * @var int
*/ */
public $course_id; public $course_id = 0;
/** /**
* 话题编号 * 话题编号
* *
* @var int * @var int
*/ */
public $topic_id; public $topic_id = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -43,4 +43,4 @@ class CourseTopic extends Model
$this->create_time = time(); $this->create_time = time();
} }
} }

View File

@ -20,97 +20,99 @@ class CourseUser extends Model
const SOURCE_CHARGE = 2; // 付费 const SOURCE_CHARGE = 2; // 付费
const SOURCE_VIP = 3; // 会员 const SOURCE_VIP = 3; // 会员
const SOURCE_IMPORT = 4; // 导入 const SOURCE_IMPORT = 4; // 导入
const SOURCE_POINT_REDEEM = 5; // 积分兑换
const SOURCE_LUCKY_REDEEM = 6; // 抽奖兑换
/** /**
* 主键编号 * 主键编号
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 课程编号 * 课程编号
* *
* @var int * @var int
*/ */
public $course_id; public $course_id = 0;
/** /**
* 用户编号 * 用户编号
* *
* @var int * @var int
*/ */
public $user_id; public $user_id = 0;
/** /**
* 计划编号 * 计划编号
* *
* @var int * @var int
*/ */
public $plan_id; public $plan_id = 0;
/** /**
* 角色类型 * 角色类型
* *
* @var int * @var int
*/ */
public $role_type; public $role_type = 0;
/** /**
* 来源类型 * 来源类型
* *
* @var int * @var int
*/ */
public $source_type; public $source_type = 0;
/** /**
* 过期时间 * 过期时间
* *
* @var int * @var int
*/ */
public $expiry_time; public $expiry_time = 0;
/** /**
* 学习时长 * 学习时长(秒)
* *
* @var int * @var int
*/ */
public $duration; public $duration = 0;
/** /**
* 学习进度 * 学习进度
* *
* @var int * @var int
*/ */
public $progress; public $progress = 0;
/** /**
* 评价标识 * 评价标识
* *
* @var int * @var int
*/ */
public $reviewed; public $reviewed = 0;
/** /**
* 删除标识 * 删除标识
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -156,7 +158,9 @@ class CourseUser extends Model
self::SOURCE_CHARGE => '付费', self::SOURCE_CHARGE => '付费',
self::SOURCE_VIP => '会员', self::SOURCE_VIP => '会员',
self::SOURCE_IMPORT => '导入', self::SOURCE_IMPORT => '导入',
self::SOURCE_POINT_REDEEM => '积分兑换',
self::SOURCE_LUCKY_REDEEM => '抽奖兑换',
]; ];
} }
} }

View File

@ -34,91 +34,91 @@ class Danmu extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 课程编号 * 课程编号
* *
* @var int * @var int
*/ */
public $course_id; public $course_id = 0;
/** /**
* 章节编号 * 章节编号
* *
* @var int * @var int
*/ */
public $chapter_id; public $chapter_id = 0;
/** /**
* 用户编号 * 用户编号
* *
* @var int * @var int
*/ */
public $owner_id; public $owner_id = 0;
/** /**
* 内容 * 内容
* *
* @var string * @var string
*/ */
public $text; public $text = '';
/** /**
* 颜色 * 颜色
* *
* @var string * @var string
*/ */
public $color; public $color = 'white';
/** /**
* 字号 * 字号
* *
* @var int * @var int
*/ */
public $size; public $size = 0;
/** /**
* 位置 * 位置
* *
* @var int * @var int
*/ */
public $position; public $position = 0;
/** /**
* 时间轴 * 时间轴
* *
* @var int * @var int
*/ */
public $time; public $time = 0;
/** /**
* 发布标识 * 发布标识
* *
* @var int * @var int
*/ */
public $published; public $published = 1;
/** /**
* 删除标识 * 删除标识
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -199,4 +199,4 @@ class Danmu extends Model
return $keys[$index]; return $keys[$index];
} }
} }

View File

@ -13,63 +13,63 @@ class Help extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 分类编号 * 分类编号
* *
* @var int * @var int
*/ */
public $category_id; public $category_id = 0;
/** /**
* 标题 * 标题
* *
* @var string * @var string
*/ */
public $title; public $title = '';
/** /**
* 内容 * 内容
* *
* @var string * @var string
*/ */
public $content; public $content = '';
/** /**
* 优先级 * 优先级
* *
* @var int * @var int
*/ */
public $priority; public $priority = 0;
/** /**
* 发布标识 * 发布标识
* *
* @var int * @var int
*/ */
public $published; public $published = 0;
/** /**
* 删除标识 * 删除标识
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -90,13 +90,6 @@ class Help extends Model
public function beforeCreate() public function beforeCreate()
{ {
/**
* text类型不会自动填充默认值
*/
if (is_null($this->content)) {
$this->content = '';
}
$this->create_time = time(); $this->create_time = time();
} }
@ -116,4 +109,4 @@ class Help extends Model
$cache->rebuild(); $cache->rebuild();
} }
} }

View File

@ -12,49 +12,49 @@ class ImFriendGroup extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 名称 * 名称
* *
* @var string * @var string
*/ */
public $name; public $name = '';
/** /**
* 优先级 * 优先级
* *
* @var int * @var int
*/ */
public $priority; public $priority = 0;
/** /**
* 状态 * 状态
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 成员数 * 成员数
* *
* @var int * @var int
*/ */
public $user_count; public $user_count = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -83,5 +83,4 @@ class ImFriendGroup extends Model
$this->update_time = time(); $this->update_time = time();
} }
} }

View File

@ -10,49 +10,49 @@ class ImFriendUser extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 用户编号 * 用户编号
* *
* @var int * @var int
*/ */
public $user_id; public $user_id = 0;
/** /**
* 好友编号 * 好友编号
* *
* @var int * @var int
*/ */
public $friend_id; public $friend_id = 0;
/** /**
* 分组编号 * 分组编号
* *
* @var int * @var int
*/ */
public $group_id; public $group_id = 0;
/** /**
* 消息数量 * 消息数量
* *
* @var int * @var int
*/ */
public $msg_count; public $msg_count = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -69,4 +69,4 @@ class ImFriendUser extends Model
$this->update_time = time(); $this->update_time = time();
} }
} }

View File

@ -22,91 +22,91 @@ class ImGroup extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 群主编号 * 群主编号
* *
* @var int * @var int
*/ */
public $owner_id; public $owner_id = 0;
/** /**
* 课程编号 * 课程编号
* *
* @var int * @var int
*/ */
public $course_id; public $course_id = 0;
/** /**
* 群组类型 * 群组类型
* *
* @var int * @var int
*/ */
public $type; public $type = 0;
/** /**
* 名称 * 名称
* *
* @var string * @var string
*/ */
public $name; public $name = '';
/** /**
* 图标 * 图标
* *
* @var string * @var string
*/ */
public $avatar; public $avatar = '';
/** /**
* 简介 * 简介
* *
* @var string * @var string
*/ */
public $about; public $about = '';
/** /**
* 发布状态 * 发布状态
* *
* @var int * @var int
*/ */
public $published; public $published = 0;
/** /**
* 删除状态 * 删除状态
* *
* @var int * @var int
*/ */
public $deleted; public $deleted = 0;
/** /**
* 成员数 * 成员数
* *
* @var int * @var int
*/ */
public $user_count; public $user_count = 0;
/** /**
* 消息数 * 消息数
* *
* @var int * @var int
*/ */
public $msg_count; public $msg_count = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -186,5 +186,4 @@ class ImGroup extends Model
]; ];
} }
} }

View File

@ -10,42 +10,42 @@ class ImGroupUser extends Model
* *
* @var int * @var int
*/ */
public $id; public $id = 0;
/** /**
* 群组编号 * 群组编号
* *
* @var int * @var int
*/ */
public $group_id; public $group_id = 0;
/** /**
* 用户编号 * 用户编号
* *
* @var int * @var int
*/ */
public $user_id; public $user_id = 0;
/** /**
* 优先级 * 优先级
* *
* @var int * @var int
*/ */
public $priority; public $priority = 0;
/** /**
* 创建时间 * 创建时间
* *
* @var int * @var int
*/ */
public $create_time; public $create_time = 0;
/** /**
* 更新时间 * 更新时间
* *
* @var int * @var int
*/ */
public $update_time; public $update_time = 0;
public function getSource(): string public function getSource(): string
{ {
@ -62,5 +62,4 @@ class ImGroupUser extends Model
$this->update_time = time(); $this->update_time = time();
} }
} }

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