From 92c2225d47e63cd4b9a2481eccba688e60e813a3 Mon Sep 17 00:00:00 2001 From: koogua Date: Tue, 1 Jun 2021 12:44:15 +0800 Subject: [PATCH 1/3] =?UTF-8?q?v1.3.6=E9=98=B6=E6=AE=B5=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- app/Caches/App.php | 31 -------- app/Caches/AppInfo.php | 32 ++++++++ app/Console/Tasks/VodEventTask.php | 57 +++++++++----- app/Http/Admin/Services/Answer.php | 29 ++++--- app/Http/Admin/Services/Article.php | 65 ++++++---------- app/Http/Admin/Services/AuthMenu.php | 1 - app/Http/Admin/Services/AuthNode.php | 2 +- app/Http/Admin/Services/Index.php | 21 +++-- app/Http/Admin/Services/Question.php | 61 +++++---------- app/Http/Admin/Views/article/edit_basic.volt | 2 +- app/Http/Admin/Views/category/list.volt | 6 +- app/Http/Admin/Views/question/list.volt | 4 +- .../Home/Controllers/AnswerController.php | 14 +++- app/Http/Home/Controllers/IndexController.php | 9 ++- app/Http/Home/Controllers/PageController.php | 4 + app/Http/Home/Controllers/UserController.php | 34 +++++++++ app/Http/Home/Services/Article.php | 30 +------- app/Http/Home/Services/Question.php | 30 +------- app/Http/Home/Views/im/group/edit.volt | 2 +- app/Http/Home/Views/search/question.volt | 1 - app/Http/Home/Views/user/answers.volt | 25 ++++++ app/Http/Home/Views/user/articles.volt | 14 ++-- app/Http/Home/Views/user/questions.volt | 26 +++++++ app/Http/Home/Views/user/show.volt | 16 ++++ app/Library/AppInfo.php | 2 +- app/Library/Helper.php | 2 + app/Models/Answer.php | 16 ---- app/Models/Article.php | 23 ++---- app/Models/Course.php | 35 +++++---- app/Models/FlashSale.php | 23 +++--- app/Models/ImGroup.php | 19 +++-- app/Models/ImNotice.php | 11 ++- app/Models/ImUser.php | 17 ++--- app/Models/Notification.php | 11 ++- app/Models/Order.php | 15 ++-- app/Models/Package.php | 19 +++-- app/Models/PointGift.php | 19 +++-- app/Models/PointHistory.php | 11 ++- app/Models/Question.php | 23 ++---- app/Models/Review.php | 9 ++- app/Models/Role.php | 11 ++- app/Models/Slide.php | 33 ++++---- app/Models/Tag.php | 19 +++-- app/Models/Task.php | 11 ++- app/Models/User.php | 17 ++--- app/Repos/User.php | 18 ----- app/Services/Logic/Answer/AnswerCreate.php | 15 ++-- app/Services/Logic/Answer/AnswerDataTrait.php | 37 +++++++++ app/Services/Logic/Answer/AnswerInfo.php | 8 ++ app/Services/Logic/Answer/AnswerList.php | 72 ++++++++++++++++++ app/Services/Logic/Answer/AnswerUpdate.php | 9 ++- app/Services/Logic/Article/ArticleCreate.php | 2 +- .../Logic/Article/ArticleDataTrait.php | 17 +++++ app/Services/Logic/Article/ArticleList.php | 11 --- app/Services/Logic/Article/ArticleUpdate.php | 2 + app/Services/Logic/Article/XmTagList.php | 50 ++++++++++++ app/Services/Logic/Comment/CommentReply.php | 2 +- app/Services/Logic/Page/PageInfo.php | 21 ++++- .../Logic/Question/QuestionCreate.php | 2 +- .../Logic/Question/QuestionDataTrait.php | 16 +++- app/Services/Logic/Question/QuestionList.php | 12 +-- .../Logic/Question/QuestionUpdate.php | 2 + app/Services/Logic/Question/XmTagList.php | 50 ++++++++++++ app/Services/Logic/User/AnswerList.php | 47 ++++++++++++ .../Logic/User/Console/AnswerList.php | 41 +--------- app/Services/Logic/User/QuestionList.php | 47 ++++++++++++ app/Services/Logic/User/UserInfo.php | 2 + app/Services/Search/ArticleDocument.php | 4 - app/Services/Search/CourseDocument.php | 4 - app/Services/Search/QuestionDocument.php | 4 - .../admin/img/default/article_cover.png | Bin 65013 -> 0 bytes public/static/home/css/common.css | 16 ++++ public/static/home/js/chapter.live.player.js | 3 +- public/static/home/js/user.console.account.js | 45 ----------- public/static/home/js/user.console.js | 13 +--- public/static/home/js/user.show.js | 10 +++ 77 files changed, 844 insertions(+), 602 deletions(-) delete mode 100644 app/Caches/App.php create mode 100644 app/Caches/AppInfo.php create mode 100644 app/Http/Home/Views/user/answers.volt create mode 100644 app/Http/Home/Views/user/questions.volt create mode 100644 app/Services/Logic/Answer/AnswerDataTrait.php create mode 100644 app/Services/Logic/Answer/AnswerList.php create mode 100644 app/Services/Logic/Article/XmTagList.php create mode 100644 app/Services/Logic/Question/XmTagList.php create mode 100644 app/Services/Logic/User/AnswerList.php create mode 100644 app/Services/Logic/User/QuestionList.php delete mode 100644 public/static/admin/img/default/article_cover.png delete mode 100644 public/static/home/js/user.console.account.js diff --git a/README.md b/README.md index a9d3c94d..ab93e614 100644 --- a/README.md +++ b/README.md @@ -84,5 +84,5 @@ Tips: 请用手机注册一个新账号,用户中心 -> 关注订阅,扫码 ### 开源助力 -毫无保留的真开源不容易,如果对你有帮助,请给我们 **STAR** !!! +毫无保留的真开源不容易,不要吝啬您的赞许和鼓励,请给我们 **STAR** !!! diff --git a/app/Caches/App.php b/app/Caches/App.php deleted file mode 100644 index 479ca191..00000000 --- a/app/Caches/App.php +++ /dev/null @@ -1,31 +0,0 @@ -lifetime; - } - - public function getKey($id = null) - { - return "app:{$id}"; - } - - public function getContent($id = null) - { - $appRepo = new AppRepo(); - - $result = $appRepo->findByAppKey($id); - - return $result ?: null; - } - -} diff --git a/app/Caches/AppInfo.php b/app/Caches/AppInfo.php new file mode 100644 index 00000000..ec5dfd00 --- /dev/null +++ b/app/Caches/AppInfo.php @@ -0,0 +1,32 @@ +lifetime; + } + + public function getKey($id = null) + { + return "_APP_INFO_"; + } + + public function getContent($id = null) + { + $appInfo = new \App\Library\AppInfo(); + + return [ + 'name' => $appInfo->name, + 'alias' => $appInfo->alias, + 'link' => $appInfo->link, + 'version' => $appInfo->version, + ]; + } + +} diff --git a/app/Console/Tasks/VodEventTask.php b/app/Console/Tasks/VodEventTask.php index 49d86fc7..d752c46a 100644 --- a/app/Console/Tasks/VodEventTask.php +++ b/app/Console/Tasks/VodEventTask.php @@ -44,10 +44,12 @@ class VodEventTask extends Task protected function handleNewFileUploadEvent($event) { - $fileId = $event['FileUploadEvent']['FileId']; - $width = $event['FileUploadEvent']['MetaData']['Height']; - $height = $event['FileUploadEvent']['MetaData']['Width']; - $duration = $event['FileUploadEvent']['MetaData']['Duration']; + $fileId = $event['FileUploadEvent']['FileId'] ?? 0; + $width = $event['FileUploadEvent']['MetaData']['Height'] ?? 0; + $height = $event['FileUploadEvent']['MetaData']['Width'] ?? 0; + $duration = $event['FileUploadEvent']['MetaData']['Duration'] ?? 0; + + if ($fileId == 0) return; $chapterRepo = new ChapterRepo(); @@ -55,6 +57,18 @@ class VodEventTask extends Task if (!$chapter) return; + $attrs = $chapter->attrs; + + /** + * 获取不到时长视为失败 + */ + if ($duration == 0) { + $attrs['file']['id'] = $fileId; + $attrs['file']['status'] = ChapterModel::FS_FAILED; + $chapter->update(['attrs' => $attrs]); + return; + } + $vodService = new VodService(); if ($width == 0 && $height == 0) { @@ -63,13 +77,8 @@ class VodEventTask extends Task $vodService->createTransVideoTask($fileId); } - /** - * @var array $attrs - */ - $attrs = $chapter->attrs; - + $attrs['file']['id'] = $fileId; $attrs['file']['status'] = ChapterModel::FS_TRANSLATING; - $attrs['duration'] = (int)$duration; $chapter->update(['attrs' => $attrs]); @@ -79,9 +88,9 @@ class VodEventTask extends Task protected function handleProcedureStateChangedEvent($event) { - $fileId = $event['ProcedureStateChangeEvent']['FileId']; + $fileId = $event['ProcedureStateChangeEvent']['FileId'] ?? 0; - $processResult = $event['ProcedureStateChangeEvent']['MediaProcessResultSet']; + if ($fileId == 0) return; $chapterRepo = new ChapterRepo(); @@ -89,6 +98,20 @@ class VodEventTask extends Task if (!$chapter) return; + $attrs = $chapter->attrs; + + $processResult = $event['ProcedureStateChangeEvent']['MediaProcessResultSet'] ?? []; + + /** + * 获取不到处理结果视为失败 + */ + if (empty($processResult)) { + $attrs['file']['id'] = $fileId; + $attrs['file']['status'] = ChapterModel::FS_FAILED; + $chapter->update(['attrs' => $attrs]); + return; + } + $failCount = $successCount = 0; foreach ($processResult as $item) { @@ -112,15 +135,9 @@ class VodEventTask extends Task $fileStatus = ChapterModel::FS_FAILED; } - if ($fileStatus == ChapterModel::FS_TRANSLATING) { - return; - } - - /** - * @var array $attrs - */ - $attrs = $chapter->attrs; + if ($fileStatus == ChapterModel::FS_TRANSLATING) return; + $attrs['file']['id'] = $fileId; $attrs['file']['status'] = $fileStatus; $chapter->update(['attrs' => $attrs]); diff --git a/app/Http/Admin/Services/Answer.php b/app/Http/Admin/Services/Answer.php index 4eda7f57..ea79042b 100644 --- a/app/Http/Admin/Services/Answer.php +++ b/app/Http/Admin/Services/Answer.php @@ -14,6 +14,7 @@ use App\Repos\Answer as AnswerRepo; use App\Repos\Question as QuestionRepo; use App\Repos\Report as ReportRepo; use App\Repos\User as UserRepo; +use App\Services\Logic\Answer\AnswerDataTrait; use App\Services\Logic\Answer\AnswerInfo as AnswerInfoService; use App\Services\Logic\Notice\System\AnswerApproved as AnswerApprovedNotice; use App\Services\Logic\Notice\System\AnswerRejected as AnswerRejectedNotice; @@ -24,6 +25,8 @@ use App\Validators\Answer as AnswerValidator; class Answer extends Service { + use AnswerDataTrait; + public function getPublishTypes() { return AnswerModel::publishTypes(); @@ -94,13 +97,16 @@ class Answer extends Service $answer = new AnswerModel(); - $answer->owner_id = $user->id; - $answer->question_id = $question->id; $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; $answer->create(); + $this->saveDynamicAttrs($answer); $this->recountQuestionAnswers($question); $this->recountUserAnswers($user); $this->handleAnswerPostPoint($answer); @@ -126,20 +132,21 @@ class Answer extends Service } if (isset($post['published'])) { - $data['published'] = $validator->checkPublishStatus($post['published']); - - $question = $this->findQuestion($answer->question_id); - - $this->recountQuestionAnswers($question); - - $user = $this->findUser($answer->owner_id); - - $this->recountUserAnswers($user); } $answer->update($data); + $this->saveDynamicAttrs($answer); + + $question = $this->findQuestion($answer->question_id); + + $this->recountQuestionAnswers($question); + + $owner = $this->findUser($answer->owner_id); + + $this->recountUserAnswers($owner); + $this->eventsManager->fire('Answer:afterUpdate', $this, $answer); return $answer; diff --git a/app/Http/Admin/Services/Article.php b/app/Http/Admin/Services/Article.php index 5af24563..5bbc16eb 100644 --- a/app/Http/Admin/Services/Article.php +++ b/app/Http/Admin/Services/Article.php @@ -15,10 +15,10 @@ use App\Models\User as UserModel; use App\Repos\Article as ArticleRepo; use App\Repos\Category as CategoryRepo; use App\Repos\Report as ReportRepo; -use App\Repos\Tag as TagRepo; use App\Repos\User as UserRepo; use App\Services\Logic\Article\ArticleDataTrait; use App\Services\Logic\Article\ArticleInfo as ArticleInfoService; +use App\Services\Logic\Article\XmTagList as XmTagListService; use App\Services\Logic\Notice\System\ArticleApproved as ArticleApprovedNotice; use App\Services\Logic\Notice\System\ArticleRejected as ArticleRejectedNotice; use App\Services\Logic\Point\History\ArticlePost as ArticlePostPointHistory; @@ -32,33 +32,9 @@ class Article extends Service public function getXmTags($id) { - $tagRepo = new TagRepo(); + $service = new XmTagListService(); - $allTags = $tagRepo->findAll(['published' => 1]); - - if ($allTags->count() == 0) return []; - - $articleTagIds = []; - - if ($id > 0) { - $article = $this->findOrFail($id); - if (!empty($article->tags)) { - $articleTagIds = kg_array_column($article->tags, 'id'); - } - } - - $list = []; - - foreach ($allTags as $tag) { - $selected = in_array($tag->id, $articleTagIds); - $list[] = [ - 'name' => $tag->name, - 'value' => $tag->id, - 'selected' => $selected, - ]; - } - - return $list; + return $service->handle($id); } public function getCategories() @@ -152,11 +128,15 @@ class Article extends Service $article = new ArticleModel(); $article->published = ArticleModel::PUBLISH_APPROVED; + $article->client_type = $this->getClientType(); + $article->client_ip = $this->getClientIp(); $article->owner_id = $user->id; $article->title = $title; $article->create(); + $this->saveDynamicAttrs($article); + $this->recountUserArticles($user); $this->eventsManager->fire('Article:afterCreate', $this, $article); @@ -208,12 +188,7 @@ class Article extends Service } if (isset($post['published'])) { - $data['published'] = $validator->checkPublishStatus($post['published']); - - $owner = $this->findUser($article->owner_id); - - $this->recountUserArticles($owner); } if (isset($post['xm_tag_ids'])) { @@ -222,8 +197,14 @@ class Article extends Service $article->update($data); + $this->saveDynamicAttrs($article); + $this->rebuildArticleIndex($article); + $owner = $this->findUser($article->owner_id); + + $this->recountUserArticles($owner); + $this->eventsManager->fire('Article:afterUpdate', $this, $article); return $article; @@ -237,14 +218,14 @@ class Article extends Service $article->update(); - $userRepo = new UserRepo(); - - $owner = $userRepo->findById($article->owner_id); - - $this->recountUserArticles($owner); + $this->saveDynamicAttrs($article); $this->rebuildArticleIndex($article); + $owner = $this->findUser($article->owner_id); + + $this->recountUserArticles($owner); + $this->eventsManager->fire('Article:afterDelete', $this, $article); return $article; @@ -258,14 +239,14 @@ class Article extends Service $article->update(); - $userRepo = new UserRepo(); - - $owner = $userRepo->findById($article->owner_id); - - $this->recountUserArticles($owner); + $this->saveDynamicAttrs($article); $this->rebuildArticleIndex($article); + $owner = $this->findUser($article->owner_id); + + $this->recountUserArticles($owner); + $this->eventsManager->fire('Article:afterRestore', $this, $article); return $article; diff --git a/app/Http/Admin/Services/AuthMenu.php b/app/Http/Admin/Services/AuthMenu.php index 1d69cd21..89ec4be7 100644 --- a/app/Http/Admin/Services/AuthMenu.php +++ b/app/Http/Admin/Services/AuthMenu.php @@ -10,7 +10,6 @@ class AuthMenu extends Component protected $authInfo; protected $authNodes = []; - protected $ownedRoutes = []; protected $owned1stLevelIds = []; protected $owned2ndLevelIds = []; protected $owned3rdLevelIds = []; diff --git a/app/Http/Admin/Services/AuthNode.php b/app/Http/Admin/Services/AuthNode.php index 952d795b..e2735bc7 100644 --- a/app/Http/Admin/Services/AuthNode.php +++ b/app/Http/Admin/Services/AuthNode.php @@ -530,7 +530,7 @@ class AuthNode extends Service ], ], [ - 'id' => '2-10', + 'id' => '2-11', 'title' => '举报队列', 'type' => 'menu', 'children' => [ diff --git a/app/Http/Admin/Services/Index.php b/app/Http/Admin/Services/Index.php index 32e0e39b..2302b631 100644 --- a/app/Http/Admin/Services/Index.php +++ b/app/Http/Admin/Services/Index.php @@ -2,8 +2,9 @@ namespace App\Http\Admin\Services; -use App\Caches\SiteGlobalStat; -use App\Caches\SiteTodayStat; +use App\Caches\AppInfo as AppInfoCache; +use App\Caches\SiteGlobalStat as SiteGlobalStatCache; +use App\Caches\SiteTodayStat as SiteTodayStatCache; use App\Library\AppInfo; use App\Library\Utils\ServerInfo; use App\Repos\Stat as StatRepo; @@ -28,7 +29,17 @@ class Index extends Service public function getAppInfo() { - return new AppInfo(); + $cache = new AppInfoCache(); + + $content = $cache->get(); + + $appInfo = new AppInfo(); + + if ($appInfo->version != $content['version']) { + $cache->rebuild(); + } + + return $appInfo; } public function getServerInfo() @@ -42,14 +53,14 @@ class Index extends Service public function getGlobalStat() { - $cache = new SiteGlobalStat(); + $cache = new SiteGlobalStatCache(); return $cache->get(); } public function getTodayStat() { - $cache = new SiteTodayStat(); + $cache = new SiteTodayStatCache(); return $cache->get(); } diff --git a/app/Http/Admin/Services/Question.php b/app/Http/Admin/Services/Question.php index 61d7f368..bf0a8249 100644 --- a/app/Http/Admin/Services/Question.php +++ b/app/Http/Admin/Services/Question.php @@ -14,13 +14,13 @@ use App\Models\User as UserModel; use App\Repos\Category as CategoryRepo; use App\Repos\Question as QuestionRepo; use App\Repos\Report as ReportRepo; -use App\Repos\Tag as TagRepo; use App\Repos\User as UserRepo; use App\Services\Logic\Notice\System\QuestionApproved as QuestionApprovedNotice; use App\Services\Logic\Notice\System\QuestionRejected as QuestionRejectedNotice; use App\Services\Logic\Point\History\QuestionPost as QuestionPostPointHistory; use App\Services\Logic\Question\QuestionDataTrait; use App\Services\Logic\Question\QuestionInfo as QuestionInfoService; +use App\Services\Logic\Question\XmTagList as XmTagListService; use App\Services\Sync\QuestionIndex as QuestionIndexSync; use App\Validators\Question as QuestionValidator; @@ -31,33 +31,9 @@ class Question extends Service public function getXmTags($id) { - $tagRepo = new TagRepo(); + $service = new XmTagListService(); - $allTags = $tagRepo->findAll(['published' => 1]); - - if ($allTags->count() == 0) return []; - - $questionTagIds = []; - - if ($id > 0) { - $question = $this->findOrFail($id); - if (!empty($question->tags)) { - $questionTagIds = kg_array_column($question->tags, 'id'); - } - } - - $list = []; - - foreach ($allTags as $tag) { - $selected = in_array($tag->id, $questionTagIds); - $list[] = [ - 'name' => $tag->name, - 'value' => $tag->id, - 'selected' => $selected, - ]; - } - - return $list; + return $service->handle($id); } public function getCategories() @@ -146,11 +122,15 @@ class Question extends Service $question = new QuestionModel(); $question->published = QuestionModel::PUBLISH_APPROVED; + $question->client_type = $this->getClientType(); + $question->client_ip = $this->getClientIp(); $question->owner_id = $user->id; $question->title = $title; $question->create(); + $this->saveDynamicAttrs($question); + $this->recountUserQuestions($user); $this->eventsManager->fire('Question:afterCreate', $this, $question); @@ -190,12 +170,7 @@ class Question extends Service } if (isset($post['published'])) { - $data['published'] = $validator->checkPublishStatus($post['published']); - - $owner = $this->findUser($question->owner_id); - - $this->recountUserQuestions($owner); } if (isset($post['xm_tag_ids'])) { @@ -204,8 +179,14 @@ class Question extends Service $question->update($data); + $this->saveDynamicAttrs($question); + $this->rebuildQuestionIndex($question); + $owner = $this->findUser($question->owner_id); + + $this->recountUserQuestions($owner); + $this->eventsManager->fire('Question:afterUpdate', $this, $question); return $question; @@ -219,14 +200,14 @@ class Question extends Service $question->update(); - $userRepo = new UserRepo(); - - $owner = $userRepo->findById($question->owner_id); - - $this->recountUserQuestions($owner); + $this->saveDynamicAttrs($question); $this->rebuildQuestionIndex($question); + $owner = $this->findUser($question->owner_id); + + $this->recountUserQuestions($owner); + $this->eventsManager->fire('Question:afterDelete', $this, $question); return $question; @@ -240,14 +221,12 @@ class Question extends Service $question->update(); - $userRepo = new UserRepo(); + $this->rebuildQuestionIndex($question); - $owner = $userRepo->findById($question->owner_id); + $owner = $this->findUser($question->owner_id); $this->recountUserQuestions($owner); - $this->rebuildQuestionIndex($question); - $this->eventsManager->fire('Question:afterRestore', $this, $question); return $question; diff --git a/app/Http/Admin/Views/article/edit_basic.volt b/app/Http/Admin/Views/article/edit_basic.volt index ebf4ea31..05659162 100644 --- a/app/Http/Admin/Views/article/edit_basic.volt +++ b/app/Http/Admin/Views/article/edit_basic.volt @@ -50,4 +50,4 @@ - \ No newline at end of file + diff --git a/app/Http/Admin/Views/category/list.volt b/app/Http/Admin/Views/category/list.volt index 1eab62ac..f4d7b5d1 100644 --- a/app/Http/Admin/Views/category/list.volt +++ b/app/Http/Admin/Views/category/list.volt @@ -4,7 +4,7 @@ {% set back_url = url({'for':'admin.category.list'},{'type':type}) %} {% set add_url = url({'for':'admin.category.add'},{'type':type,'parent_id':parent.id}) %} - {% set allow_add = (type == 1 and parent.level < 2) or (type == 2 and parent.level < 1) or (type == 3 and parent.level < 1) %} + {% set allow_add = (type == 1 and parent.level < 2) or (type == 2 and parent.level < 1) %}
@@ -55,14 +55,12 @@ {{ item.id }} {% if item.type == 1 %} {% if item.level == 1 %} - {{ item.name }} + {{ item.name }} {% else %} {{ item.name }} {% endif %} {% elseif item.type == 2 %} {{ item.name }} - {% elseif item.type == 3 %} - {{ item.name }} {% endif %} {{ item.level }} {{ item.child_count }} diff --git a/app/Http/Admin/Views/question/list.volt b/app/Http/Admin/Views/question/list.volt index dca7fe5c..168e7fe9 100644 --- a/app/Http/Admin/Views/question/list.volt +++ b/app/Http/Admin/Views/question/list.volt @@ -87,8 +87,8 @@
  • 审核问题
  • {% elseif item.published == 2 %}
  • 预览问题
  • +
  • 回答问题
  • {% endif %} -
  • 回答问题
  • 编辑问题
  • {% if item.deleted == 0 %}
  • 删除问题
  • @@ -128,7 +128,7 @@ $.ajax({ type: 'POST', url: url, - data: {closed: data.value}, + data: {closed: closed}, success: function (res) { layer.msg(res.msg, {icon: 1}); }, diff --git a/app/Http/Home/Controllers/AnswerController.php b/app/Http/Home/Controllers/AnswerController.php index 04ab77f9..8c711b10 100644 --- a/app/Http/Home/Controllers/AnswerController.php +++ b/app/Http/Home/Controllers/AnswerController.php @@ -47,13 +47,19 @@ class AnswerController extends Controller */ public function showAction($id) { - $service = new AnswerService(); + $service = new AnswerInfoService(); - $answer = $service->getAnswer($id); + $answer = $service->handle($id); + + $questionId = $answer['question']['id']; + + if ($answer['me']['owned'] == 0) { + $this->response->redirect(['for' => 'home.error.403']); + } $location = $this->url->get( - ['for' => 'home.question.show', 'id' => $answer->question_id], - ['answer_id' => $answer->id], + ['for' => 'home.question.show', 'id' => $questionId], + ['answer_id' => $id], ); $this->response->redirect($location); diff --git a/app/Http/Home/Controllers/IndexController.php b/app/Http/Home/Controllers/IndexController.php index 04375285..48daa877 100644 --- a/app/Http/Home/Controllers/IndexController.php +++ b/app/Http/Home/Controllers/IndexController.php @@ -13,7 +13,7 @@ class IndexController extends Controller public function beforeExecuteRoute(Dispatcher $dispatcher) { - if ($this->isMobileBrowser()) { + if ($this->isMobileBrowser() && $this->h5Enabled()) { $this->response->redirect('/h5', true); @@ -66,4 +66,11 @@ class IndexController extends Controller $this->view->setVar('vip_courses', $service->getSimpleVipCourses()); } + protected function h5Enabled() + { + $file = public_path('h5/index.html'); + + return file_exists($file); + } + } diff --git a/app/Http/Home/Controllers/PageController.php b/app/Http/Home/Controllers/PageController.php index 38b31f97..07b2d349 100644 --- a/app/Http/Home/Controllers/PageController.php +++ b/app/Http/Home/Controllers/PageController.php @@ -20,6 +20,10 @@ class PageController extends Controller $page = $service->handle($id); + if ($page['me']['owned'] == 0) { + $this->response->redirect(['for' => 'home.error.403']); + } + $featuredCourses = $this->getFeaturedCourses(); $this->seo->prependTitle($page['title']); diff --git a/app/Http/Home/Controllers/UserController.php b/app/Http/Home/Controllers/UserController.php index 8e113aac..83824167 100644 --- a/app/Http/Home/Controllers/UserController.php +++ b/app/Http/Home/Controllers/UserController.php @@ -2,10 +2,12 @@ namespace App\Http\Home\Controllers; +use App\Services\Logic\User\AnswerList as UserAnswerListService; 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\QuestionList as UserQuestionListService; use App\Services\Logic\User\UserInfo as UserInfoService; use Phalcon\Mvc\View; @@ -61,6 +63,38 @@ class UserController extends Controller $this->view->setVar('pager', $pager); } + /** + * @Get("/{id:[0-9]+}/questions", name="home.user.questions") + */ + public function questionsAction($id) + { + $service = new UserQuestionListService(); + + $pager = $service->handle($id); + + $pager->target = 'tab-questions'; + + $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW); + $this->view->pick('user/questions'); + $this->view->setVar('pager', $pager); + } + + /** + * @Get("/{id:[0-9]+}/answers", name="home.user.answers") + */ + public function answersAction($id) + { + $service = new UserAnswerListService(); + + $pager = $service->handle($id); + + $pager->target = 'tab-answers'; + + $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW); + $this->view->pick('user/answers'); + $this->view->setVar('pager', $pager); + } + /** * @Get("/{id:[0-9]+}/friends", name="home.user.friends") */ diff --git a/app/Http/Home/Services/Article.php b/app/Http/Home/Services/Article.php index 9ec7c15d..60afd566 100644 --- a/app/Http/Home/Services/Article.php +++ b/app/Http/Home/Services/Article.php @@ -6,7 +6,7 @@ use App\Models\Article as ArticleModel; use App\Models\Category as CategoryModel; use App\Models\Reason as ReasonModel; use App\Repos\Category as CategoryRepo; -use App\Repos\Tag as TagRepo; +use App\Services\Logic\Article\XmTagList as XmTagListService; use App\Services\Logic\ArticleTrait; class Article extends Service @@ -25,33 +25,9 @@ class Article extends Service public function getXmTags($id) { - $tagRepo = new TagRepo(); + $service = new XmTagListService(); - $allTags = $tagRepo->findAll(['published' => 1], 'priority'); - - if ($allTags->count() == 0) return []; - - $articleTagIds = []; - - if ($id > 0) { - $article = $this->checkArticle($id); - if (!empty($article->tags)) { - $articleTagIds = kg_array_column($article->tags, 'id'); - } - } - - $list = []; - - foreach ($allTags as $tag) { - $selected = in_array($tag->id, $articleTagIds); - $list[] = [ - 'name' => $tag->name, - 'value' => $tag->id, - 'selected' => $selected, - ]; - } - - return $list; + return $service->handle($id); } public function getCategories() diff --git a/app/Http/Home/Services/Question.php b/app/Http/Home/Services/Question.php index c8af59cc..a719ab54 100644 --- a/app/Http/Home/Services/Question.php +++ b/app/Http/Home/Services/Question.php @@ -5,7 +5,7 @@ namespace App\Http\Home\Services; use App\Models\Category as CategoryModel; use App\Models\Question as QuestionModel; use App\Repos\Category as CategoryRepo; -use App\Repos\Tag as TagRepo; +use App\Services\Logic\Question\XmTagList as XmTagListService; use App\Services\Logic\QuestionTrait; use App\Services\Logic\Service as LogicService; @@ -36,33 +36,9 @@ class Question extends LogicService public function getXmTags($id) { - $tagRepo = new TagRepo(); + $service = new XmTagListService(); - $allTags = $tagRepo->findAll(['published' => 1], 'priority'); - - if ($allTags->count() == 0) return []; - - $questionTagIds = []; - - if ($id > 0) { - $question = $this->checkQuestion($id); - if (!empty($question->tags)) { - $questionTagIds = kg_array_column($question->tags, 'id'); - } - } - - $list = []; - - foreach ($allTags as $tag) { - $selected = in_array($tag->id, $questionTagIds); - $list[] = [ - 'name' => $tag->name, - 'value' => $tag->id, - 'selected' => $selected, - ]; - } - - return $list; + return $service->handle($id); } public function getQuestion($id) diff --git a/app/Http/Home/Views/im/group/edit.volt b/app/Http/Home/Views/im/group/edit.volt index 6803e993..a35d6160 100644 --- a/app/Http/Home/Views/im/group/edit.volt +++ b/app/Http/Home/Views/im/group/edit.volt @@ -2,7 +2,7 @@ {% block content %} - {% set update_url = url({'for':'home.igm.update','id':group.id}) %} + {% set update_url = url({'for':'home.im_group.update','id':group.id}) %} {% set name_readonly = group.type == 1 ? 'readonly="readonly"' : '' %}
    diff --git a/app/Http/Home/Views/search/question.volt b/app/Http/Home/Views/search/question.volt index 6f28739e..4dec9446 100644 --- a/app/Http/Home/Views/search/question.volt +++ b/app/Http/Home/Views/search/question.volt @@ -3,7 +3,6 @@ {% for item in pager.items %} {% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %} {% set question_url = url({'for':'home.question.show','id':item.id}) %} - {% set solved_class = item.solved ? 'column solved' : 'column' %}
    diff --git a/app/Http/Home/Views/user/answers.volt b/app/Http/Home/Views/user/answers.volt new file mode 100644 index 00000000..30dbb919 --- /dev/null +++ b/app/Http/Home/Views/user/answers.volt @@ -0,0 +1,25 @@ +{% if pager.total_pages > 0 %} +
    +
    + {% for item in pager.items %} + {% set answer_url = url({'for':'home.answer.show','id':item.id}) %} +
    +
    +
    + +
    {{ substr(item.summary,0,80) }}
    +
    + {{ item.create_time|time_ago }} + + {{ item.comment_count }} 评论 +
    +
    +
    +
    + {% endfor %} +
    +
    + {{ partial('partials/pager_ajax') }} +{% endif %} \ No newline at end of file diff --git a/app/Http/Home/Views/user/articles.volt b/app/Http/Home/Views/user/articles.volt index e7ba66f4..e6d554df 100644 --- a/app/Http/Home/Views/user/articles.volt +++ b/app/Http/Home/Views/user/articles.volt @@ -1,23 +1,19 @@ {{ partial('macros/article') }} {% if pager.total_pages > 0 %} -
    +
    {% for item in pager.items %} {% set article_url = url({'for':'home.article.show','id':item.id}) %} -
    -
    - {{ source_type(item.source_type) }} -
    - - {{ item.title }} - -
    +
    +
    +
    {{ substr(item.summary,0,80) }}
    + {{ item.create_time|time_ago }} {{ item.view_count }} 浏览 {{ item.comment_count }} 评论 diff --git a/app/Http/Home/Views/user/questions.volt b/app/Http/Home/Views/user/questions.volt new file mode 100644 index 00000000..b83eb067 --- /dev/null +++ b/app/Http/Home/Views/user/questions.volt @@ -0,0 +1,26 @@ +{% if pager.total_pages > 0 %} +
    +
    + {% for item in pager.items %} + {% set question_url = url({'for':'home.question.show','id':item.id}) %} +
    +
    +
    + +
    {{ substr(item.summary,0,80) }}
    +
    + {{ item.create_time|time_ago }} + {{ item.view_count }} 浏览 + + {{ item.answer_count }} 回答 +
    +
    +
    +
    + {% endfor %} +
    +
    + {{ partial('partials/pager_ajax') }} +{% endif %} \ No newline at end of file diff --git a/app/Http/Home/Views/user/show.volt b/app/Http/Home/Views/user/show.volt index 82a50354..f43de825 100644 --- a/app/Http/Home/Views/user/show.volt +++ b/app/Http/Home/Views/user/show.volt @@ -43,11 +43,15 @@ {% set show_tab_courses = user.course_count > 0 %} {% set show_tab_articles = user.article_count > 0 %} + {% set show_tab_questions = user.question_count > 0 %} + {% set show_tab_answers = user.answer_count > 0 %} {% set show_tab_friends = user.friend_count > 0 %} {% set show_tab_groups = user.group_count > 0 %} {% set courses_url = url({'for':'home.user.courses','id':user.id}) %} {% set articles_url = url({'for':'home.user.articles','id':user.id}) %} + {% set questions_url = url({'for':'home.user.questions','id':user.id}) %} + {% set answers_url = url({'for':'home.user.answers','id':user.id}) %} {% set friends_url = url({'for':'home.user.friends','id':user.id}) %} {% set groups_url = url({'for':'home.user.groups','id':user.id}) %} @@ -58,6 +62,12 @@ {% if show_tab_articles %}
  • 文章
  • {% endif %} + {% if show_tab_questions %} +
  • 提问
  • + {% endif %} + {% if show_tab_answers %} +
  • 回答
  • + {% endif %} {% if show_tab_friends %}
  • 好友
  • {% endif %} @@ -70,6 +80,12 @@ {% if show_tab_articles %}
    {% endif %} + {% if show_tab_questions %} +
    + {% endif %} + {% if show_tab_answers %} +
    + {% endif %} {% if show_tab_friends %}
    {% endif %} diff --git a/app/Library/AppInfo.php b/app/Library/AppInfo.php index 3da14655..b0c2f504 100644 --- a/app/Library/AppInfo.php +++ b/app/Library/AppInfo.php @@ -11,7 +11,7 @@ class AppInfo protected $link = 'https://koogua.com'; - protected $version = '1.3.5'; + protected $version = '1.3.6'; public function __get($name) { diff --git a/app/Library/Helper.php b/app/Library/Helper.php index 79eabbdd..7bb4534a 100644 --- a/app/Library/Helper.php +++ b/app/Library/Helper.php @@ -449,6 +449,8 @@ function kg_parse_summary($content, $length = 100) $content = strip_tags($content); + $content = trim($content); + return kg_substr($content, 0, $length); } diff --git a/app/Models/Answer.php b/app/Models/Answer.php index e2fa9a30..40dab0cc 100644 --- a/app/Models/Answer.php +++ b/app/Models/Answer.php @@ -153,27 +153,11 @@ class Answer extends Model public function beforeCreate() { - if (empty($this->cover)) { - $this->cover = kg_parse_first_content_image($this->content); - } - - if (empty($this->summary)) { - $this->summary = kg_parse_summary($this->content); - } - $this->create_time = time(); } public function beforeUpdate() { - if (empty($this->cover)) { - $this->cover = kg_parse_first_content_image($this->content); - } - - if (empty($this->summary)) { - $this->summary = kg_parse_summary($this->content); - } - $this->update_time = time(); } diff --git a/app/Models/Article.php b/app/Models/Article.php index 644696cf..5a69307e 100644 --- a/app/Models/Article.php +++ b/app/Models/Article.php @@ -225,14 +225,6 @@ class Article extends Model public function beforeCreate() { - if (empty($this->cover)) { - $this->cover = kg_parse_first_content_image($this->content); - } - - if (is_array($this->tags) || is_object($this->tags)) { - $this->tags = kg_json_encode($this->tags); - } - $this->create_time = time(); } @@ -246,19 +238,14 @@ class Article extends Model $sync->addItem($this->id); } - if (empty($this->cover)) { - $this->cover = kg_parse_first_content_image($this->content); - } + $this->update_time = time(); + } - if (empty($this->summary)) { - $this->summary = kg_parse_summary($this->content); - } - - if (is_array($this->tags) || is_array($this->tags)) { + public function beforeSave() + { + if (is_array($this->tags) || is_object($this->tags)) { $this->tags = kg_json_encode($this->tags); } - - $this->update_time = time(); } public function afterCreate() diff --git a/app/Models/Course.php b/app/Models/Course.php index 8db6710a..1d9927a8 100644 --- a/app/Models/Course.php +++ b/app/Models/Course.php @@ -313,12 +313,6 @@ class Course extends Model $this->attrs = kg_json_encode($this->attrs); } - if (empty($this->cover)) { - $this->cover = kg_default_course_cover_path(); - } elseif (Text::startsWith($this->cover, 'http')) { - $this->cover = self::getCoverPath($this->cover); - } - $this->create_time = time(); } @@ -332,22 +326,10 @@ class Course extends Model $sync->addItem($this->id); } - if (Text::startsWith($this->cover, 'http')) { - $this->cover = self::getCoverPath($this->cover); - } - - if (empty($this->summary)) { - $this->summary = kg_parse_summary($this->details); - } - if (is_array($this->attrs) || is_object($this->attrs)) { $this->attrs = kg_json_encode($this->attrs); } - if (empty($this->origin_price)) { - $this->origin_price = 1.5 * $this->market_price; - } - if ($this->deleted == 1) { $this->published = 0; } @@ -355,6 +337,23 @@ class Course extends Model $this->update_time = time(); } + public function beforeSave() + { + if (empty($this->cover)) { + $this->cover = kg_default_course_cover_path(); + } elseif (Text::startsWith($this->cover, 'http')) { + $this->cover = self::getCoverPath($this->cover); + } + + if (empty($this->summary)) { + $this->summary = kg_parse_summary($this->details); + } + + if (empty($this->origin_price)) { + $this->origin_price = 1.5 * $this->market_price; + } + } + public function afterCreate() { $cache = new MaxCourseIdCache(); diff --git a/app/Models/FlashSale.php b/app/Models/FlashSale.php index 81c6ab62..6009d062 100644 --- a/app/Models/FlashSale.php +++ b/app/Models/FlashSale.php @@ -125,18 +125,19 @@ class FlashSale extends Model public function beforeCreate() { - if (is_array($this->item_info) || is_object($this->item_info)) { - $this->item_info = kg_json_encode($this->item_info); - } - - if (is_array($this->schedules) || is_object($this->schedules)) { - $this->schedules = kg_json_encode($this->schedules); - } - $this->create_time = time(); } public function beforeUpdate() + { + if ($this->deleted == 1) { + $this->published = 0; + } + + $this->update_time = time(); + } + + public function beforeSave() { if (is_array($this->item_info) || is_object($this->item_info)) { $this->item_info = kg_json_encode($this->item_info); @@ -145,12 +146,6 @@ class FlashSale extends Model if (is_array($this->schedules) || is_object($this->schedules)) { $this->schedules = kg_json_encode($this->schedules); } - - if ($this->deleted == 1) { - $this->published = 0; - } - - $this->update_time = time(); } public function afterCreate() diff --git a/app/Models/ImGroup.php b/app/Models/ImGroup.php index 677c0308..0ba90945 100644 --- a/app/Models/ImGroup.php +++ b/app/Models/ImGroup.php @@ -127,12 +127,6 @@ class ImGroup extends Model public function beforeCreate() { - if (empty($this->avatar)) { - $this->avatar = kg_default_group_avatar_path(); - } elseif (Text::startsWith($this->avatar, 'http')) { - $this->avatar = self::getAvatarPath($this->avatar); - } - $this->create_time = time(); } @@ -143,10 +137,6 @@ class ImGroup extends Model $sync->addItem($this->id); } - if (Text::startsWith($this->avatar, 'http')) { - $this->avatar = self::getAvatarPath($this->avatar); - } - if ($this->deleted == 1) { $this->published = 0; } @@ -154,6 +144,15 @@ class ImGroup extends Model $this->update_time = time(); } + public function beforeSave() + { + if (empty($this->avatar)) { + $this->avatar = kg_default_group_avatar_path(); + } elseif (Text::startsWith($this->avatar, 'http')) { + $this->avatar = self::getAvatarPath($this->avatar); + } + } + public function afterCreate() { $cache = new MaxImGroupIdCache(); diff --git a/app/Models/ImNotice.php b/app/Models/ImNotice.php index 31b29225..6b26a4cb 100644 --- a/app/Models/ImNotice.php +++ b/app/Models/ImNotice.php @@ -85,20 +85,19 @@ class ImNotice extends Model public function beforeCreate() { - if (is_array($this->item_info)) { - $this->item_info = kg_json_encode($this->item_info); - } - $this->create_time = time(); } public function beforeUpdate() + { + $this->update_time = time(); + } + + public function beforeSave() { if (is_array($this->item_info)) { $this->item_info = kg_json_encode($this->item_info); } - - $this->update_time = time(); } public function afterFetch() diff --git a/app/Models/ImUser.php b/app/Models/ImUser.php index 52b5e951..4725f21e 100644 --- a/app/Models/ImUser.php +++ b/app/Models/ImUser.php @@ -112,22 +112,21 @@ class ImUser extends Model public function beforeCreate() { - if (empty($this->avatar)) { - $this->avatar = kg_default_user_avatar_path(); - } elseif (Text::startsWith($this->avatar, 'http')) { - $this->avatar = self::getAvatarPath($this->avatar); - } - $this->create_time = time(); } public function beforeUpdate() { - if (Text::startsWith($this->avatar, 'http')) { + $this->update_time = time(); + } + + public function beforeSave() + { + if (empty($this->avatar)) { + $this->avatar = kg_default_user_avatar_path(); + } elseif (Text::startsWith($this->avatar, 'http')) { $this->avatar = self::getAvatarPath($this->avatar); } - - $this->update_time = time(); } public function afterFetch() diff --git a/app/Models/Notification.php b/app/Models/Notification.php index b7cfab4e..defa7c44 100644 --- a/app/Models/Notification.php +++ b/app/Models/Notification.php @@ -180,20 +180,19 @@ class Notification extends Model public function beforeCreate() { - if (is_array($this->event_info) || is_object($this->event_info)) { - $this->event_info = kg_json_encode($this->event_info); - } - $this->create_time = time(); } public function beforeUpdate() + { + $this->update_time = time(); + } + + public function beforeSave() { if (is_array($this->event_info) || is_object($this->event_info)) { $this->event_info = kg_json_encode($this->event_info); } - - $this->update_time = time(); } public function afterFetch() diff --git a/app/Models/Order.php b/app/Models/Order.php index 5e6ab4f5..7574d40a 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -170,18 +170,15 @@ class Order extends Model { $this->sn = date('YmdHis') . rand(1000, 9999); - if (is_array($this->item_info) || is_object($this->item_info)) { - $this->item_info = kg_json_encode($this->item_info); - } - - if (is_array($this->promotion_info) || is_object($this->promotion_info)) { - $this->promotion_info = kg_json_encode($this->promotion_info); - } - $this->create_time = time(); } public function beforeUpdate() + { + $this->update_time = time(); + } + + public function beforeSave() { if (is_array($this->item_info) || is_object($this->item_info)) { $this->item_info = kg_json_encode($this->item_info); @@ -190,8 +187,6 @@ class Order extends Model if (is_array($this->promotion_info) || is_object($this->promotion_info)) { $this->promotion_info = kg_json_encode($this->promotion_info); } - - $this->update_time = time(); } public function afterSave() diff --git a/app/Models/Package.php b/app/Models/Package.php index b9e27eb5..07c46194 100644 --- a/app/Models/Package.php +++ b/app/Models/Package.php @@ -105,21 +105,11 @@ class Package extends Model public function beforeCreate() { - if (empty($this->cover)) { - $this->cover = kg_default_package_cover_path(); - } elseif (Text::startsWith($this->cover, 'http')) { - $this->cover = self::getCoverPath($this->cover); - } - $this->create_time = time(); } public function beforeUpdate() { - if (Text::startsWith($this->cover, 'http')) { - $this->cover = self::getCoverPath($this->cover); - } - if ($this->deleted == 1) { $this->published = 0; } @@ -127,6 +117,15 @@ class Package extends Model $this->update_time = time(); } + public function beforeSave() + { + if (empty($this->cover)) { + $this->cover = kg_default_package_cover_path(); + } elseif (Text::startsWith($this->cover, 'http')) { + $this->cover = self::getCoverPath($this->cover); + } + } + public function afterCreate() { $cache = new MaxPackageIdCache(); diff --git a/app/Models/PointGift.php b/app/Models/PointGift.php index 63c1de87..2b567ab4 100644 --- a/app/Models/PointGift.php +++ b/app/Models/PointGift.php @@ -166,21 +166,11 @@ class PointGift extends Model $this->attrs = kg_json_encode($this->attrs); } - if (empty($this->cover)) { - $this->cover = kg_default_gift_cover_path(); - } elseif (Text::startsWith($this->cover, 'http')) { - $this->cover = self::getCoverPath($this->cover); - } - $this->create_time = time(); } public function beforeUpdate() { - if (Text::startsWith($this->cover, 'http')) { - $this->cover = self::getCoverPath($this->cover); - } - if (is_array($this->attrs) || is_object($this->attrs)) { $this->attrs = kg_json_encode($this->attrs); } @@ -192,6 +182,15 @@ class PointGift extends Model $this->update_time = time(); } + public function beforeSave() + { + if (empty($this->cover)) { + $this->cover = kg_default_gift_cover_path(); + } elseif (Text::startsWith($this->cover, 'http')) { + $this->cover = self::getCoverPath($this->cover); + } + } + public function afterCreate() { $cache = new MaxPointGiftIdCache(); diff --git a/app/Models/PointHistory.php b/app/Models/PointHistory.php index e2688a1b..6aa8de9d 100644 --- a/app/Models/PointHistory.php +++ b/app/Models/PointHistory.php @@ -95,20 +95,19 @@ class PointHistory extends Model public function beforeCreate() { - if (is_array($this->event_info) || is_object($this->event_info)) { - $this->event_info = kg_json_encode($this->event_info); - } - $this->create_time = time(); } public function beforeUpdate() + { + $this->update_time = time(); + } + + public function beforeSave() { if (is_array($this->event_info) || is_object($this->event_info)) { $this->event_info = kg_json_encode($this->event_info); } - - $this->update_time = time(); } public function afterFetch() diff --git a/app/Models/Question.php b/app/Models/Question.php index 0b9b2564..ca731b15 100644 --- a/app/Models/Question.php +++ b/app/Models/Question.php @@ -239,14 +239,6 @@ class Question extends Model public function beforeCreate() { - if (is_array($this->tags) || is_object($this->tags)) { - $this->tags = kg_json_encode($this->tags); - } - - if (empty($this->cover)) { - $this->cover = kg_parse_first_content_image($this->content); - } - $this->create_time = time(); } @@ -260,19 +252,14 @@ class Question extends Model $sync->addItem($this->id); } + $this->update_time = time(); + } + + public function beforeSave() + { if (is_array($this->tags) || is_object($this->tags)) { $this->tags = kg_json_encode($this->tags); } - - if (empty($this->cover)) { - $this->cover = kg_parse_first_content_image($this->content); - } - - if (empty($this->summary)) { - $this->summary = kg_parse_summary($this->content); - } - - $this->update_time = time(); } public function afterCreate() diff --git a/app/Models/Review.php b/app/Models/Review.php index 83589aad..c2610eaa 100644 --- a/app/Models/Review.php +++ b/app/Models/Review.php @@ -152,15 +152,11 @@ class Review extends Model public function beforeCreate() { - $this->rating = $this->getAvgRating(); - $this->create_time = time(); } public function beforeUpdate() { - $this->rating = $this->getAvgRating(); - if ($this->deleted == 1) { $this->published = 0; } @@ -168,6 +164,11 @@ class Review extends Model $this->update_time = time(); } + public function beforeSave() + { + $this->rating = $this->getAvgRating(); + } + protected function getAvgRating() { $sumRating = $this->rating1 + $this->rating2 + $this->rating3; diff --git a/app/Models/Role.php b/app/Models/Role.php index faf819fc..2478f9e1 100644 --- a/app/Models/Role.php +++ b/app/Models/Role.php @@ -103,20 +103,19 @@ class Role extends Model public function beforeCreate() { - if (is_array($this->routes) || is_object($this->routes)) { - $this->routes = kg_json_encode($this->routes); - } - $this->create_time = time(); } public function beforeUpdate() + { + $this->update_time = time(); + } + + public function beforeSave() { if (is_array($this->routes) || is_object($this->routes)) { $this->routes = kg_json_encode($this->routes); } - - $this->update_time = time(); } public function afterFetch() diff --git a/app/Models/Slide.php b/app/Models/Slide.php index cbe149bf..1fc5c03a 100644 --- a/app/Models/Slide.php +++ b/app/Models/Slide.php @@ -124,6 +124,20 @@ class Slide extends Model } public function beforeCreate() + { + $this->create_time = time(); + } + + public function beforeUpdate() + { + if ($this->deleted == 1) { + $this->published = 0; + } + + $this->update_time = time(); + } + + public function beforeSave() { if (empty($this->cover)) { $this->cover = kg_default_slide_cover_path(); @@ -134,25 +148,6 @@ class Slide extends Model if (is_array($this->target_attrs) || is_object($this->target_attrs)) { $this->target_attrs = kg_json_encode($this->target_attrs); } - - $this->create_time = time(); - } - - public function beforeUpdate() - { - if (Text::startsWith($this->cover, 'http')) { - $this->cover = self::getCoverPath($this->cover); - } - - if (is_array($this->target_attrs) || is_object($this->target_attrs)) { - $this->target_attrs = kg_json_encode($this->target_attrs); - } - - if ($this->deleted == 1) { - $this->published = 0; - } - - $this->update_time = time(); } public function afterFetch() diff --git a/app/Models/Tag.php b/app/Models/Tag.php index eca6f7ab..4d6a957f 100644 --- a/app/Models/Tag.php +++ b/app/Models/Tag.php @@ -98,21 +98,11 @@ class Tag extends Model public function beforeCreate() { - if (empty($this->icon)) { - $this->icon = kg_default_icon_path(); - } elseif (Text::startsWith($this->icon, 'http')) { - $this->icon = self::getIconPath($this->icon); - } - $this->create_time = time(); } public function beforeUpdate() { - if (Text::startsWith($this->icon, 'http')) { - $this->icon = self::getIconPath($this->icon); - } - if ($this->deleted == 1) { $this->published = 0; } @@ -120,6 +110,15 @@ class Tag 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 MaxTagIdCache(); diff --git a/app/Models/Task.php b/app/Models/Task.php index 8ac27e11..5c2278ce 100644 --- a/app/Models/Task.php +++ b/app/Models/Task.php @@ -126,20 +126,19 @@ class Task extends Model public function beforeCreate() { - if (is_array($this->item_info) || is_object($this->item_info)) { - $this->item_info = kg_json_encode($this->item_info); - } - $this->create_time = time(); } public function beforeUpdate() + { + $this->update_time = time(); + } + + public function beforeSave() { if (is_array($this->item_info) || is_object($this->item_info)) { $this->item_info = kg_json_encode($this->item_info); } - - $this->update_time = time(); } public function afterFetch() diff --git a/app/Models/User.php b/app/Models/User.php index d07fab74..891284e4 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -199,12 +199,6 @@ class User extends Model public function beforeCreate() { - if (empty($this->avatar)) { - $this->avatar = kg_default_user_avatar_path(); - } elseif (Text::startsWith($this->avatar, 'http')) { - $this->avatar = self::getAvatarPath($this->avatar); - } - $this->create_time = time(); } @@ -215,11 +209,16 @@ class User extends Model $sync->addItem($this->id); } - if (Text::startsWith($this->avatar, 'http')) { + $this->update_time = time(); + } + + public function beforeSave() + { + if (empty($this->avatar)) { + $this->avatar = kg_default_user_avatar_path(); + } elseif (Text::startsWith($this->avatar, 'http')) { $this->avatar = self::getAvatarPath($this->avatar); } - - $this->update_time = time(); } public function afterCreate() diff --git a/app/Repos/User.php b/app/Repos/User.php index c6b19ea9..4692118e 100644 --- a/app/Repos/User.php +++ b/app/Repos/User.php @@ -5,8 +5,6 @@ namespace App\Repos; use App\Library\Paginator\Adapter\QueryBuilder as PagerQueryBuilder; use App\Models\Answer as AnswerModel; use App\Models\Article as ArticleModel; -use App\Models\ArticleFavorite as ArticleFavoriteModel; -use App\Models\CourseFavorite as CourseFavoriteModel; use App\Models\CourseUser as CourseUserModel; use App\Models\ImUser as ImUserModel; use App\Models\Notification as NotificationModel; @@ -199,22 +197,6 @@ class User extends Repository ]); } - public function countCourseFavorites($userId) - { - return (int)CourseFavoriteModel::count([ - 'conditions' => 'user_id = :user_id: AND deleted = 0', - 'bind' => ['user_id' => $userId], - ]); - } - - public function countArticleFavorites($userId) - { - return (int)ArticleFavoriteModel::count([ - 'conditions' => 'user_id = :user_id: AND deleted = 0', - 'bind' => ['user_id' => $userId], - ]); - } - public function countUnreadNotifications($userId) { return (int)NotificationModel::count([ diff --git a/app/Services/Logic/Answer/AnswerCreate.php b/app/Services/Logic/Answer/AnswerCreate.php index 5b1871b8..990c4110 100644 --- a/app/Services/Logic/Answer/AnswerCreate.php +++ b/app/Services/Logic/Answer/AnswerCreate.php @@ -22,6 +22,7 @@ class AnswerCreate extends LogicService use ClientTrait; use QuestionTrait; use AnswerTrait; + use AnswerDataTrait; public function handle() { @@ -41,15 +42,15 @@ class AnswerCreate extends LogicService $answer = new AnswerModel(); - $answer->published = $this->getPublishStatus($user); - $answer->content = $validator->checkContent($post['content']); - $answer->client_type = $this->getClientType(); - $answer->client_ip = $this->getClientIp(); - $answer->question_id = $question->id; - $answer->owner_id = $user->id; + $data = $this->handlePostData($post); - $answer->create(); + $data['published'] = $this->getPublishStatus($user); + $data['question_id'] = $question->id; + $data['owner_id'] = $user->id; + $answer->create($data); + + $this->saveDynamicAttrs($answer); $this->incrUserDailyAnswerCount($user); $this->recountQuestionAnswers($question); $this->recountUserAnswers($user); diff --git a/app/Services/Logic/Answer/AnswerDataTrait.php b/app/Services/Logic/Answer/AnswerDataTrait.php new file mode 100644 index 00000000..2bb8b0ad --- /dev/null +++ b/app/Services/Logic/Answer/AnswerDataTrait.php @@ -0,0 +1,37 @@ +getClientType(); + $data['client_ip'] = $this->getClientIp(); + + $validator = new AnswerValidator(); + + $data['content'] = $validator->checkContent($post['content']); + + return $data; + } + + protected function saveDynamicAttrs(AnswerModel $answer) + { + $answer->cover = kg_parse_first_content_image($answer->content); + + $answer->summary = kg_parse_summary($answer->content); + + $answer->update(); + } + +} diff --git a/app/Services/Logic/Answer/AnswerInfo.php b/app/Services/Logic/Answer/AnswerInfo.php index a49a7267..70f74c19 100644 --- a/app/Services/Logic/Answer/AnswerInfo.php +++ b/app/Services/Logic/Answer/AnswerInfo.php @@ -75,8 +75,16 @@ class AnswerInfo extends LogicService { $me = [ 'liked' => 0, + 'owned' => 0, ]; + $isOwner = $user->id == $answer->owner_id; + $approved = $answer->published = AnswerModel::PUBLISH_APPROVED; + + if ($isOwner || $approved) { + $me['owned'] = 1; + } + if ($user->id > 0) { $likeRepo = new AnswerLikeRepo(); diff --git a/app/Services/Logic/Answer/AnswerList.php b/app/Services/Logic/Answer/AnswerList.php new file mode 100644 index 00000000..832132f5 --- /dev/null +++ b/app/Services/Logic/Answer/AnswerList.php @@ -0,0 +1,72 @@ +getParams(); + + $params['deleted'] = 0; + + $sort = $pagerQuery->getSort(); + $page = $pagerQuery->getPage(); + $limit = $pagerQuery->getLimit(); + + $answerRepo = new AnswerRepo(); + + $pager = $answerRepo->paginate($params, $sort, $page, $limit); + + return $this->handleAnswers($pager); + } + + public function handleAnswers($pager) + { + if ($pager->total_items == 0) { + return $pager; + } + + $builder = new AnswerListBuilder(); + + $answers = $pager->items->toArray(); + + $questions = $builder->getQuestions($answers); + + $users = $builder->getUsers($answers); + + $items = []; + + foreach ($answers as $answer) { + + $question = $questions[$answer['question_id']] ?? new \stdClass(); + $owner = $users[$answer['owner_id']] ?? new \stdClass(); + + $items[] = [ + 'id' => $answer['id'], + 'summary' => $answer['summary'], + 'published' => $answer['published'], + 'accepted' => $answer['accepted'], + 'comment_count' => $answer['comment_count'], + 'like_count' => $answer['like_count'], + 'create_time' => $answer['create_time'], + 'update_time' => $answer['update_time'], + 'question' => $question, + 'owner' => $owner, + ]; + } + + $pager->items = $items; + + return $pager; + } + +} diff --git a/app/Services/Logic/Answer/AnswerUpdate.php b/app/Services/Logic/Answer/AnswerUpdate.php index 3cfc159d..3506e15b 100644 --- a/app/Services/Logic/Answer/AnswerUpdate.php +++ b/app/Services/Logic/Answer/AnswerUpdate.php @@ -14,6 +14,7 @@ class AnswerUpdate extends LogicService use ClientTrait; use QuestionTrait; use AnswerTrait; + use AnswerDataTrait; public function handle($id) { @@ -29,11 +30,11 @@ class AnswerUpdate extends LogicService $validator->checkIfAllowEdit($answer); - $answer->content = $validator->checkContent($post['content']); - $answer->client_type = $this->getClientType(); - $answer->client_ip = $this->getClientIp(); + $data = $this->handlePostData($post); - $answer->update(); + $answer->update($data); + + $this->saveDynamicAttrs($answer); $this->eventsManager->fire('Answer:afterUpdate', $this, $answer); diff --git a/app/Services/Logic/Article/ArticleCreate.php b/app/Services/Logic/Article/ArticleCreate.php index 5ab11e4c..39a026ce 100644 --- a/app/Services/Logic/Article/ArticleCreate.php +++ b/app/Services/Logic/Article/ArticleCreate.php @@ -29,7 +29,6 @@ class ArticleCreate extends LogicService $data = $this->handlePostData($post); $data['published'] = $this->getPublishStatus($user); - $data['owner_id'] = $user->id; $article->create($data); @@ -38,6 +37,7 @@ class ArticleCreate extends LogicService $this->saveTags($article, $post['xm_tag_ids']); } + $this->saveDynamicAttrs($article); $this->incrUserDailyArticleCount($user); $this->recountUserArticles($user); diff --git a/app/Services/Logic/Article/ArticleDataTrait.php b/app/Services/Logic/Article/ArticleDataTrait.php index 8dc2bfba..0c005068 100644 --- a/app/Services/Logic/Article/ArticleDataTrait.php +++ b/app/Services/Logic/Article/ArticleDataTrait.php @@ -19,6 +19,9 @@ trait ArticleDataTrait { $data = []; + $data['client_type'] = $this->getClientType(); + $data['client_ip'] = $this->getClientIp(); + $validator = new ArticleValidator(); $data['title'] = $validator->checkTitle($post['title']); @@ -48,6 +51,20 @@ trait ArticleDataTrait return $data; } + protected function saveDynamicAttrs(ArticleModel $article) + { + $article->cover = kg_parse_first_content_image($article->content); + + $article->summary = kg_parse_summary($article->content); + + $article->update(); + + /** + * 重新执行afterFetch + */ + $article->afterFetch(); + } + protected function saveTags(ArticleModel $article, $tagIds) { $originTagIds = []; diff --git a/app/Services/Logic/Article/ArticleList.php b/app/Services/Logic/Article/ArticleList.php index ae58b3ea..684f455a 100644 --- a/app/Services/Logic/Article/ArticleList.php +++ b/app/Services/Logic/Article/ArticleList.php @@ -8,7 +8,6 @@ use App\Models\Article as ArticleModel; use App\Repos\Article as ArticleRepo; use App\Services\Logic\Service as LogicService; use App\Validators\ArticleQuery as ArticleQueryValidator; -use Phalcon\Text; class ArticleList extends LogicService { @@ -52,18 +51,8 @@ class ArticleList extends LogicService $items = []; - $baseUrl = kg_cos_url(); - foreach ($articles as $article) { - if (!empty($article['cover']) && !Text::startsWith($article['cover'], 'http')) { - $article['cover'] = $baseUrl . $article['cover']; - } - - if (empty($article['summary'])) { - $article['summary'] = kg_parse_summary($article['content']); - } - $article['tags'] = json_decode($article['tags'], true); $category = $categories[$article['category_id']] ?? new \stdClass(); diff --git a/app/Services/Logic/Article/ArticleUpdate.php b/app/Services/Logic/Article/ArticleUpdate.php index 9046a313..79b41cf1 100644 --- a/app/Services/Logic/Article/ArticleUpdate.php +++ b/app/Services/Logic/Article/ArticleUpdate.php @@ -44,6 +44,8 @@ class ArticleUpdate extends LogicService $this->saveTags($article, $post['xm_tag_ids']); } + $this->saveDynamicAttrs($article); + $this->eventsManager->fire('Article:afterUpdate', $this, $article); return $article; diff --git a/app/Services/Logic/Article/XmTagList.php b/app/Services/Logic/Article/XmTagList.php new file mode 100644 index 00000000..450a8123 --- /dev/null +++ b/app/Services/Logic/Article/XmTagList.php @@ -0,0 +1,50 @@ +findAll(['published' => 1]); + + if ($allTags->count() == 0) return []; + + $articleTagIds = []; + + if ($id > 0) { + $article = $this->findArticle($id); + if (!empty($article->tags)) { + $articleTagIds = kg_array_column($article->tags, 'id'); + } + } + + $list = []; + + foreach ($allTags as $tag) { + $selected = in_array($tag->id, $articleTagIds); + $list[] = [ + 'name' => $tag->name, + 'value' => $tag->id, + 'selected' => $selected, + ]; + } + + return $list; + } + + protected function findArticle($id) + { + $articleRepo = new ArticleRepo(); + + return $articleRepo->findById($id); + } + +} diff --git a/app/Services/Logic/Comment/CommentReply.php b/app/Services/Logic/Comment/CommentReply.php index 33b7bb45..500ca074 100644 --- a/app/Services/Logic/Comment/CommentReply.php +++ b/app/Services/Logic/Comment/CommentReply.php @@ -40,7 +40,7 @@ class CommentReply extends LogicService 'owner_id' => $user->id, ]; - $item = $validator->checkItem($comment->item_type, $comment->item_id); + $item = $validator->checkItem($comment->item_id, $comment->item_type); /** * 子评论中回复用户 diff --git a/app/Services/Logic/Page/PageInfo.php b/app/Services/Logic/Page/PageInfo.php index 50e0c6a6..7431d923 100644 --- a/app/Services/Logic/Page/PageInfo.php +++ b/app/Services/Logic/Page/PageInfo.php @@ -3,6 +3,7 @@ namespace App\Services\Logic\Page; use App\Models\Page as PageModel; +use App\Models\User as UserModel; use App\Services\Logic\PageTrait; use App\Services\Logic\Service as LogicService; @@ -13,22 +14,38 @@ class PageInfo extends LogicService public function handle($id) { + $user = $this->getCurrentUser(true); + $page = $this->checkPage($id); - return $this->handlePage($page); + return $this->handlePage($page, $user); } - protected function handlePage(PageModel $page) + protected function handlePage(PageModel $page, UserModel $user) { $page->content = kg_parse_markdown($page->content); + $me = $this->handleMeInfo($page, $user); + return [ 'id' => $page->id, 'title' => $page->title, 'content' => $page->content, 'create_time' => $page->create_time, 'update_time' => $page->update_time, + 'me' => $me, ]; } + protected function handleMeInfo(PageModel $page, UserModel $user) + { + $me = ['owned' => 0]; + + if ($page->published == 1) { + $me['owned'] = 1; + } + + return $me; + } + } diff --git a/app/Services/Logic/Question/QuestionCreate.php b/app/Services/Logic/Question/QuestionCreate.php index 54ce8c41..7e756eb5 100644 --- a/app/Services/Logic/Question/QuestionCreate.php +++ b/app/Services/Logic/Question/QuestionCreate.php @@ -28,7 +28,6 @@ class QuestionCreate extends LogicService $data = $this->handlePostData($post); $data['published'] = $this->getPublishStatus($user); - $data['owner_id'] = $user->id; $question->create($data); @@ -37,6 +36,7 @@ class QuestionCreate extends LogicService $this->saveTags($question, $post['xm_tag_ids']); } + $this->saveDynamicAttrs($question); $this->incrUserDailyQuestionCount($user); $this->recountUserQuestions($user); diff --git a/app/Services/Logic/Question/QuestionDataTrait.php b/app/Services/Logic/Question/QuestionDataTrait.php index b412332a..6a92b0c3 100644 --- a/app/Services/Logic/Question/QuestionDataTrait.php +++ b/app/Services/Logic/Question/QuestionDataTrait.php @@ -36,7 +36,21 @@ trait QuestionDataTrait return $data; } - + + protected function saveDynamicAttrs(QuestionModel $question) + { + $question->cover = kg_parse_first_content_image($question->content); + + $question->summary = kg_parse_summary($question->content); + + $question->update(); + + /** + * 重新执行afterFetch + */ + $question->afterFetch(); + } + protected function saveTags(QuestionModel $question, $tagIds) { $originTagIds = []; diff --git a/app/Services/Logic/Question/QuestionList.php b/app/Services/Logic/Question/QuestionList.php index cc90cc02..08c1c9f6 100644 --- a/app/Services/Logic/Question/QuestionList.php +++ b/app/Services/Logic/Question/QuestionList.php @@ -8,7 +8,6 @@ use App\Models\Question as QuestionModel; use App\Repos\Question as QuestionRepo; use App\Services\Logic\Service as LogicService; use App\Validators\QuestionQuery as QuestionQueryValidator; -use Phalcon\Text; class QuestionList extends LogicService { @@ -49,21 +48,12 @@ class QuestionList extends LogicService $items = []; - $baseUrl = kg_cos_url(); - foreach ($questions as $question) { - if (!empty($question['cover']) && !Text::startsWith($question['cover'], 'http')) { - $question['cover'] = $baseUrl . $question['cover']; - } - - if (empty($question['summary'])) { - $question['summary'] = kg_parse_summary($question['content'], 80); - } - $question['tags'] = json_decode($question['tags'], true); $owner = $users[$question['owner_id']] ?? new \stdClass(); + $lastReplier = $users[$question['last_replier_id']] ?? new \stdClass(); $items[] = [ diff --git a/app/Services/Logic/Question/QuestionUpdate.php b/app/Services/Logic/Question/QuestionUpdate.php index ed6979b5..4404ac21 100644 --- a/app/Services/Logic/Question/QuestionUpdate.php +++ b/app/Services/Logic/Question/QuestionUpdate.php @@ -50,6 +50,8 @@ class QuestionUpdate extends LogicService $this->saveTags($question, $post['xm_tag_ids']); } + $this->saveDynamicAttrs($question); + $this->eventsManager->fire('Question:afterUpdate', $this, $question); return $question; diff --git a/app/Services/Logic/Question/XmTagList.php b/app/Services/Logic/Question/XmTagList.php new file mode 100644 index 00000000..65bbb41d --- /dev/null +++ b/app/Services/Logic/Question/XmTagList.php @@ -0,0 +1,50 @@ +findAll(['published' => 1]); + + if ($allTags->count() == 0) return []; + + $questionTagIds = []; + + if ($id > 0) { + $question = $this->findQuestion($id); + if (!empty($question->tags)) { + $questionTagIds = kg_array_column($question->tags, 'id'); + } + } + + $list = []; + + foreach ($allTags as $tag) { + $selected = in_array($tag->id, $questionTagIds); + $list[] = [ + 'name' => $tag->name, + 'value' => $tag->id, + 'selected' => $selected, + ]; + } + + return $list; + } + + protected function findQuestion($id) + { + $questionRepo = new QuestionRepo(); + + return $questionRepo->findById($id); + } + +} diff --git a/app/Services/Logic/User/AnswerList.php b/app/Services/Logic/User/AnswerList.php new file mode 100644 index 00000000..109528a5 --- /dev/null +++ b/app/Services/Logic/User/AnswerList.php @@ -0,0 +1,47 @@ +checkUser($id); + + $pagerQuery = new PagerQuery(); + + $params = $pagerQuery->getParams(); + + $params['owner_id'] = $user->id; + $params['published'] = AnswerModel::PUBLISH_APPROVED; + $params['deleted'] = 0; + + $sort = $pagerQuery->getSort(); + $page = $pagerQuery->getPage(); + $limit = $pagerQuery->getLimit(); + + $answerRepo = new AnswerRepo(); + + $pager = $answerRepo->paginate($params, $sort, $page, $limit); + + return $this->handleAnswers($pager); + } + + protected function handleAnswers($pager) + { + $service = new AnswerListService(); + + return $service->handleAnswers($pager); + } + +} diff --git a/app/Services/Logic/User/Console/AnswerList.php b/app/Services/Logic/User/Console/AnswerList.php index b956f440..24792b9c 100644 --- a/app/Services/Logic/User/Console/AnswerList.php +++ b/app/Services/Logic/User/Console/AnswerList.php @@ -2,9 +2,9 @@ namespace App\Services\Logic\User\Console; -use App\Builders\AnswerList as AnswerListBuilder; use App\Library\Paginator\Query as PagerQuery; use App\Repos\Answer as AnswerRepo; +use App\Services\Logic\Answer\AnswerList as AnswerListService; use App\Services\Logic\Service as LogicService; class AnswerList extends LogicService @@ -34,44 +34,9 @@ class AnswerList extends LogicService protected function handleAnswers($pager) { - if ($pager->total_items == 0) { - return $pager; - } + $service = new AnswerListService(); - $builder = new AnswerListBuilder(); - - $answers = $pager->items->toArray(); - - $questions = $builder->getQuestions($answers); - - $users = $builder->getUsers($answers); - - $items = []; - - foreach ($answers as $answer) { - - $answer['summary'] = kg_parse_summary($answer['content'], 64); - - $question = $questions[$answer['question_id']] ?? new \stdClass(); - $owner = $users[$answer['owner_id']] ?? new \stdClass(); - - $items[] = [ - 'id' => $answer['id'], - 'summary' => $answer['summary'], - 'published' => $answer['published'], - 'accepted' => $answer['accepted'], - 'comment_count' => $answer['comment_count'], - 'like_count' => $answer['like_count'], - 'create_time' => $answer['create_time'], - 'update_time' => $answer['update_time'], - 'question' => $question, - 'owner' => $owner, - ]; - } - - $pager->items = $items; - - return $pager; + return $service->handleAnswers($pager); } } diff --git a/app/Services/Logic/User/QuestionList.php b/app/Services/Logic/User/QuestionList.php new file mode 100644 index 00000000..932d16a6 --- /dev/null +++ b/app/Services/Logic/User/QuestionList.php @@ -0,0 +1,47 @@ +checkUser($id); + + $pagerQuery = new PagerQuery(); + + $params = $pagerQuery->getParams(); + + $params['owner_id'] = $user->id; + $params['published'] = QuestionModel::PUBLISH_APPROVED; + $params['deleted'] = 0; + + $sort = $pagerQuery->getSort(); + $page = $pagerQuery->getPage(); + $limit = $pagerQuery->getLimit(); + + $articleRepo = new QuestionRepo(); + + $pager = $articleRepo->paginate($params, $sort, $page, $limit); + + return $this->handleQuestions($pager); + } + + protected function handleQuestions($pager) + { + $service = new QuestionListService(); + + return $service->handleQuestions($pager); + } + +} diff --git a/app/Services/Logic/User/UserInfo.php b/app/Services/Logic/User/UserInfo.php index d6a6a36f..b5bb88fa 100644 --- a/app/Services/Logic/User/UserInfo.php +++ b/app/Services/Logic/User/UserInfo.php @@ -37,6 +37,8 @@ class UserInfo extends LogicService 'locked' => $user->locked, 'course_count' => $user->course_count, 'article_count' => $user->article_count, + 'question_count' => $user->question_count, + 'answer_count' => $user->answer_count, 'friend_count' => $imUser->friend_count, 'group_count' => $imUser->group_count, 'active_time' => $user->active_time, diff --git a/app/Services/Search/ArticleDocument.php b/app/Services/Search/ArticleDocument.php index 2ac3c4a2..9d2610c3 100644 --- a/app/Services/Search/ArticleDocument.php +++ b/app/Services/Search/ArticleDocument.php @@ -35,10 +35,6 @@ class ArticleDocument extends Component */ public function formatDocument(ArticleModel $article) { - if (empty($article->summary)) { - $article->summary = kg_parse_summary($article->content); - } - if (is_array($article->tags) || is_object($article->tags)) { $article->tags = kg_json_encode($article->tags); } diff --git a/app/Services/Search/CourseDocument.php b/app/Services/Search/CourseDocument.php index 6e8853b9..1a59650e 100644 --- a/app/Services/Search/CourseDocument.php +++ b/app/Services/Search/CourseDocument.php @@ -61,10 +61,6 @@ class CourseDocument extends Component $course->cover = CourseModel::getCoverPath($course->cover); - if (empty($course->summary)) { - $course->summary = kg_parse_summary($course->details); - } - return [ 'id' => $course->id, 'title' => $course->title, diff --git a/app/Services/Search/QuestionDocument.php b/app/Services/Search/QuestionDocument.php index 64b8de41..e056766e 100644 --- a/app/Services/Search/QuestionDocument.php +++ b/app/Services/Search/QuestionDocument.php @@ -36,10 +36,6 @@ class QuestionDocument extends Component */ public function formatDocument(QuestionModel $question) { - if (empty($question->summary)) { - $question->summary = kg_parse_summary($question->content); - } - if (is_array($question->tags) || is_object($question->tags)) { $question->tags = kg_json_encode($question->tags); } diff --git a/public/static/admin/img/default/article_cover.png b/public/static/admin/img/default/article_cover.png deleted file mode 100644 index 45118a54ca668371a059d02d35ba0637bebdc77a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65013 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 0) { - var $tabCourses = $('#tab-courses'); - helper.ajaxLoadHtml($tabCourses.data('url'), $tabCourses.attr('id')); - } - - if ($('#tab-users').length > 0) { - var $tabUsers = $('#tab-users'); - helper.ajaxLoadHtml($tabUsers.data('url'), $tabUsers.attr('id')); - } - }); \ No newline at end of file diff --git a/public/static/home/js/user.show.js b/public/static/home/js/user.show.js index b5f070a6..7571113b 100644 --- a/public/static/home/js/user.show.js +++ b/public/static/home/js/user.show.js @@ -13,6 +13,16 @@ layui.use(['jquery', 'helper'], function () { helper.ajaxLoadHtml($tabArticles.data('url'), $tabArticles.attr('id')); } + if ($('#tab-questions').length > 0) { + var $tabQuestions = $('#tab-questions'); + helper.ajaxLoadHtml($tabQuestions.data('url'), $tabQuestions.attr('id')); + } + + if ($('#tab-answers').length > 0) { + var $tabAnswers = $('#tab-answers'); + helper.ajaxLoadHtml($tabAnswers.data('url'), $tabAnswers.attr('id')); + } + if ($('#tab-friends').length > 0) { var $tabFriends = $('#tab-friends'); helper.ajaxLoadHtml($tabFriends.data('url'), $tabFriends.attr('id')); From 57f587f4c441977b88c15e28320756857afee796 Mon Sep 17 00:00:00 2001 From: koogua Date: Thu, 3 Jun 2021 12:10:24 +0800 Subject: [PATCH 2/3] =?UTF-8?q?v1.3.6=E9=98=B6=E6=AE=B5=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=EF=BC=8Ccherry-pick?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Admin/Views/course/chapters.volt | 2 +- app/Http/Home/Views/answer/add.volt | 10 +- app/Http/Home/Views/answer/edit.volt | 10 +- app/Http/Home/Views/article/edit.volt | 96 +++++++++---------- app/Http/Home/Views/question/edit.volt | 34 +++---- app/Http/Home/Views/user/console/answers.volt | 6 +- app/Models/User.php | 7 ++ app/Repos/User.php | 9 ++ app/Services/Logic/Answer/AnswerCreate.php | 7 -- app/Services/Logic/Answer/AnswerDataTrait.php | 6 ++ app/Services/Logic/Article/ArticleCreate.php | 5 - .../Logic/Article/ArticleDataTrait.php | 6 ++ .../Logic/Comment/AfterCreateTrait.php | 21 +++- app/Services/Logic/Comment/CommentCreate.php | 22 ++--- .../Logic/Comment/CommentDataTrait.php | 45 +++++++++ app/Services/Logic/Comment/CommentReply.php | 26 ++--- app/Services/Logic/Comment/CountTrait.php | 17 +++- .../Logic/Question/QuestionCreate.php | 5 - .../Logic/Question/QuestionDataTrait.php | 6 ++ db/migrations/20210602034627.php | 34 +++++++ public/static/home/css/common.css | 18 ++-- 21 files changed, 250 insertions(+), 142 deletions(-) create mode 100644 app/Services/Logic/Comment/CommentDataTrait.php create mode 100644 db/migrations/20210602034627.php diff --git a/app/Http/Admin/Views/course/chapters.volt b/app/Http/Admin/Views/course/chapters.volt index 32b117fc..64bd6282 100644 --- a/app/Http/Admin/Views/course/chapters.volt +++ b/app/Http/Admin/Views/course/chapters.volt @@ -55,7 +55,7 @@ {{ item.id }} - {{ item.title }} + {{ item.title }} {{ item.lesson_count }} diff --git a/app/Http/Home/Views/answer/add.volt b/app/Http/Home/Views/answer/add.volt index ef3e4b2b..ca714746 100644 --- a/app/Http/Home/Views/answer/add.volt +++ b/app/Http/Home/Views/answer/add.volt @@ -12,19 +12,19 @@
    -
    -
    - +
    +
    +
    -
    +
    -
    +
    diff --git a/app/Http/Home/Views/answer/edit.volt b/app/Http/Home/Views/answer/edit.volt index 1f9d9918..2d9ab136 100644 --- a/app/Http/Home/Views/answer/edit.volt +++ b/app/Http/Home/Views/answer/edit.volt @@ -12,19 +12,19 @@
    -
    -
    - +
    +
    +
    -
    +
    -
    +
    diff --git a/app/Http/Home/Views/article/edit.volt b/app/Http/Home/Views/article/edit.volt index ebe74200..4ca2ccc5 100644 --- a/app/Http/Home/Views/article/edit.volt +++ b/app/Http/Home/Views/article/edit.volt @@ -16,10 +16,10 @@
    - -
    +
    +
    -
    +
    @@ -31,57 +31,57 @@
    -
    - -
    -
    +
    +
    -
    +
    @@ -30,24 +30,24 @@
    -
    -
    -{% endblock %} - -{% block include_js %} - - {{ js_include('home/js/user.console.js') }} - {% endblock %} \ No newline at end of file diff --git a/app/Http/Home/Views/user/console/favorites.volt b/app/Http/Home/Views/user/console/favorites.volt index 46adf29e..4c67244a 100644 --- a/app/Http/Home/Views/user/console/favorites.volt +++ b/app/Http/Home/Views/user/console/favorites.volt @@ -28,10 +28,4 @@
    -{% endblock %} - -{% block include_js %} - - {{ js_include('home/js/user.console.js') }} - {% endblock %} \ No newline at end of file diff --git a/app/Http/Home/Views/user/console/friends.volt b/app/Http/Home/Views/user/console/friends.volt index cd8c52fc..d69ea2b0 100644 --- a/app/Http/Home/Views/user/console/friends.volt +++ b/app/Http/Home/Views/user/console/friends.volt @@ -44,7 +44,7 @@ {{ item.area }} {{ item.active_time|time_ago }} - + {% endfor %} @@ -56,10 +56,4 @@
    -{% endblock %} - -{% block include_js %} - - {{ js_include('home/js/my.im.js') }} - {% endblock %} \ No newline at end of file diff --git a/app/Http/Home/Views/user/console/notifications.volt b/app/Http/Home/Views/user/console/notifications.volt index 60cbff10..a5e4a83b 100644 --- a/app/Http/Home/Views/user/console/notifications.volt +++ b/app/Http/Home/Views/user/console/notifications.volt @@ -42,10 +42,4 @@
    -{% endblock %} - -{% block include_js %} - - {{ js_include('home/js/user.console.js') }} - {% endblock %} \ No newline at end of file diff --git a/app/Models/Consult.php b/app/Models/Consult.php index ab200716..e856b550 100644 --- a/app/Models/Consult.php +++ b/app/Models/Consult.php @@ -89,7 +89,7 @@ class Consult extends Model * * @var int */ - public $priority = 0; + public $priority = self::PRIORITY_LOW; /** * 私密标识 diff --git a/app/Models/Course.php b/app/Models/Course.php index 1d9927a8..59054f1f 100644 --- a/app/Models/Course.php +++ b/app/Models/Course.php @@ -129,7 +129,7 @@ class Course extends Model * * @var float */ - public $origin_price; + public $origin_price = 0.00; /** * 优惠价格