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

Merge branch 'develop' into demo

This commit is contained in:
koogua 2021-04-29 17:09:02 +08:00
commit 90cfa61c50
25 changed files with 199 additions and 135 deletions

View File

@ -1,3 +1,16 @@
### [v1.3.3](https://gitee.com/koogua/course-tencent-cloud/releases/v1.3.3)(2021-04-30)
### 更新
- 前台增加文章发布功能
- 增加文章,咨询,评价,评论相关事件站内提醒
- 增加文章,咨询,评价,评论事件埋点
- 后台首页增加若干统计项目
- 后台增加文章审核功能
- 重构积分历史记录
- 优化在线统计方式
- 优化前台界面
### [v1.3.2](https://gitee.com/koogua/course-tencent-cloud/releases/v1.3.2)(2021-04-20)
### 更新

View File

@ -40,7 +40,7 @@ class ArticleRelatedList extends Cache
$where = [
'tag_id' => $tagIds[$randKey],
'published' => 1,
'published' => ArticleModel::PUBLISH_APPROVED,
];
$pager = $articleRepo->paginate($where);

View File

@ -140,36 +140,36 @@ class AuthNode extends Service
],
[
'id' => '1-4',
'title' => '题管理',
'title' => '题管理',
'type' => 'menu',
'children' => [
[
'id' => '1-4-1',
'title' => '题列表',
'title' => '题列表',
'type' => 'menu',
'route' => 'admin.topic.list',
],
[
'id' => '1-4-5',
'title' => '搜索题',
'title' => '搜索题',
'type' => 'menu',
'route' => 'admin.topic.search',
],
[
'id' => '1-4-2',
'title' => '添加题',
'title' => '添加题',
'type' => 'menu',
'route' => 'admin.topic.add',
],
[
'id' => '1-4-3',
'title' => '编辑题',
'title' => '编辑题',
'type' => 'button',
'route' => 'admin.topic.edit',
],
[
'id' => '1-4-4',
'title' => '删除题',
'title' => '删除题',
'type' => 'button',
'route' => 'admin.topic.delete',
],

View File

@ -4,7 +4,7 @@
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.topic.create'}) }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>添加题</legend>
<legend>添加题</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">标题</label>

View File

@ -4,7 +4,7 @@
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.topic.update','id':topic.id}) }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>编辑题</legend>
<legend>编辑题</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">标题</label>

View File

@ -8,15 +8,15 @@
<div class="kg-nav">
<div class="kg-nav-left">
<span class="layui-breadcrumb">
<a><cite>题管理</cite></a>
<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>添加
<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>搜索
<i class="layui-icon layui-icon-search"></i>搜索
</a>
</div>
</div>

View File

@ -4,7 +4,7 @@
<form class="layui-form kg-form" method="GET" action="{{ url({'for':'admin.topic.list'}) }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>搜索题</legend>
<legend>搜索题</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">编号</label>

View File

@ -11,6 +11,7 @@ use App\Services\Logic\User\Console\GroupList as GroupListService;
use App\Services\Logic\User\Console\NotificationList as NotificationListService;
use App\Services\Logic\User\Console\NotificationRead as NotificationReadService;
use App\Services\Logic\User\Console\NotifyStats as NotifyStatsService;
use App\Services\Logic\User\Console\Online as OnlineService;
use App\Services\Logic\User\Console\OrderList as OrderListService;
use App\Services\Logic\User\Console\ProfileInfo as ProfileInfoService;
use App\Services\Logic\User\Console\ProfileUpdate as ProfileUpdateService;
@ -183,4 +184,16 @@ class UserConsoleController extends Controller
return $this->jsonSuccess();
}
/**
* @Post("/online", name="api.uc.online")
*/
public function onlineAction()
{
$service = new OnlineService();
$service->handle();
return $this->jsonSuccess();
}
}

View File

@ -18,6 +18,7 @@ use App\Services\Logic\User\Console\GroupList as GroupListService;
use App\Services\Logic\User\Console\NotificationList as NotificationListService;
use App\Services\Logic\User\Console\NotificationRead as NotificationReadService;
use App\Services\Logic\User\Console\NotifyStats as NotifyStatsService;
use App\Services\Logic\User\Console\Online as OnlineService;
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;
@ -369,4 +370,16 @@ class UserConsoleController extends Controller
return $this->jsonSuccess($content);
}
/**
* @Post("/online", name="home.uc.online")
*/
public function onlineAction()
{
$service = new OnlineService();
$service->handle();
return $this->jsonSuccess();
}
}

View File

@ -2,11 +2,7 @@
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\History\SiteVisit as SiteVisitPointHistory;
use App\Traits\Client as ClientTrait;
use Phalcon\Events\Event as PhEvent;
@ -17,102 +13,7 @@ class Site extends Listener
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 SiteVisitPointHistory();
$service->handle($user);
$tomorrow = strtotime($todayDate) + 86400;
$lifetime = $tomorrow - time();
$cache->save($keyName, 1, $lifetime);
}
}

View File

@ -16,9 +16,10 @@ class Reason
106 => '低俗色情',
107 => '广告软文',
108 => '封面反感',
109 => '抄袭他人作品',
110 => '涉嫌非法集资',
111 => '其它问题',
109 => '归类与主题不符',
110 => '抄袭他人作品',
111 => '内容涉嫌违法',
112 => '其它问题',
];
}

View File

@ -60,6 +60,7 @@ class ArticleInfo extends LogicService
'comment_count' => $article->comment_count,
'favorite_count' => $article->favorite_count,
'create_time' => $article->create_time,
'update_time' => $article->update_time,
];
}

View File

@ -21,6 +21,7 @@ class ArticleList extends LogicService
$params = $this->checkQueryParams($params);
$params['published'] = ArticleModel::PUBLISH_APPROVED;
$params['private'] = 0;
$params['deleted'] = 0;
$sort = $pagerQuery->getSort();

View File

@ -23,9 +23,9 @@ class CommentList extends LogicService
$params = $pagerQuery->getParams();
$params['item_type'] = CommentModel::ITEM_ARTICLE;
$params['item_id'] = $article->id;
$params['published'] = 1;
$params['item_type'] = CommentModel::ITEM_ARTICLE;
$params['published'] = CommentModel::PUBLISH_APPROVED;
$sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage();

View File

@ -23,9 +23,9 @@ class CommentList extends LogicService
$params = $pagerQuery->getParams();
$params['item_type'] = CommentModel::ITEM_CHAPTER;
$params['item_id'] = $chapter->id;
$params['published'] = 1;
$params['item_type'] = CommentModel::ITEM_CHAPTER;
$params['published'] = CommentModel::PUBLISH_APPROVED;
$sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage();

View File

@ -37,6 +37,7 @@ trait CommentListTrait
'like_count' => $comment['like_count'],
'reply_count' => $comment['reply_count'],
'create_time' => $comment['create_time'],
'update_time' => $comment['update_time'],
'to_user' => $toUser,
'owner' => $owner,
'me' => $me,

View File

@ -36,6 +36,7 @@ trait ConsultListTrait
'like_count' => $consult['like_count'],
'reply_time' => $consult['reply_time'],
'create_time' => $consult['create_time'],
'update_time' => $consult['update_time'],
'owner' => $owner,
'me' => $me,
];

View File

@ -63,6 +63,7 @@ class ReviewList extends LogicService
'content' => $review['content'],
'like_count' => $review['like_count'],
'create_time' => $review['create_time'],
'update_time' => $review['update_time'],
'owner' => $owner,
'me' => $me,
];

View File

@ -3,6 +3,7 @@
namespace App\Services\Logic\User;
use App\Library\Paginator\Query as PagerQuery;
use App\Models\Article as ArticleModel;
use App\Repos\Article as ArticleRepo;
use App\Services\Logic\Article\ArticleList as ArticleListService;
use App\Services\Logic\Service as LogicService;
@ -22,7 +23,9 @@ class ArticleList extends LogicService
$params = $pagerQuery->getParams();
$params['owner_id'] = $user->id;
$params['published'] = 1;
$params['published'] = ArticleModel::PUBLISH_APPROVED;
$params['private'] = 0;
$params['deleted'] = 0;
$sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage();

View File

@ -0,0 +1,101 @@
<?php
namespace App\Services\Logic\User\Console;
use App\Models\Online as OnlineModel;
use App\Models\User as UserModel;
use App\Repos\Online as OnlineRepo;
use App\Services\Logic\Point\History\SiteVisit as SiteVisitPointHistory;
use App\Services\Logic\Service as LogicService;
use App\Traits\Client as ClientTrait;
class Online extends LogicService
{
use ClientTrait;
public function handle()
{
$user = $this->getLoginUser();
$this->handleVisitLog($user);
$this->handleVisitPoint($user);
}
protected function handleVisitLog(UserModel $user)
{
$now = time();
if ($now - $user->active_time < 900) return;
$user->active_time = $now;
$user->update();
$onlineRepo = new OnlineRepo();
$records = $onlineRepo->findByUserDate($user->id, date('Ymd'));
$clientType = $this->getClientType();
$clientIp = $this->getClientIp();
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);
}
}
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 SiteVisitPointHistory();
$service->handle($user);
$tomorrow = strtotime($todayDate) + 86400;
$lifetime = $tomorrow - time();
$cache->save($keyName, 1, $lifetime);
}
}

View File

@ -3,6 +3,7 @@
namespace App\Services\Logic\User\Console;
use App\Library\Paginator\Query as PagerQuery;
use App\Models\PointRedeem as PointRedeemModel;
use App\Repos\PointRedeem as PointRedeemRepo;
use App\Services\Logic\Service as LogicService;
use App\Services\Logic\UserTrait;
@ -42,25 +43,31 @@ class PointRedeemList extends LogicService
$items = [];
foreach ($pager->items as $item) {
/**
* @var PointRedeemModel[] $redeems
*/
$redeems = $pager->items;
foreach ($redeems as $redeem) {
$items[] = [
'id' => $item->id,
'status' => $item->status,
'create_time' => $item->create_time,
'id' => $redeem->id,
'status' => $redeem->status,
'create_time' => $redeem->create_time,
'update_time' => $redeem->update_time,
'user' => [
'id' => $item->user_id,
'name' => $item->user_name,
'id' => $redeem->user_id,
'name' => $redeem->user_name,
],
'gift' => [
'id' => $item->gift_id,
'name' => $item->gift_name,
'type' => $item->gift_type,
'point' => $item->gift_point,
'id' => $redeem->gift_id,
'name' => $redeem->gift_name,
'type' => $redeem->gift_type,
'point' => $redeem->gift_point,
],
'contact' => [
'name' => $item->contact_name,
'phone' => $item->contact_phone,
'address' => $item->contact_address,
'name' => $redeem->contact_name,
'phone' => $redeem->contact_phone,
'address' => $redeem->contact_address,
],
];
}

View File

@ -31,10 +31,12 @@ class ProfileInfo extends LogicService
'gender' => $user->gender,
'vip' => $user->vip,
'locked' => $user->locked,
'vip_expiry_time' => $user->vip_expiry_time,
'lock_expiry_time' => $user->lock_expiry_time,
'edu_role' => $user->edu_role,
'admin_role' => $user->admin_role,
'vip_expiry_time' => $user->vip_expiry_time,
'lock_expiry_time' => $user->lock_expiry_time,
'create_time' => $user->create_time,
'update_time' => $user->update_time,
];
}

View File

@ -69,6 +69,7 @@ class RefundList extends LogicService
'apply_note' => $refund['apply_note'],
'review_note' => $refund['review_note'],
'create_time' => $refund['create_time'],
'update_time' => $refund['update_time'],
];
}

View File

@ -41,6 +41,7 @@ class UserInfo extends LogicService
'group_count' => $imUser->group_count,
'active_time' => $user->active_time,
'create_time' => $user->create_time,
'update_time' => $user->update_time,
];
}

View File

@ -58,6 +58,9 @@ layui.use(['jquery', 'form', 'element', 'layer', 'helper'], function () {
}
});
}, 30000);
setInterval(function () {
$.post('/uc/online');
}, 30000);
}
form.on('submit(go)', function (data) {