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

Merge branch 'koogua/v1.3.9' into demo

This commit is contained in:
koogua 2021-07-23 20:13:30 +08:00
commit 1eef7c3cf0
34 changed files with 361 additions and 47 deletions

View File

@ -13,9 +13,9 @@
- 优化API的分页返回结构 - 优化API的分页返回结构
- 增加文章问答评论相关API - 增加文章问答评论相关API
- 增加重新统计tag中相关计数计划任务 - 增加重新统计tag中相关计数计划任务
- 增加tag的使用范围,文章,问题,课程计数 - 增加tag的使用范围文章,问题,课程计数
- 站点logo和favicon使用随机文件名 - 站点logo和favicon使用随机文件名
- 增加评价审核 - 增加评价,咨询审核
- 去除编辑器中的酷瓜云课堂标识 - 去除编辑器中的酷瓜云课堂标识
- 清理数据迁移文件 - 清理数据迁移文件

View File

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

View File

@ -27,6 +27,18 @@ class ModerationController extends Controller
$this->view->setVar('pager', $pager); $this->view->setVar('pager', $pager);
} }
/**
* @Get("/consults", name="admin.mod.consults")
*/
public function consultsAction()
{
$modService = new ModerationService();
$pager = $modService->getConsults();
$this->view->setVar('pager', $pager);
}
/** /**
* @Get("/articles", name="admin.mod.articles") * @Get("/articles", name="admin.mod.articles")
*/ */

View File

@ -514,6 +514,12 @@ class AuthNode extends Service
'type' => 'menu', 'type' => 'menu',
'route' => 'admin.mod.reviews', 'route' => 'admin.mod.reviews',
], ],
[
'id' => '2-10-6',
'title' => '咨询审核',
'type' => 'menu',
'route' => 'admin.mod.consults',
],
[ [
'id' => '2-10-1', 'id' => '2-10-1',
'title' => '文章审核', 'title' => '文章审核',
@ -631,6 +637,12 @@ class AuthNode extends Service
'type' => 'button', 'type' => 'button',
'route' => 'admin.consult.delete', 'route' => 'admin.consult.delete',
], ],
[
'id' => '2-2-5',
'title' => '审核咨询',
'type' => 'button',
'route' => 'admin.consult.moderate',
],
], ],
], ],
[ [

View File

@ -15,12 +15,18 @@ use App\Models\Course as CourseModel;
use App\Repos\Chapter as ChapterRepo; use App\Repos\Chapter as ChapterRepo;
use App\Repos\Consult as ConsultRepo; use App\Repos\Consult as ConsultRepo;
use App\Repos\Course as CourseRepo; use App\Repos\Course as CourseRepo;
use App\Services\Logic\Consult\ConsultInfo as ConsultInfoService;
use App\Services\Logic\Notice\ConsultReply as ConsultReplyNotice; use App\Services\Logic\Notice\ConsultReply as ConsultReplyNotice;
use App\Validators\Consult as ConsultValidator; use App\Validators\Consult as ConsultValidator;
class Consult extends Service class Consult extends Service
{ {
public function getPublishTypes()
{
return ConsultModel::publishTypes();
}
public function getConsults() public function getConsults()
{ {
$pagerQuery = new PagerQuery(); $pagerQuery = new PagerQuery();
@ -52,6 +58,13 @@ class Consult extends Service
return $this->findOrFail($id); return $this->findOrFail($id);
} }
public function getConsultInfo($id)
{
$service = new ConsultInfoService();
return $service->handle($id);
}
public function updateConsult($id) public function updateConsult($id)
{ {
$consult = $this->findOrFail($id); $consult = $this->findOrFail($id);
@ -116,6 +129,31 @@ class Consult extends Service
$this->handleItemConsults($consult); $this->handleItemConsults($consult);
} }
public function moderate($id)
{
$type = $this->request->getPost('type', ['trim', 'string']);
$consult = $this->findOrFail($id);
if ($type == 'approve') {
$consult->published = ConsultModel::PUBLISH_APPROVED;
} elseif ($type == 'reject') {
$consult->published = ConsultModel::PUBLISH_REJECTED;
}
$consult->update();
$this->handleItemConsults($consult);
if ($type == 'approve') {
$this->eventsManager->fire('Consult:afterApprove', $this, $consult);
} elseif ($type == 'reject') {
$this->eventsManager->fire('Consult:afterReject', $this, $consult);
}
return $consult;
}
protected function handleItemConsults(ConsultModel $consult) protected function handleItemConsults(ConsultModel $consult)
{ {
if ($consult->course_id > 0) { if ($consult->course_id > 0) {

View File

@ -80,6 +80,7 @@ class Index extends Service
$statRepo = new StatRepo(); $statRepo = new StatRepo();
$reviewCount = $statRepo->countPendingReviews(); $reviewCount = $statRepo->countPendingReviews();
$consultCount = $statRepo->countPendingConsults();
$articleCount = $statRepo->countPendingArticles(); $articleCount = $statRepo->countPendingArticles();
$questionCount = $statRepo->countPendingQuestions(); $questionCount = $statRepo->countPendingQuestions();
$answerCount = $statRepo->countPendingAnswers(); $answerCount = $statRepo->countPendingAnswers();
@ -87,6 +88,7 @@ class Index extends Service
return [ return [
'review_count' => $reviewCount, 'review_count' => $reviewCount,
'consult_count' => $consultCount,
'article_count' => $articleCount, 'article_count' => $articleCount,
'question_count' => $questionCount, 'question_count' => $questionCount,
'answer_count' => $answerCount, 'answer_count' => $answerCount,

View File

@ -9,17 +9,20 @@ namespace App\Http\Admin\Services;
use App\Builders\AnswerList as AnswerListBuilder; use App\Builders\AnswerList as AnswerListBuilder;
use App\Builders\ArticleList as ArticleListBuilder; use App\Builders\ArticleList as ArticleListBuilder;
use App\Builders\ConsultList as ConsultListBuilder;
use App\Builders\QuestionList as QuestionListBuilder; use App\Builders\QuestionList as QuestionListBuilder;
use App\Builders\ReviewList as ReviewListBuilder; use App\Builders\ReviewList as ReviewListBuilder;
use App\Library\Paginator\Query as PagerQuery; use App\Library\Paginator\Query as PagerQuery;
use App\Models\Answer as AnswerModel; use App\Models\Answer as AnswerModel;
use App\Models\Article as ArticleModel; use App\Models\Article as ArticleModel;
use App\Models\Comment as CommentModel; use App\Models\Comment as CommentModel;
use App\Models\Consult as ConsultModel;
use App\Models\Question as QuestionModel; use App\Models\Question as QuestionModel;
use App\Models\Review as ReviewModel; use App\Models\Review as ReviewModel;
use App\Repos\Answer as AnswerRepo; use App\Repos\Answer as AnswerRepo;
use App\Repos\Article as ArticleRepo; use App\Repos\Article as ArticleRepo;
use App\Repos\Comment as CommentRepo; use App\Repos\Comment as CommentRepo;
use App\Repos\Consult as ConsultRepo;
use App\Repos\Question as QuestionRepo; use App\Repos\Question as QuestionRepo;
use App\Repos\Review as ReviewRepo; use App\Repos\Review as ReviewRepo;
@ -46,6 +49,26 @@ class Moderation extends Service
return $this->handleReviews($pager); return $this->handleReviews($pager);
} }
public function getConsults()
{
$pagerQuery = new PagerQuery();
$params = $pagerQuery->getParams();
$params['published'] = ConsultModel::PUBLISH_PENDING;
$params['deleted'] = 0;
$sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage();
$limit = $pagerQuery->getLimit();
$consultRepo = new ConsultRepo();
$pager = $consultRepo->paginate($params, $sort, $page, $limit);
return $this->handleConsults($pager);
}
public function getArticles() public function getArticles()
{ {
$pagerQuery = new PagerQuery(); $pagerQuery = new PagerQuery();
@ -143,6 +166,23 @@ class Moderation extends Service
return $pager; return $pager;
} }
protected function handleConsults($pager)
{
if ($pager->total_items > 0) {
$builder = new ConsultListBuilder();
$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) protected function handleArticles($pager)
{ {
if ($pager->total_items > 0) { if ($pager->total_items > 0) {

View File

@ -12,7 +12,7 @@
<div class="title">{{ answer.question.title }}</div> <div class="title">{{ answer.question.title }}</div>
<div class="meta"> <div class="meta">
<span><a href="{{ owner_url }}" target="_blank">{{ answer.owner.name }}</a></span> <span><a href="{{ owner_url }}" target="_blank">{{ answer.owner.name }}</a></span>
<span>{{ date('Y-m-d H:i',answer.create_time) }}</span> <span>{{ date('Y-m-d H:i:s',answer.create_time) }}</span>
</div> </div>
<div class="content markdown-body">{{ answer.content }}</div> <div class="content markdown-body">{{ answer.content }}</div>
</div> </div>

View File

@ -15,7 +15,7 @@
<div class="meta"> <div class="meta">
<span class="layui-badge layui-bg-green">{{ source_type(article.source_type) }}</span> <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><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:s',article.create_time) }}</span>
</div> </div>
<div class="content markdown-body">{{ article.content }}</div> <div class="content markdown-body">{{ article.content }}</div>
{% if article.tags %} {% if article.tags %}

View File

@ -13,7 +13,7 @@
<div class="kg-mod-preview"> <div class="kg-mod-preview">
<div class="meta"> <div class="meta">
<span><a href="{{ owner_url }}" target="_blank">{{ comment.owner.name }}</a></span> <span><a href="{{ owner_url }}" target="_blank">{{ comment.owner.name }}</a></span>
<span>{{ date('Y-m-d H:i',comment.create_time) }}</span> <span>{{ date('Y-m-d H:i:s',comment.create_time) }}</span>
</div> </div>
<div class="content markdown-body">{{ comment.content }}</div> <div class="content markdown-body">{{ comment.content }}</div>
</div> </div>

View File

@ -46,9 +46,10 @@
</thead> </thead>
<tbody> <tbody>
{% for item in pager.items %} {% for item in pager.items %}
{% set item.answer = item.answer ? item.answer : '等待回复ING...' %} {% set item.answer = item.answer ? item.answer : 'N/A' %}
{% set list_by_course_url = url({'for':'admin.consult.list'},{'course_id':item.course.id}) %} {% set list_by_course_url = url({'for':'admin.consult.list'},{'course_id':item.course.id}) %}
{% set list_by_user_url = url({'for':'admin.consult.list'},{'owner_id':item.owner.id}) %} {% set list_by_user_url = url({'for':'admin.consult.list'},{'owner_id':item.owner.id}) %}
{% set moderate_url = url({'for':'admin.consult.moderate','id':item.id}) %}
{% set edit_url = url({'for':'admin.consult.edit','id':item.id}) %} {% set edit_url = url({'for':'admin.consult.edit','id':item.id}) %}
{% set update_url = url({'for':'admin.consult.update','id':item.id}) %} {% set update_url = url({'for':'admin.consult.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.consult.delete','id':item.id}) %} {% set delete_url = url({'for':'admin.consult.delete','id':item.id}) %}
@ -64,9 +65,9 @@
<p>编号:{{ item.owner.id }}</p> <p>编号:{{ item.owner.id }}</p>
</td> </td>
<td> <td>
<p>提问:{{ date('Y-m-d H:i:s',item.create_time) }}</p> <p>提问:{{ date('Y-m-d H:i',item.create_time) }}</p>
{% if item.reply_time > 0 %} {% if item.reply_time > 0 %}
<p>回复:{{ date('Y-m-d H:i:s',item.reply_time) }}</p> <p>回复:{{ date('Y-m-d H:i',item.reply_time) }}</p>
{% else %} {% else %}
<p>回复N/A</p> <p>回复N/A</p>
{% endif %} {% endif %}
@ -76,6 +77,9 @@
<div class="kg-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
{% if item.published == 1 %}
<li><a href="{{ moderate_url }}">审核</a></li>
{% endif %}
<li><a href="{{ edit_url }}">编辑</a></li> <li><a href="{{ edit_url }}">编辑</a></li>
{% if item.deleted == 0 %} {% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li> <li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>

View File

@ -0,0 +1,57 @@
{% extends 'templates/main.volt' %}
{% block content %}
<fieldset class="layui-elem-field layui-field-title">
<legend>审核内容</legend>
</fieldset>
<form class="layui-form kg-form">
{% if consult.course.id is defined %}
<div class="layui-form-item">
<label class="layui-form-label">课程名称</label>
<div class="layui-input-block">
<div class="layui-form-mid">{{ consult.course.title }}</div>
</div>
</div>
{% endif %}
{% if consult.chapter.id is defined %}
<div class="layui-form-item">
<label class="layui-form-label">章节名称</label>
<div class="layui-input-block">
<div class="layui-form-mid">{{ consult.chapter.title }}</div>
</div>
</div>
{% endif %}
<div class="layui-form-item">
<label class="layui-form-label">咨询内容</label>
<div class="layui-input-block">
<div class="layui-form-mid">{{ consult.question }}</div>
</div>
</div>
</form>
<fieldset class="layui-elem-field layui-field-title">
<legend>审核意见</legend>
</fieldset>
{% set moderate_url = url({'for':'admin.consult.moderate','id':consult.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="通过">
<input type="radio" name="type" value="reject" title="拒绝">
</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 %}

View File

@ -24,6 +24,14 @@
<input class="layui-input" type="text" name="owner_id" placeholder="用户编号精确匹配"> <input class="layui-input" type="text" name="owner_id" placeholder="用户编号精确匹配">
</div> </div>
</div> </div>
<div class="layui-form-item">
<label class="layui-form-label">发布状态</label>
<div class="layui-input-block">
{% for value,title in publish_types %}
<input type="radio" name="published" value="{{ value }}" title="{{ title }}">
{% endfor %}
</div>
</div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">私密</label> <label class="layui-form-label">私密</label>
<div class="layui-input-block"> <div class="layui-input-block">
@ -31,13 +39,6 @@
<input type="radio" name="private" value="0" title="否"> <input type="radio" name="private" value="0" title="否">
</div> </div>
</div> </div>
<div class="layui-form-item">
<label class="layui-form-label">发布</label>
<div class="layui-input-block">
<input type="radio" name="published" value="1" title="是">
<input type="radio" name="published" value="0" title="否">
</div>
</div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">删除</label> <label class="layui-form-label">删除</label>
<div class="layui-input-block"> <div class="layui-input-block">

View File

@ -10,6 +10,14 @@
</div> </div>
</div> </div>
</div> </div>
<div class="layui-col-md2">
<div class="kg-stat-card">
<div class="name">咨询</div>
<div class="count">
<a href="{{ url({'for':'admin.mod.consults'}) }}">{{ mod_stat.consult_count }}</a>
</div>
</div>
</div>
<div class="layui-col-md2"> <div class="layui-col-md2">
<div class="kg-stat-card"> <div class="kg-stat-card">
<div class="name">文章</div> <div class="name">文章</div>

View File

@ -41,7 +41,7 @@
<p>昵称:<a href="{{ owner_url }}" target="_blank">{{ item.owner.name }}</a></p> <p>昵称:<a href="{{ owner_url }}" target="_blank">{{ item.owner.name }}</a></p>
<p>编号:{{ item.owner.id }}</p> <p>编号:{{ item.owner.id }}</p>
</td> </td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td> <td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td class="center"> <td class="center">
<a href="{{ moderate_url }}" class="layui-btn layui-btn-sm">详情</a> <a href="{{ moderate_url }}" class="layui-btn layui-btn-sm">详情</a>
</td> </td>

View File

@ -45,7 +45,7 @@
<p>昵称:<a href="{{ owner_url }}" target="_blank">{{ item.owner.name }}</a></p> <p>昵称:<a href="{{ owner_url }}" target="_blank">{{ item.owner.name }}</a></p>
<p>编号:{{ item.owner.id }}</p> <p>编号:{{ item.owner.id }}</p>
</td> </td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td> <td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td class="center"> <td class="center">
<a href="{{ moderate_url }}" class="layui-btn layui-btn-sm">详情</a> <a href="{{ moderate_url }}" class="layui-btn layui-btn-sm">详情</a>
</td> </td>

View File

@ -37,7 +37,7 @@
<p>昵称:<a href="{{ owner_url }}" target="_blank">{{ item.owner.name }}</a></p> <p>昵称:<a href="{{ owner_url }}" target="_blank">{{ item.owner.name }}</a></p>
<p>编号:{{ item.owner.id }}</p> <p>编号:{{ item.owner.id }}</p>
</td> </td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td> <td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td class="center"> <td class="center">
<a href="{{ moderate_url }}" class="layui-btn layui-btn-sm">详情</a> <a href="{{ moderate_url }}" class="layui-btn layui-btn-sm">详情</a>
</td> </td>

View File

@ -0,0 +1,64 @@
{% 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 item.answer = item.answer ? item.answer : 'N/A' %}
{% 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.consult.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.question }}">提问:{{ item.question }}</p>
<p class="layui-elip kg-item-elip" title="{{ item.answer }}">回复:{{ item.answer }}</p>
</td>
<td>
<p>昵称:<a href="{{ owner_url }}">{{ item.owner.name }}</a></p>
<p>编号:{{ item.owner.id }}</p>
</td>
<td>
<p>提问:{{ date('Y-m-d H:i:s',item.create_time) }}</p>
{% if item.reply_time > 0 %}
<p>回复:{{ date('Y-m-d H:i:s',item.reply_time) }}</p>
{% else %}
<p>回复N/A</p>
{% endif %}
</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

@ -44,7 +44,7 @@
<p>昵称:<a href="{{ owner_url }}" target="_blank">{{ item.owner.name }}</a></p> <p>昵称:<a href="{{ owner_url }}" target="_blank">{{ item.owner.name }}</a></p>
<p>编号:{{ item.owner.id }}</p> <p>编号:{{ item.owner.id }}</p>
</td> </td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td> <td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td class="center"> <td class="center">
<a href="{{ moderate_url }}" class="layui-btn layui-btn-sm">详情</a> <a href="{{ moderate_url }}" class="layui-btn layui-btn-sm">详情</a>
</td> </td>

View File

@ -17,13 +17,15 @@
<col> <col>
<col> <col>
<col> <col>
<col>
<col width="10%"> <col width="10%">
</colgroup> </colgroup>
<thead> <thead>
<tr> <tr>
<th>內容</th> <th>內容</th>
<th>用户</th>
<th>评分</th> <th>评分</th>
<th>用户</th>
<th>时间</th>
<th>操作</th> <th>操作</th>
</tr> </tr>
</thead> </thead>
@ -36,17 +38,17 @@
<td> <td>
<p>课程:<a href="{{ course_url }}">{{ item.course.title }}</a>{{ item.course.id }}</p> <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 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>
<td> <td>
<p>内容实用:{{ item.rating1 }}</p> <p>内容实用:{{ item.rating1 }}</p>
<p>通俗易懂:{{ item.rating2 }}</p> <p>通俗易懂:{{ item.rating2 }}</p>
<p>逻辑清晰:{{ item.rating3 }}</p> <p>逻辑清晰:{{ item.rating3 }}</p>
</td> </td>
<td>
<p>昵称:<a href="{{ owner_url }}">{{ item.owner.name }}</a></p>
<p>编号:{{ item.owner.id }}</p>
</td>
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td class="center"> <td class="center">
<a href="{{ moderate_url }}" class="layui-btn layui-btn-sm">详情</a> <a href="{{ moderate_url }}" class="layui-btn layui-btn-sm">详情</a>
</td> </td>

View File

@ -45,8 +45,8 @@
<tr> <tr>
<td>{{ item.id }}</td> <td>{{ item.id }}</td>
<td><a href="{{ edit_url }}">{{ item.title }}</a></td> <td><a href="{{ edit_url }}">{{ item.title }}</a></td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td> <td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td>{{ date('Y-m-d H:i',item.update_time) }}</td> <td>{{ date('Y-m-d H:i:s',item.update_time) }}</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><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>
<td class="center"> <td class="center">

View File

@ -12,7 +12,7 @@
<div class="title">{{ question.title }}</div> <div class="title">{{ question.title }}</div>
<div class="meta"> <div class="meta">
<span><a href="{{ owner_url }}" target="_blank">{{ question.owner.name }}</a></span> <span><a href="{{ owner_url }}" target="_blank">{{ question.owner.name }}</a></span>
<span>{{ date('Y-m-d H:i',question.create_time) }}</span> <span>{{ date('Y-m-d H:i:s',question.create_time) }}</span>
</div> </div>
<div class="content markdown-body">{{ question.content }}</div> <div class="content markdown-body">{{ question.content }}</div>
{% if question.tags %} {% if question.tags %}

View File

@ -44,8 +44,8 @@
{% for item in pager.items %} {% for item in pager.items %}
{% set list_by_course_url = url({'for':'admin.review.list'},{'course_id':item.course.id}) %} {% 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 list_by_owner_url = url({'for':'admin.review.list'},{'owner_id':item.owner.id}) %}
{% set moderate_url = url({'for':'admin.review.moderate','id':item.id}) %}
{% set edit_url = url({'for':'admin.review.edit','id':item.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 update_url = url({'for':'admin.review.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.review.delete','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}) %} {% set restore_url = url({'for':'admin.review.restore','id':item.id}) %}
@ -70,7 +70,7 @@
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
{% if item.published == 1 %} {% if item.published == 1 %}
<li><a href="{{ review_url }}">审核</a></li> <li><a href="{{ moderate_url }}">审核</a></li>
{% endif %} {% endif %}
<li><a href="{{ edit_url }}">编辑</a></li> <li><a href="{{ edit_url }}">编辑</a></li>
{% if item.deleted == 0 %} {% if item.deleted == 0 %}

View File

@ -2,10 +2,6 @@
{% block content %} {% 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"> <fieldset class="layui-elem-field layui-field-title">
<legend>审核内容</legend> <legend>审核内容</legend>
</fieldset> </fieldset>
@ -35,7 +31,7 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">评价内容</label> <label class="layui-form-label">评价内容</label>
<div class="layui-input-block"> <div class="layui-input-block">
<div class="layui-form-mid gray">{{ review.content }}</div> <div class="layui-form-mid">{{ review.content }}</div>
</div> </div>
</div> </div>
</form> </form>
@ -50,8 +46,8 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">审核</label> <label class="layui-form-label">审核</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="type" value="approve" title="通过" lay-filter="review"> <input type="radio" name="type" value="approve" title="通过">
<input type="radio" name="type" value="reject" title="拒绝" lay-filter="review"> <input type="radio" name="type" value="reject" title="拒绝">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">

View File

@ -53,8 +53,8 @@
<td>{{ item.id }}</td> <td>{{ item.id }}</td>
<td><a href="{{ edit_url }}">{{ item.title }}</a></td> <td><a href="{{ edit_url }}">{{ item.title }}</a></td>
<td>{{ item.course_count }}</td> <td>{{ item.course_count }}</td>
<td>{{ date('Y-m-d H:i',item.create_time) }}</td> <td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td>{{ date('Y-m-d H:i',item.update_time) }}</td> <td>{{ date('Y-m-d H:i:s',item.update_time) }}</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><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"> <td class="center">
<div class="kg-dropdown"> <div class="kg-dropdown">

View File

@ -12,6 +12,13 @@ use Phalcon\Mvc\Model\Behavior\SoftDelete;
class Consult extends Model class Consult extends Model
{ {
/**
* 发布状态
*/
const PUBLISH_PENDING = 1; // 审核中
const PUBLISH_APPROVED = 2; // 已发布
const PUBLISH_REJECTED = 3; // 未通过
/** /**
* 优先级 * 优先级
*/ */
@ -183,4 +190,13 @@ class Consult extends Model
$this->update_time = time(); $this->update_time = time();
} }
public static function publishTypes()
{
return [
self::PUBLISH_PENDING => '审核中',
self::PUBLISH_APPROVED => '已发布',
self::PUBLISH_REJECTED => '未通过',
];
}
} }

View File

@ -367,16 +367,16 @@ class Course extends Repository
public function countConsults($courseId) public function countConsults($courseId)
{ {
return (int)ConsultModel::count([ return (int)ConsultModel::count([
'conditions' => 'course_id = :course_id: AND published = 1 AND deleted = 0', 'conditions' => 'course_id = ?1 AND published = ?2 AND deleted = 0',
'bind' => ['course_id' => $courseId], 'bind' => [1 => $courseId, 2 => ConsultModel::PUBLISH_APPROVED],
]); ]);
} }
public function countReviews($courseId) public function countReviews($courseId)
{ {
return (int)ReviewModel::count([ return (int)ReviewModel::count([
'conditions' => 'course_id = :course_id: AND published = :published: AND deleted = 0', 'conditions' => 'course_id = ?1 AND published = ?2 AND deleted = 0',
'bind' => ['course_id' => $courseId, 'published' => ReviewModel::PUBLISH_APPROVED], 'bind' => [1 => $courseId, 2 => ReviewModel::PUBLISH_APPROVED],
]); ]);
} }
@ -392,8 +392,8 @@ class Course extends Repository
{ {
return (int)ReviewModel::average([ return (int)ReviewModel::average([
'column' => 'rating', 'column' => 'rating',
'conditions' => 'course_id = :course_id: AND published = 1 AND deleted = 0', 'conditions' => 'course_id = ?1 AND published = ?2 AND deleted = 0',
'bind' => ['course_id' => $courseId], 'bind' => [1 => $courseId, 2 => ReviewModel::PUBLISH_APPROVED],
]); ]);
} }

View File

@ -10,6 +10,7 @@ namespace App\Repos;
use App\Models\Answer as AnswerModel; use App\Models\Answer as AnswerModel;
use App\Models\Article as ArticleModel; use App\Models\Article as ArticleModel;
use App\Models\Comment as CommentModel; use App\Models\Comment as CommentModel;
use App\Models\Consult as ConsultModel;
use App\Models\Online as OnlineModel; use App\Models\Online as OnlineModel;
use App\Models\Order as OrderModel; use App\Models\Order as OrderModel;
use App\Models\OrderStatus as OrderStatusModel; use App\Models\OrderStatus as OrderStatusModel;
@ -32,6 +33,14 @@ class Stat extends Repository
]); ]);
} }
public function countPendingConsults()
{
return (int)ConsultModel::count([
'conditions' => 'published = :published: AND deleted = 0',
'bind' => ['published' => ConsultModel::PUBLISH_PENDING],
]);
}
public function countPendingArticles() public function countPendingArticles()
{ {
return (int)ArticleModel::count([ return (int)ArticleModel::count([

View File

@ -25,7 +25,7 @@ class TeacherConsult extends Repository
if (!empty($where['user_id'])) { if (!empty($where['user_id'])) {
$builder->andWhere('cu.user_id = :user_id:', ['user_id' => $where['user_id']]); $builder->andWhere('cu.user_id = :user_id:', ['user_id' => $where['user_id']]);
$builder->andWhere('cu.role_type = :role_type:', ['role_type' => CourseUserModel::ROLE_TEACHER]); $builder->andWhere('cu.role_type = :role_type:', ['role_type' => CourseUserModel::ROLE_TEACHER]);
$builder->andWhere('cu.deleted = :deleted:', ['deleted' => 0]); $builder->andWhere('cu.deleted = 0');
} }
if (isset($where['replied'])) { if (isset($where['replied'])) {
@ -36,6 +36,10 @@ class TeacherConsult extends Repository
} }
} }
$builder->andWhere('c.published = :published:', ['published' => ConsultModel::PUBLISH_APPROVED]);
$builder->andWhere('c.deleted = 0');
switch ($sort) { switch ($sort) {
default: default:
$orderBy = 'c.id DESC'; $orderBy = 'c.id DESC';

View File

@ -32,6 +32,7 @@ class ConsultList extends LogicService
'course_id' => $course->id, 'course_id' => $course->id,
'private' => 0, 'private' => 0,
'published' => 1, 'published' => 1,
'deleted' => 0,
]; ];
$consultRepo = new ConsultRepo(); $consultRepo = new ConsultRepo();

View File

@ -42,6 +42,7 @@ class CourseList extends LogicService
} }
$params['published'] = 1; $params['published'] = 1;
$params['deleted'] = 0;
$sort = $pagerQuery->getSort(); $sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage(); $page = $pagerQuery->getPage();

View File

@ -33,6 +33,7 @@ class ReviewList extends LogicService
$params = [ $params = [
'course_id' => $course->id, 'course_id' => $course->id,
'published' => ReviewModel::PUBLISH_APPROVED, 'published' => ReviewModel::PUBLISH_APPROVED,
'deleted' => 0,
]; ];
$reviewRepo = new ReviewRepo(); $reviewRepo = new ReviewRepo();

View File

@ -24,7 +24,7 @@ class ConsultList extends LogicService
$params = $pagerQuery->getParams(); $params = $pagerQuery->getParams();
$params['owner_id'] = $user->id; $params['owner_id'] = $user->id;
$params['published'] = 1; $params['deleted'] = 0;
$sort = $pagerQuery->getSort(); $sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage(); $page = $pagerQuery->getPage();

View File

@ -20,6 +20,7 @@ final class V20210720153027 extends AbstractMigration
$this->handleTagScopes(); $this->handleTagScopes();
$this->handleCategoryIcon(); $this->handleCategoryIcon();
$this->handleReviewPublish(); $this->handleReviewPublish();
$this->handleConsultPublish();
} }
protected function createCourseTagTable() protected function createCourseTagTable()
@ -189,6 +190,21 @@ final class V20210720153027 extends AbstractMigration
->execute(); ->execute();
} }
protected function handleConsultPublish()
{
$this->getQueryBuilder()
->update('kg_review')
->set('published', 2)
->where(['published' => 1])
->execute();
$this->getQueryBuilder()
->update('kg_review')
->set('published', 3)
->where(['published' => 0])
->execute();
}
protected function handleRoleRoutes() protected function handleRoleRoutes()
{ {
$roles = $this->getQueryBuilder() $roles = $this->getQueryBuilder()