1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-08-10 00:11:38 +08:00

Merge branch 'koogua/v1.5.9'

This commit is contained in:
koogua 2022-09-20 17:58:22 +08:00
commit 1c42df299e
168 changed files with 845 additions and 1010 deletions

1
.gitignore vendored
View File

@ -5,7 +5,6 @@
/config/xs.course.ini
/config/xs.article.ini
/config/xs.question.ini
/config/xs.user.ini
/config/alipay/*.crt
/config/wxpay/*.pem
/db/migrations/schema.php

View File

@ -1,3 +1,18 @@
### [v1.5.9](https://gitee.com/koogua/course-tencent-cloud/releases/v1.5.9)(2022-09-20)
- 修正内容图片上传问题
- 去除user全文索引
- 调整notice目录结构
- 更新默认图片
- 更新直播名格式化
- 更新微博分享链接
- 文章单页等增加SEO关键字
- 专题增加封面上传
- 优化router扫描规则
- 升级layui至v2.7.6
- 增加用户协议和隐私政策
- 优化错误日志
### [v1.5.8](https://gitee.com/koogua/course-tencent-cloud/releases/v1.5.8)(2022-08-28)
- 整理migrations

View File

@ -6,10 +6,10 @@
酷瓜云课堂依托腾讯云基础服务架构采用C扩展框架Phalcon开发GPL-2.0开源协议,致力开源网课系统,开源网校系统,开源知识付费系统,开源在线教育系统。
![star](https://koogua.com/gitee/badge?user=koogua&project=course-tencent-cloud&type=star)
![fork](https://koogua.com/gitee/badge?user=koogua&project=course-tencent-cloud&type=fork)
![license](https://koogua.com/gitee/badge?user=koogua&project=course-tencent-cloud&type=license)
![release](https://koogua.com/gitee/badge?user=koogua&project=course-tencent-cloud&type=release)
![star](https://www.koogua.com/gitee/badge?user=koogua&project=course-tencent-cloud&type=star)
![fork](https://www.koogua.com/gitee/badge?user=koogua&project=course-tencent-cloud&type=fork)
![license](https://www.koogua.com/gitee/badge?user=koogua&project=course-tencent-cloud&type=license)
![release](https://www.koogua.com/gitee/badge?user=koogua&project=course-tencent-cloud&type=release)
### 系统功能
@ -62,19 +62,19 @@ Tips: 请用手机注册一个新账号,用户中心 -> 关注订阅,扫码
### 项目组件
- 后台框架:[phalcon 3.4.5](https://phalcon.io)
- 前端框架:[layui 2.6.8](https://layui.com) [layim 3.9.8](https://www.layui.com/layim)(已授权)
- 前端框架:[layui 2.7.6](https://layui.com)
- 全文检索:[xunsearch 1.4.9](http://www.xunsearch.com)
- 即时通讯:[workerman 3.5.22](https://workerman.net)
- 基础依赖:[php7.3](https://php.net) [mysql5.7](https://mysql.com) [redis5.0](https://redis.io)
### 项目文档
- [运行环境搭建](https://koogua.com/page/wiki)
- [系统服务配置](https://koogua.com/page/wiki)
- [客户终端配置](https://koogua.com/page/wiki)
- [运行环境搭建](https://www.koogua.com/page/wiki)
- [系统服务配置](https://www.koogua.com/page/wiki)
- [客户终端配置](https://www.koogua.com/page/wiki)
### 意见反馈
- [码云平台](https://gitee.com/koogua/course-tencent-cloud/issues)
- [官方社区](https://koogua.com/community)
- [官方社区](https://www.koogua.com/community)
- QQ交流群: 787363898

View File

@ -104,14 +104,8 @@ class CleanDemoDataTask extends Task
$courseIndexTask = new CourseIndexTask();
$courseIndexTask->cleanAction();
$groupIndexTask = new GroupIndexTask();
$groupIndexTask->cleanAction();
$questionIndexTask = new QuestionIndexTask();
$questionIndexTask->cleanAction();
$userIndexTask = new UserIndexTask();
$userIndexTask->cleanAction();
}
protected function isDemoEnv()

View File

@ -19,7 +19,7 @@ use App\Repos\Vip as VipRepo;
use App\Services\Logic\Deliver\CourseDeliver as CourseDeliverService;
use App\Services\Logic\Deliver\PackageDeliver as PackageDeliverService;
use App\Services\Logic\Deliver\VipDeliver as VipDeliverService;
use App\Services\Logic\Notice\OrderFinish as OrderFinishNotice;
use App\Services\Logic\Notice\External\OrderFinish as OrderFinishNotice;
use App\Services\Logic\Point\History\OrderConsume as OrderConsumePointHistory;
use Phalcon\Mvc\Model;
use Phalcon\Mvc\Model\Resultset;

View File

@ -8,16 +8,15 @@
namespace App\Console\Tasks;
use App\Models\Task as TaskModel;
use App\Services\Logic\Notice\AccountLogin as AccountLoginNotice;
use App\Services\Logic\Notice\ConsultReply as ConsultReplyNotice;
use App\Services\Logic\Notice\DingTalk\ConsultCreate as ConsultCreateNotice;
use App\Services\Logic\Notice\DingTalk\CustomService as CustomServiceNotice;
use App\Services\Logic\Notice\DingTalk\ServerMonitor as ServerMonitorNotice;
use App\Services\Logic\Notice\DingTalk\TeacherLive as TeacherLiveNotice;
use App\Services\Logic\Notice\LiveBegin as LiveBeginNotice;
use App\Services\Logic\Notice\OrderFinish as OrderFinishNotice;
use App\Services\Logic\Notice\PointGoodsDeliver as PointGoodsDeliverNotice;
use App\Services\Logic\Notice\RefundFinish as RefundFinishNotice;
use App\Services\Logic\Notice\External\AccountLogin as AccountLoginNotice;
use App\Services\Logic\Notice\External\ConsultReply as ConsultReplyNotice;
use App\Services\Logic\Notice\External\DingTalk\ConsultCreate as ConsultCreateNotice;
use App\Services\Logic\Notice\External\DingTalk\ServerMonitor as ServerMonitorNotice;
use App\Services\Logic\Notice\External\DingTalk\TeacherLive as TeacherLiveNotice;
use App\Services\Logic\Notice\External\LiveBegin as LiveBeginNotice;
use App\Services\Logic\Notice\External\OrderFinish as OrderFinishNotice;
use App\Services\Logic\Notice\External\PointGoodsDeliver as PointGoodsDeliverNotice;
use App\Services\Logic\Notice\External\RefundFinish as RefundFinishNotice;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;
@ -62,9 +61,6 @@ class NoticeTask extends Task
case TaskModel::TYPE_STAFF_NOTICE_SERVER_MONITOR:
$this->handleServerMonitorNotice($task);
break;
case TaskModel::TYPE_STAFF_NOTICE_CUSTOM_SERVICE:
$this->handleCustomServiceNotice($task);
break;
}
$task->status = TaskModel::STATUS_FINISHED;
@ -157,13 +153,6 @@ class NoticeTask extends Task
$notice->handleTask($task);
}
protected function handleCustomServiceNotice(TaskModel $task)
{
$notice = new CustomServiceNotice();
$notice->handleTask($task);
}
/**
* @param int $limit
* @return ResultsetInterface|Resultset|TaskModel[]
@ -181,7 +170,6 @@ class NoticeTask extends Task
TaskModel::TYPE_STAFF_NOTICE_CONSULT_CREATE,
TaskModel::TYPE_STAFF_NOTICE_TEACHER_LIVE,
TaskModel::TYPE_STAFF_NOTICE_SERVER_MONITOR,
TaskModel::TYPE_STAFF_NOTICE_CUSTOM_SERVICE,
];
$status = TaskModel::STATUS_PENDING;

View File

@ -17,7 +17,7 @@ use App\Repos\User as UserRepo;
use App\Repos\Vip as VipRepo;
use App\Services\Logic\Deliver\CourseDeliver as CourseDeliverService;
use App\Services\Logic\Deliver\VipDeliver as VipDeliverService;
use App\Services\Logic\Notice\DingTalk\PointGiftRedeem as PointGiftRedeemNotice;
use App\Services\Logic\Notice\External\DingTalk\PointGiftRedeem as PointGiftRedeemNotice;
use App\Services\Logic\Point\History\PointGiftRefund as PointGiftRefundPointHistory;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;

View File

@ -16,7 +16,7 @@ use App\Repos\Order as OrderRepo;
use App\Repos\Refund as RefundRepo;
use App\Repos\Trade as TradeRepo;
use App\Repos\User as UserRepo;
use App\Services\Logic\Notice\RefundFinish as RefundFinishNotice;
use App\Services\Logic\Notice\External\RefundFinish as RefundFinishNotice;
use App\Services\Pay\Alipay as AlipayService;
use App\Services\Pay\Wxpay as WxpayService;
use Phalcon\Mvc\Model\Resultset;

View File

@ -9,7 +9,7 @@ namespace App\Console\Tasks;
use App\Library\Benchmark;
use App\Models\User as UserModel;
use App\Services\Logic\Notice\DingTalk\ServerMonitor as ServerMonitorNotice;
use App\Services\Logic\Notice\External\DingTalk\ServerMonitor as ServerMonitorNotice;
use App\Services\Search\UserSearcher;
use GatewayClient\Gateway;

View File

@ -1,65 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Console\Tasks;
use App\Repos\User as UserRepo;
use App\Services\Search\UserDocument;
use App\Services\Search\UserSearcher;
use App\Services\Sync\UserIndex as UserIndexSync;
class SyncUserIndexTask extends Task
{
public function mainAction()
{
$redis = $this->getRedis();
$key = $this->getSyncKey();
$userIds = $redis->sRandMember($key, 1000);
if (!$userIds) return;
$userRepo = new UserRepo();
$users = $userRepo->findByIds($userIds);
if ($users->count() == 0) return;
$document = new UserDocument();
$handler = new UserSearcher();
$index = $handler->getXS()->getIndex();
$index->openBuffer();
foreach ($users as $user) {
$doc = $document->setDocument($user);
if ($user->deleted == 0) {
$index->update($doc);
} else {
$index->del($user->id);
}
}
$index->closeBuffer();
$redis->sRem($key, ...$userIds);
}
protected function getSyncKey()
{
$sync = new UserIndexSync();
return $sync->getSyncKey();
}
}

View File

@ -9,7 +9,7 @@ namespace App\Console\Tasks;
use App\Models\ChapterLive as ChapterLiveModel;
use App\Repos\ChapterLive as ChapterLiveRepo;
use App\Services\Logic\Notice\DingTalk\TeacherLive as TeacherLiveNotice;
use App\Services\Logic\Notice\External\DingTalk\TeacherLive as TeacherLiveNotice;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;

View File

@ -1,154 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Console\Tasks;
use App\Models\User as UserModel;
use App\Repos\User as UserRepo;
use App\Services\Search\UserDocument;
use App\Services\Search\UserSearcher;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;
class UserIndexTask extends Task
{
/**
* 搜索测试
*
* @command: php console.php user_index search {query}
* @param array $params
* @throws \XSException
*/
public function searchAction($params)
{
$query = $params[0] ?? null;
if (!$query) {
exit('please special a query word' . PHP_EOL);
}
$result = $this->searchUsers($query);
var_export($result);
}
/**
* 清空索引
*
* @command: php console.php user_index clean
*/
public function cleanAction()
{
$this->cleanUserIndex();
}
/**
* 重建索引
*
* @command: php console.php user_index rebuild
*/
public function rebuildAction()
{
$this->rebuildUserIndex();
}
/**
* 清空索引
*/
protected function cleanUserIndex()
{
$handler = new UserSearcher();
$index = $handler->getXS()->getIndex();
echo '------ start clean user index ------' . PHP_EOL;
$index->clean();
echo '------ end clean user index ------' . PHP_EOL;
}
/**
* 重建索引
*/
protected function rebuildUserIndex()
{
$limit = 1000;
$totalCount = $this->countUsers();
if ($totalCount == 0) return;
$page = ceil($totalCount / $limit);
$handler = new UserSearcher();
$documenter = new UserDocument();
$index = $handler->getXS()->getIndex();
echo '------ start rebuild user index ------' . PHP_EOL;
$index->beginRebuild();
for ($i = 0; $i < $page; $i++) {
$offset = $i * $limit;
$users = $this->findUsers($limit, $offset);
if ($users->count() == 0) break;
foreach ($users as $user) {
$document = $documenter->setDocument($user);
$index->add($document);
}
echo "------ fetch users: {$limit},{$offset} ------" . PHP_EOL;
}
$index->endRebuild();
echo '------ end rebuild user index ------' . PHP_EOL;
}
/**
* 搜索课程
*
* @param string $query
* @return array
* @throws \XSException
*/
protected function searchUsers($query)
{
$handler = new UserSearcher();
return $handler->search($query);
}
/**
* @param int $limit
* @param int $offset
* @return ResultsetInterface|Resultset|UserModel[]
*/
protected function findUsers($limit, $offset)
{
return UserModel::query()
->where('deleted = 0')
->limit($limit, $offset)
->execute();
}
protected function countUsers()
{
$userRepo = new UserRepo();
return $userRepo->countUsers();
}
}

View File

@ -55,7 +55,7 @@ class PageController extends Controller
}
/**
* @Get("/{id:[0-9]+}/edit", name="admin.page.edit")
* @Get("/{id}/edit", name="admin.page.edit")
*/
public function editAction($id)
{

View File

@ -13,8 +13,8 @@ use App\Http\Admin\Services\WxpayTest as WxpayTestService;
use App\Services\Captcha as CaptchaService;
use App\Services\DingTalkNotice as DingTalkNoticeService;
use App\Services\Live as LiveService;
use App\Services\Logic\Notice\Mail\Test as MailTestService;
use App\Services\Logic\Notice\Sms\Test as SmsTestService;
use App\Services\Logic\Notice\External\Mail\Test as MailTestService;
use App\Services\Logic\Notice\External\Sms\Test as SmsTestService;
use App\Services\MyStorage as StorageService;
use App\Services\Vod as VodService;
use App\Services\WeChat as WeChatService;

View File

@ -123,8 +123,10 @@ class UploadController extends Controller
$items['user_avatar'] = $service->uploadDefaultUserAvatar();
$items['course_cover'] = $service->uploadDefaultCourseCover();
$items['package_cover'] = $service->uploadDefaultPackageCover();
$items['topic_cover'] = $service->uploadDefaultTopicCover();
$items['gift_cover'] = $service->uploadDefaultGiftCover();
$items['vip_cover'] = $service->uploadDefaultVipCover();
$items['category_icon'] = $service->uploadDefaultCategoryIcon();
foreach ($items as $item) {
if (!$item) return $this->jsonError(['msg' => '上传文件失败']);

View File

@ -21,9 +21,9 @@ use App\Repos\Report as ReportRepo;
use App\Repos\User as UserRepo;
use App\Services\Logic\Answer\AnswerDataTrait;
use App\Services\Logic\Answer\AnswerInfo as AnswerInfoService;
use App\Services\Logic\Notice\System\AnswerApproved as AnswerApprovedNotice;
use App\Services\Logic\Notice\System\AnswerRejected as AnswerRejectedNotice;
use App\Services\Logic\Notice\System\QuestionAnswered as QuestionAnsweredNotice;
use App\Services\Logic\Notice\Internal\AnswerApproved as AnswerApprovedNotice;
use App\Services\Logic\Notice\Internal\AnswerRejected as AnswerRejectedNotice;
use App\Services\Logic\Notice\Internal\QuestionAnswered as QuestionAnsweredNotice;
use App\Services\Logic\Point\History\AnswerPost as AnswerPostPointHistory;
use App\Validators\Answer as AnswerValidator;

View File

@ -24,8 +24,8 @@ use App\Repos\User as UserRepo;
use App\Services\Logic\Article\ArticleDataTrait;
use App\Services\Logic\Article\ArticleInfo as ArticleInfoService;
use App\Services\Logic\Article\XmTagList as XmTagListService;
use App\Services\Logic\Notice\System\ArticleApproved as ArticleApprovedNotice;
use App\Services\Logic\Notice\System\ArticleRejected as ArticleRejectedNotice;
use App\Services\Logic\Notice\Internal\ArticleApproved as ArticleApprovedNotice;
use App\Services\Logic\Notice\Internal\ArticleRejected as ArticleRejectedNotice;
use App\Services\Logic\Point\History\ArticlePost as ArticlePostPointHistory;
use App\Services\Sync\ArticleIndex as ArticleIndexSync;
use App\Validators\Article as ArticleValidator;
@ -169,6 +169,10 @@ class Article extends Service
$data['title'] = $validator->checkTitle($post['title']);
}
if (isset($post['keywords'])) {
$data['keywords'] = $validator->checkKeywords($post['keywords']);
}
if (isset($post['content'])) {
$data['content'] = $validator->checkContent($post['content']);
$data['word_count'] = WordUtil::getWordCount($data['content']);

View File

@ -16,7 +16,7 @@ use App\Repos\Chapter as ChapterRepo;
use App\Repos\Consult as ConsultRepo;
use App\Repos\Course as CourseRepo;
use App\Services\Logic\Consult\ConsultInfo as ConsultInfoService;
use App\Services\Logic\Notice\ConsultReply as ConsultReplyNotice;
use App\Services\Logic\Notice\External\ConsultReply as ConsultReplyNotice;
use App\Validators\Consult as ConsultValidator;
class Consult extends Service

View File

@ -103,6 +103,10 @@ class Help extends Service
$data['content'] = $validator->checkContent($post['content']);
}
if (isset($post['keywords'])) {
$data['keywords'] = $validator->checkKeywords($post['keywords']);
}
if (isset($post['priority'])) {
$data['priority'] = $validator->checkPriority($post['priority']);
}

View File

@ -115,7 +115,7 @@ class Index extends Service
public function getReleases()
{
$url = 'https://koogua.com/api/releases';
$url = 'https://www.koogua.com/api/releases';
$client = new Client();

View File

@ -122,14 +122,14 @@ class Package extends Service
$data = [];
if (isset($post['cover'])) {
$data['cover'] = $validator->checkCover($post['cover']);
}
if (isset($post['title'])) {
$data['title'] = $validator->checkTitle($post['title']);
}
if (isset($post['cover'])) {
$data['cover'] = $validator->checkCover($post['cover']);
}
if (isset($post['summary'])) {
$data['summary'] = $validator->checkSummary($post['summary']);
}

View File

@ -86,6 +86,10 @@ class Page extends Service
$data['content'] = $validator->checkContent($post['content']);
}
if (isset($post['keywords'])) {
$data['keywords'] = $validator->checkKeywords($post['keywords']);
}
if (isset($post['published'])) {
$data['published'] = $validator->checkPublishStatus($post['published']);
}

View File

@ -11,7 +11,7 @@ use App\Library\Paginator\Query as PagerQuery;
use App\Models\PointGift as PointGiftModel;
use App\Models\PointGiftRedeem as PointGiftRedeemModel;
use App\Repos\PointGiftRedeem as PointGiftRedeemRepo;
use App\Services\Logic\Notice\PointGoodsDeliver as PointGoodsDeliverNotice;
use App\Services\Logic\Notice\External\PointGoodsDeliver as PointGoodsDeliverNotice;
use App\Validators\PointGiftRedeem as PointGiftRedeemValidator;
class PointGiftRedeem extends Service

View File

@ -20,8 +20,8 @@ use App\Repos\Category as CategoryRepo;
use App\Repos\Question as QuestionRepo;
use App\Repos\Report as ReportRepo;
use App\Repos\User as UserRepo;
use App\Services\Logic\Notice\System\QuestionApproved as QuestionApprovedNotice;
use App\Services\Logic\Notice\System\QuestionRejected as QuestionRejectedNotice;
use App\Services\Logic\Notice\Internal\QuestionApproved as QuestionApprovedNotice;
use App\Services\Logic\Notice\Internal\QuestionRejected as QuestionRejectedNotice;
use App\Services\Logic\Point\History\QuestionPost as QuestionPostPointHistory;
use App\Services\Logic\Question\QuestionDataTrait;
use App\Services\Logic\Question\QuestionInfo as QuestionInfoService;
@ -167,6 +167,10 @@ class Question extends Service
$data['content'] = $validator->checkContent($post['content']);
}
if (isset($post['keywords'])) {
$data['keywords'] = $validator->checkKeywords($post['keywords']);
}
if (isset($post['anonymous'])) {
$data['anonymous'] = $validator->checkAnonymousStatus($post['anonymous']);
}

View File

@ -112,6 +112,10 @@ class Topic extends Service
$data['title'] = $validator->checkTitle($post['title']);
}
if (isset($post['cover'])) {
$data['cover'] = $validator->checkCover($post['cover']);
}
if (isset($post['summary'])) {
$data['summary'] = $validator->checkSummary($post['summary']);
}

View File

@ -13,6 +13,12 @@
<div id="xm-tag-ids"></div>
</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="keywords" value="{{ article.keywords }}" placeholder="多个关键字用逗号分隔">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">来源类型</label>
<div class="layui-input-block">

View File

@ -23,6 +23,12 @@
<input class="layui-input" type="text" name="title" value="{{ help.title }}" 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="keywords" value="{{ help.keywords }}" placeholder="多个关键字用逗号分隔">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">内容</label>
<div class="layui-input-block">

View File

@ -1,11 +0,0 @@
{%- macro type_info(value) %}
{% if value == 1 %}
课程
{% elseif value == 2 %}
水吧
{% elseif value == 3 %}
职工
{% else %}
未知
{% endif %}
{%- endmacro %}

View File

@ -18,6 +18,12 @@
<input class="layui-input" type="text" name="alias" value="{{ page.alias }}" placeholder="可以通过 /page/{别名} 访问页面">
</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="keywords" value="{{ page.keywords }}" placeholder="多个关键字用逗号分隔">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">内容</label>
<div class="layui-input-block">

View File

@ -11,6 +11,12 @@
<div id="xm-tag-ids"></div>
</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="keywords" value="{{ question.keywords }}" placeholder="多个关键字用逗号分隔">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">匿名</label>
<div class="layui-input-block">

View File

@ -13,6 +13,18 @@
<input type="radio" name="register_with_email" value="0" title="否" {% if local_auth.register_with_email == "0" %}checked="checked"{% endif %}>
</div>
</div>
<div class="layui-form-item" style="margin-bottom:20px;">
<label class="layui-form-label">用户协议</label>
<div class="layui-input-block">
<a class="layui-btn layui-btn-normal" href="{{ url({'for':'admin.page.edit','id':'terms'}) }}">前往设置</a>
</div>
</div>
<div class="layui-form-item" style="margin-bottom:20px;">
<label class="layui-form-label">隐私政策</label>
<div class="layui-input-block">
<a class="layui-btn layui-btn-normal" href="{{ url({'for':'admin.page.edit','id':'privacy'}) }}">前往设置</a>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">

View File

@ -117,6 +117,10 @@
<td>用户头像</td>
<td>public/static/admin/img/default/user_cover.png</td>
</tr>
<tr>
<td>分类图标</td>
<td>public/static/admin/img/default/category_icon.png</td>
</tr>
<tr>
<td>课程封面</td>
<td>public/static/admin/img/default/course_cover.png</td>
@ -125,6 +129,10 @@
<td>套餐封面</td>
<td>public/static/admin/img/default/package_cover.png</td>
</tr>
<tr>
<td>专题封面</td>
<td>public/static/admin/img/default/topic_cover.png</td>
</tr>
<tr>
<td>会员封面</td>
<td>public/static/admin/img/default/vip_cover.png</td>

View File

@ -12,6 +12,16 @@
<input class="layui-input" type="text" name="title" value="{{ topic.title }}" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">封面</label>
<div class="layui-input-inline">
<img id="img-cover" class="kg-cover" src="{{ topic.cover }}">
<input type="hidden" name="cover" value="{{ topic.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">
@ -38,6 +48,7 @@
{% block include_js %}
{{ js_include('lib/xm-select.js') }}
{{ js_include('admin/js/cover.upload.js') }}
{% endblock %}

View File

@ -9,9 +9,7 @@ namespace App\Http\Api\Controllers;
use App\Services\Logic\Search\Article as ArticleSearch;
use App\Services\Logic\Search\Course as CourseSearch;
use App\Services\Logic\Search\Group as GroupSearch;
use App\Services\Logic\Search\Question as QuestionSearch;
use App\Services\Logic\Search\User as UserSearch;
/**
* @RoutePrefix("/api/search")
@ -46,7 +44,7 @@ class SearchController extends Controller
/**
* @param string $type
* @return ArticleSearch|QuestionSearch|CourseSearch|GroupSearch|UserSearch
* @return ArticleSearch|QuestionSearch|CourseSearch
*/
protected function getSearchService($type)
{
@ -57,12 +55,6 @@ class SearchController extends Controller
case 'question':
$service = new QuestionSearch();
break;
case 'group':
$service = new GroupSearch();
break;
case 'user':
$service = new UserSearch();
break;
default:
$service = new CourseSearch();
break;

View File

@ -12,7 +12,7 @@ use App\Models\User as UserModel;
use App\Repos\Connect as ConnectRepo;
use App\Repos\User as UserRepo;
use App\Services\Auth\Api as ApiAuthService;
use App\Services\Logic\Notice\AccountLogin as AccountLoginNoticeService;
use App\Services\Logic\Notice\External\AccountLogin as AccountLoginNoticeService;
use App\Services\OAuth\QQ as QQAuth;
use App\Services\OAuth\WeChat as WeChatAuth;
use App\Services\OAuth\WeiBo as WeiBoAuth;

View File

@ -9,9 +9,7 @@ namespace App\Http\Home\Controllers;
use App\Services\Logic\Search\Article as ArticleSearchService;
use App\Services\Logic\Search\Course as CourseSearchService;
use App\Services\Logic\Search\Group as GroupSearchService;
use App\Services\Logic\Search\Question as QuestionSearchService;
use App\Services\Logic\Search\User as UserSearchService;
/**
* @RoutePrefix("/search")
@ -48,7 +46,7 @@ class SearchController extends Controller
/**
* @param string $type
* @return ArticleSearchService|QuestionSearchService|CourseSearchService|GroupSearchService|UserSearchService
* @return ArticleSearchService|QuestionSearchService|CourseSearchService
*/
protected function getSearchService($type)
{
@ -59,12 +57,6 @@ class SearchController extends Controller
case 'question':
$service = new QuestionSearchService();
break;
case 'group':
$service = new GroupSearchService();
break;
case 'user':
$service = new UserSearchService();
break;
default:
$service = new CourseSearchService();
break;

View File

@ -16,7 +16,7 @@ use App\Repos\WeChatSubscribe as WeChatSubscribeRepo;
use App\Services\Auth\Home as AuthService;
use App\Services\Auth\Home as HomeAuthService;
use App\Services\Logic\Account\Register as RegisterService;
use App\Services\Logic\Notice\AccountLogin as AccountLoginNotice;
use App\Services\Logic\Notice\External\AccountLogin as AccountLoginNotice;
use App\Services\OAuth\QQ as QQAuth;
use App\Services\OAuth\WeiBo as WeiBoAuth;
use App\Services\OAuth\WeiXin as WeiXinAuth;

View File

@ -4,6 +4,8 @@
{% set register_with_phone = local_oauth.register_with_phone == 1 %}
{% set register_with_email = local_oauth.register_with_email == 1 %}
{% set terms_url = url({'for':'home.page.show','id':'terms'}) %}
{% set privacy_url = url({'for':'home.page.show','id':'privacy'}) %}
{% set action_url = url({'for':'home.account.do_register'}) %}
<div class="layui-breadcrumb breadcrumb">
@ -38,6 +40,7 @@
{% block include_js %}
{{ js_include('https://ssl.captcha.qq.com/TCaptcha.js',false) }}
{{ js_include('home/js/account.register.js') }}
{{ js_include('home/js/captcha.verify.phone.js') }}
{{ js_include('home/js/captcha.verify.email.js') }}

View File

@ -17,6 +17,14 @@
<button id="cv-email-emit-btn" class="layui-btn layui-btn-disabled" type="button" disabled="disabled">获取验证码</button>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<div class="agree">
<div class="left"><input id="cv-email-agree" type="checkbox" name="agree" lay-skin="primary"></div>
<div class="right">我已阅读并同意<a href="{{ terms_url }}" target="_blank">《用户协议》</a>和<a href="{{ privacy_url }}" target="_blank">《隐私政策》</a></div>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button id="cv-email-submit-btn" class="layui-btn layui-btn-fluid layui-btn-disabled" disabled="disabled" lay-submit="true" lay-filter="go">注册帐号</button>

View File

@ -17,6 +17,14 @@
<button id="cv-phone-emit-btn" class="layui-btn layui-btn-disabled" type="button" disabled="disabled">获取验证码</button>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<div class="agree">
<div class="left"><input id="cv-phone-agree" type="checkbox" name="agree" lay-skin="primary"></div>
<div class="right">我已阅读并同意<a href="{{ terms_url }}" target="_blank">《用户协议》</a>和<a href="{{ privacy_url }}" target="_blank">《隐私政策》</a></div>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button id="cv-phone-submit-btn" class="layui-btn layui-btn-fluid layui-btn-disabled" disabled="disabled" lay-submit="true" lay-filter="go">注册帐号</button>

View File

@ -2,6 +2,9 @@
{% block content %}
{% set terms_url = url({'for':'home.page.show','id':'terms'}) %}
{% set privacy_url = url({'for':'home.page.show','id':'privacy'}) %}
<div class="layui-breadcrumb breadcrumb">
<a href="/">首页</a>
<a><cite>登录绑定</cite></a>
@ -29,6 +32,7 @@
{% block include_js %}
{{ js_include('https://ssl.captcha.qq.com/TCaptcha.js',false) }}
{{ js_include('home/js/connect.bind.js') }}
{{ js_include('home/js/captcha.verify.js') }}
{% endblock %}

View File

@ -9,6 +9,14 @@
<input class="layui-input" type="password" name="password" autocomplete="off" placeholder="密码" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<div class="agree">
<div class="left"><input id="login-agree" type="checkbox" name="agree" lay-skin="primary"></div>
<div class="right">我已阅读并同意<a href="{{ terms_url }}" target="_blank">《用户协议》</a>和<a href="{{ privacy_url }}" target="_blank">《隐私政策》</a></div>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button id="submit-btn" class="layui-btn layui-btn-fluid" lay-submit="true" lay-filter="go">登录并绑定已有帐号</button>

View File

@ -17,6 +17,14 @@
<button id="cv-emit-btn" class="layui-btn layui-btn-primary layui-btn-disabled" type="button" disabled="disabled">获取验证码</button>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<div class="agree">
<div class="left"><input id="register-agree" type="checkbox" name="agree" lay-skin="primary"></div>
<div class="right">我已阅读并同意<a href="{{ terms_url }}" target="_blank">《用户协议》</a>和<a href="{{ privacy_url }}" target="_blank">《隐私政策》</a></div>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button id="cv-submit-btn" class="layui-btn layui-btn-fluid layui-btn-disabled" disabled="disabled" lay-submit="true" lay-filter="go">注册并绑定帐号</button>

View File

@ -1,9 +0,0 @@
{%- macro type_info(value) %}
{% if value == 1 %}
课程
{% elseif value == 2 %}
水吧
{% elseif value == 3 %}
职工
{% endif %}
{%- endmacro %}

View File

@ -4,7 +4,7 @@
{{ partial('macros/course') }}
{% set types = {'course':'课程','article':'专栏','question':'问答','user':'用户'} %}
{% set types = {'course':'课程','article':'专栏','question':'问答'} %}
{% set type = request.get('type','trim','course') %}
{% set query = request.get('query','striptags','') %}
@ -39,10 +39,6 @@
<div class="layui-tab-item layui-show">
{{ partial('search/question') }}
</div>
{% elseif type == 'user' %}
<div class="layui-tab-item layui-show">
{{ partial('search/user') }}
</div>
{% endif %}
</div>
</div>

View File

@ -1,29 +0,0 @@
{{ partial('macros/user') }}
{% if pager.total_pages > 0 %}
<div class="search-user-list">
{% for item in pager.items %}
{% set user_url = url({'for':'home.user.show','id':item.id}) %}
{% set item.about = item.about|default('这个家伙真懒,什么也没有留下!') %}
<div class="search-user-card">
<div class="avatar">
<a href="{{ user_url }}" target="_blank">
<img src="{{ item.avatar }}!avatar_160" alt="{{ item.name }}">
</a>
</div>
<div class="info">
<div class="name">
<a href="{{ user_url }}" target="_blank">{{ item.name }}</a>
</div>
<div class="about">{{ item.about }}</div>
<div class="meta">
<span>性别:{{ gender_info(item.gender) }}</span>
<span>地区:{{ item.area }}</span>
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
{{ partial('search/empty') }}
{% endif %}

View File

@ -14,9 +14,9 @@ class AppInfo
protected $alias = 'CTC';
protected $link = 'https://koogua.com';
protected $link = 'https://www.koogua.com';
protected $version = '1.5.8';
protected $version = '1.5.9';
public function __get($name)
{

View File

@ -199,16 +199,6 @@ function kg_default_user_avatar_path()
return '/img/default/user_avatar.png';
}
/**
* 获取默认群组头像路径
*
* @return string
*/
function kg_default_group_avatar_path()
{
return '/img/default/group_avatar.png';
}
/**
* 获取默认课程封面路径
*
@ -229,6 +219,16 @@ function kg_default_package_cover_path()
return '/img/default/package_cover.png';
}
/**
* 获取默认专题封面路径
*
* @return string
*/
function kg_default_topic_cover_path()
{
return '/img/default/topic_cover.png';
}
/**
* 获取默认会员封面路径
*
@ -256,17 +256,17 @@ function kg_default_gift_cover_path()
*/
function kg_default_slide_cover_path()
{
return '/img/default/course_cover.png';
return '/img/default/slide_cover.png';
}
/**
* 获取默认图标路径
* 获取默认分类图标路径
*
* @return string
*/
function kg_default_icon_path()
function kg_default_category_icon_path()
{
return '/img/default/user_avatar.png';
return '/img/default/category_icon.png';
}
/**
@ -315,20 +315,6 @@ function kg_cos_user_avatar_url($path, $style = null)
return kg_cos_img_url($path, $style);
}
/**
* 获取群组头像URL
*
* @param string $path
* @param string $style
* @return string
*/
function kg_cos_group_avatar_url($path, $style = null)
{
$path = $path ?: kg_default_group_avatar_path();
return kg_cos_img_url($path, $style);
}
/**
* 获取课程封面URL
*
@ -357,6 +343,20 @@ function kg_cos_package_cover_url($path, $style = null)
return kg_cos_img_url($path, $style);
}
/**
* 获取专题封面URL
*
* @param string $path
* @param string $style
* @return string
*/
function kg_cos_topic_cover_url($path, $style = null)
{
$path = $path ?: kg_default_topic_cover_path();
return kg_cos_img_url($path, $style);
}
/**
* 获取会员封面URL
*
@ -394,19 +394,21 @@ function kg_cos_gift_cover_url($path, $style = null)
*/
function kg_cos_slide_cover_url($path, $style = null)
{
$path = $path ?: kg_default_slide_cover_path();
return kg_cos_img_url($path, $style);
}
/**
* 获取图标URL
* 获取分类图标URL
*
* @param string $path
* @param string $style
* @return string
*/
function kg_cos_icon_url($path, $style = null)
function kg_cos_category_icon_url($path, $style = null)
{
$path = $path ?: kg_default_icon_path();
$path = $path ?: kg_default_category_icon_path();
return kg_cos_img_url($path, $style);
}
@ -442,13 +444,39 @@ function kg_clean_html($content)
* @param int $length
* @return string
*/
function kg_parse_summary($content, $length = 100)
function kg_parse_summary($content, $length = 150)
{
$content = trim(strip_tags($content));
return kg_substr($content, 0, $length);
}
/**
* 解析关键字
*
* @param string $content
* @return string
*/
function kg_parse_keywords($content)
{
$search = ['|', ';', '', '、', ','];
$keywords = str_replace($search, '@', $content);
$keywords = explode('@', $keywords);
$list = [];
foreach ($keywords as $keyword) {
$keyword = trim($keyword);
if (kg_strlen($keyword) > 1) {
$list[] = $keyword;
}
}
return implode('', $list);
}
/**
* 解析内容中上传首图
*

View File

@ -8,7 +8,7 @@
namespace App\Listeners;
use App\Models\User as UserModel;
use App\Services\Logic\Notice\AccountLogin as AccountLoginNoticeService;
use App\Services\Logic\Notice\External\AccountLogin as AccountLoginNoticeService;
use App\Services\Logic\Point\History\AccountRegister as AccountRegisterPointHistory;
use Phalcon\Events\Event as PhEvent;

View File

@ -64,6 +64,13 @@ class Article extends Model
*/
public $content = '';
/**
* 关键字
*
* @var string
*/
public $keywords = '';
/**
* 标签
*

View File

@ -150,7 +150,7 @@ class Category extends Model
public function beforeSave()
{
if (empty($this->icon)) {
$this->icon = kg_default_icon_path();
$this->icon = kg_default_category_icon_path();
} elseif (Text::startsWith($this->icon, 'http')) {
$this->icon = self::getIconPath($this->icon);
}
@ -166,7 +166,7 @@ class Category extends Model
public function afterFetch()
{
if (!Text::startsWith($this->icon, 'http')) {
$this->icon = kg_cos_icon_url($this->icon);
$this->icon = kg_cos_category_icon_url($this->icon);
}
}

View File

@ -99,12 +99,12 @@ class ChapterLive extends Model
public static function generateStreamName($id)
{
return "chapter_{$id}";
return sprintf('chapter-%03d', $id);
}
public static function parseFromStreamName($streamName)
{
return str_replace('chapter_', '', $streamName);
return (int)str_replace('chapter-', '', $streamName);
}
}

View File

@ -34,6 +34,13 @@ class Help extends Model
*/
public $title = '';
/**
* 关键字
*
* @var string
*/
public $keywords = '';
/**
* 内容
*

View File

@ -95,15 +95,6 @@ class Notification extends Model
const TYPE_ANSWER_COMMENTED = 227;
const TYPE_ANSWER_LIKED = 228;
/* -------------- 微聊相关 -------------- */
const TYPE_FRIEND_REQUEST = 0; // 好友请求
const TYPE_FRIEND_ACCEPTED = 0; // 好友被接受
const TYPE_FRIEND_REFUSED = 0; // 好友被拒绝
const TYPE_GROUP_REQUEST = 0; // 入群请求
const TYPE_GROUP_ACCEPTED = 0; // 入群被接受
const TYPE_GROUP_REFUSED = 0; // 入群被拒绝
/* -------------- 评论相关 -------------- */
const TYPE_COMMENT_CREATED = 500;

View File

@ -34,6 +34,13 @@ class Page extends Model
*/
public $alias = '';
/**
* 关键字
*
* @var string
*/
public $keywords = '';
/**
* 内容
*

View File

@ -85,6 +85,13 @@ class Question extends Model
*/
public $tags = [];
/**
* 关键字
*
* @var string
*/
public $keywords = '';
/**
* 概要
*

View File

@ -149,7 +149,7 @@ class Tag extends Model
public function beforeSave()
{
if (empty($this->icon)) {
$this->icon = kg_default_icon_path();
$this->icon = kg_default_category_icon_path();
} elseif (Text::startsWith($this->icon, 'http')) {
$this->icon = self::getIconPath($this->icon);
}
@ -169,7 +169,7 @@ class Tag extends Model
public function afterFetch()
{
if (!Text::startsWith($this->icon, 'http')) {
$this->icon = kg_cos_icon_url($this->icon);
$this->icon = kg_cos_category_icon_url($this->icon);
}
if (is_string($this->scopes) && $this->scopes != 'all') {

View File

@ -35,7 +35,7 @@ class Task extends Model
const TYPE_STAFF_NOTICE_CONSULT_CREATE = 31; // 咨询创建通知
const TYPE_STAFF_NOTICE_TEACHER_LIVE = 32; // 直播讲师通知
const TYPE_STAFF_NOTICE_SERVER_MONITOR = 33; // 服务监控通知
const TYPE_STAFF_NOTICE_CUSTOM_SERVICE = 34; // 客服消息通知
const TYPE_STAFF_NOTICE_CUSTOM_SERVICE = 34; // 客服消息通知(废弃)
const TYPE_STAFF_NOTICE_POINT_GIFT_REDEEM = 35; // 积分兑换通知
const TYPE_STAFF_NOTICE_LUCKY_GIFT_REDEEM = 36; // 抽奖兑换通知

View File

@ -9,6 +9,7 @@ namespace App\Models;
use App\Caches\MaxTopicId as MaxTopicIdCache;
use Phalcon\Mvc\Model\Behavior\SoftDelete;
use Phalcon\Text;
class Topic extends Model
{
@ -27,6 +28,13 @@ class Topic extends Model
*/
public $title = '';
/**
* 封面
*
* @var string
*/
public $cover = '';
/**
* 简介
*
@ -96,6 +104,15 @@ class Topic extends Model
$this->update_time = time();
}
public function beforeSave()
{
if (empty($this->cover)) {
$this->cover = kg_default_topic_cover_path();
} elseif (Text::startsWith($this->cover, 'http')) {
$this->cover = self::getCoverPath($this->cover);
}
}
public function afterCreate()
{
$cache = new MaxTopicIdCache();
@ -103,4 +120,20 @@ class Topic extends Model
$cache->rebuild();
}
public function afterFetch()
{
if (!Text::startsWith($this->cover, 'http')) {
$this->cover = kg_cos_topic_cover_url($this->cover);
}
}
public static function getCoverPath($url)
{
if (Text::startsWith($url, 'http')) {
return parse_url($url, PHP_URL_PATH);
}
return $url;
}
}

View File

@ -9,7 +9,6 @@ namespace App\Models;
use App\Caches\MaxUserId as MaxUserIdCache;
use App\Caches\User as UserCache;
use App\Services\Sync\UserIndex as UserIndexSync;
use Phalcon\Mvc\Model\Behavior\SoftDelete;
use Phalcon\Text;
@ -216,11 +215,6 @@ class User extends Model
public function beforeUpdate()
{
if (time() - $this->update_time > 3 * 3600) {
$sync = new UserIndexSync();
$sync->addItem($this->id);
}
$this->update_time = time();
}

View File

@ -12,7 +12,7 @@ use App\Models\Chapter as ChapterModel;
use App\Models\ChapterLive as ChapterLiveModel;
use App\Repos\Chapter as ChapterRepo;
use App\Repos\CourseUser as CourseUserRepo;
use App\Services\Logic\Notice\LiveBegin as LiveBeginNotice;
use App\Services\Logic\Notice\External\LiveBegin as LiveBeginNotice;
use Phalcon\Logger\Adapter\File as FileLogger;
class LiveNotify extends Service

View File

@ -10,7 +10,7 @@ namespace App\Services\Logic\Answer;
use App\Models\Answer as AnswerModel;
use App\Models\User as UserModel;
use App\Services\Logic\AnswerTrait;
use App\Services\Logic\Notice\System\AnswerAccepted as AnswerAcceptedNotice;
use App\Services\Logic\Notice\Internal\AnswerAccepted as AnswerAcceptedNotice;
use App\Services\Logic\Point\History\AnswerAccepted as AnswerAcceptPointHistory;
use App\Services\Logic\QuestionTrait;
use App\Services\Logic\Service as LogicService;

View File

@ -13,7 +13,7 @@ use App\Models\User as UserModel;
use App\Repos\Question as QuestionRepo;
use App\Repos\User as UserRepo;
use App\Services\Logic\AnswerTrait;
use App\Services\Logic\Notice\System\QuestionAnswered as QuestionAnsweredNotice;
use App\Services\Logic\Notice\Internal\QuestionAnswered as QuestionAnsweredNotice;
use App\Services\Logic\Point\History\AnswerPost as AnswerPostPointHistory;
use App\Services\Logic\QuestionTrait;
use App\Services\Logic\Service as LogicService;

View File

@ -12,7 +12,7 @@ use App\Models\AnswerLike as AnswerLikeModel;
use App\Models\User as UserModel;
use App\Repos\AnswerLike as AnswerLikeRepo;
use App\Services\Logic\AnswerTrait;
use App\Services\Logic\Notice\System\AnswerLiked as AnswerLikedNotice;
use App\Services\Logic\Notice\Internal\AnswerLiked as AnswerLikedNotice;
use App\Services\Logic\Point\History\AnswerLiked as AnswerLikedPointHistory;
use App\Services\Logic\Service as LogicService;
use App\Validators\UserLimit as UserLimitValidator;

View File

@ -12,7 +12,7 @@ use App\Models\ArticleFavorite as ArticleFavoriteModel;
use App\Models\User as UserModel;
use App\Repos\ArticleFavorite as ArticleFavoriteRepo;
use App\Services\Logic\ArticleTrait;
use App\Services\Logic\Notice\System\ArticleFavorited as ArticleFavoritedNotice;
use App\Services\Logic\Notice\Internal\ArticleFavorited as ArticleFavoritedNotice;
use App\Services\Logic\Service as LogicService;
use App\Validators\UserLimit as UserLimitValidator;

View File

@ -49,6 +49,7 @@ class ArticleInfo extends LogicService
'title' => $article->title,
'cover' => $article->cover,
'summary' => $article->summary,
'keywords' => $article->keywords,
'tags' => $article->tags,
'content' => $article->content,
'private' => $article->private,

View File

@ -12,7 +12,7 @@ use App\Models\ArticleLike as ArticleLikeModel;
use App\Models\User as UserModel;
use App\Repos\ArticleLike as ArticleLikeRepo;
use App\Services\Logic\ArticleTrait;
use App\Services\Logic\Notice\System\ArticleLiked as ArticleLikedNotice;
use App\Services\Logic\Notice\Internal\ArticleLiked as ArticleLikedNotice;
use App\Services\Logic\Point\History\ArticleLiked as ArticleLikedPointHistory;
use App\Services\Logic\Service as LogicService;
use App\Validators\UserLimit as UserLimitValidator;

View File

@ -11,10 +11,10 @@ use App\Models\Answer as AnswerModel;
use App\Models\Article as ArticleModel;
use App\Models\Comment as CommentModel;
use App\Models\Question as QuestionModel;
use App\Services\Logic\Notice\System\AnswerCommented as AnswerCommentedNotice;
use App\Services\Logic\Notice\System\ArticleCommented as ArticleCommentedNotice;
use App\Services\Logic\Notice\System\CommentReplied as CommentRepliedNotice;
use App\Services\Logic\Notice\System\QuestionCommented as QuestionCommentedNotice;
use App\Services\Logic\Notice\Internal\AnswerCommented as AnswerCommentedNotice;
use App\Services\Logic\Notice\Internal\ArticleCommented as ArticleCommentedNotice;
use App\Services\Logic\Notice\Internal\CommentReplied as CommentRepliedNotice;
use App\Services\Logic\Notice\Internal\QuestionCommented as QuestionCommentedNotice;
use App\Services\Logic\Point\History\CommentPost as CommentPostPointHistory;
trait AfterCreateTrait

View File

@ -12,7 +12,7 @@ use App\Models\CommentLike as CommentLikeModel;
use App\Models\User as UserModel;
use App\Repos\CommentLike as CommentLikeRepo;
use App\Services\Logic\CommentTrait;
use App\Services\Logic\Notice\System\CommentLiked as CommentLikedNotice;
use App\Services\Logic\Notice\Internal\CommentLiked as CommentLikedNotice;
use App\Services\Logic\Service as LogicService;
use App\Validators\UserLimit as UserLimitValidator;

View File

@ -15,7 +15,7 @@ use App\Repos\Chapter as ChapterRepo;
use App\Repos\Course as CourseRepo;
use App\Services\Logic\ChapterTrait;
use App\Services\Logic\CourseTrait;
use App\Services\Logic\Notice\DingTalk\ConsultCreate as ConsultCreateNotice;
use App\Services\Logic\Notice\External\DingTalk\ConsultCreate as ConsultCreateNotice;
use App\Services\Logic\Service as LogicService;
use App\Traits\Client as ClientTrait;
use App\Validators\Consult as ConsultValidator;

View File

@ -12,7 +12,7 @@ use App\Models\ConsultLike as ConsultLikeModel;
use App\Models\User as UserModel;
use App\Repos\ConsultLike as ConsultLikeRepo;
use App\Services\Logic\ConsultTrait;
use App\Services\Logic\Notice\System\ConsultLiked as ConsultLikedNotice;
use App\Services\Logic\Notice\Internal\ConsultLiked as ConsultLikedNotice;
use App\Services\Logic\Service as LogicService;
use App\Validators\UserLimit as UserLimitValidator;

View File

@ -9,7 +9,7 @@ namespace App\Services\Logic\Consult;
use App\Models\Consult as ConsultModel;
use App\Services\Logic\ConsultTrait;
use App\Services\Logic\Notice\ConsultReply as ConsultReplyNotice;
use App\Services\Logic\Notice\External\ConsultReply as ConsultReplyNotice;
use App\Services\Logic\Service as LogicService;
use App\Validators\Consult as ConsultValidator;

View File

@ -28,6 +28,7 @@ class HelpInfo extends LogicService
return [
'id' => $help->id,
'title' => $help->title,
'keywords' => $help->keywords,
'content' => $help->content,
'published' => $help->published,
'deleted' => $help->deleted,

View File

@ -1,68 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\DingTalk;
use App\Models\ImMessage as ImMessageModel;
use App\Models\Task as TaskModel;
use App\Repos\ImMessage as ImMessageRepo;
use App\Repos\User as UserRepo;
use App\Services\DingTalkNotice;
class CustomService extends DingTalkNotice
{
public function handleTask(TaskModel $task)
{
if (!$this->enabled) return;
$messageRepo = new ImMessageRepo();
$message = $messageRepo->findById($task->item_id);
$userRepo = new UserRepo();
$sender = $userRepo->findById($message->sender_id);
$content = kg_ph_replace("{user.name} 通过在线客服给你发送了消息:{message.content}", [
'user.name' => $sender->name,
'message.content' => $message->content,
]);
$this->atCustomService($content);
}
public function createTask(ImMessageModel $message)
{
if (!$this->enabled) return;
$keyName = "dingtalk_custom_service_notice:{$message->sender_id}";
$cache = $this->getCache();
$content = $cache->get($keyName);
if ($content) return;
$cache->save($keyName, 1, 3600);
$task = new TaskModel();
$itemInfo = [
'im_message' => ['id' => $message->id],
];
$task->item_id = $message->id;
$task->item_info = $itemInfo;
$task->item_type = TaskModel::TYPE_STAFF_NOTICE_CUSTOM_SERVICE;
$task->priority = TaskModel::PRIORITY_MIDDLE;
$task->status = TaskModel::STATUS_PENDING;
$task->create();
}
}

View File

@ -5,12 +5,12 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice;
namespace App\Services\Logic\Notice\External;
use App\Models\Task as TaskModel;
use App\Models\User as UserModel;
use App\Repos\WeChatSubscribe as WeChatSubscribeRepo;
use App\Services\Logic\Notice\WeChat\AccountLogin as WeChatAccountLoginNotice;
use App\Services\Logic\Notice\External\WeChat\AccountLogin as WeChatAccountLoginNotice;
use App\Services\Logic\Service as LogicService;
use App\Traits\Client as ClientTrait;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice;
namespace App\Services\Logic\Notice\External;
use App\Models\Consult as ConsultModel;
use App\Models\Task as TaskModel;
@ -13,8 +13,8 @@ use App\Repos\Consult as ConsultRepo;
use App\Repos\Course as CourseRepo;
use App\Repos\User as UserRepo;
use App\Repos\WeChatSubscribe as WeChatSubscribeRepo;
use App\Services\Logic\Notice\Sms\ConsultReply as SmsConsultReplyNotice;
use App\Services\Logic\Notice\WeChat\ConsultReply as WeChatConsultReplyNotice;
use App\Services\Logic\Notice\External\Sms\ConsultReply as SmsConsultReplyNotice;
use App\Services\Logic\Notice\External\WeChat\ConsultReply as WeChatConsultReplyNotice;
use App\Services\Logic\Service as LogicService;
class ConsultReply extends LogicService

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\DingTalk;
namespace App\Services\Logic\Notice\External\DingTalk;
use App\Models\Consult as ConsultModel;
use App\Models\Task as TaskModel;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\DingTalk;
namespace App\Services\Logic\Notice\External\DingTalk;
use App\Models\PointGift as PointGiftModel;
use App\Models\PointGiftRedeem as PointGiftRedeemModel;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\DingTalk;
namespace App\Services\Logic\Notice\External\DingTalk;
use App\Models\Task as TaskModel;
use App\Services\DingTalkNotice;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\DingTalk;
namespace App\Services\Logic\Notice\External\DingTalk;
use App\Models\ChapterLive as ChapterLiveModel;
use App\Models\Task as TaskModel;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice;
namespace App\Services\Logic\Notice\External;
use App\Models\Chapter as ChapterModel;
use App\Models\CourseUser as CourseUserModel;
@ -14,8 +14,8 @@ use App\Repos\Chapter as ChapterRepo;
use App\Repos\Course as CourseRepo;
use App\Repos\User as UserRepo;
use App\Repos\WeChatSubscribe as WeChatSubscribeRepo;
use App\Services\Logic\Notice\Sms\LiveBegin as SmsLiveBeginNotice;
use App\Services\Logic\Notice\WeChat\LiveBegin as WeChatLiveBeginNotice;
use App\Services\Logic\Notice\External\Sms\LiveBegin as SmsLiveBeginNotice;
use App\Services\Logic\Notice\External\WeChat\LiveBegin as WeChatLiveBeginNotice;
use App\Services\Logic\Service as LogicService;
class LiveBegin extends LogicService

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\Mail;
namespace App\Services\Logic\Notice\External\Mail;
use App\Services\Mailer;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\Mail;
namespace App\Services\Logic\Notice\External\Mail;
use App\Services\Mailer as MailerService;
use App\Services\Verify as VerifyService;

View File

@ -5,15 +5,15 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice;
namespace App\Services\Logic\Notice\External;
use App\Models\Order as OrderModel;
use App\Models\Task as TaskModel;
use App\Repos\Order as OrderRepo;
use App\Repos\User as UserRepo;
use App\Repos\WeChatSubscribe as WeChatSubscribeRepo;
use App\Services\Logic\Notice\Sms\OrderFinish as SmsOrderFinishNotice;
use App\Services\Logic\Notice\WeChat\OrderFinish as WeChatOrderFinishNotice;
use App\Services\Logic\Notice\External\Sms\OrderFinish as SmsOrderFinishNotice;
use App\Services\Logic\Notice\External\WeChat\OrderFinish as WeChatOrderFinishNotice;
use App\Services\Logic\Service as LogicService;
class OrderFinish extends LogicService

View File

@ -5,15 +5,15 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice;
namespace App\Services\Logic\Notice\External;
use App\Models\PointGiftRedeem as PointGiftRedeemModel;
use App\Models\Task as TaskModel;
use App\Repos\PointGiftRedeem as PointGiftRedeemRepo;
use App\Repos\User as UserRepo;
use App\Repos\WeChatSubscribe as WeChatSubscribeRepo;
use App\Services\Logic\Notice\Sms\GoodsDeliver as SmsGoodsDeliverNotice;
use App\Services\Logic\Notice\WeChat\GoodsDeliver as WeChatGoodsDeliverNotice;
use App\Services\Logic\Notice\External\Sms\GoodsDeliver as SmsGoodsDeliverNotice;
use App\Services\Logic\Notice\External\WeChat\GoodsDeliver as WeChatGoodsDeliverNotice;
use App\Services\Logic\Service as LogicService;
class PointGoodsDeliver extends LogicService

View File

@ -5,15 +5,15 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice;
namespace App\Services\Logic\Notice\External;
use App\Models\Refund as RefundModel;
use App\Models\Task as TaskModel;
use App\Repos\Refund as RefundRepo;
use App\Repos\User as UserRepo;
use App\Repos\WeChatSubscribe as WeChatSubscribeRepo;
use App\Services\Logic\Notice\Sms\RefundFinish as SmsRefundFinishNotice;
use App\Services\Logic\Notice\WeChat\RefundFinish as WeChatRefundFinishNotice;
use App\Services\Logic\Notice\External\Sms\RefundFinish as SmsRefundFinishNotice;
use App\Services\Logic\Notice\External\WeChat\RefundFinish as WeChatRefundFinishNotice;
use App\Services\Logic\Service as LogicService;
class RefundFinish extends LogicService

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\Sms;
namespace App\Services\Logic\Notice\External\Sms;
use App\Models\User as UserModel;
use App\Repos\Account as AccountRepo;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\Sms;
namespace App\Services\Logic\Notice\External\Sms;
use App\Models\User as UserModel;
use App\Repos\Account as AccountRepo;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\Sms;
namespace App\Services\Logic\Notice\External\Sms;
use App\Models\User as UserModel;
use App\Repos\Account as AccountRepo;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\Sms;
namespace App\Services\Logic\Notice\External\Sms;
use App\Models\User as UserModel;
use App\Repos\Account as AccountRepo;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\Sms;
namespace App\Services\Logic\Notice\External\Sms;
use App\Models\User as UserModel;
use App\Repos\Account as AccountRepo;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\Sms;
namespace App\Services\Logic\Notice\External\Sms;
use App\Services\Smser;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\Sms;
namespace App\Services\Logic\Notice\External\Sms;
use App\Services\Smser as SmserService;
use App\Services\Verify as VerifyService;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\WeChat;
namespace App\Services\Logic\Notice\External\WeChat;
use App\Models\WeChatSubscribe as WeChatSubscribeModel;
use App\Services\WeChatNotice;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\WeChat;
namespace App\Services\Logic\Notice\External\WeChat;
use App\Models\WeChatSubscribe as WeChatSubscribeModel;
use App\Services\WeChatNotice;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\WeChat;
namespace App\Services\Logic\Notice\External\WeChat;
use App\Models\WeChatSubscribe as WeChatSubscribeModel;
use App\Services\WeChatNotice;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\WeChat;
namespace App\Services\Logic\Notice\External\WeChat;
use App\Models\WeChatSubscribe as WeChatSubscribeModel;
use App\Services\WeChatNotice;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\WeChat;
namespace App\Services\Logic\Notice\External\WeChat;
use App\Models\WeChatSubscribe as WeChatSubscribeModel;
use App\Services\WeChatNotice;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\WeChat;
namespace App\Services\Logic\Notice\External\WeChat;
use App\Models\WeChatSubscribe as WeChatSubscribeModel;
use App\Services\WeChatNotice;

View File

@ -5,7 +5,7 @@
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Notice\System;
namespace App\Services\Logic\Notice\Internal;
use App\Models\Answer as AnswerModel;
use App\Models\Notification as NotificationModel;

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