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

Merge branch 'koogua/v1.3.9' into demo

# Conflicts:
#	app/Library/AppInfo.php
This commit is contained in:
koogua 2021-07-23 15:43:06 +08:00
commit e3e1e3dab7
191 changed files with 11061 additions and 10710 deletions

View File

@ -1,3 +1,24 @@
### [v1.3.9](https://gitee.com/koogua/course-tencent-cloud/releases/v1.3.9)(2021-07-24)
### 更新
- 修正分类下无课程时会查询出所有课程问题
- 修正sitemap中的部分路径问题
- 修正课程套餐相关问题
- 优化问答部分相关逻辑
- 优化评论部分相关逻辑
- 优化浏览器Title显示
- 优化审核和举报相关逻辑
- 优化命令行脚本执行输出
- 优化API的分页返回结构
- 增加文章问答评论相关API
- 增加重新统计tag中相关计数计划任务
- 增加tag的使用范围,文章,问题,课程计数
- 站点logo和favicon使用随机文件名
- 增加评价审核
- 去除编辑器中的酷瓜云课堂标识
- 清理数据迁移文件
### [v1.3.8](https://gitee.com/koogua/course-tencent-cloud/releases/v1.3.8)(2021-07-11)
### 更新

View File

@ -64,9 +64,9 @@ Tips: 请用手机注册一个新账号,用户中心 -> 关注订阅,扫码
### 项目文档
- [运行环境搭建](https://gitee.com/koogua/course-tencent-cloud/wikis)
- [系统服务配置](https://gitee.com/koogua/course-tencent-cloud/wikis)
- [客户终端配置](https://gitee.com/koogua/course-tencent-cloud/wikis)
- [运行环境搭建](https://koogua.com/page/wiki)
- [系统服务配置](https://koogua.com/page/wiki)
- [客户终端配置](https://koogua.com/page/wiki)
### 意见反馈

View File

@ -28,6 +28,8 @@ class CategoryTreeList extends Builder
$list[] = [
'id' => $category->id,
'name' => $category->name,
'alias' => $category->alias,
'icon' => $category->icon,
'children' => $this->handleChildren($category),
];
}
@ -49,6 +51,8 @@ class CategoryTreeList extends Builder
$list[] = [
'id' => $category->id,
'name' => $category->name,
'alias' => $category->alias,
'icon' => $category->icon,
];
}

View File

@ -314,9 +314,9 @@ class CleanLogTask extends Task
if (strtotime($today) - strtotime($date) >= $keepDays * 86400) {
$deleted = unlink($file);
if ($deleted) {
echo "delete {$file} success" . PHP_EOL;
echo "------ delete {$file} success ------" . PHP_EOL;
} else {
echo "delete {$file} failed" . PHP_EOL;
echo "------ delete {$file} failed -------" . PHP_EOL;
}
}
}

View File

@ -20,14 +20,20 @@ class CloseFlashSaleOrderTask extends Task
{
$orders = $this->findOrders();
echo sprintf('pending orders: %s', $orders->count()) . PHP_EOL;
if ($orders->count() == 0) return;
echo '------ start close order task ------' . PHP_EOL;
foreach ($orders as $order) {
$this->pushFlashSaleQueue($order->promotion_id);
$this->deleteUserOrderCache($order->owner_id, $order->promotion_id);
$order->status = OrderModel::STATUS_CLOSED;
$order->update();
}
echo '------ end close order task ------' . PHP_EOL;
}
protected function pushFlashSaleQueue($saleId)

View File

@ -18,12 +18,18 @@ class CloseOrderTask extends Task
{
$orders = $this->findOrders();
echo sprintf('pending orders: %s', $orders->count()) . PHP_EOL;
if ($orders->count() == 0) return;
echo '------ start close order task ------' . PHP_EOL;
foreach ($orders as $order) {
$order->status = OrderModel::STATUS_CLOSED;
$order->update();
}
echo '------ end close order task ------' . PHP_EOL;
}
/**

View File

@ -0,0 +1,52 @@
<?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\Question as QuestionModel;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;
class CloseQuestionTask extends Task
{
public function mainAction()
{
$questions = $this->findQuestions();
echo sprintf('pending questions: %s', $questions->count()) . PHP_EOL;
if ($questions->count() == 0) return;
echo '------ start close question task ------' . PHP_EOL;
foreach ($questions as $question) {
$question->closed = 1;
$question->update();
}
echo '------ end close question task ------' . PHP_EOL;
}
/**
* 查找待关闭问题
*
* @param int $limit
* @return ResultsetInterface|Resultset|QuestionModel[]
*/
protected function findQuestions($limit = 1000)
{
$time = time() - 7 * 86400;
return QuestionModel::query()
->where('create_time < :time:', ['time' => $time])
->andWhere('answer_count = 0')
->limit($limit)
->execute();
}
}

View File

@ -20,8 +20,12 @@ class CloseTradeTask extends Task
{
$trades = $this->findTrades();
echo sprintf('pending trades: %s', $trades->count()) . PHP_EOL;
if ($trades->count() == 0) return;
echo '------ start close trade ------' . PHP_EOL;
foreach ($trades as $trade) {
if ($trade->channel == TradeModel::CHANNEL_ALIPAY) {
$this->handleAlipayTrade($trade);
@ -29,6 +33,8 @@ class CloseTradeTask extends Task
$this->handleWxpayTrade($trade);
}
}
echo '------ end close trade ------' . PHP_EOL;
}
/**

View File

@ -33,8 +33,12 @@ class DeliverTask extends Task
$tasks = $this->findTasks(30);
echo sprintf('pending tasks: %s', $tasks->count()) . PHP_EOL;
if ($tasks->count() == 0) return;
echo '------ start deliver task ------' . PHP_EOL;
$orderRepo = new OrderRepo();
foreach ($tasks as $task) {
@ -107,6 +111,8 @@ class DeliverTask extends Task
$this->handleOrderRefund($order);
}
}
echo '------ end deliver task ------' . PHP_EOL;
}
protected function handleCourseOrder(OrderModel $order)

View File

@ -31,11 +31,20 @@ class OptimizeTableTask extends Task
$tableName = $sessionModel->getSource();
if (UserSessionModel::count() < 1000000) {
echo sprintf('no need to optimize table: %s', $tableName) . PHP_EOL;
return;
}
echo sprintf('------ start optimize table: %s ------', $tableName) . PHP_EOL;
$this->db->delete($tableName, 'expire_time < :expire_time', [
'expire_time' => strtotime('-3 days'),
]);
$this->db->execute("OPTIMIZE TABLE {$tableName}");
echo sprintf('------ end optimize table: %s ------', $tableName) . PHP_EOL;
}
protected function optimizeUserTokenTable()
@ -44,63 +53,87 @@ class OptimizeTableTask extends Task
$tableName = $tokenModel->getSource();
if (UserTokenModel::count() < 1000000) {
echo sprintf('no need to optimize table: %s', $tableName) . PHP_EOL;
return;
}
echo sprintf('------ start optimize table: %s ------', $tableName) . PHP_EOL;
$this->db->delete($tableName, 'expire_time < :expire_time', [
'expire_time' => strtotime('-3 days'),
]);
$this->db->execute("OPTIMIZE TABLE {$tableName}");
echo sprintf('------ end optimize table: %s ------', $tableName) . PHP_EOL;
}
protected function optimizeImMessageTable()
{
$count = ImMessageModel::count();
if ($count < 1000000) return;
$messageModel = new ImMessageModel();
$tableName = $messageModel->getSource();
if (ImMessageModel::count() < 1000000) {
echo sprintf('no need to optimize table: %s', $tableName) . PHP_EOL;
return;
}
echo sprintf('------ start optimize table: %s ------', $tableName) . PHP_EOL;
$this->db->delete($tableName, 'create_time < :create_time', [
'create_time' => strtotime('-6 months'),
]);
$this->db->execute("OPTIMIZE TABLE {$tableName}");
echo sprintf('------ end optimize table: %s ------', $tableName) . PHP_EOL;
}
protected function optimizeLearningTable()
{
$count = LearningModel::count();
if ($count < 1000000) return;
$learningModel = new LearningModel();
$tableName = $learningModel->getSource();
if (LearningModel::count() < 1000000) {
echo sprintf('no need to optimize table: %s', $tableName) . PHP_EOL;
return;
}
echo sprintf('------ start optimize table: %s ------', $tableName) . PHP_EOL;
$this->db->delete($tableName, 'create_time < :create_time', [
'create_time' => strtotime('-6 months'),
]);
$this->db->execute("OPTIMIZE TABLE {$tableName}");
echo sprintf('------ end optimize table: %s ------', $tableName) . PHP_EOL;
}
protected function optimizeTaskTable()
{
$count = TaskModel::count();
if ($count < 1000000) return;
$taskModel = new TaskModel();
$tableName = $taskModel->getSource();
if (TaskModel::count() < 1000000) {
echo sprintf('no need to optimize table: %s', $tableName) . PHP_EOL;
return;
}
echo sprintf('------ start optimize table: %s ------', $tableName) . PHP_EOL;
$this->db->delete($tableName, 'create_time < :create_time AND status > :status', [
'create_time' => strtotime('-6 months'),
'status' => TaskModel::STATUS_PENDING,
]);
$this->db->execute("OPTIMIZE TABLE {$tableName}");
echo sprintf('------ end optimize table: %s ------', $tableName) . PHP_EOL;
}
}

View File

@ -32,8 +32,12 @@ class PointGiftDeliverTask extends Task
$tasks = $this->findTasks(30);
echo sprintf('pending tasks: %s', $tasks->count()) . PHP_EOL;
if ($tasks->count() == 0) return;
echo '------ start deliver task ------' . PHP_EOL;
$redeemRepo = new PointRedeemRepo();
foreach ($tasks as $task) {
@ -94,6 +98,8 @@ class PointGiftDeliverTask extends Task
$this->handlePointRefund($redeem);
}
}
echo '------ end deliver task ------' . PHP_EOL;
}
protected function handleCourseRedeem(PointRedeemModel $redeem)

View File

@ -33,8 +33,12 @@ class RefundTask extends Task
$tasks = $this->findTasks(30);
echo sprintf('pending tasks: %s', $tasks->count()) . PHP_EOL;
if ($tasks->count() == 0) return;
echo '------ start refund task ------' . PHP_EOL;
$tradeRepo = new TradeRepo();
$orderRepo = new OrderRepo();
$refundRepo = new RefundRepo();
@ -115,6 +119,8 @@ class RefundTask extends Task
$refund->update();
}
}
echo '------ end refund task ------' . PHP_EOL;
}
/**

View File

@ -18,14 +18,18 @@ class RevokeVipTask extends Task
{
$users = $this->findUsers();
if ($users->count() == 0) {
return;
}
echo sprintf('pending users: %s', $users->count()) . PHP_EOL;
if ($users->count() == 0) return;
echo '------ start revoke vip task ------' . PHP_EOL;
foreach ($users as $user) {
$user->vip = 0;
$user->update();
}
echo '------ end revoke vip task ------' . PHP_EOL;
}
/**

View File

@ -202,12 +202,11 @@ class SitemapTask extends Task
protected function addOthers()
{
$this->sitemap->addItem('/course/list', 0.6);
$this->sitemap->addItem('/im/group/list', 0.6);
$this->sitemap->addItem('/teacher/list', 0.6);
$this->sitemap->addItem('/vip', 0.6);
$this->sitemap->addItem('/help', 0.6);
$this->sitemap->addItem('/search', 0.6);
$this->sitemap->addItem("{$this->siteUrl}/course/list", 0.6);
$this->sitemap->addItem("{$this->siteUrl}/im/group/list", 0.6);
$this->sitemap->addItem("{$this->siteUrl}/teacher/list", 0.6);
$this->sitemap->addItem("{$this->siteUrl}/vip", 0.6);
$this->sitemap->addItem("{$this->siteUrl}/help", 0.6);
}
}

View File

@ -0,0 +1,42 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Console\Tasks;
use App\Library\AppInfo;
use GuzzleHttp\Client;
class SyncAppInfoTask extends Task
{
public function mainAction()
{
$url = 'https://koogua.com/api/instance/collect';
$site = $this->getSettings('site');
$serverHost = parse_url($site['url'], PHP_URL_HOST);
$serverIp = gethostbyname($serverHost);
$appInfo = new AppInfo();
$params = [
'server_host' => $serverHost,
'server_ip' => $serverIp,
'app_name' => $appInfo->get('name'),
'app_alias' => $appInfo->get('alias'),
'app_version' => $appInfo->get('version'),
'app_link' => $appInfo->get('link'),
];
$client = new Client();
$client->request('POST', $url, ['form_params' => $params]);
}
}

View File

@ -0,0 +1,52 @@
<?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\Tag as TagModel;
use App\Repos\Tag as TagRepo;
class SyncTagCountTask extends Task
{
public function mainAction()
{
$tags = $this->findTags();
echo sprintf('pending tags: %s', $tags->count()) . PHP_EOL;
if ($tags->count() == 0) return;
echo '------ start recount task ------' . PHP_EOL;
foreach ($tags as $tag) {
$this->recountTaggedItems($tag);
}
echo '------ end recount task ------' . PHP_EOL;
}
protected function recountTaggedItems(TagModel $tag)
{
$tagRepo = new TagRepo();
$tag->follow_count = $tagRepo->countFollows($tag->id);
$tag->course_count = $tagRepo->countCourses($tag->id);
$tag->article_count = $tagRepo->countArticles($tag->id);
$tag->question_count = $tagRepo->countQuestions($tag->id);
$tag->update();
}
protected function findTags()
{
return TagModel::query()
->where('published = 1')
->execute();
}
}

View File

@ -18,11 +18,17 @@ class UnlockUserTask extends Task
{
$users = $this->findUsers();
echo sprintf('pending users: %s', $users->count()) . PHP_EOL;
if ($users->count() == 0) return;
echo '------ start unlock user task ------' . PHP_EOL;
foreach ($users as $user) {
$user->update(['locked' => 0]);
}
echo '------ end unlock user task ------' . PHP_EOL;
}
/**

View File

@ -9,6 +9,7 @@ namespace App\Console\Tasks;
use App\Caches\NavTreeList as NavTreeListCache;
use App\Caches\Setting as SettingCache;
use App\Caches\AppInfo as AppInfoCache;
use App\Models\Setting as SettingModel;
class UpgradeTask extends Task
@ -16,6 +17,7 @@ class UpgradeTask extends Task
public function mainAction()
{
$this->resetAppInfoAction();
$this->resetSettingAction();
$this->resetAnnotationAction();
$this->resetMetadataAction();
@ -23,6 +25,22 @@ class UpgradeTask extends Task
$this->resetNavAction();
}
/**
* 重置应用信息
*
* @command: php console.php upgrade reset_app_info
*/
public function resetAppInfoAction()
{
echo '------ start reset app info ------' . PHP_EOL;
$cache = new AppInfoCache();
$cache->rebuild();
echo '------ end reset app info ------' . PHP_EOL;
}
/**
* 重置系统设置
*

View File

@ -164,15 +164,15 @@ class AnswerController extends Controller
}
/**
* @Route("/{id:[0-9]+}/publish/review", name="admin.answer.publish_review")
* @Route("/{id:[0-9]+}/moderate", name="admin.answer.moderate")
*/
public function publishReviewAction($id)
public function moderateAction($id)
{
$answerService = new AnswerService();
if ($this->request->isPost()) {
$answerService->publishReview($id);
$answerService->moderate($id);
$location = $this->url->get(['for' => 'admin.mod.answers']);
@ -187,27 +187,26 @@ class AnswerController extends Controller
$reasons = $answerService->getReasons();
$answer = $answerService->getAnswerInfo($id);
$this->view->pick('answer/publish_review');
$this->view->setVar('reasons', $reasons);
$this->view->setVar('answer', $answer);
}
/**
* @Route("/{id:[0-9]+}/report/review", name="admin.answer.report_review")
* @Route("/{id:[0-9]+}/report", name="admin.answer.report")
*/
public function reportReviewAction($id)
public function reportAction($id)
{
$answerService = new AnswerService();
if ($this->request->isPost()) {
$answerService->reportReview($id);
$answerService->report($id);
$location = $this->url->get(['for' => 'admin.report.answers']);
$content = [
'location' => $location,
'msg' => '审核举报成功',
'msg' => '处理举报成功',
];
return $this->jsonSuccess($content);
@ -216,7 +215,6 @@ class AnswerController extends Controller
$answer = $answerService->getAnswerInfo($id);
$reports = $answerService->getReports($id);
$this->view->pick('answer/report_review');
$this->view->setVar('answer', $answer);
$this->view->setVar('reports', $reports);
}

View File

@ -174,15 +174,15 @@ class ArticleController extends Controller
}
/**
* @Route("/{id:[0-9]+}/publish/review", name="admin.article.publish_review")
* @Route("/{id:[0-9]+}/moderate", name="admin.article.moderate")
*/
public function publishReviewAction($id)
public function moderateAction($id)
{
$articleService = new ArticleService();
if ($this->request->isPost()) {
$articleService->publishReview($id);
$articleService->moderate($id);
$location = $this->url->get(['for' => 'admin.mod.articles']);
@ -197,27 +197,26 @@ class ArticleController extends Controller
$reasons = $articleService->getReasons();
$article = $articleService->getArticleInfo($id);
$this->view->pick('article/publish_review');
$this->view->setVar('reasons', $reasons);
$this->view->setVar('article', $article);
}
/**
* @Route("/{id:[0-9]+}/report/review", name="admin.article.report_review")
* @Route("/{id:[0-9]+}/report", name="admin.article.report")
*/
public function reportReviewAction($id)
public function reportAction($id)
{
$articleService = new ArticleService();
if ($this->request->isPost()) {
$articleService->reportReview($id);
$articleService->report($id);
$location = $this->url->get(['for' => 'admin.report.articles']);
$content = [
'location' => $location,
'msg' => '审核举报成功',
'msg' => '处理举报成功',
];
return $this->jsonSuccess($content);
@ -226,7 +225,6 @@ class ArticleController extends Controller
$article = $articleService->getArticleInfo($id);
$reports = $articleService->getReports($id);
$this->view->pick('article/report_review');
$this->view->setVar('reports', $reports);
$this->view->setVar('article', $article);
}

View File

@ -84,21 +84,21 @@ class CommentController extends Controller
}
/**
* @Route("/{id:[0-9]+}/publish/review", name="admin.comment.publish_review")
* @Route("/{id:[0-9]+}/moderate", name="admin.comment.moderate")
*/
public function publishReviewAction($id)
public function moderateAction($id)
{
$commentService = new CommentService();
if ($this->request->isPost()) {
$commentService->publishReview($id);
$commentService->moderate($id);
$location = $this->url->get(['for' => 'admin.mod.comments']);
$content = [
'location' => $location,
'msg' => '审核回答成功',
'msg' => '审核评论成功',
];
return $this->jsonSuccess($content);
@ -107,27 +107,26 @@ class CommentController extends Controller
$reasons = $commentService->getReasons();
$comment = $commentService->getCommentInfo($id);
$this->view->pick('comment/publish_review');
$this->view->setVar('reasons', $reasons);
$this->view->setVar('comment', $comment);
}
/**
* @Route("/{id:[0-9]+}/report/review", name="admin.comment.report_review")
* @Route("/{id:[0-9]+}/report", name="admin.comment.report")
*/
public function reportReviewAction($id)
public function reportAction($id)
{
$commentService = new CommentService();
if ($this->request->isPost()) {
$commentService->reportReview($id);
$commentService->report($id);
$location = $this->url->get(['for' => 'admin.report.comments']);
$content = [
'location' => $location,
'msg' => '审核举报成功',
'msg' => '处理举报成功',
];
return $this->jsonSuccess($content);
@ -136,7 +135,6 @@ class CommentController extends Controller
$comment = $commentService->getCommentInfo($id);
$reports = $commentService->getReports($id);
$this->view->pick('comment/report_review');
$this->view->setVar('comment', $comment);
$this->view->setVar('reports', $reports);
}

View File

@ -15,6 +15,18 @@ use App\Http\Admin\Services\Moderation as ModerationService;
class ModerationController extends Controller
{
/**
* @Get("/reviews", name="admin.mod.reviews")
*/
public function reviewsAction()
{
$modService = new ModerationService();
$pager = $modService->getReviews();
$this->view->setVar('pager', $pager);
}
/**
* @Get("/articles", name="admin.mod.articles")
*/

View File

@ -170,15 +170,15 @@ class QuestionController extends Controller
}
/**
* @Route("/{id:[0-9]+}/publish/review", name="admin.question.publish_review")
* @Route("/{id:[0-9]+}/moderate", name="admin.question.moderate")
*/
public function publishReviewAction($id)
public function moderateAction($id)
{
$questionService = new QuestionService();
if ($this->request->isPost()) {
$questionService->publishReview($id);
$questionService->moderate($id);
$location = $this->url->get(['for' => 'admin.mod.questions']);
@ -193,27 +193,26 @@ class QuestionController extends Controller
$reasons = $questionService->getReasons();
$question = $questionService->getQuestionInfo($id);
$this->view->pick('question/publish_review');
$this->view->setVar('reasons', $reasons);
$this->view->setVar('question', $question);
}
/**
* @Route("/{id:[0-9]+}/report/review", name="admin.question.report_review")
* @Route("/{id:[0-9]+}/report", name="admin.question.report")
*/
public function reportReviewAction($id)
public function reportAction($id)
{
$questionService = new QuestionService();
if ($this->request->isPost()) {
$questionService->reportReview($id);
$questionService->report($id);
$location = $this->url->get(['for' => 'admin.report.questions']);
$content = [
'location' => $location,
'msg' => '审核举报成功',
'msg' => '处理举报成功',
];
return $this->jsonSuccess($content);
@ -222,7 +221,6 @@ class QuestionController extends Controller
$question = $questionService->getQuestionInfo($id);
$reports = $questionService->getReports($id);
$this->view->pick('question/report_review');
$this->view->setVar('question', $question);
$this->view->setVar('reports', $reports);
}

View File

@ -20,7 +20,11 @@ class ReviewController extends Controller
*/
public function searchAction()
{
$reviewService = new ReviewService();
$publishTypes = $reviewService->getPublishTypes();
$this->view->setVar('publish_types', $publishTypes);
}
/**
@ -110,4 +114,30 @@ class ReviewController extends Controller
return $this->jsonSuccess($content);
}
/**
* @Route("/{id:[0-9]+}/moderate", name="admin.review.moderate")
*/
public function moderateAction($id)
{
$reviewService = new ReviewService();
if ($this->request->isPost()) {
$reviewService->moderate($id);
$location = $this->url->get(['for' => 'admin.mod.reviews']);
$content = [
'location' => $location,
'msg' => '审核评价成功',
];
return $this->jsonSuccess($content);
}
$review = $reviewService->getReviewInfo($id);
$this->view->setVar('review', $review);
}
}

View File

@ -51,11 +51,13 @@ class TagController extends Controller
$tagService = new TagService;
$tag2 = $tagService->getTag($id);
$scopeTypes = $tagService->getScopeTypes();
/**
* 注意:"tag"变量被volt引擎内置占用另取名字避免冲突
*/
$this->view->setVar('tag2', $tag2);
$this->view->setVar('scope_types', $scopeTypes);
}
/**

View File

@ -100,22 +100,30 @@ class Answer extends Service
$question = $validator->checkQuestion($post['question_id']);
$data = $this->handlePostData($post);
$answer = new AnswerModel();
$answer->published = AnswerModel::PUBLISH_APPROVED;
$answer->client_type = $this->getClientType();
$answer->client_ip = $this->getClientIp();
$answer->content = $validator->checkContent($post['content']);
$answer->question_id = $question->id;
$answer->owner_id = $user->id;
$data['published'] = AnswerModel::PUBLISH_APPROVED;
$data['question_id'] = $question->id;
$data['owner_id'] = $user->id;
$answer->create();
$answer->create($data);
$question->last_answer_id = $answer->id;
$question->last_replier_id = $answer->owner_id;
$question->last_reply_time = $answer->create_time;
$question->update();
$this->saveDynamicAttrs($answer);
$this->recountQuestionAnswers($question);
$this->recountUserAnswers($user);
$this->handleAnswerPostPoint($answer);
$this->handleQuestionAnsweredNotice($answer);
if ($answer->owner_id != $question->owner_id) {
$this->handleAnswerPostPoint($answer);
$this->handleQuestionAnsweredNotice($answer);
}
$this->eventsManager->fire('Answer:afterCreate', $this, $answer);
@ -199,7 +207,7 @@ class Answer extends Service
return $answer;
}
public function publishReview($id)
public function moderate($id)
{
$type = $this->request->getPost('type', ['trim', 'string']);
$reason = $this->request->getPost('reason', ['trim', 'string']);
@ -229,7 +237,11 @@ class Answer extends Service
if ($type == 'approve') {
$this->handleAnswerPostPoint($answer);
if ($answer->owner_id != $question->owner_id) {
$this->handleAnswerPostPoint($answer);
$this->handleQuestionAnsweredNotice($answer);
}
$this->handleAnswerApprovedNotice($answer, $sender);
$this->eventsManager->fire('Answer:afterApprove', $this, $answer);
@ -250,7 +262,7 @@ class Answer extends Service
return $answer;
}
public function reportReview($id)
public function report($id)
{
$accepted = $this->request->getPost('accepted', 'int', 0);
$deleted = $this->request->getPost('deleted', 'int', 0);

View File

@ -257,7 +257,7 @@ class Article extends Service
return $article;
}
public function publishReview($id)
public function moderate($id)
{
$type = $this->request->getPost('type', ['trim', 'string']);
$reason = $this->request->getPost('reason', ['trim', 'string']);
@ -309,7 +309,7 @@ class Article extends Service
return $article;
}
public function reportReview($id)
public function report($id)
{
$accepted = $this->request->getPost('accepted', 'int', 0);
$deleted = $this->request->getPost('deleted', 'int', 0);

View File

@ -330,13 +330,13 @@ class AuthNode extends Service
'id' => '1-7-10',
'title' => '审核文章',
'type' => 'button',
'route' => 'admin.article.publish_review',
'route' => 'admin.article.moderate',
],
[
'id' => '1-7-11',
'title' => '审核举报',
'type' => 'button',
'route' => 'admin.article.report_review',
'route' => 'admin.article.report',
],
],
],
@ -385,13 +385,13 @@ class AuthNode extends Service
'id' => '1-10-10',
'title' => '审核问题',
'type' => 'button',
'route' => 'admin.question.publish_review',
'route' => 'admin.question.moderate',
],
[
'id' => '1-10-11',
'title' => '审核举报',
'type' => 'button',
'route' => 'admin.question.report_review',
'route' => 'admin.question.report',
],
],
],
@ -440,13 +440,13 @@ class AuthNode extends Service
'id' => '1-11-10',
'title' => '审核回答',
'type' => 'button',
'route' => 'admin.answer.publish_review',
'route' => 'admin.answer.moderate',
],
[
'id' => '1-11-11',
'title' => '审核举报',
'type' => 'button',
'route' => 'admin.answer.report_review',
'route' => 'admin.answer.report',
],
],
],
@ -483,13 +483,13 @@ class AuthNode extends Service
'id' => '1-9-5',
'title' => '评论审核',
'type' => 'button',
'route' => 'admin.comment.publish_review',
'route' => 'admin.comment.moderate',
],
[
'id' => '1-9-6',
'title' => '举报审核',
'type' => 'button',
'route' => 'admin.comment.report_review',
'route' => 'admin.comment.report',
],
],
],
@ -508,6 +508,12 @@ class AuthNode extends Service
'title' => '审核队列',
'type' => 'menu',
'children' => [
[
'id' => '2-10-5',
'title' => '评价审核',
'type' => 'menu',
'route' => 'admin.mod.reviews',
],
[
'id' => '2-10-1',
'title' => '文章审核',
@ -656,6 +662,12 @@ class AuthNode extends Service
'type' => 'button',
'route' => 'admin.review.delete',
],
[
'id' => '2-3-5',
'title' => '审核评价',
'type' => 'button',
'route' => 'admin.review.moderate',
],
],
],
[

View File

@ -115,6 +115,10 @@ class Category extends Service
$data['name'] = $validator->checkName($post['name']);
}
if (isset($post['icon'])) {
$data['icon'] = $validator->checkIcon($post['icon']);
}
if (isset($post['priority'])) {
$data['priority'] = $validator->checkPriority($post['priority']);
}

View File

@ -15,12 +15,18 @@ use App\Models\Reason as ReasonModel;
use App\Models\Report as ReportModel;
use App\Repos\Comment as CommentRepo;
use App\Repos\Report as ReportRepo;
use App\Repos\User as UserRepo;
use App\Services\Logic\Comment\AfterCreateTrait;
use App\Services\Logic\Comment\CommentInfo as CommentInfoService;
use App\Services\Logic\Comment\CountTrait;
use App\Validators\Comment as CommentValidator;
class Comment extends Service
{
use AfterCreateTrait;
use CountTrait;
public function getReasons()
{
return ReasonModel::commentRejectOptions();
@ -99,27 +105,57 @@ class Comment extends Service
public function deleteComment($id)
{
$page = $this->findOrFail($id);
$comment = $this->findOrFail($id);
$page->deleted = 1;
$comment->deleted = 1;
$page->update();
$comment->update();
return $page;
$validator = new CommentValidator();
if ($comment->parent_id > 0) {
$parent = $validator->checkParent($comment->parent_id);
$this->decrCommentReplyCount($parent);
}
$item = $validator->checkItem($comment->item_id, $comment->item_type);
$this->decrItemCommentCount($item);
$owner = $this->findUser($comment->owner_id);
$this->decrUserCommentCount($owner);
return $comment;
}
public function restoreComment($id)
{
$page = $this->findOrFail($id);
$comment = $this->findOrFail($id);
$page->deleted = 0;
$comment->deleted = 0;
$page->update();
$comment->update();
return $page;
$validator = new CommentValidator();
if ($comment->parent_id > 0) {
$parent = $validator->checkParent($comment->parent_id);
$this->incrCommentReplyCount($parent);
}
$item = $validator->checkItem($comment->item_id, $comment->item_type);
$this->incrItemCommentCount($item);
$owner = $this->findUser($comment->owner_id);
$this->incrUserCommentCount($owner);
return $comment;
}
public function publishReview($id)
public function moderate($id)
{
$type = $this->request->getPost('type', ['trim', 'string']);
$reason = $this->request->getPost('reason', ['trim', 'string']);
@ -143,6 +179,25 @@ class Comment extends Service
if ($type == 'approve') {
$owner = $this->findUser($comment->owner_id);
$item = $validator->checkItem($comment->item_id, $comment->item_type);
$this->incrItemCommentCount($item);
$this->incrUserCommentCount($owner);
if ($comment->parent_id == 0) {
$this->handleItemCommentedNotice($item, $comment);
}
if ($comment->parent_id > 0) {
$parent = $validator->checkParent($comment->parent_id);
$this->incrCommentReplyCount($parent);
$this->handleCommentRepliedNotice($comment);
}
$this->handleCommentPostPoint($comment);
$this->eventsManager->fire('Comment:afterApprove', $this, $comment);
} elseif ($type == 'reject') {
@ -153,7 +208,7 @@ class Comment extends Service
return $comment;
}
public function reportReview($id)
public function report($id)
{
$accepted = $this->request->getPost('accepted', 'int', 0);
$deleted = $this->request->getPost('deleted', 'int', 0);
@ -188,6 +243,13 @@ class Comment extends Service
return $validator->checkComment($id);
}
protected function findUser($id)
{
$userRepo = new UserRepo();
return $userRepo->findById($id);
}
protected function handleComments($pager)
{
if ($pager->total_items > 0) {

View File

@ -40,7 +40,7 @@ class Index extends Service
$appInfo = new AppInfo();
if ($appInfo->version != $content['version']) {
if (empty($content) || $appInfo->get('version') != $content['version']) {
$cache->rebuild();
}
@ -79,12 +79,14 @@ class Index extends Service
{
$statRepo = new StatRepo();
$reviewCount = $statRepo->countPendingReviews();
$articleCount = $statRepo->countPendingArticles();
$questionCount = $statRepo->countPendingQuestions();
$answerCount = $statRepo->countPendingAnswers();
$commentCount = $statRepo->countPendingComments();
return [
'review_count' => $reviewCount,
'article_count' => $articleCount,
'question_count' => $questionCount,
'answer_count' => $answerCount,
@ -111,7 +113,7 @@ class Index extends Service
public function getReleases()
{
$url = 'https://koogua.com/api-releases.json';
$url = 'https://koogua.com/api/releases';
$client = new Client();

View File

@ -10,19 +10,42 @@ namespace App\Http\Admin\Services;
use App\Builders\AnswerList as AnswerListBuilder;
use App\Builders\ArticleList as ArticleListBuilder;
use App\Builders\QuestionList as QuestionListBuilder;
use App\Builders\ReviewList as ReviewListBuilder;
use App\Library\Paginator\Query as PagerQuery;
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\Models\Review as ReviewModel;
use App\Repos\Answer as AnswerRepo;
use App\Repos\Article as ArticleRepo;
use App\Repos\Comment as CommentRepo;
use App\Repos\Question as QuestionRepo;
use App\Repos\Review as ReviewRepo;
class Moderation extends Service
{
public function getReviews()
{
$pagerQuery = new PagerQuery();
$params = $pagerQuery->getParams();
$params['published'] = ReviewModel::PUBLISH_PENDING;
$params['deleted'] = 0;
$sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage();
$limit = $pagerQuery->getLimit();
$reviewRepo = new ReviewRepo();
$pager = $reviewRepo->paginate($params, $sort, $page, $limit);
return $this->handleReviews($pager);
}
public function getArticles()
{
$pagerQuery = new PagerQuery();
@ -103,6 +126,23 @@ class Moderation extends Service
return $this->handleComments($pager);
}
protected function handleReviews($pager)
{
if ($pager->total_items > 0) {
$builder = new ReviewListBuilder();
$pipeA = $pager->items->toArray();
$pipeB = $builder->handleCourses($pipeA);
$pipeC = $builder->handleUsers($pipeB);
$pipeD = $builder->objects($pipeC);
$pager->items = $pipeD;
}
return $pager;
}
protected function handleArticles($pager)
{
if ($pager->total_items > 0) {

View File

@ -150,8 +150,8 @@ class Package extends Service
$package->update($data);
$this->handlePackagedCourses($package);
$this->updatePackageCourseCount($package);
$this->rebuildPackageCache($package);
return $package;
@ -165,6 +165,7 @@ class Package extends Service
$package->update();
$this->handlePackagedCourses($package);
$this->rebuildPackageCache($package);
return $package;
@ -178,6 +179,7 @@ class Package extends Service
$package->update();
$this->handlePackagedCourses($package);
$this->rebuildPackageCache($package);
return $package;
@ -225,6 +227,20 @@ class Package extends Service
}
}
protected function handlePackagedCourses(PackageModel $package)
{
$packageRepo = new PackageRepo();
$courses = $packageRepo->findCourses($package->id);
if ($courses->count() == 0) return;
foreach ($courses as $course) {
$this->rebuildCoursePackageCache($course);
$this->recountCoursePackages($course);
}
}
protected function updatePackageCourseCount(PackageModel $package)
{
$packageRepo = new PackageRepo();
@ -260,11 +276,20 @@ class Package extends Service
$cache->rebuild($package->id);
}
protected function rebuildCoursePackageCache($courseId)
protected function rebuildCoursePackageCache(CourseModel $course)
{
$cache = new CoursePackageListCache();
$cache->rebuild($courseId);
$cache->rebuild($course->id);
}
protected function recountCoursePackages(CourseModel $course)
{
$courseRepo = new CourseRepo();
$course->package_count = $courseRepo->countPackages($course->id);
$course->update();
}
protected function findOrFail($id)

View File

@ -237,7 +237,7 @@ class Question extends Service
return $question;
}
public function publishReview($id)
public function moderate($id)
{
$type = $this->request->getPost('type', ['trim', 'string']);
$reason = $this->request->getPost('reason', ['trim', 'string']);
@ -285,7 +285,7 @@ class Question extends Service
return $question;
}
public function reportReview($id)
public function report($id)
{
$accepted = $this->request->getPost('accepted', 'int', 0);
$deleted = $this->request->getPost('deleted', 'int', 0);

View File

@ -7,8 +7,12 @@
namespace App\Http\Admin\Services;
use App\Models\Chapter as ChapterModel;
use App\Models\Course as CourseModel;
use App\Models\Resource as ResourceModel;
use App\Models\Upload as UploadModel;
use App\Repos\Chapter as ChapterRepo;
use App\Repos\Course as CourseRepo;
use App\Repos\Upload as UploadRepo;
use App\Services\Storage as StorageService;
use App\Validators\Chapter as ChapterValidator;
@ -25,7 +29,6 @@ class Resource extends Service
$validator = new ChapterValidator();
$chapter = $validator->checkChapter($post['chapter_id']);
$course = $validator->checkCourse($chapter->course_id);
$uploadRepo = new UploadRepo();
@ -54,11 +57,8 @@ class Resource extends Service
$resource->create();
$chapter->resource_count += 1;
$chapter->update();
$course->resource_count += 1;
$course->update();
$this->recountChapterResources($chapter);
$this->recountCourseResources($course);
return $upload;
}
@ -103,15 +103,8 @@ class Resource extends Service
$resource->delete();
if ($course->resource_count > 1) {
$course->resource_count -= 1;
$course->update();
}
if ($chapter->resource_count > 1) {
$chapter->resource_count -= 1;
$chapter->update();
}
$this->recountChapterResources($chapter);
$this->recountCourseResources($course);
}
protected function findOrFail($id)
@ -121,4 +114,22 @@ class Resource extends Service
return $validator->checkResource($id);
}
protected function recountChapterResources(ChapterModel $chapter)
{
$chapterRepo = new ChapterRepo();
$chapter->resource_count = $chapterRepo->countResources($chapter->id);
$chapter->update();
}
protected function recountCourseResources(CourseModel $course)
{
$courseRepo = new CourseRepo();
$course->resource_count = $courseRepo->countResources($course->id);
$course->update();
}
}

View File

@ -10,14 +10,21 @@ namespace App\Http\Admin\Services;
use App\Builders\ReviewList as ReviewListBuilder;
use App\Library\Paginator\Query as PagerQuery;
use App\Models\Course as CourseModel;
use App\Models\Review as ReviewModel;
use App\Repos\Course as CourseRepo;
use App\Repos\Review as ReviewRepo;
use App\Services\CourseStat as CourseStatService;
use App\Services\Logic\Review\ReviewInfo as ReviewInfoService;
use App\Validators\Review as ReviewValidator;
class Review extends Service
{
public function getPublishTypes()
{
return ReviewModel::publishTypes();
}
public function getReviews()
{
$pagerQuery = new PagerQuery();
@ -49,6 +56,13 @@ class Review extends Service
return $this->findOrFail($id);
}
public function getReviewInfo($id)
{
$service = new ReviewInfoService();
return $service->handle($id);
}
public function updateReview($id)
{
$review = $this->findOrFail($id);
@ -86,6 +100,8 @@ class Review extends Service
$this->updateCourseRating($course);
$this->eventsManager->fire('Review:afterUpdate', $this, $review);
return $review;
}
@ -100,6 +116,8 @@ class Review extends Service
$course = $this->findCourse($review->course_id);
$this->recountCourseReviews($course);
$this->eventsManager->fire('Review:afterReview', $this, $review);
}
public function restoreReview($id)
@ -113,6 +131,35 @@ class Review extends Service
$course = $this->findCourse($review->course_id);
$this->recountCourseReviews($course);
$this->eventsManager->fire('Review:afterRestore', $this, $review);
}
public function moderate($id)
{
$type = $this->request->getPost('type', ['trim', 'string']);
$review = $this->findOrFail($id);
if ($type == 'approve') {
$review->published = ReviewModel::PUBLISH_APPROVED;
} elseif ($type == 'reject') {
$review->published = ReviewModel::PUBLISH_REJECTED;
}
$review->update();
$course = $this->findCourse($review->course_id);
$this->recountCourseReviews($course);
if ($type == 'approve') {
$this->eventsManager->fire('Review:afterApprove', $this, $review);
} elseif ($type == 'reject') {
$this->eventsManager->fire('Review:afterReject', $this, $review);
}
return $review;
}
protected function findOrFail($id)

View File

@ -16,6 +16,11 @@ use App\Validators\Tag as TagValidator;
class Tag extends Service
{
public function getScopeTypes()
{
return TagModel::scopeTypes();
}
public function getTags()
{
$pagerQuery = new PagerQuery();
@ -84,6 +89,14 @@ class Tag extends Service
$data['published'] = $validator->checkPublishStatus($post['published']);
}
if (isset($post['scope_type'])) {
if ($post['scope_type'] == 'all') {
$data['scopes'] = 'all';
}else {
$data['scopes'] = $post['scopes'] ?? [];
}
}
$tag->update($data);
$this->rebuildTagCache($tag);

View File

@ -44,7 +44,7 @@
{% set edit_url = url({'for':'admin.answer.edit','id':item.id}) %}
{% set delete_url = url({'for':'admin.answer.delete','id':item.id}) %}
{% set restore_url = url({'for':'admin.answer.restore','id':item.id}) %}
{% set review_url = url({'for':'admin.answer.publish_review','id':item.id}) %}
{% set review_url = url({'for':'admin.answer.moderate','id':item.id}) %}
<tr>
<td>
<P>问题:<a href="{{ question_url }}" target="_blank">{{ item.question.title }}</a></P>

View File

@ -21,9 +21,9 @@
<legend>审核意见</legend>
</fieldset>
{% set review_url = url({'for':'admin.answer.publish_review','id':answer.id}) %}
{% set moderate_url = url({'for':'admin.answer.moderate','id':answer.id}) %}
<form class="layui-form kg-form kg-review-form" method="POST" action="{{ review_url }}">
<form class="layui-form kg-form kg-mod-form" method="POST" action="{{ moderate_url }}">
<div class="layui-form-item">
<label class="layui-form-label">审核</label>
<div class="layui-input-block">

View File

@ -5,7 +5,7 @@
{{ partial('macros/question') }}
{% set owner_url = url({'for':'home.user.show','id':answer.owner.id}) %}
{% set review_url = url({'for':'admin.answer.report_review','id':answer.id}) %}
{% set report_url = url({'for':'admin.answer.report','id':answer.id}) %}
<fieldset class="layui-elem-field layui-field-title">
<legend>审核举报</legend>
@ -55,7 +55,7 @@
</table>
</div>
<div class="layui-tab-item">
<form class="layui-form kg-form kg-review-form" method="POST" action="{{ review_url }}">
<form class="layui-form kg-form kg-mod-form" method="POST" action="{{ report_url }}">
<div class="layui-form-item">
<label class="layui-form-label">有效举报</label>
<div class="layui-input-block">

View File

@ -38,8 +38,8 @@
<thead>
<tr>
<th>文章</th>
<th>评论</th>
<th>浏览</th>
<th>评论</th>
<th>点赞</th>
<th>收藏</th>
<th>状态</th>
@ -56,7 +56,7 @@
{% set update_url = url({'for':'admin.article.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.article.delete','id':item.id}) %}
{% set restore_url = url({'for':'admin.article.restore','id':item.id}) %}
{% set review_url = url({'for':'admin.article.publish_review','id':item.id}) %}
{% set review_url = url({'for':'admin.article.moderate','id':item.id}) %}
{% set comment_url = url({'for':'admin.comment.list'},{'item_id':item.id,'item_type':2}) %}
<tr>
<td>

View File

@ -15,7 +15,7 @@
<div class="meta">
<span class="layui-badge layui-bg-green">{{ source_type(article.source_type) }}</span>
<span><a href="{{ owner_url }}" target="_blank">{{ article.owner.name }}</a></span>
<span>{{ date('Y-m-d H:i',article.create_time) }}</span>
<span>{{ date('Y-m-d H:i:',article.create_time) }}</span>
</div>
<div class="content markdown-body">{{ article.content }}</div>
{% if article.tags %}
@ -36,9 +36,9 @@
<legend>审核意见</legend>
</fieldset>
{% set review_url = url({'for':'admin.article.publish_review','id':article.id}) %}
{% set moderate_url = url({'for':'admin.article.moderate','id':article.id}) %}
<form class="layui-form kg-form kg-review-form" method="POST" action="{{ review_url }}">
<form class="layui-form kg-form kg-mod-form" method="POST" action="{{ moderate_url }}">
<div class="layui-form-item">
<label class="layui-form-label">审核</label>
<div class="layui-input-block">

View File

@ -5,7 +5,7 @@
{{ partial('macros/article') }}
{% set owner_url = url({'for':'home.user.show','id':article.owner.id}) %}
{% set review_url = url({'for':'admin.article.report_review','id':article.id}) %}
{% set report_url = url({'for':'admin.article.report','id':article.id}) %}
<fieldset class="layui-elem-field layui-field-title">
<legend>审核举报</legend>
@ -68,7 +68,7 @@
</table>
</div>
<div class="layui-tab-item">
<form class="layui-form kg-form kg-review-form" method="POST" action="{{ review_url }}">
<form class="layui-form kg-form kg-mod-form" method="POST" action="{{ report_url }}">
<div class="layui-form-item">
<label class="layui-form-label">有效举报</label>
<div class="layui-input-block">

View File

@ -6,6 +6,16 @@
<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" style="width: 80px;">
<img id="img-icon" class="kg-icon" src="{{ category.icon }}">
<input type="hidden" name="icon" value="{{ category.icon }}">
</div>
<div class="layui-input-inline" style="padding-top:15px;">
<button id="change-icon" 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">
@ -34,4 +44,10 @@
</div>
</form>
{% endblock %}
{% block include_js %}
{{ js_include('admin/js/icon.upload.js') }}
{% endblock %}

View File

@ -31,11 +31,13 @@
<col>
<col>
<col>
<col>
<col width="12%">
</colgroup>
<thead>
<tr>
<th>编号</th>
<th>图标</th>
<th>名称</th>
<th>层级</th>
<th>子节点</th>
@ -53,6 +55,7 @@
{% set restore_url = url({'for':'admin.category.restore','id':item.id}) %}
<tr>
<td>{{ item.id }}</td>
<td><img class="kg-icon" src="{{ item.icon }}" alt="{{ item.name }}"></td>
{% if item.type == 1 %}
{% if item.level == 1 %}
<td><a href="{{ child_url }}"><i class="layui-icon layui-icon-add-circle"></i> {{ item.name }}</a></td>

View File

@ -5,7 +5,6 @@
{{ partial('macros/comment') }}
{% set owner_url = url({'for':'home.user.show','id':comment.owner.id}) %}
{% set review_url = url({'for':'admin.comment.publish_review','id':comment.id}) %}
<fieldset class="layui-elem-field layui-field-title">
<legend>审核内容</legend>
@ -23,7 +22,9 @@
<legend>审核意见</legend>
</fieldset>
<form class="layui-form kg-form kg-review-form" method="POST" action="{{ review_url }}">
{% set moderate_url = url({'for':'admin.comment.moderate','id':comment.id}) %}
<form class="layui-form kg-form kg-mod-form" method="POST" action="{{ moderate_url }}">
<div class="layui-form-item">
<label class="layui-form-label">审核</label>
<div class="layui-input-block">

View File

@ -5,7 +5,7 @@
{{ partial('macros/comment') }}
{% set owner_url = url({'for':'home.user.show','id':comment.owner.id}) %}
{% set review_url = url({'for':'admin.comment.report_review','id':comment.id}) %}
{% set report_url = url({'for':'admin.comment.report','id':comment.id}) %}
<fieldset class="layui-elem-field layui-field-title">
<legend>审核举报</legend>
@ -54,7 +54,7 @@
</table>
</div>
<div class="layui-tab-item">
<form class="layui-form kg-form kg-review-form" method="POST" action="{{ review_url }}">
<form class="layui-form kg-form kg-mod-form" method="POST" action="{{ report_url }}">
<div class="layui-form-item">
<label class="layui-form-label">有效举报</label>
<div class="layui-input-block">

View File

@ -2,7 +2,15 @@
<div class="layui-card-header">审核队列</div>
<div class="layui-card-body">
<div class="layui-row layui-col-space10">
<div class="layui-col-md3">
<div class="layui-col-md2">
<div class="kg-stat-card">
<div class="name">评价</div>
<div class="count">
<a href="{{ url({'for':'admin.mod.reviews'}) }}">{{ mod_stat.review_count }}</a>
</div>
</div>
</div>
<div class="layui-col-md2">
<div class="kg-stat-card">
<div class="name">文章</div>
<div class="count">
@ -10,7 +18,7 @@
</div>
</div>
</div>
<div class="layui-col-md3">
<div class="layui-col-md2">
<div class="kg-stat-card">
<div class="name">提问</div>
<div class="count">
@ -18,7 +26,7 @@
</div>
</div>
</div>
<div class="layui-col-md3">
<div class="layui-col-md2">
<div class="kg-stat-card">
<div class="name">回答</div>
<div class="count">
@ -26,7 +34,7 @@
</div>
</div>
</div>
<div class="layui-col-md3">
<div class="layui-col-md2">
<div class="kg-stat-card">
<div class="name">评论</div>
<div class="count">

View File

@ -2,7 +2,7 @@
<div class="layui-card-header">举报队列</div>
<div class="layui-card-body">
<div class="layui-row layui-col-space10">
<div class="layui-col-md3">
<div class="layui-col-md2">
<div class="kg-stat-card">
<div class="name">文章</div>
<div class="count">
@ -10,7 +10,7 @@
</div>
</div>
</div>
<div class="layui-col-md3">
<div class="layui-col-md2">
<div class="kg-stat-card">
<div class="name">提问</div>
<div class="count">
@ -18,7 +18,7 @@
</div>
</div>
</div>
<div class="layui-col-md3">
<div class="layui-col-md2">
<div class="kg-stat-card">
<div class="name">回答</div>
<div class="count">
@ -26,7 +26,7 @@
</div>
</div>
</div>
<div class="layui-col-md3">
<div class="layui-col-md2">
<div class="kg-stat-card">
<div class="name">评论</div>
<div class="count">

View File

@ -0,0 +1,11 @@
{%- macro publish_status(type) %}
{% if type == 1 %}
审核中
{% elseif type == 2 %}
已发布
{% elseif type == 3 %}
未通过
{% else %}
未知
{% endif %}
{%- endmacro %}

View File

@ -31,7 +31,7 @@
{% for item in pager.items %}
{% set question_url = url({'for':'home.question.show','id':item.question.id}) %}
{% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %}
{% set review_url = url({'for':'admin.answer.publish_review','id':item.id}) %}
{% set moderate_url = url({'for':'admin.answer.moderate','id':item.id}) %}
<tr>
<td>
<P>问题:<a href="{{ question_url }}" target="_blank">{{ item.question.title }}</a></P>
@ -43,7 +43,7 @@
</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td class="center">
<a href="{{ review_url }}" class="layui-btn layui-btn-sm">详情</a>
<a href="{{ moderate_url }}" class="layui-btn layui-btn-sm">详情</a>
</td>
</tr>
{% endfor %}

View File

@ -30,7 +30,7 @@
<tbody>
{% for item in pager.items %}
{% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %}
{% set review_url = url({'for':'admin.article.publish_review','id':item.id}) %}
{% set moderate_url = url({'for':'admin.article.moderate','id':item.id}) %}
<tr>
<td>
<p>标题:{{ item.title }}</p>
@ -47,7 +47,7 @@
</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td class="center">
<a href="{{ review_url }}" class="layui-btn layui-btn-sm">详情</a>
<a href="{{ moderate_url }}" class="layui-btn layui-btn-sm">详情</a>
</td>
</tr>
{% endfor %}

View File

@ -30,7 +30,7 @@
<tbody>
{% for item in pager.items %}
{% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %}
{% set review_url = url({'for':'admin.comment.publish_review','id':item.id}) %}
{% set moderate_url = url({'for':'admin.comment.moderate','id':item.id}) %}
<tr>
<td>{{ substr(item.content,0,32) }}</td>
<td>
@ -39,7 +39,7 @@
</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td class="center">
<a href="{{ review_url }}" class="layui-btn layui-btn-sm">详情</a>
<a href="{{ moderate_url }}" class="layui-btn layui-btn-sm">详情</a>
</td>
</tr>
{% endfor %}

View File

@ -30,7 +30,7 @@
<tbody>
{% for item in pager.items %}
{% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %}
{% set review_url = url({'for':'admin.question.publish_review','id':item.id}) %}
{% set moderate_url = url({'for':'admin.question.moderate','id':item.id}) %}
<tr>
<td>
<p>标题:{{ item.title }}</p>
@ -46,7 +46,7 @@
</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td class="center">
<a href="{{ review_url }}" class="layui-btn layui-btn-sm">详情</a>
<a href="{{ moderate_url }}" class="layui-btn layui-btn-sm">详情</a>
</td>
</tr>
{% endfor %}

View File

@ -0,0 +1,60 @@
{% extends 'templates/main.volt' %}
{% block content %}
{% set search_url = url({'for':'admin.consult.search'}) %}
<div class="kg-nav">
<div class="kg-nav-left">
<span class="layui-breadcrumb">
<a><cite>评价审核</cite></a>
</span>
</div>
</div>
<table class="layui-table kg-table layui-form">
<colgroup>
<col>
<col>
<col>
<col width="10%">
</colgroup>
<thead>
<tr>
<th>內容</th>
<th>用户</th>
<th>评分</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for item in pager.items %}
{% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %}
{% set course_url = url({'for':'home.course.show','id':item.course.id}) %}
{% set moderate_url = url({'for':'admin.review.moderate','id':item.id}) %}
<tr>
<td>
<p>课程:<a href="{{ course_url }}">{{ item.course.title }}</a>{{ item.course.id }}</p>
<p class="layui-elip kg-item-elip" title="{{ item.content }}">评价:{{ item.content }}</p>
<p>时间:{{ date('Y-m-d H:i',item.create_time) }}</p>
</td>
<td>
<p>昵称:<a href="{{ owner_url }}">{{ item.owner.name }}</a></p>
<p>编号:{{ item.owner.id }}</p>
</td>
<td>
<p>内容实用:{{ item.rating1 }}</p>
<p>通俗易懂:{{ item.rating2 }}</p>
<p>逻辑清晰:{{ item.rating3 }}</p>
</td>
<td class="center">
<a href="{{ moderate_url }}" class="layui-btn layui-btn-sm">详情</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ partial('partials/pager') }}
{% endblock %}

View File

@ -37,8 +37,8 @@
<thead>
<tr>
<th>问题</th>
<th>回答</th>
<th>浏览</th>
<th>回答</th>
<th>点赞</th>
<th>收藏</th>
<th>状态</th>
@ -54,7 +54,7 @@
{% set update_url = url({'for':'admin.question.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.question.delete','id':item.id}) %}
{% set restore_url = url({'for':'admin.question.restore','id':item.id}) %}
{% set review_url = url({'for':'admin.question.publish_review','id':item.id}) %}
{% set review_url = url({'for':'admin.question.moderate','id':item.id}) %}
{% set answer_add_url = url({'for':'admin.answer.add'},{'question_id':item.id}) %}
{% set answer_list_url = url({'for':'admin.answer.list'},{'question_id':item.id}) %}
<tr>
@ -73,8 +73,8 @@
<span>创建:{{ date('Y-m-d',item.create_time) }}</span>
</p>
</td>
<td>{{ item.answer_count }}</td>
<td>{{ item.view_count }}</td>
<td>{{ item.answer_count }}</td>
<td>{{ item.like_count }}</td>
<td>{{ item.favorite_count }}</td>
<td>{{ publish_status(item.published) }}</td>

View File

@ -28,9 +28,9 @@
<legend>审核意见</legend>
</fieldset>
{% set review_url = url({'for':'admin.question.publish_review','id':question.id}) %}
{% set moderate_url = url({'for':'admin.question.moderate','id':question.id}) %}
<form class="layui-form kg-form kg-review-form" method="POST" action="{{ review_url }}">
<form class="layui-form kg-form kg-mod-form" method="POST" action="{{ moderate_url }}">
<div class="layui-form-item">
<label class="layui-form-label">审核</label>
<div class="layui-input-block">
@ -38,17 +38,15 @@
<input type="radio" name="type" value="reject" title="拒绝" lay-filter="review">
</div>
</div>
<div id="reason-block" style="display:none;">
<div class="layui-form-item">
<label class="layui-form-label">理由</label>
<div class="layui-input-block">
<select name="reason">
<option value="">请选择</option>
{% for value,name in reasons %}
<option value="{{ value }}">{{ name }}</option>
{% endfor %}
</select>
</div>
<div class="layui-form-item" id="reason-block" style="display:none;">
<label class="layui-form-label">理由</label>
<div class="layui-input-block">
<select name="reason">
<option value="">请选择</option>
{% for value,name in reasons %}
<option value="{{ value }}">{{ name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="layui-form-item">

View File

@ -5,7 +5,7 @@
{{ partial('macros/question') }}
{% set owner_url = url({'for':'home.user.show','id':question.owner.id}) %}
{% set review_url = url({'for':'admin.question.report_review','id':question.id}) %}
{% set report_url = url({'for':'admin.question.report','id':question.id}) %}
<fieldset class="layui-elem-field layui-field-title">
<legend>审核举报</legend>
@ -62,7 +62,7 @@
</table>
</div>
<div class="layui-tab-item">
<form class="layui-form kg-form kg-review-form" method="POST" action="{{ review_url }}">
<form class="layui-form kg-form kg-mod-form" method="POST" action="{{ report_url }}">
<div class="layui-form-item">
<label class="layui-form-label">有效举报</label>
<div class="layui-input-block">

View File

@ -33,7 +33,7 @@
{% for item in pager.items %}
{% set question_url = url({'for':'home.question.show','id':item.question.id}) %}
{% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %}
{% set review_url = url({'for':'admin.answer.report_review','id':item.id}) %}
{% set report_url = url({'for':'admin.answer.report','id':item.id}) %}
<tr>
<td>
<P>问题:<a href="{{ question_url }}" target="_blank">{{ item.question.title }}</a></P>
@ -46,7 +46,7 @@
<td>{{ item.report_count }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td class="center">
<a href="{{ review_url }}" class="layui-btn layui-btn-sm">详情</a>
<a href="{{ report_url }}" class="layui-btn layui-btn-sm">详情</a>
</td>
</tr>
{% endfor %}

View File

@ -33,7 +33,7 @@
{% for item in pager.items %}
{% set article_url = url({'for':'home.article.show','id':item.id}) %}
{% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %}
{% set review_url = url({'for':'admin.article.report_review','id':item.id}) %}
{% set report_url = url({'for':'admin.article.report','id':item.id}) %}
<tr>
<td>
<p>标题:<a href="{{ article_url }}" target="_blank">{{ item.title }}</a></p>
@ -51,7 +51,7 @@
<td>{{ item.report_count }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td class="center">
<a href="{{ review_url }}" class="layui-btn layui-btn-sm">详情</a>
<a href="{{ report_url }}" class="layui-btn layui-btn-sm">详情</a>
</td>
</tr>
{% endfor %}

View File

@ -32,7 +32,7 @@
<tbody>
{% for item in pager.items %}
{% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %}
{% set review_url = url({'for':'admin.comment.report_review','id':item.id}) %}
{% set report_url = url({'for':'admin.comment.report','id':item.id}) %}
<tr>
<td>{{ substr(item.content,0,120) }}</td>
<td>
@ -42,7 +42,7 @@
<td>{{ item.report_count }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td class="center">
<a href="{{ review_url }}" class="layui-btn layui-btn-sm">详情</a>
<a href="{{ report_url }}" class="layui-btn layui-btn-sm">详情</a>
</td>
</tr>
{% endfor %}

View File

@ -33,7 +33,7 @@
{% for item in pager.items %}
{% set question_url = url({'for':'home.question.show','id':item.id}) %}
{% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %}
{% set review_url = url({'for':'admin.question.report_review','id':item.id}) %}
{% set report_url = url({'for':'admin.question.report','id':item.id}) %}
<tr>
<td>
<p>标题:<a href="{{ question_url }}" target="_blank">{{ item.title }}</a></p>
@ -50,7 +50,7 @@
<td>{{ item.report_count }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td>
<td class="center">
<a href="{{ review_url }}" class="layui-btn layui-btn-sm">详情</a>
<a href="{{ report_url }}" class="layui-btn layui-btn-sm">详情</a>
</td>
</tr>
{% endfor %}

View File

@ -10,27 +10,27 @@
<label class="layui-form-label">内容实用</label>
<div class="layui-input-block">
<div id="rating1" class="kg-rating"></div>
<input type="hidden" name="rating1" value="{{ review.rating1 }}"/>
<input type="hidden" name="rating1" value="{{ review.rating1 }}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">通俗易懂</label>
<div class="layui-input-block">
<div id="rating2" class="kg-rating"></div>
<input type="hidden" name="rating2" value="{{ review.rating2 }}"/>
<input type="hidden" name="rating2" value="{{ review.rating2 }}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">逻辑清晰</label>
<div class="layui-input-block">
<div id="rating3" class="kg-rating"></div>
<input type="hidden" name="rating3" value="{{ review.rating3 }}"/>
<input type="hidden" name="rating3" value="{{ review.rating3 }}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">课程评价</label>
<div class="layui-input-block">
<div class="layui-form-mid gray">{{ review.content }}</div>
<textarea name="content" class="layui-textarea">{{ review.content }}</textarea>
</div>
</div>
<div class="layui-form-item">
@ -67,7 +67,6 @@
rate.render({
elem: '#rating1',
value: $rating1.val(),
readonly: true,
choose: function (value) {
$rating1.val(value);
}
@ -76,7 +75,6 @@
rate.render({
elem: '#rating2',
value: $rating2.val(),
readonly: true,
choose: function (value) {
$rating2.val(value);
}
@ -85,7 +83,6 @@
rate.render({
elem: '#rating3',
value: $rating3.val(),
readonly: true,
choose: function (value) {
$rating3.val(value);
}

View File

@ -2,6 +2,8 @@
{% block content %}
{{ partial('macros/review') }}
{% set search_url = url({'for':'admin.consult.search'}) %}
<div class="kg-nav">
@ -26,15 +28,15 @@
<col>
<col>
<col>
<col width="10%">
<col>
<col width="10%">
</colgroup>
<thead>
<tr>
<th>內容</th>
<th>评分</th>
<th>用户</th>
<th>发布</th>
<th>评分</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
@ -43,6 +45,7 @@
{% set list_by_course_url = url({'for':'admin.review.list'},{'course_id':item.course.id}) %}
{% set list_by_owner_url = url({'for':'admin.review.list'},{'owner_id':item.owner.id}) %}
{% set edit_url = url({'for':'admin.review.edit','id':item.id}) %}
{% set review_url = url({'for':'admin.review.moderate','id':item.id}) %}
{% set update_url = url({'for':'admin.review.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.review.delete','id':item.id}) %}
{% set restore_url = url({'for':'admin.review.restore','id':item.id}) %}
@ -52,20 +55,23 @@
<p class="layui-elip kg-item-elip" title="{{ item.content }}">评价:{{ item.content }}</p>
<p>时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p>
</td>
<td>
<p>昵称:<a href="{{ list_by_owner_url }}">{{ item.owner.name }}</a></p>
<p>编号:{{ item.owner.id }}</p>
</td>
<td>
<p>内容实用:{{ item.rating1 }}</p>
<p>通俗易懂:{{ item.rating2 }}</p>
<p>逻辑清晰:{{ item.rating3 }}</p>
</td>
<td>
<p>昵称:<a href="{{ list_by_owner_url }}">{{ item.owner.name }}</a></p>
<p>编号:{{ item.owner.id }}</p>
</td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
<td>{{ publish_status(item.published) }}</td>
<td class="center">
<div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul>
{% if item.published == 1 %}
<li><a href="{{ review_url }}">审核</a></li>
{% endif %}
<li><a href="{{ edit_url }}">编辑</a></li>
{% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>

View File

@ -0,0 +1,103 @@
{% extends 'templates/main.volt' %}
{% block content %}
{{ partial('macros/article') }}
{% set owner_url = url({'for':'home.user.show','id':review.owner.id}) %}
<fieldset class="layui-elem-field layui-field-title">
<legend>审核内容</legend>
</fieldset>
<form class="layui-form kg-form">
<div class="layui-form-item">
<label class="layui-form-label">内容实用</label>
<div class="layui-input-block">
<div id="rating1" class="kg-rating"></div>
<input type="hidden" name="rating1" value="{{ review.rating1 }}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">通俗易懂</label>
<div class="layui-input-block">
<div id="rating2" class="kg-rating"></div>
<input type="hidden" name="rating2" value="{{ review.rating2 }}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">逻辑清晰</label>
<div class="layui-input-block">
<div id="rating3" class="kg-rating"></div>
<input type="hidden" name="rating3" value="{{ review.rating3 }}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">评价内容</label>
<div class="layui-input-block">
<div class="layui-form-mid gray">{{ review.content }}</div>
</div>
</div>
</form>
<fieldset class="layui-elem-field layui-field-title">
<legend>审核意见</legend>
</fieldset>
{% set moderate_url = url({'for':'admin.review.moderate','id':review.id}) %}
<form class="layui-form kg-form kg-mod-form" method="POST" action="{{ moderate_url }}">
<div class="layui-form-item">
<label class="layui-form-label">审核</label>
<div class="layui-input-block">
<input type="radio" name="type" value="approve" title="通过" lay-filter="review">
<input type="radio" name="type" value="reject" title="拒绝" lay-filter="review">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button id="kg-submit" 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', 'rate'], function () {
var $ = layui.jquery;
var rate = layui.rate;
var $rating1 = $('input[name=rating1]');
var $rating2 = $('input[name=rating2]');
var $rating3 = $('input[name=rating3]');
rate.render({
elem: '#rating1',
value: $rating1.val(),
readonly: true,
});
rate.render({
elem: '#rating2',
value: $rating2.val(),
readonly: true,
});
rate.render({
elem: '#rating3',
value: $rating3.val(),
readonly: true,
});
});
</script>
{% endblock %}

View File

@ -25,10 +25,11 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">发布</label>
<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="否">
{% for value,title in publish_types %}
<input type="radio" name="published" value="{{ value }}" title="{{ title }}">
{% endfor %}
</div>
</div>
<div class="layui-form-item">

View File

@ -2,6 +2,8 @@
{% block content %}
{% set scope_style = tag2.scopes == 'all' ? 'display:none;' : '' %}
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.tag.update','id':tag2.id}) }}">
<fieldset class="layui-elem-field layui-field-title">
<legend>编辑标签</legend>
@ -22,6 +24,21 @@
<input class="layui-input" type="text" name="name" value="{{ tag2.name }}" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">范围</label>
<div class="layui-input-block">
<input type="radio" name="scope_type" value="all" title="全部" lay-filter="scope_type" {% if tag2.scopes == 'all' %}checked="checked"{% endif %}>
<input type="radio" name="scope_type" value="custom" title="自定" lay-filter="scope_type" {% if tag2.scopes != 'all' %}checked="checked"{% endif %}>
</div>
</div>
<div class="layui-form-item" id="scope-block" style="{{ scope_style }}">
<label class="layui-form-label"></label>
<div class="layui-input-block">
{% for value,title in scope_types %}
<input type="checkbox" name="scopes[]" value="{{ value }}" title="{{ title }}" {% if value in tag2.scopes %}checked="checked"{% endif %}>
{% endfor %}
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">发布</label>
<div class="layui-input-block">
@ -44,4 +61,28 @@
{{ js_include('admin/js/icon.upload.js') }}
{% endblock %}
{% block inline_js %}
<script>
layui.use(['jquery', 'form'], function () {
var $ = layui.jquery;
var form = layui.form;
form.on('radio(scope_type)', function (data) {
var block = $('#scope-block');
if (data.value === 'custom') {
block.show();
} else {
block.hide();
}
});
});
</script>
{% endblock %}

View File

@ -30,6 +30,7 @@
<col>
<col>
<col>
<col>
<col width="12%">
</colgroup>
<thead>
@ -37,9 +38,10 @@
<th>编号</th>
<th>图标</th>
<th>名称</th>
<th>关注数</th>
<th>创建时间</th>
<th>更新时间</th>
<th>关注</th>
<th>课程</th>
<th>文章</th>
<th>问题</th>
<th>发布</th>
<th>操作</th>
</tr>
@ -54,8 +56,9 @@
<td><img class="kg-icon" src="{{ item.icon }}" alt="{{ item.name }}"></td>
<td><a href="{{ edit_url }}">{{ item.name }}</a></td>
<td>{{ item.follow_count }}</td>
<td>{{ date('Y-m-d',item.create_time) }}</td>
<td>{{ date('Y-m-d',item.update_time) }}</td>
<td>{{ item.course_count }}</td>
<td>{{ item.article_count }}</td>
<td>{{ item.question_count }}</td>
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}>
</td>
<td class="center">

View File

@ -0,0 +1,150 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Http\Api\Controllers;
use App\Services\Logic\Answer\AnswerAccept as AnswerAcceptService;
use App\Services\Logic\Answer\AnswerCreate as AnswerCreateService;
use App\Services\Logic\Answer\AnswerDelete as AnswerDeleteService;
use App\Services\Logic\Answer\AnswerInfo as AnswerInfoService;
use App\Services\Logic\Answer\AnswerLike as AnswerLikeService;
use App\Services\Logic\Answer\AnswerUpdate as AnswerUpdateService;
use App\Services\Logic\Answer\CommentList as CommentListService;
/**
* @RoutePrefix("/api/answer")
*/
class AnswerController extends Controller
{
/**
* @Get("/{id:[0-9]+}/info", name="api.answer.info")
*/
public function infoAction($id)
{
$service = new AnswerInfoService();
$answer = $service->handle($id);
return $this->jsonSuccess(['answer' => $answer]);
}
/**
* @Get("/{id:[0-9]+}/comments", name="api.answer.comments")
*/
public function commentsAction($id)
{
$service = new CommentListService();
$pager = $service->handle($id);
return $this->jsonPaginate($pager);
}
/**
* @Post("/create", name="api.answer.create")
*/
public function createAction()
{
$service = new AnswerCreateService();
$answer = $service->handle();
$content = [
'answer' => $answer,
'msg' => '创建回答成功',
];
return $this->jsonSuccess($content);
}
/**
* @Post("/{id:[0-9]+}/update", name="api.answer.update")
*/
public function updateAction($id)
{
$service = new AnswerUpdateService();
$answer = $service->handle($id);
$content = [
'answer' => $answer,
'msg' => '更新回答成功',
];
return $this->jsonSuccess($content);
}
/**
* @Post("/{id:[0-9]+}/delete", name="api.answer.delete")
*/
public function deleteAction($id)
{
$service = new AnswerDeleteService();
$service->handle($id);
return $this->jsonSuccess(['msg' => '删除回答成功']);
}
/**
* @Post("/{id:[0-9]+}/accept", name="api.answer.accept")
*/
public function acceptAction($id)
{
$service = new AnswerAcceptService();
$data = $service->handle($id);
$msg = $data['action'] == 'do' ? '采纳成功' : '取消采纳成功';
return $this->jsonSuccess(['data' => $data, 'msg' => $msg]);
}
/**
* @Post("/{id:[0-9]+}/unaccept", name="api.answer.unaccept")
*/
public function unacceptAction($id)
{
$service = new AnswerAcceptService();
$data = $service->handle($id);
$msg = $data['action'] == 'do' ? '采纳成功' : '取消采纳成功';
return $this->jsonSuccess(['data' => $data, 'msg' => $msg]);
}
/**
* @Post("/{id:[0-9]+}/like", name="api.answer.like")
*/
public function likeAction($id)
{
$service = new AnswerLikeService();
$data = $service->handle($id);
$msg = $data['action'] == 'do' ? '点赞成功' : '取消点赞成功';
return $this->jsonSuccess(['data' => $data, 'msg' => $msg]);
}
/**
* @Post("/{id:[0-9]+}/like", name="api.answer.unlike")
*/
public function unlikeAction($id)
{
$service = new AnswerLikeService();
$data = $service->handle($id);
$msg = $data['action'] == 'do' ? '点赞成功' : '取消点赞成功';
return $this->jsonSuccess(['data' => $data, 'msg' => $msg]);
}
}

View File

@ -0,0 +1,127 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Http\Api\Controllers;
use App\Services\Logic\Article\ArticleFavorite as ArticleFavoriteService;
use App\Services\Logic\Article\ArticleInfo as ArticleInfoService;
use App\Services\Logic\Article\ArticleLike as ArticleLikeService;
use App\Services\Logic\Article\ArticleList as ArticleListService;
use App\Services\Logic\Article\CategoryList as CategoryListService;
use App\Services\Logic\Article\CommentList as CommentListService;
/**
* @RoutePrefix("/api/article")
*/
class ArticleController extends Controller
{
/**
* @Get("/categories", name="api.article.categories")
*/
public function categoriesAction()
{
$service = new CategoryListService();
$categories = $service->handle();
return $this->jsonSuccess(['categories' => $categories]);
}
/**
* @Get("/list", name="api.article.list")
*/
public function listAction()
{
$service = new ArticleListService();
$pager = $service->handle();
return $this->jsonPaginate($pager);
}
/**
* @Get("/{id:[0-9]+}/info", name="api.article.info")
*/
public function infoAction($id)
{
$service = new ArticleInfoService();
$article = $service->handle($id);
return $this->jsonSuccess(['article' => $article]);
}
/**
* @Get("/{id:[0-9]+}/comments", name="api.article.comments")
*/
public function commentsAction($id)
{
$service = new CommentListService();
$pager = $service->handle($id);
return $this->jsonPaginate($pager);
}
/**
* @Post("/{id:[0-9]+}/favorite", name="api.article.favorite")
*/
public function favoriteAction($id)
{
$service = new ArticleFavoriteService();
$data = $service->handle($id);
$msg = $data['action'] == 'do' ? '收藏成功' : '取消收藏成功';
return $this->jsonSuccess(['data' => $data, 'msg' => $msg]);
}
/**
* @Post("/{id:[0-9]+}/unfavorite", name="api.article.unfavorite")
*/
public function unfavoriteAction($id)
{
$service = new ArticleFavoriteService();
$data = $service->handle($id);
$msg = $data['action'] == 'do' ? '收藏成功' : '取消收藏成功';
return $this->jsonSuccess(['data' => $data, 'msg' => $msg]);
}
/**
* @Post("/{id:[0-9]+}/like", name="api.article.like")
*/
public function likeAction($id)
{
$service = new ArticleLikeService();
$data = $service->handle($id);
$msg = $data['action'] == 'do' ? '点赞成功' : '取消点赞成功';
return $this->jsonSuccess(['data' => $data, 'msg' => $msg]);
}
/**
* @Post("/{id:[0-9]+}/like", name="api.article.unlike")
*/
public function unlikeAction($id)
{
$service = new ArticleLikeService();
$data = $service->handle($id);
$msg = $data['action'] == 'do' ? '点赞成功' : '取消点赞成功';
return $this->jsonSuccess(['data' => $data, 'msg' => $msg]);
}
}

View File

@ -7,6 +7,7 @@
namespace App\Http\Api\Controllers;
use App\Services\Logic\Article\CommentList as CommentListService;
use App\Services\Logic\Chapter\ChapterInfo as ChapterInfoService;
use App\Services\Logic\Chapter\ChapterLike as ChapterLikeService;
use App\Services\Logic\Chapter\ConsultList as ChapterConsultListService;
@ -19,6 +20,18 @@ use App\Services\Logic\Chapter\ResourceList as ChapterResourceListService;
class ChapterController extends Controller
{
/**
* @Get("/{id:[0-9]+}/comments", name="api.chapter.comments")
*/
public function commentsAction($id)
{
$service = new CommentListService();
$pager = $service->handle($id);
return $this->jsonPaginate($pager);
}
/**
* @Get("/{id:[0-9]+}/consults", name="api.chapter.consults")
*/
@ -28,7 +41,7 @@ class ChapterController extends Controller
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**

View File

@ -0,0 +1,119 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Http\Api\Controllers;
use App\Services\Logic\Comment\CommentCreate as CommentCreateService;
use App\Services\Logic\Comment\CommentDelete as CommentDeleteService;
use App\Services\Logic\Comment\CommentInfo as CommentInfoService;
use App\Services\Logic\Comment\CommentLike as CommentLikeService;
use App\Services\Logic\Comment\CommentReply as CommentReplyService;
use App\Services\Logic\Comment\ReplyList as ReplyListService;
/**
* @RoutePrefix("/api/comment")
*/
class CommentController extends Controller
{
/**
* @Get("/{id:[0-9]+}/replies", name="api.comment.replies")
*/
public function repliesAction($id)
{
$service = new ReplyListService();
$pager = $service->handle($id);
return $this->jsonPaginate($pager);
}
/**
* @Get("/{id:[0-9]+}/info", name="home.comment.info")
*/
public function infoAction($id)
{
$service = new CommentInfoService();
$comment = $service->handle($id);
return $this->jsonSuccess(['comment' => $comment]);
}
/**
* @Post("/create", name="home.comment.create")
*/
public function createAction()
{
$service = new CommentCreateService();
$comment = $service->handle();
$service = new CommentInfoService();
$comment = $service->handle($comment->id);
return $this->jsonSuccess(['comment' => $comment]);
}
/**
* @Post("/{id:[0-9]+}/reply", name="home.comment.reply")
*/
public function replyAction($id)
{
$service = new CommentReplyService();
$comment = $service->handle($id);
$service = new CommentInfoService();
$comment = $service->handle($comment->id);
return $this->jsonSuccess(['comment' => $comment]);
}
/**
* @Post("/{id:[0-9]+}/delete", name="home.comment.delete")
*/
public function deleteAction($id)
{
$service = new CommentDeleteService();
$service->handle($id);
return $this->jsonSuccess(['msg' => '删除评论成功']);
}
/**
* @Post("/{id:[0-9]+}/like", name="home.comment.like")
*/
public function likeAction($id)
{
$service = new CommentLikeService();
$data = $service->handle($id);
$msg = $data['action'] == 'do' ? '点赞成功' : '取消点赞成功';
return $this->jsonSuccess(['data' => $data, 'msg' => $msg]);
}
/**
* @Post("/{id:[0-9]+}/like", name="home.comment.like")
*/
public function unlikeAction($id)
{
$service = new CommentLikeService();
$data = $service->handle($id);
$msg = $data['action'] == 'do' ? '点赞成功' : '取消点赞成功';
return $this->jsonSuccess(['data' => $data, 'msg' => $msg]);
}
}

View File

@ -7,14 +7,14 @@
namespace App\Http\Api\Controllers;
use App\Services\Logic\Course\CategoryList as CourseCategoryListService;
use App\Services\Logic\Course\ChapterList as CourseChapterListService;
use App\Services\Logic\Course\ConsultList as CourseConsultListService;
use App\Services\Logic\Course\CategoryList as CategoryListService;
use App\Services\Logic\Course\ChapterList as ChapterListService;
use App\Services\Logic\Course\ConsultList as ConsultListService;
use App\Services\Logic\Course\CourseFavorite as CourseFavoriteService;
use App\Services\Logic\Course\CourseInfo as CourseInfoService;
use App\Services\Logic\Course\CourseList as CourseListService;
use App\Services\Logic\Course\PackageList as CoursePackageListService;
use App\Services\Logic\Course\ReviewList as CourseReviewListService;
use App\Services\Logic\Course\PackageList as PackageListService;
use App\Services\Logic\Course\ReviewList as ReviewListService;
/**
* @RoutePrefix("/api/course")
@ -27,7 +27,7 @@ class CourseController extends Controller
*/
public function categoriesAction()
{
$service = new CourseCategoryListService();
$service = new CategoryListService();
$categories = $service->handle();
@ -43,7 +43,7 @@ class CourseController extends Controller
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
@ -63,7 +63,7 @@ class CourseController extends Controller
*/
public function chaptersAction($id)
{
$service = new CourseChapterListService();
$service = new ChapterListService();
$chapters = $service->handle($id);
@ -75,7 +75,7 @@ class CourseController extends Controller
*/
public function packagesAction($id)
{
$service = new CoursePackageListService();
$service = new PackageListService();
$packages = $service->handle($id);
@ -87,11 +87,11 @@ class CourseController extends Controller
*/
public function consultsAction($id)
{
$service = new CourseConsultListService();
$service = new ConsultListService();
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
@ -99,11 +99,11 @@ class CourseController extends Controller
*/
public function reviewsAction($id)
{
$service = new CourseReviewListService();
$service = new ReviewListService();
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**

View File

@ -26,7 +26,7 @@ class ImGroupController extends Controller
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
@ -50,7 +50,7 @@ class ImGroupController extends Controller
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
}

View File

@ -25,7 +25,7 @@ class LiveController extends Controller
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**

View File

@ -0,0 +1,140 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Http\Api\Controllers;
use App\Services\Logic\Question\AnswerList as AnswerListService;
use App\Services\Logic\Question\CategoryList as CategoryListService;
use App\Services\Logic\Question\CommentList as CommentListService;
use App\Services\Logic\Question\QuestionFavorite as QuestionFavoriteService;
use App\Services\Logic\Question\QuestionInfo as QuestionInfoService;
use App\Services\Logic\Question\QuestionLike as QuestionLikeService;
use App\Services\Logic\Question\QuestionList as QuestionListService;
/**
* @RoutePrefix("/api/question")
*/
class QuestionController extends Controller
{
/**
* @Get("/categories", name="api.question.categories")
*/
public function categoriesAction()
{
$service = new CategoryListService();
$categories = $service->handle();
return $this->jsonSuccess(['categories' => $categories]);
}
/**
* @Get("/list", name="api.question.list")
*/
public function listAction()
{
$service = new QuestionListService();
$pager = $service->handle();
return $this->jsonPaginate($pager);
}
/**
* @Get("/{id:[0-9]+}/info", name="api.question.info")
*/
public function infoAction($id)
{
$service = new QuestionInfoService();
$question = $service->handle($id);
return $this->jsonSuccess(['question' => $question]);
}
/**
* @Get("/{id:[0-9]+}/answers", name="api.question.answers")
*/
public function answersAction($id)
{
$service = new AnswerListService();
$pager = $service->handle($id);
return $this->jsonPaginate($pager);
}
/**
* @Get("/{id:[0-9]+}/comments", name="api.question.comments")
*/
public function commentsAction($id)
{
$service = new CommentListService();
$pager = $service->handle($id);
return $this->jsonPaginate($pager);
}
/**
* @Post("/{id:[0-9]+}/favorite", name="api.question.favorite")
*/
public function favoriteAction($id)
{
$service = new QuestionFavoriteService();
$data = $service->handle($id);
$msg = $data['action'] == 'do' ? '收藏成功' : '取消收藏成功';
return $this->jsonSuccess(['data' => $data, 'msg' => $msg]);
}
/**
* @Post("/{id:[0-9]+}/unfavorite", name="api.question.unfavorite")
*/
public function unfavoriteAction($id)
{
$service = new QuestionFavoriteService();
$data = $service->handle($id);
$msg = $data['action'] == 'do' ? '收藏成功' : '取消收藏成功';
return $this->jsonSuccess(['data' => $data, 'msg' => $msg]);
}
/**
* @Post("/{id:[0-9]+}/like", name="api.question.like")
*/
public function likeAction($id)
{
$service = new QuestionLikeService();
$data = $service->handle($id);
$msg = $data['action'] == 'do' ? '点赞成功' : '取消点赞成功';
return $this->jsonSuccess(['data' => $data, 'msg' => $msg]);
}
/**
* @Post("/{id:[0-9]+}/like", name="api.question.unlike")
*/
public function unlikeAction($id)
{
$service = new QuestionLikeService();
$data = $service->handle($id);
$msg = $data['action'] == 'do' ? '点赞成功' : '取消点赞成功';
return $this->jsonSuccess(['data' => $data, 'msg' => $msg]);
}
}

View File

@ -33,14 +33,14 @@ class SearchController extends Controller
];
if (empty($query)) {
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
$service = $this->getSearchService($type);
$pager = $service->search();
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**

View File

@ -26,7 +26,7 @@ class TeacherController extends Controller
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
@ -50,7 +50,7 @@ class TeacherController extends Controller
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
}

View File

@ -8,6 +8,8 @@
namespace App\Http\Api\Controllers;
use App\Services\Logic\User\Console\AccountInfo as AccountInfoService;
use App\Services\Logic\User\Console\AnswerList as AnswerListService;
use App\Services\Logic\User\Console\ArticleList as ArticleListService;
use App\Services\Logic\User\Console\ConsultList as ConsultListService;
use App\Services\Logic\User\Console\CourseList as CourseListService;
use App\Services\Logic\User\Console\FavoriteList as FavoriteListService;
@ -20,6 +22,7 @@ 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;
use App\Services\Logic\User\Console\QuestionList as QuestionListService;
use App\Services\Logic\User\Console\RefundList as RefundListService;
use App\Services\Logic\User\Console\ReviewList as ReviewListService;
@ -62,7 +65,43 @@ class UserConsoleController extends Controller
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
* @Get("/articles", name="api.uc.articles")
*/
public function articlesAction()
{
$service = new ArticleListService();
$pager = $service->handle();
return $this->jsonPaginate($pager);
}
/**
* @Get("/questions", name="api.uc.questions")
*/
public function questionsAction()
{
$service = new QuestionListService();
$pager = $service->handle();
return $this->jsonPaginate($pager);
}
/**
* @Get("/answers", name="api.uc.answers")
*/
public function answersAction()
{
$service = new AnswerListService();
$pager = $service->handle();
return $this->jsonPaginate($pager);
}
/**
@ -74,7 +113,7 @@ class UserConsoleController extends Controller
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
@ -86,7 +125,7 @@ class UserConsoleController extends Controller
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
@ -98,7 +137,7 @@ class UserConsoleController extends Controller
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
@ -110,7 +149,7 @@ class UserConsoleController extends Controller
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
@ -122,7 +161,7 @@ class UserConsoleController extends Controller
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
@ -134,7 +173,7 @@ class UserConsoleController extends Controller
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
@ -146,7 +185,7 @@ class UserConsoleController extends Controller
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
@ -162,7 +201,7 @@ class UserConsoleController extends Controller
$service->handle();
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**

View File

@ -7,10 +7,12 @@
namespace App\Http\Api\Controllers;
use App\Services\Logic\User\ArticleList as UserArticleListService;
use App\Services\Logic\User\CourseList as UserCourseListService;
use App\Services\Logic\User\FriendList as UserFriendListService;
use App\Services\Logic\User\GroupList as UserGroupListService;
use App\Services\Logic\User\AnswerList as AnswerListService;
use App\Services\Logic\User\ArticleList as ArticleListService;
use App\Services\Logic\User\CourseList as CourseListService;
use App\Services\Logic\User\FriendList as FriendListService;
use App\Services\Logic\User\GroupList as GroupListService;
use App\Services\Logic\User\QuestionList as QuestionListService;
use App\Services\Logic\User\UserInfo as UserInfoService;
/**
@ -36,11 +38,11 @@ class UserController extends Controller
*/
public function coursesAction($id)
{
$service = new UserCourseListService();
$service = new CourseListService();
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
@ -48,11 +50,35 @@ class UserController extends Controller
*/
public function articlesAction($id)
{
$service = new UserArticleListService();
$service = new ArticleListService();
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
* @Get("/{id:[0-9]+}/questions", name="api.user.questions")
*/
public function questionsAction($id)
{
$service = new QuestionListService();
$pager = $service->handle($id);
return $this->jsonPaginate($pager);
}
/**
* @Get("/{id:[0-9]+}/answers", name="api.user.answers")
*/
public function answersAction($id)
{
$service = new AnswerListService();
$pager = $service->handle($id);
return $this->jsonPaginate($pager);
}
/**
@ -60,11 +86,11 @@ class UserController extends Controller
*/
public function friendsAction($id)
{
$service = new UserFriendListService();
$service = new FriendListService();
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
@ -72,11 +98,11 @@ class UserController extends Controller
*/
public function groupsAction($id)
{
$service = new UserGroupListService();
$service = new GroupListService();
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
}

View File

@ -27,7 +27,7 @@ class VipController extends Controller
$pager = $service->handle($type);
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
/**
@ -39,7 +39,7 @@ class VipController extends Controller
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
return $this->jsonPaginate($pager);
}
}

View File

@ -32,6 +32,8 @@ class AccountController extends Controller
$captcha = $service->getSettings('captcha');
$this->seo->prependTitle('注册');
$this->view->setVar('return_url', $returnUrl);
$this->view->setVar('captcha', $captcha);
}
@ -74,6 +76,8 @@ class AccountController extends Controller
$returnUrl = $this->request->getHTTPReferer();
$this->seo->prependTitle('登录');
$this->view->setVar('oauth_provider', $oauthProvider);
$this->view->setVar('return_url', $returnUrl);
$this->view->setVar('captcha', $captcha);
@ -136,6 +140,8 @@ class AccountController extends Controller
$captcha = $service->getSettings('captcha');
$this->seo->prependTitle('忘记密码');
$this->view->pick('account/forget_password');
$this->view->setVar('captcha', $captcha);
}

View File

@ -60,12 +60,12 @@ class AnswerController extends Controller
return $this->notFound();
}
$questionId = $answer['question']['id'];
if ($answer['me']['owned'] == 0) {
$this->response->redirect(['for' => 'home.error.403']);
}
$questionId = $answer['question']['id'];
$location = $this->url->get(
['for' => 'home.question.show', 'id' => $questionId],
['answer_id' => $id],

View File

@ -110,7 +110,7 @@ class ArticleController extends Controller
$this->response->redirect(['for' => 'home.error.403']);
}
$this->seo->prependTitle($article['title']);
$this->seo->prependTitle(['专栏', $article['title']]);
$this->seo->setDescription($article['summary']);
$this->view->setVar('article', $article);

View File

@ -55,7 +55,7 @@ class ImGroupController extends Controller
return $this->notFound();
}
$this->seo->prependTitle([$group['name'], '群组']);
$this->seo->prependTitle(['群组', $group['name']]);
$this->view->pick('im/group/show');
$this->view->setVar('group', $group);

View File

@ -61,6 +61,8 @@ class OrderController extends Controller
$confirm = $service->handle($itemId, $itemType);
$this->seo->prependTitle('确认订单');
$this->view->setVar('confirm', $confirm);
}
@ -100,6 +102,8 @@ class OrderController extends Controller
$this->response->redirect(['for' => 'home.uc.orders']);
}
$this->seo->prependTitle('支付订单');
$this->view->setVar('pay_provider', $payProvider);
$this->view->setVar('order', $order);
}

View File

@ -35,7 +35,7 @@ class PageController extends Controller
$featuredCourses = $this->getFeaturedCourses();
$this->seo->prependTitle($page['title']);
$this->seo->prependTitle(['单页', $page['title']]);
$this->view->setVar('page', $page);
$this->view->setVar('featured_courses', $featuredCourses);

View File

@ -109,7 +109,7 @@ class QuestionController extends Controller
$this->response->redirect(['for' => 'home.error.403']);
}
$this->seo->prependTitle($question['title']);
$this->seo->prependTitle(['问答', $question['title']]);
$this->seo->setDescription($question['summary']);
$this->view->setVar('question', $question);

View File

@ -35,7 +35,7 @@ class UserController extends Controller
return $this->notFound();
}
$this->seo->prependTitle([$user['name'], '个人主页']);
$this->seo->prependTitle(['空间', $user['name']]);
$this->view->setVar('user', $user);
}

View File

@ -4,7 +4,6 @@
{{ partial('macros/article') }}
{% set article_list_url = url({'for':'home.article.list'}) %}
{% set article_edit_url = url({'for':'home.article.edit','id':article.id}) %}
{% set article_delete_url = url({'for':'home.article.delete','id':article.id}) %}
{% set article_owner_url = url({'for':'home.user.show','id':article.owner.id}) %}
@ -14,7 +13,7 @@
<div class="breadcrumb">
<span class="layui-breadcrumb">
<a href="/">首页</a>
<a href="{{ article_list_url }}">专栏</a>
<a><cite>专栏</cite></a>
<a><cite>详情</cite></a>
</span>
<span class="share">

View File

@ -90,7 +90,7 @@
function loadPageHtml(target, params) {
$.get('/im/chat/history', params, function (res) {
var html = laytpl($tpl.val()).render({
data: res.items
data: res.pager.items
});
target.html(html);
});

View File

@ -8,7 +8,7 @@
<div class="breadcrumb">
<span class="layui-breadcrumb">
<a href="/">首页</a>
<a href="{{ url({'for':'home.im_group.list'}) }}">群组</a>
<a><cite>群组</cite></a>
<a><cite>{{ group.name }}</cite></a>
</span>
</div>

View File

@ -4,7 +4,6 @@
{{ partial('macros/question') }}
{% set question_list_url = url({'for':'home.question.list'}) %}
{% set question_report_url = url({'for':'home.report.add'},{'item_id':question.id,'item_type':107}) %}
{% set question_edit_url = url({'for':'home.question.edit','id':question.id}) %}
{% set question_delete_url = url({'for':'home.question.delete','id':question.id}) %}
@ -19,7 +18,7 @@
<div class="breadcrumb">
<span class="layui-breadcrumb">
<a href="/">首页</a>
<a href="{{ question_list_url }}">问答</a>
<a><cite>问答</cite></a>
<a><cite>详情</cite></a>
</span>
<span class="share">
@ -65,7 +64,7 @@
{% endif %}
</div>
<div id="answer-anchor"></div>
{% if question.me.answered == 0 %}
{% if question.me.answered == 0 and question.published == 2 %}
<div class="answer-wrap wrap">
<button class="layui-btn layui-btn-fluid btn-answer" data-url="{{ answer_add_url }}">回答问题</button>
</div>

View File

@ -9,7 +9,7 @@
<div class="breadcrumb">
<span class="layui-breadcrumb">
<a href="/">首页</a>
<a><cite>个人主页</cite></a>
<a><cite>空间</cite></a>
<a><cite>{{ user.name }}</cite></a>
</span>
<span class="share">

View File

@ -16,9 +16,14 @@ class AppInfo
protected $link = 'https://koogua.com';
protected $version = '1.3.8';
protected $version = '1.3.9';
public function __get($name)
{
return $this->get($name);
}
public function get($name)
{
if (isset($this->{$name})) {
return $this->{$name};

View File

@ -9,6 +9,7 @@ namespace App\Models;
use App\Caches\MaxCategoryId as MaxCategoryIdCache;
use Phalcon\Mvc\Model\Behavior\SoftDelete;
use Phalcon\Text;
class Category extends Model
{
@ -56,6 +57,20 @@ class Category extends Model
*/
public $name = '';
/**
* 别名
*
* @var string
*/
public $alias = '';
/**
* 图标
*
* @var string
*/
public $icon = '';
/**
* 路径
*
@ -136,6 +151,15 @@ class Category extends Model
$this->update_time = time();
}
public function beforeSave()
{
if (empty($this->icon)) {
$this->icon = kg_default_icon_path();
} elseif (Text::startsWith($this->icon, 'http')) {
$this->icon = self::getIconPath($this->icon);
}
}
public function afterCreate()
{
$cache = new MaxCategoryIdCache();
@ -143,6 +167,22 @@ class Category extends Model
$cache->rebuild();
}
public function afterFetch()
{
if (!Text::startsWith($this->icon, 'http')) {
$this->icon = kg_cos_icon_url($this->icon);
}
}
public static function getIconPath($url)
{
if (Text::startsWith($url, 'http')) {
return parse_url($url, PHP_URL_PATH);
}
return $url;
}
public static function types()
{
return [

View File

@ -101,6 +101,13 @@ class Course extends Model
*/
public $summary = '';
/**
* 标签
*
* @var array|string
*/
public $tags = [];
/**
* 关键字
*
@ -350,6 +357,10 @@ class Course extends Model
$this->cover = self::getCoverPath($this->cover);
}
if (is_array($this->tags) || is_object($this->tags)) {
$this->tags = kg_json_encode($this->tags);
}
if (empty($this->summary)) {
$this->summary = kg_parse_summary($this->details);
}
@ -378,6 +389,10 @@ class Course extends Model
$this->cover = kg_cos_course_cover_url($this->cover);
}
if (is_string($this->tags)) {
$this->tags = json_decode($this->tags, true);
}
if (is_string($this->attrs)) {
$this->attrs = json_decode($this->attrs, true);
}

51
app/Models/CourseTag.php Normal file
View File

@ -0,0 +1,51 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Models;
class CourseTag extends Model
{
/**
* 主键编号
*
* @var int
*/
public $id = 0;
/**
* 课程编号
*
* @var int
*/
public $course_id = 0;
/**
* 标签编号
*
* @var int
*/
public $tag_id = 0;
/**
* 创建时间
*
* @var int
*/
public $create_time = 0;
public function getSource(): string
{
return 'kg_course_tag';
}
public function beforeCreate()
{
$this->create_time = time();
}
}

View File

@ -12,6 +12,13 @@ use Phalcon\Mvc\Model\Behavior\SoftDelete;
class Review extends Model
{
/**
* 发布状态
*/
const PUBLISH_PENDING = 1; // 审核中
const PUBLISH_APPROVED = 2; // 已发布
const PUBLISH_REJECTED = 3; // 未通过
/**
* 主键编号
*
@ -101,7 +108,7 @@ class Review extends Model
*
* @var int
*/
public $published = 1;
public $published = self::PUBLISH_PENDING;
/**
* 删除标识
@ -181,4 +188,13 @@ class Review extends Model
return round($sumRating / 3, 2);
}
public static function publishTypes()
{
return [
self::PUBLISH_PENDING => '审核中',
self::PUBLISH_APPROVED => '已发布',
self::PUBLISH_REJECTED => '未通过',
];
}
}

View File

@ -14,6 +14,13 @@ use Phalcon\Text;
class Tag extends Model
{
/**
* 范围类型
*/
const SCOPE_ARTICLE = 1;
const SCOPE_QUESTION = 2;
const SCOPE_COURSE = 3;
/**
* 主键编号
*
@ -42,6 +49,13 @@ class Tag extends Model
*/
public $icon = '';
/**
* 范围
*
* @var array|string
*/
public $scopes = 'all';
/**
* 优先级
*
@ -70,6 +84,27 @@ class Tag extends Model
*/
public $follow_count = 0;
/**
* 课程数量
*
* @var int
*/
public $course_count = 0;
/**
* 文章数量
*
* @var int
*/
public $article_count = 0;
/**
* 问题数量
*
* @var int
*/
public $question_count = 0;
/**
* 创建时间
*
@ -122,6 +157,10 @@ class Tag extends Model
} elseif (Text::startsWith($this->icon, 'http')) {
$this->icon = self::getIconPath($this->icon);
}
if (is_array($this->scopes) || is_object($this->scopes)) {
$this->scopes = kg_json_encode($this->scopes);
}
}
public function afterCreate()
@ -136,6 +175,10 @@ class Tag extends Model
if (!Text::startsWith($this->icon, 'http')) {
$this->icon = kg_cos_icon_url($this->icon);
}
if (is_string($this->scopes) && $this->scopes != 'all') {
$this->scopes = json_decode($this->scopes, true);
}
}
public static function getIconPath($url)
@ -147,4 +190,13 @@ class Tag extends Model
return $url;
}
public static function scopeTypes()
{
return [
self::SCOPE_ARTICLE => '文章',
self::SCOPE_QUESTION => '问答',
self::SCOPE_COURSE => '课程',
];
}
}

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