diff --git a/CHANGELOG.md b/CHANGELOG.md index 505a5ed3..3e1502d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +### [v1.6.7](https://gitee.com/koogua/course-tencent-cloud/releases/v1.6.7)(2023-12-15) + +- 增加文章分类功能 +- 增加问题分类功能 +- 增加审核等批量功能 +- 增加若干业务插件埋点 +- 精简重构大量业务逻辑 +- 移除秒杀营销功能 +- 已发现的问题修复 + ### [v1.6.6](https://gitee.com/koogua/course-tencent-cloud/releases/v1.6.6)(2023-08-30) - 还原意外删除的AnswerList.php文件 diff --git a/app/Builders/ArticleList.php b/app/Builders/ArticleList.php index 7ef8ca46..68a78f5d 100644 --- a/app/Builders/ArticleList.php +++ b/app/Builders/ArticleList.php @@ -7,7 +7,7 @@ namespace App\Builders; -use App\Caches\CategoryList as CategoryListCache; +use App\Caches\CategoryAllList as CategoryAllListCache; use App\Models\Category as CategoryModel; use App\Repos\User as UserRepo; @@ -47,7 +47,7 @@ class ArticleList extends Builder public function getCategories() { - $cache = new CategoryListCache(); + $cache = new CategoryAllListCache(); $items = $cache->get(CategoryModel::TYPE_ARTICLE); diff --git a/app/Builders/CourseList.php b/app/Builders/CourseList.php index e5a3c383..d0dffdf4 100644 --- a/app/Builders/CourseList.php +++ b/app/Builders/CourseList.php @@ -7,7 +7,7 @@ namespace App\Builders; -use App\Caches\CategoryList as CategoryListCache; +use App\Caches\CategoryAllList as CategoryAllListCache; use App\Models\Category as CategoryModel; use App\Repos\User as UserRepo; @@ -38,7 +38,7 @@ class CourseList extends Builder public function getCategories() { - $cache = new CategoryListCache(); + $cache = new CategoryAllListCache(); $items = $cache->get(CategoryModel::TYPE_COURSE); diff --git a/app/Builders/DanmuList.php b/app/Builders/DanmuList.php deleted file mode 100644 index 2ee29569..00000000 --- a/app/Builders/DanmuList.php +++ /dev/null @@ -1,104 +0,0 @@ -getCourses($danmus); - - foreach ($danmus as $key => $danmu) { - $danmus[$key]['course'] = $courses[$danmu['course_id']] ?? new \stdClass(); - } - - return $danmus; - } - - public function handleChapters(array $danmus) - { - $chapters = $this->getChapters($danmus); - - foreach ($danmus as $key => $danmu) { - $danmus[$key]['chapter'] = $chapters[$danmu['chapter_id']] ?? new \stdClass(); - } - - return $danmus; - } - - public function handleUsers(array $danmus) - { - $users = $this->getUsers($danmus); - - foreach ($danmus as $key => $danmu) { - $danmus[$key]['owner'] = $users[$danmu['owner_id']] ?? new \stdClass(); - } - - return $danmus; - } - - public function getCourses(array $danmus) - { - $ids = kg_array_column($danmus, 'course_id'); - - $courseRepo = new CourseRepo(); - - $courses = $courseRepo->findByIds($ids, ['id', 'title']); - - $result = []; - - foreach ($courses->toArray() as $course) { - $result[$course['id']] = $course; - } - - return $result; - } - - public function getChapters(array $danmus) - { - $ids = kg_array_column($danmus, 'chapter_id'); - - $chapterRepo = new ChapterRepo(); - - $chapters = $chapterRepo->findByIds($ids, ['id', 'title']); - - $result = []; - - foreach ($chapters->toArray() as $chapter) { - $result[$chapter['id']] = $chapter; - } - - return $result; - } - - public function getUsers(array $danmus) - { - $ids = kg_array_column($danmus, 'owner_id'); - - $userRepo = new UserRepo(); - - $users = $userRepo->findShallowUserByIds($ids); - - $baseUrl = kg_cos_url(); - - $result = []; - - foreach ($users->toArray() as $user) { - $user['avatar'] = $baseUrl . $user['avatar']; - $result[$user['id']] = $user; - } - - return $result; - } - -} diff --git a/app/Builders/HelpList.php b/app/Builders/HelpList.php index f451548d..bc0ee1c2 100644 --- a/app/Builders/HelpList.php +++ b/app/Builders/HelpList.php @@ -7,7 +7,7 @@ namespace App\Builders; -use App\Caches\CategoryList as CategoryListCache; +use App\Caches\CategoryAllList as CategoryAllListCache; use App\Models\Category as CategoryModel; class HelpList extends Builder @@ -26,7 +26,7 @@ class HelpList extends Builder public function getCategories() { - $cache = new CategoryListCache(); + $cache = new CategoryAllListCache(); $items = $cache->get(CategoryModel::TYPE_HELP); diff --git a/app/Builders/QuestionList.php b/app/Builders/QuestionList.php index aeabd0e8..b4d25292 100644 --- a/app/Builders/QuestionList.php +++ b/app/Builders/QuestionList.php @@ -7,7 +7,7 @@ namespace App\Builders; -use App\Caches\CategoryList as CategoryListCache; +use App\Caches\CategoryAllList as CategoryAllListCache; use App\Models\Category as CategoryModel; use App\Repos\User as UserRepo; @@ -27,8 +27,8 @@ class QuestionList extends Builder { $categories = $this->getCategories(); - foreach ($questions as $key => $article) { - $questions[$key]['category'] = $categories[$article['category_id']] ?? new \stdClass(); + foreach ($questions as $key => $question) { + $questions[$key]['category'] = $categories[$question['category_id']] ?? new \stdClass(); } return $questions; @@ -48,7 +48,7 @@ class QuestionList extends Builder public function getCategories() { - $cache = new CategoryListCache(); + $cache = new CategoryAllListCache(); $items = $cache->get(CategoryModel::TYPE_QUESTION); diff --git a/app/Builders/UserList.php b/app/Builders/UserList.php index 7dbb1f27..fcee87c5 100644 --- a/app/Builders/UserList.php +++ b/app/Builders/UserList.php @@ -8,6 +8,7 @@ namespace App\Builders; use App\Models\User as UserModel; +use App\Repos\Account as AccountRepo; use App\Repos\Role as RoleRepo; class UserList extends Builder @@ -24,6 +25,17 @@ class UserList extends Builder return $users; } + public function handleAccounts(array $users) + { + $accounts = $this->getAccounts($users); + + foreach ($users as $key => $user) { + $users[$key]['account'] = $accounts[$user['id']] ?? new \stdClass(); + } + + return $users; + } + public function handleAdminRoles(array $users) { $roles = $this->getAdminRoles($users); @@ -46,6 +58,26 @@ class UserList extends Builder return $users; } + protected function getAccounts(array $users) + { + $ids = kg_array_column($users, 'id'); + + $accountRepo = new AccountRepo(); + + $accounts = $accountRepo->findByIds($ids); + + $result = []; + + foreach ($accounts as $account) { + $result[$account->id] = [ + 'phone' => $account->phone, + 'email' => $account->email, + ]; + } + + return $result; + } + protected function getAdminRoles(array $users) { $ids = kg_array_column($users, 'admin_role'); diff --git a/app/Caches/AppInfo.php b/app/Caches/AppInfo.php index 0803bb9a..dd93d1b2 100644 --- a/app/Caches/AppInfo.php +++ b/app/Caches/AppInfo.php @@ -27,10 +27,10 @@ class AppInfo extends Cache $appInfo = new \App\Library\AppInfo(); return [ - 'name' => $appInfo->name, - 'alias' => $appInfo->alias, - 'link' => $appInfo->link, - 'version' => $appInfo->version, + 'name' => $appInfo->get('name'), + 'alias' => $appInfo->get('alias'), + 'link' => $appInfo->get('link'), + 'version' => $appInfo->get('version'), ]; } diff --git a/app/Caches/CategoryAllList.php b/app/Caches/CategoryAllList.php new file mode 100644 index 00000000..01866cc0 --- /dev/null +++ b/app/Caches/CategoryAllList.php @@ -0,0 +1,46 @@ +lifetime; + } + + public function getKey($id = null) + { + return "category_all_list:{$id}"; + } + + public function getContent($id = null) + { + /** + * @var Resultset $categories + */ + $categories = CategoryModel::query() + ->columns(['id', 'parent_id', 'name', 'priority', 'level', 'path']) + ->where('type = :type:', ['type' => $id]) + ->orderBy('level ASC, priority ASC') + ->execute(); + + if ($categories->count() == 0) { + return []; + } + + return $categories->toArray(); + } + +} diff --git a/app/Caches/CategoryList.php b/app/Caches/CategoryList.php index 78a203eb..aede8d99 100644 --- a/app/Caches/CategoryList.php +++ b/app/Caches/CategoryList.php @@ -25,10 +25,6 @@ class CategoryList extends Cache return "category_list:{$id}"; } - /** - * @param null $id - * @return array - */ public function getContent($id = null) { /** diff --git a/app/Caches/CourseCategoryList.php b/app/Caches/CourseCategoryList.php deleted file mode 100644 index 12681a06..00000000 --- a/app/Caches/CourseCategoryList.php +++ /dev/null @@ -1,59 +0,0 @@ -lifetime; - } - - public function getKey($id = null) - { - return "course_category_list:{$id}"; - } - - public function getContent($id = null) - { - $courseRepo = new CourseRepo(); - - $categories = $courseRepo->findCategories($id); - - if ($categories->count() == 0) { - return []; - } - - return $this->handleContent($categories); - } - - /** - * @param CategoryModel[] $categories - * @return array - */ - public function handleContent($categories) - { - $result = []; - - foreach ($categories as $category) { - $result[] = [ - 'id' => $category->id, - 'name' => $category->name, - ]; - } - - return $result; - } - -} diff --git a/app/Caches/CourseRecommendedList.php b/app/Caches/CourseRecommendedList.php deleted file mode 100644 index c810082f..00000000 --- a/app/Caches/CourseRecommendedList.php +++ /dev/null @@ -1,90 +0,0 @@ -lifetime; - } - - public function getKey($id = null) - { - return "course_recommended_list:{$id}"; - } - - public function getContent($id = null) - { - $courses = $this->findCourses(5); - - if ($courses->count() == 0) { - return []; - } - - return $this->handleContent($courses); - } - - /** - * @param CourseModel[] $courses - * @return array - */ - public function handleContent($courses) - { - $result = []; - - foreach ($courses as $course) { - - $userCount = $course->user_count; - - if ($course->fake_user_count > $course->user_count) { - $userCount = $course->fake_user_count; - } - - $result[] = [ - 'id' => $course->id, - 'title' => $course->title, - 'cover' => $course->cover, - 'model' => $course->model, - 'level' => $course->level, - 'rating' => round($course->rating, 1), - 'market_price' => (float)$course->market_price, - 'vip_price' => (float)$course->vip_price, - 'user_count' => $userCount, - 'lesson_count' => $course->lesson_count, - 'review_count' => $course->review_count, - 'favorite_count' => $course->favorite_count, - ]; - } - - return $result; - } - - /** - * @param int $limit - * @return ResultsetInterface|Resultset|CourseModel[] - */ - public function findCourses($limit = 5) - { - return CourseModel::query() - ->where('market_price > 0') - ->andWhere('published = 1') - ->andWhere('deleted = 0') - ->orderBy('RAND()') - ->limit($limit) - ->execute(); - } - -} diff --git a/app/Caches/CourseTeacherList.php b/app/Caches/CourseTeacherList.php deleted file mode 100644 index 1c676f1a..00000000 --- a/app/Caches/CourseTeacherList.php +++ /dev/null @@ -1,63 +0,0 @@ -lifetime; - } - - public function getKey($id = null) - { - return "course_teacher_list:{$id}"; - } - - public function getContent($id = null) - { - $courseRepo = new CourseRepo(); - - $users = $courseRepo->findTeachers($id); - - if ($users->count() == 0) { - return []; - } - - return $this->handleContent($users); - } - - /** - * @param UserModel[] $users - * @return array - */ - public function handleContent($users) - { - $result = []; - - foreach ($users as $user) { - $result[] = [ - 'id' => $user->id, - 'name' => $user->name, - 'avatar' => $user->avatar, - 'vip' => $user->vip, - 'title' => $user->title, - 'about' => $user->about, - ]; - } - - return $result; - } - -} diff --git a/app/Caches/FeaturedArticleList.php b/app/Caches/FeaturedArticleList.php index bd5fc0f2..bdf4d92d 100644 --- a/app/Caches/FeaturedArticleList.php +++ b/app/Caches/FeaturedArticleList.php @@ -14,13 +14,13 @@ use Phalcon\Mvc\Model\ResultsetInterface; class FeaturedArticleList extends Cache { - protected $lifetime = 86400; + protected $lifetime = 3600; + + protected $limit = 5; public function getLifetime() { - $tomorrow = strtotime('tomorrow'); - - return $tomorrow - time(); + return $this->lifetime; } public function getKey($id = null) @@ -30,9 +30,7 @@ class FeaturedArticleList extends Cache public function getContent($id = null) { - $limit = 8; - - $articles = $this->findArticles($limit); + $articles = $this->findArticles($this->limit); if ($articles->count() == 0) { return []; @@ -41,20 +39,10 @@ class FeaturedArticleList extends Cache $result = []; foreach ($articles as $article) { - - $userCount = $article->user_count; - - if ($article->fake_user_count > $article->user_count) { - $userCount = $article->fake_user_count; - } - $result[] = [ 'id' => $article->id, 'title' => $article->title, 'cover' => $article->cover, - 'market_price' => (float)$article->market_price, - 'vip_price' => (float)$article->vip_price, - 'user_count' => $userCount, 'favorite_count' => $article->favorite_count, 'comment_count' => $article->comment_count, 'view_count' => $article->view_count, @@ -69,13 +57,13 @@ class FeaturedArticleList extends Cache * @param int $limit * @return ResultsetInterface|Resultset|ArticleModel[] */ - protected function findArticles($limit = 8) + protected function findArticles($limit = 5) { return ArticleModel::query() ->where('featured = 1') - ->andWhere('published = 1') + ->andWhere('published = :published:', ['published' => ArticleModel::PUBLISH_APPROVED]) ->andWhere('deleted = 0') - ->orderBy('id DESC') + ->orderBy('RAND()') ->limit($limit) ->execute(); } diff --git a/app/Caches/FeaturedCourseList.php b/app/Caches/FeaturedCourseList.php index cb2817a8..d9b26459 100644 --- a/app/Caches/FeaturedCourseList.php +++ b/app/Caches/FeaturedCourseList.php @@ -14,13 +14,13 @@ use Phalcon\Mvc\Model\ResultsetInterface; class FeaturedCourseList extends Cache { - protected $lifetime = 86400; + protected $lifetime = 3600; + + protected $limit = 5; public function getLifetime() { - $tomorrow = strtotime('tomorrow'); - - return $tomorrow - time(); + return $this->lifetime; } public function getKey($id = null) @@ -30,9 +30,7 @@ class FeaturedCourseList extends Cache public function getContent($id = null) { - $limit = 8; - - $courses = $this->findCourses($limit); + $courses = $this->findCourses($this->limit); if ($courses->count() == 0) { return []; @@ -71,13 +69,13 @@ class FeaturedCourseList extends Cache * @param int $limit * @return ResultsetInterface|Resultset|CourseModel[] */ - protected function findCourses($limit = 8) + protected function findCourses($limit = 5) { return CourseModel::query() ->where('featured = 1') ->andWhere('published = 1') ->andWhere('deleted = 0') - ->orderBy('id DESC') + ->orderBy('RAND()') ->limit($limit) ->execute(); } diff --git a/app/Caches/FeaturedQuestionList.php b/app/Caches/FeaturedQuestionList.php new file mode 100644 index 00000000..4508b6ec --- /dev/null +++ b/app/Caches/FeaturedQuestionList.php @@ -0,0 +1,72 @@ +lifetime; + } + + public function getKey($id = null) + { + return 'featured_question_list'; + } + + public function getContent($id = null) + { + $questions = $this->findQuestions($this->limit); + + if ($questions->count() == 0) { + return []; + } + + $result = []; + + foreach ($questions as $question) { + + $result[] = [ + 'id' => $question->id, + 'title' => $question->title, + 'cover' => $question->cover, + 'favorite_count' => $question->favorite_count, + 'answer_count' => $question->answer_count, + 'view_count' => $question->view_count, + 'like_count' => $question->like_count, + ]; + } + + return $result; + } + + /** + * @param int $limit + * @return ResultsetInterface|Resultset|QuestionModel[] + */ + protected function findQuestions($limit = 5) + { + return QuestionModel::query() + ->where('featured = 1') + ->andWhere('published = :published:', ['published' => QuestionModel::PUBLISH_APPROVED]) + ->andWhere('deleted = 0') + ->orderBy('RAND()') + ->limit($limit) + ->execute(); + } + +} diff --git a/app/Caches/FlashSale.php b/app/Caches/FlashSale.php deleted file mode 100644 index d8b89f43..00000000 --- a/app/Caches/FlashSale.php +++ /dev/null @@ -1,36 +0,0 @@ -lifetime; - } - - public function getKey($id = null) - { - return "flash_sale:{$id}"; - } - - public function getContent($id = null) - { - $saleRepo = new FlashSaleRepo(); - - $sale = $saleRepo->findById($id); - - return $sale ?: null; - } - -} diff --git a/app/Caches/HelpList.php b/app/Caches/HelpList.php index 2899bbd8..5c30bea4 100644 --- a/app/Caches/HelpList.php +++ b/app/Caches/HelpList.php @@ -15,7 +15,7 @@ use Phalcon\Mvc\Model\ResultsetInterface; class HelpList extends Cache { - protected $lifetime = 365 * 86400; + protected $lifetime = 7 * 86400; public function getLifetime() { diff --git a/app/Caches/HotQuestionList.php b/app/Caches/HotQuestionList.php index 64220fd8..3afbec0b 100644 --- a/app/Caches/HotQuestionList.php +++ b/app/Caches/HotQuestionList.php @@ -14,13 +14,11 @@ use Phalcon\Mvc\Model\ResultsetInterface; class HotQuestionList extends Cache { - protected $lifetime = 86400; + protected $lifetime = 3600; public function getLifetime() { - $tomorrow = strtotime('tomorrow'); - - return $tomorrow - time(); + return $this->lifetime; } public function getKey($id = null) diff --git a/app/Caches/IndexArticleList.php b/app/Caches/IndexArticleList.php index c892923f..43075b7c 100644 --- a/app/Caches/IndexArticleList.php +++ b/app/Caches/IndexArticleList.php @@ -14,7 +14,7 @@ use App\Services\Logic\Article\ArticleList as ArticleListService; class IndexArticleList extends Cache { - protected $lifetime = 15 * 60; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Caches/IndexFeaturedCourseList.php b/app/Caches/IndexFeaturedCourseList.php index f7d0e6ae..77bb347b 100644 --- a/app/Caches/IndexFeaturedCourseList.php +++ b/app/Caches/IndexFeaturedCourseList.php @@ -19,7 +19,7 @@ use Phalcon\Mvc\Model\ResultsetInterface; class IndexFeaturedCourseList extends Cache { - protected $lifetime = 86400; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Caches/IndexFlashSaleList.php b/app/Caches/IndexFlashSaleList.php deleted file mode 100644 index 7fd379b6..00000000 --- a/app/Caches/IndexFlashSaleList.php +++ /dev/null @@ -1,36 +0,0 @@ -handle(); - - return $sales[0]['items'] ?? []; - } - -} diff --git a/app/Caches/IndexFreeCourseList.php b/app/Caches/IndexFreeCourseList.php index bc20a9dc..9ae4226c 100644 --- a/app/Caches/IndexFreeCourseList.php +++ b/app/Caches/IndexFreeCourseList.php @@ -19,7 +19,7 @@ use Phalcon\Mvc\Model\ResultsetInterface; class IndexFreeCourseList extends Cache { - protected $lifetime = 86400; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Caches/IndexLiveList.php b/app/Caches/IndexLiveList.php index 734150a1..ae3dff4e 100644 --- a/app/Caches/IndexLiveList.php +++ b/app/Caches/IndexLiveList.php @@ -18,7 +18,7 @@ use Phalcon\Mvc\Model\ResultsetInterface; class IndexLiveList extends Cache { - protected $lifetime = 86400; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Caches/IndexNewCourseList.php b/app/Caches/IndexNewCourseList.php index 4975cb27..457eb8ce 100644 --- a/app/Caches/IndexNewCourseList.php +++ b/app/Caches/IndexNewCourseList.php @@ -19,7 +19,7 @@ use Phalcon\Mvc\Model\ResultsetInterface; class IndexNewCourseList extends Cache { - protected $lifetime = 86400; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Caches/IndexQuestionList.php b/app/Caches/IndexQuestionList.php index b79db98b..12bb02c1 100644 --- a/app/Caches/IndexQuestionList.php +++ b/app/Caches/IndexQuestionList.php @@ -14,7 +14,7 @@ use App\Services\Logic\Question\QuestionList as QuestionListService; class IndexQuestionList extends Cache { - protected $lifetime = 15 * 60; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Caches/IndexSimpleFeaturedCourseList.php b/app/Caches/IndexSimpleFeaturedCourseList.php index b5433216..616a37bd 100644 --- a/app/Caches/IndexSimpleFeaturedCourseList.php +++ b/app/Caches/IndexSimpleFeaturedCourseList.php @@ -17,7 +17,7 @@ use Phalcon\Mvc\Model\ResultsetInterface; class IndexSimpleFeaturedCourseList extends Cache { - protected $lifetime = 86400; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Caches/IndexSimpleFreeCourseList.php b/app/Caches/IndexSimpleFreeCourseList.php index 34a6d4f7..16b0e64f 100644 --- a/app/Caches/IndexSimpleFreeCourseList.php +++ b/app/Caches/IndexSimpleFreeCourseList.php @@ -17,7 +17,7 @@ use Phalcon\Mvc\Model\ResultsetInterface; class IndexSimpleFreeCourseList extends Cache { - protected $lifetime = 86400; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Caches/IndexSimpleNewCourseList.php b/app/Caches/IndexSimpleNewCourseList.php index 7dffa5af..9dbd225c 100644 --- a/app/Caches/IndexSimpleNewCourseList.php +++ b/app/Caches/IndexSimpleNewCourseList.php @@ -17,7 +17,7 @@ use Phalcon\Mvc\Model\ResultsetInterface; class IndexSimpleNewCourseList extends Cache { - protected $lifetime = 86400; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Caches/IndexSimpleVipCourseList.php b/app/Caches/IndexSimpleVipCourseList.php index 6756b39e..90f8b493 100644 --- a/app/Caches/IndexSimpleVipCourseList.php +++ b/app/Caches/IndexSimpleVipCourseList.php @@ -17,7 +17,7 @@ use Phalcon\Mvc\Model\ResultsetInterface; class IndexSimpleVipCourseList extends Cache { - protected $lifetime = 86400; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Caches/IndexSlideList.php b/app/Caches/IndexSlideList.php index abc7d28c..00f15ae1 100644 --- a/app/Caches/IndexSlideList.php +++ b/app/Caches/IndexSlideList.php @@ -14,7 +14,7 @@ use Phalcon\Mvc\Model\ResultsetInterface; class IndexSlideList extends Cache { - protected $lifetime = 365 * 86400; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Caches/IndexVipCourseList.php b/app/Caches/IndexVipCourseList.php index 6b268160..e11ce1b2 100644 --- a/app/Caches/IndexVipCourseList.php +++ b/app/Caches/IndexVipCourseList.php @@ -19,7 +19,7 @@ use Phalcon\Mvc\Model\ResultsetInterface; class IndexVipCourseList extends Cache { - protected $lifetime = 86400; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Caches/MaxFlashSaleId.php b/app/Caches/MaxFlashSaleId.php deleted file mode 100644 index b6a7030c..00000000 --- a/app/Caches/MaxFlashSaleId.php +++ /dev/null @@ -1,34 +0,0 @@ -lifetime; - } - - public function getKey($id = null) - { - return 'max_flash_sale_id'; - } - - public function getContent($id = null) - { - $sale = FlashSaleModel::findFirst(['order' => 'id DESC']); - - return $sale->id ?? 0; - } - -} diff --git a/app/Caches/TaggedArticleList.php b/app/Caches/TaggedArticleList.php index d57faf7b..05640fff 100644 --- a/app/Caches/TaggedArticleList.php +++ b/app/Caches/TaggedArticleList.php @@ -13,9 +13,9 @@ use App\Repos\Article as ArticleRepo; class TaggedArticleList extends Cache { - protected $limit = 5; + protected $limit = 15; - protected $lifetime = 86400; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Caches/TaggedQuestionList.php b/app/Caches/TaggedQuestionList.php index 7495823b..f6adb8b4 100644 --- a/app/Caches/TaggedQuestionList.php +++ b/app/Caches/TaggedQuestionList.php @@ -13,9 +13,9 @@ use App\Repos\Question as QuestionRepo; class TaggedQuestionList extends Cache { - protected $limit = 5; + protected $limit = 15; - protected $lifetime = 86400; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Caches/TopAnswererList.php b/app/Caches/TopAnswererList.php index 37991604..4acaa8e7 100644 --- a/app/Caches/TopAnswererList.php +++ b/app/Caches/TopAnswererList.php @@ -16,7 +16,7 @@ use Phalcon\Mvc\Model\ResultsetInterface; class TopAnswererList extends Cache { - protected $lifetime = 86400; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Caches/TopAuthorList.php b/app/Caches/TopAuthorList.php index 882e4cab..1e6a2404 100644 --- a/app/Caches/TopAuthorList.php +++ b/app/Caches/TopAuthorList.php @@ -16,7 +16,7 @@ use Phalcon\Mvc\Model\ResultsetInterface; class TopAuthorList extends Cache { - protected $lifetime = 86400; + protected $lifetime = 3600; public function getLifetime() { diff --git a/app/Console/Tasks/CleanDemoDataTask.php b/app/Console/Tasks/CleanDemoDataTask.php index 24cba3df..fabd6a6d 100644 --- a/app/Console/Tasks/CleanDemoDataTask.php +++ b/app/Console/Tasks/CleanDemoDataTask.php @@ -8,12 +8,13 @@ namespace App\Console\Tasks; use App\Caches\CategoryList as CategoryListCache; +use App\Caches\CategoryAllList as CategoryAllListCache; use App\Caches\CategoryTreeList as CategoryTreeListCache; use App\Caches\IndexSlideList as IndexSlideListCache; use App\Models\Account as AccountModel; use App\Models\Category as CategoryModel; use App\Repos\User as UserRepo; -use App\Services\Utils\IndexCourseCache as IndexCourseCacheUtil; +use App\Services\Utils\IndexPageCache as IndexPageCacheUtil; class CleanDemoDataTask extends Task { @@ -81,17 +82,19 @@ class CleanDemoDataTask extends Task protected function cleanCache() { - $util = new IndexCourseCacheUtil(); + $util = new IndexPageCacheUtil(); $util->rebuild(); $slideListCache = new IndexSlideListCache(); $slideListCache->rebuild(); $categoryListCache = new CategoryListCache(); + $categoryAllListCache = new CategoryAllListCache(); $categoryTreeListCache = new CategoryTreeListCache(); foreach (CategoryModel::types() as $key => $value) { $categoryListCache->rebuild($key); + $categoryAllListCache->rebuild($key); $categoryTreeListCache->rebuild($key); } } @@ -114,7 +117,7 @@ class CleanDemoDataTask extends Task $user = $userRepo->findById(100015); - return $user ? true : false; + return (bool)$user; } } diff --git a/app/Console/Tasks/CloseFlashSaleOrderTask.php b/app/Console/Tasks/CloseFlashSaleOrderTask.php deleted file mode 100644 index b83afe2b..00000000 --- a/app/Console/Tasks/CloseFlashSaleOrderTask.php +++ /dev/null @@ -1,86 +0,0 @@ -findOrders(); - - echo sprintf('pending orders: %s', $orders->count()) . PHP_EOL; - - if ($orders->count() == 0) return; - - echo '------ start close order task ------' . PHP_EOL; - - foreach ($orders as $order) { - $this->incrFlashSaleStock($order->promotion_id); - $this->pushFlashSaleQueue($order->promotion_id); - $this->deleteUserOrderCache($order->owner_id, $order->promotion_id); - $order->status = OrderModel::STATUS_CLOSED; - $order->update(); - } - - echo '------ end close order task ------' . PHP_EOL; - } - - protected function incrFlashSaleStock($saleId) - { - $flashSaleRepo = new FlashSaleRepo(); - - $flashSale = $flashSaleRepo->findById($saleId); - - $flashSale->stock += 1; - - $flashSale->update(); - } - - protected function pushFlashSaleQueue($saleId) - { - $queue = new FlashSaleQueue(); - - $queue->push($saleId); - } - - protected function deleteUserOrderCache($userId, $saleId) - { - $cache = new UserOrderCache(); - - $cache->delete($userId, $saleId); - } - - /** - * 查找待关闭订单 - * - * @param int $limit - * @return ResultsetInterface|Resultset|OrderModel[] - */ - protected function findOrders($limit = 1000) - { - $status = OrderModel::STATUS_PENDING; - $type = OrderModel::PROMOTION_FLASH_SALE; - $time = time() - 15 * 60; - - return OrderModel::query() - ->where('status = :status:', ['status' => $status]) - ->andWhere('promotion_type = :type:', ['type' => $type]) - ->andWhere('create_time < :time:', ['time' => $time]) - ->limit($limit) - ->execute(); - } - -} diff --git a/app/Console/Tasks/CloseOrderTask.php b/app/Console/Tasks/CloseOrderTask.php index f56c9077..8b17ed81 100644 --- a/app/Console/Tasks/CloseOrderTask.php +++ b/app/Console/Tasks/CloseOrderTask.php @@ -42,11 +42,9 @@ class CloseOrderTask extends Task { $status = OrderModel::STATUS_PENDING; $time = time() - 12 * 3600; - $type = 0; return OrderModel::query() ->where('status = :status:', ['status' => $status]) - ->andWhere('promotion_type = :type:', ['type' => $type]) ->andWhere('create_time < :time:', ['time' => $time]) ->limit($limit) ->execute(); diff --git a/app/Console/Tasks/DeliverTask.php b/app/Console/Tasks/DeliverTask.php index 1e34d458..6fe6c8a3 100644 --- a/app/Console/Tasks/DeliverTask.php +++ b/app/Console/Tasks/DeliverTask.php @@ -172,9 +172,7 @@ class DeliverTask extends Task ]; foreach ($orders as $order) { - $case1 = in_array($order->item_type, $itemTypes); - $case2 = $order->promotion_type == 0; - if ($case1 && $case2) { + if (in_array($order->item_type, $itemTypes)) { $order->status = OrderModel::STATUS_CLOSED; $order->update(); } diff --git a/app/Console/Tasks/RefundTask.php b/app/Console/Tasks/RefundTask.php index 108cc60e..d28dc013 100644 --- a/app/Console/Tasks/RefundTask.php +++ b/app/Console/Tasks/RefundTask.php @@ -168,7 +168,8 @@ class RefundTask extends Task protected function handleCourseOrderRefund(OrderModel $order) { $courseUserRepo = new CourseUserRepo(); - $courseUser = $courseUserRepo->findCourseStudent($order->item_id, $order->owner_id); + + $courseUser = $courseUserRepo->findCourseUser($order->item_id, $order->owner_id); if ($courseUser) { $courseUser->deleted = 1; @@ -191,7 +192,7 @@ class RefundTask extends Task foreach ($itemInfo['courses'] as $course) { - $courseUser = $courseUserRepo->findCourseStudent($course['id'], $order->owner_id); + $courseUser = $courseUserRepo->findCourseUser($course['id'], $order->owner_id); if ($courseUser) { $courseUser->deleted = 1; diff --git a/app/Http/Admin/Controllers/AnswerController.php b/app/Http/Admin/Controllers/AnswerController.php index 0e1a1fec..d592c327 100644 --- a/app/Http/Admin/Controllers/AnswerController.php +++ b/app/Http/Admin/Controllers/AnswerController.php @@ -61,12 +61,15 @@ class AnswerController extends Controller { $answerService = new AnswerService(); + $publishTypes = $answerService->getPublishTypes(); + $answer = $answerService->getAnswer($id); $questionService = new QuestionService(); $question = $questionService->getQuestion($answer->question_id); + $this->view->setVar('publish_types', $publishTypes); $this->view->setVar('question', $question); $this->view->setVar('answer', $answer); } @@ -219,4 +222,40 @@ class AnswerController extends Controller $this->view->setVar('reports', $reports); } + /** + * @Post("/moderate/batch", name="admin.answer.batch_moderate") + */ + public function batchModerateAction() + { + $answerService = new AnswerService(); + + $answerService->batchModerate(); + + $location = $this->url->get(['for' => 'admin.mod.answers']); + + $content = [ + 'location' => $location, + 'msg' => '批量审核成功', + ]; + + return $this->jsonSuccess($content); + } + + /** + * @Post("/delete/batch", name="admin.answer.batch_delete") + */ + public function batchDeleteAction() + { + $answerService = new AnswerService(); + + $answerService->batchDelete(); + + $content = [ + 'location' => $this->request->getHTTPReferer(), + 'msg' => '批量删除成功', + ]; + + return $this->jsonSuccess($content); + } + } diff --git a/app/Http/Admin/Controllers/ArticleController.php b/app/Http/Admin/Controllers/ArticleController.php index d6d8a7b9..2da839d3 100644 --- a/app/Http/Admin/Controllers/ArticleController.php +++ b/app/Http/Admin/Controllers/ArticleController.php @@ -38,12 +38,12 @@ class ArticleController extends Controller $publishTypes = $articleService->getPublishTypes(); $sourceTypes = $articleService->getSourceTypes(); - $categories = $articleService->getCategories(); + $categoryOptions = $articleService->getCategoryOptions(); $xmTags = $articleService->getXmTags(0); $this->view->setVar('publish_types', $publishTypes); $this->view->setVar('source_types', $sourceTypes); - $this->view->setVar('categories', $categories); + $this->view->setVar('category_options', $categoryOptions); $this->view->setVar('xm_tags', $xmTags); } @@ -64,11 +64,7 @@ class ArticleController extends Controller */ public function addAction() { - $articleService = new ArticleService(); - $categories = $articleService->getCategories(); - - $this->view->setVar('categories', $categories); } /** @@ -80,14 +76,14 @@ class ArticleController extends Controller $publishTypes = $articleService->getPublishTypes(); $sourceTypes = $articleService->getSourceTypes(); - $categories = $articleService->getCategories(); + $categoryOptions = $articleService->getCategoryOptions(); $article = $articleService->getArticle($id); $xmTags = $articleService->getXmTags($id); + $this->view->setVar('article', $article); $this->view->setVar('publish_types', $publishTypes); $this->view->setVar('source_types', $sourceTypes); - $this->view->setVar('categories', $categories); - $this->view->setVar('article', $article); + $this->view->setVar('category_options', $categoryOptions); $this->view->setVar('xm_tags', $xmTags); } @@ -229,4 +225,40 @@ class ArticleController extends Controller $this->view->setVar('article', $article); } + /** + * @Post("/moderate/batch", name="admin.article.batch_moderate") + */ + public function batchModerateAction() + { + $articleService = new ArticleService(); + + $articleService->batchModerate(); + + $location = $this->url->get(['for' => 'admin.mod.articles']); + + $content = [ + 'location' => $location, + 'msg' => '批量审核成功', + ]; + + return $this->jsonSuccess($content); + } + + /** + * @Post("/delete/batch", name="admin.article.batch_delete") + */ + public function batchDeleteAction() + { + $articleService = new ArticleService(); + + $articleService->batchDelete(); + + $content = [ + 'location' => $this->request->getHTTPReferer(), + 'msg' => '批量删除成功', + ]; + + return $this->jsonSuccess($content); + } + } diff --git a/app/Http/Admin/Controllers/CommentController.php b/app/Http/Admin/Controllers/CommentController.php index ec0ad6b0..eea1a474 100644 --- a/app/Http/Admin/Controllers/CommentController.php +++ b/app/Http/Admin/Controllers/CommentController.php @@ -139,4 +139,40 @@ class CommentController extends Controller $this->view->setVar('reports', $reports); } + /** + * @Post("/moderate/batch", name="admin.comment.batch_moderate") + */ + public function batchModerateAction() + { + $commentService = new CommentService(); + + $commentService->batchModerate(); + + $location = $this->url->get(['for' => 'admin.mod.comments']); + + $content = [ + 'location' => $location, + 'msg' => '批量审核成功', + ]; + + return $this->jsonSuccess($content); + } + + /** + * @Post("/delete/batch", name="admin.comment.batch_delete") + */ + public function batchDeleteAction() + { + $commentService = new CommentService(); + + $commentService->batchDelete(); + + $content = [ + 'location' => $this->request->getHTTPReferer(), + 'msg' => '批量删除成功', + ]; + + return $this->jsonSuccess($content); + } + } diff --git a/app/Http/Admin/Controllers/ConsultController.php b/app/Http/Admin/Controllers/ConsultController.php index c0cbdb9c..92a22c0d 100644 --- a/app/Http/Admin/Controllers/ConsultController.php +++ b/app/Http/Admin/Controllers/ConsultController.php @@ -23,8 +23,10 @@ class ConsultController extends Controller $consultService = new ConsultService(); $publishTypes = $consultService->getPublishTypes(); + $xmCourses = $consultService->getXmCourses(); $this->view->setVar('publish_types', $publishTypes); + $this->view->setVar('xm_courses', $xmCourses); } /** @@ -55,8 +57,11 @@ class ConsultController extends Controller { $consultService = new ConsultService(); + $publishTypes = $consultService->getPublishTypes(); + $consult = $consultService->getConsult($id); + $this->view->setVar('publish_types', $publishTypes); $this->view->setVar('consult', $consult); } @@ -135,9 +140,47 @@ class ConsultController extends Controller return $this->jsonSuccess($content); } + $reasons = $consultService->getReasons(); $consult = $consultService->getConsultInfo($id); + $this->view->setVar('reasons', $reasons); $this->view->setVar('consult', $consult); } + /** + * @Post("/moderate/batch", name="admin.consult.batch_moderate") + */ + public function batchModerateAction() + { + $consultService = new ConsultService(); + + $consultService->batchModerate(); + + $location = $this->url->get(['for' => 'admin.mod.consults']); + + $content = [ + 'location' => $location, + 'msg' => '批量审核成功', + ]; + + return $this->jsonSuccess($content); + } + + /** + * @Post("/delete/batch", name="admin.consult.batch_delete") + */ + public function batchDeleteAction() + { + $consultService = new ConsultService(); + + $consultService->batchDelete(); + + $content = [ + 'location' => $this->request->getHTTPReferer(), + 'msg' => '批量删除成功', + ]; + + return $this->jsonSuccess($content); + } + } diff --git a/app/Http/Admin/Controllers/CourseController.php b/app/Http/Admin/Controllers/CourseController.php index 2121110f..84d7c264 100644 --- a/app/Http/Admin/Controllers/CourseController.php +++ b/app/Http/Admin/Controllers/CourseController.php @@ -8,6 +8,8 @@ namespace App\Http\Admin\Controllers; use App\Http\Admin\Services\Course as CourseService; +use App\Http\Admin\Services\CourseLearning as CourseLearningService; +use App\Http\Admin\Services\CourseUser as CourseUserService; use App\Models\Category as CategoryModel; use Phalcon\Mvc\View; @@ -37,13 +39,13 @@ class CourseController extends Controller { $courseService = new CourseService(); - $xmCategories = $courseService->getXmCategories(0); - $xmTeachers = $courseService->getXmTeachers(0); + $categoryOptions = $courseService->getCategoryOptions(); + $teacherOptions = $courseService->getTeacherOptions(); $modelTypes = $courseService->getModelTypes(); $levelTypes = $courseService->getLevelTypes(); - $this->view->setVar('xm_categories', $xmCategories); - $this->view->setVar('xm_teachers', $xmTeachers); + $this->view->setVar('category_options', $categoryOptions); + $this->view->setVar('teacher_options', $teacherOptions); $this->view->setVar('model_types', $modelTypes); $this->view->setVar('level_types', $levelTypes); } @@ -103,17 +105,21 @@ class CourseController extends Controller $cos = $courseService->getSettings('cos'); $course = $courseService->getCourse($id); - $xmTeachers = $courseService->getXmTeachers($id); - $xmCategories = $courseService->getXmCategories($id); + $xmTags = $courseService->getXmTags($id); $xmCourses = $courseService->getXmCourses($id); + $levelTypes = $courseService->getLevelTypes(); + $categoryOptions = $courseService->getCategoryOptions(); + $teacherOptions = $courseService->getTeacherOptions(); $studyExpiryOptions = $courseService->getStudyExpiryOptions(); $refundExpiryOptions = $courseService->getRefundExpiryOptions(); $this->view->setVar('cos', $cos); $this->view->setVar('course', $course); - $this->view->setVar('xm_teachers', $xmTeachers); - $this->view->setVar('xm_categories', $xmCategories); + $this->view->setVar('xm_tags', $xmTags); $this->view->setVar('xm_courses', $xmCourses); + $this->view->setVar('level_types', $levelTypes); + $this->view->setVar('category_options', $categoryOptions); + $this->view->setVar('teacher_options', $teacherOptions); $this->view->setVar('study_expiry_options', $studyExpiryOptions); $this->view->setVar('refund_expiry_options', $refundExpiryOptions); } @@ -193,4 +199,78 @@ class CourseController extends Controller $this->view->setVar('resources', $resources); } + /** + * @Get("/{id:[0-9]+}/learnings", name="admin.course.learnings") + */ + public function learningsAction($id) + { + $service = new CourseLearningService(); + + $pager = $service->getLearnings($id); + + $this->view->setVar('pager', $pager); + } + + /** + * @Get("/{id:[0-9]+}/users", name="admin.course.users") + */ + public function usersAction($id) + { + $service = new CourseService(); + $course = $service->getCourse($id); + + $service = new CourseUserService(); + $pager = $service->getUsers($id); + + $this->view->setVar('course', $course); + $this->view->setVar('pager', $pager); + } + + /** + * @Get("/{id:[0-9]+}/user/search", name="admin.course.search_user") + */ + public function searchUserAction($id) + { + $service = new CourseService(); + $course = $service->getCourse($id); + + $service = new CourseUserService(); + $sourceTypes = $service->getSourceTypes(); + + $this->view->pick('course/search_user'); + $this->view->setVar('source_types', $sourceTypes); + $this->view->setVar('course', $course); + } + + /** + * @Get("/{id:[0-9]+}/user/add", name="admin.course.add_user") + */ + public function addUserAction($id) + { + $service = new CourseService(); + $course = $service->getCourse($id); + + $this->view->pick('course/add_user'); + $this->view->setVar('course', $course); + } + + /** + * @Post("/{id:[0-9]+}/user/create", name="admin.course.create_user") + */ + public function createUserAction($id) + { + $service = new CourseUserService(); + + $service->create($id); + + $location = $this->url->get(['for' => 'admin.course.users']); + + $content = [ + 'location' => $location, + 'msg' => '添加学员成功', + ]; + + return $this->jsonSuccess($content); + } + } diff --git a/app/Http/Admin/Controllers/FlashSaleController.php b/app/Http/Admin/Controllers/FlashSaleController.php deleted file mode 100644 index 9249d971..00000000 --- a/app/Http/Admin/Controllers/FlashSaleController.php +++ /dev/null @@ -1,153 +0,0 @@ -getFlashSales(); - - $this->view->setVar('pager', $pager); - } - - /** - * @Get("/search", name="admin.flash_sale.search") - */ - public function searchAction() - { - $service = new FlashSaleService(); - - $itemTypes = $service->getItemTypes(); - - $this->view->setVar('item_types', $itemTypes); - } - - /** - * @Get("/add", name="admin.flash_sale.add") - */ - public function addAction() - { - $service = new FlashSaleService(); - - $itemTypes = $service->getItemTypes(); - $xmPackages = $service->getXmPackages(); - $xmCourses = $service->getXmCourses(); - $xmVips = $service->getXmVips(); - - $this->view->setVar('item_types', $itemTypes); - $this->view->setVar('xm_packages', $xmPackages); - $this->view->setVar('xm_courses', $xmCourses); - $this->view->setVar('xm_vips', $xmVips); - } - - /** - * @Get("/{id:[0-9]+}/edit", name="admin.flash_sale.edit") - */ - public function editAction($id) - { - $service = new FlashSaleService(); - - $sale = $service->getFlashSale($id); - $xmSchedules = $service->getXmSchedules($id); - - $this->view->setVar('sale', $sale); - $this->view->setVar('xm_schedules', $xmSchedules); - } - - /** - * @Post("/create", name="admin.flash_sale.create") - */ - public function createAction() - { - $service = new FlashSaleService(); - - $sale = $service->createFlashSale(); - - $location = $this->url->get([ - 'for' => 'admin.flash_sale.edit', - 'id' => $sale->id, - ]); - - $content = [ - 'location' => $location, - 'msg' => '添加商品成功', - ]; - - return $this->jsonSuccess($content); - } - - /** - * @Post("/{id:[0-9]+}/update", name="admin.flash_sale.update") - */ - public function updateAction($id) - { - $service = new FlashSaleService(); - - $service->updateFlashSale($id); - - $location = $this->url->get(['for' => 'admin.flash_sale.list']); - - $content = [ - 'location' => $location, - 'msg' => '更新商品成功', - ]; - - return $this->jsonSuccess($content); - } - - /** - * @Post("/{id:[0-9]+}/delete", name="admin.flash_sale.delete") - */ - public function deleteAction($id) - { - $service = new FlashSaleService(); - - $service->deleteFlashSale($id); - - $location = $this->request->getHTTPReferer(); - - $content = [ - 'location' => $location, - 'msg' => '删除商品成功', - ]; - - return $this->jsonSuccess($content); - } - - /** - * @Post("/{id:[0-9]+}/restore", name="admin.flash_sale.restore") - */ - public function restoreAction($id) - { - $service = new FlashSaleService(); - - $service->restoreFlashSale($id); - - $location = $this->request->getHTTPReferer(); - - $content = [ - 'location' => $location, - 'msg' => '还原商品成功', - ]; - - return $this->jsonSuccess($content); - } - -} diff --git a/app/Http/Admin/Controllers/QuestionController.php b/app/Http/Admin/Controllers/QuestionController.php index 0bc2aebf..f6140c1f 100644 --- a/app/Http/Admin/Controllers/QuestionController.php +++ b/app/Http/Admin/Controllers/QuestionController.php @@ -23,7 +23,7 @@ class QuestionController extends Controller { $location = $this->url->get( ['for' => 'admin.category.list'], - ['type' => CategoryModel::TYPE_ARTICLE] + ['type' => CategoryModel::TYPE_QUESTION] ); return $this->response->redirect($location); @@ -37,12 +37,10 @@ class QuestionController extends Controller $questionService = new QuestionService(); $publishTypes = $questionService->getPublishTypes(); - $categories = $questionService->getCategories(); - $xmTags = $questionService->getXmTags(0); + $categoryOptions = $questionService->getCategoryOptions(); + $this->view->setVar('category_options', $categoryOptions); $this->view->setVar('publish_types', $publishTypes); - $this->view->setVar('categories', $categories); - $this->view->setVar('xm_tags', $xmTags); } /** @@ -62,11 +60,7 @@ class QuestionController extends Controller */ public function addAction() { - $questionService = new QuestionService(); - $categories = $questionService->getCategories(); - - $this->view->setVar('categories', $categories); } /** @@ -77,12 +71,12 @@ class QuestionController extends Controller $questionService = new QuestionService(); $publishTypes = $questionService->getPublishTypes(); - $categories = $questionService->getCategories(); + $categoryOptions = $questionService->getCategoryOptions(); $question = $questionService->getQuestion($id); $xmTags = $questionService->getXmTags($id); $this->view->setVar('publish_types', $publishTypes); - $this->view->setVar('categories', $categories); + $this->view->setVar('category_options', $categoryOptions); $this->view->setVar('question', $question); $this->view->setVar('xm_tags', $xmTags); } @@ -225,4 +219,41 @@ class QuestionController extends Controller $this->view->setVar('reports', $reports); } + + /** + * @Post("/moderate/batch", name="admin.question.batch_moderate") + */ + public function batchModerateAction() + { + $questionService = new QuestionService(); + + $questionService->batchModerate(); + + $location = $this->url->get(['for' => 'admin.mod.questions']); + + $content = [ + 'location' => $location, + 'msg' => '批量审核成功', + ]; + + return $this->jsonSuccess($content); + } + + /** + * @Post("/delete/batch", name="admin.question.batch_delete") + */ + public function batchDeleteAction() + { + $questionService = new QuestionService(); + + $questionService->batchDelete(); + + $content = [ + 'location' => $this->request->getHTTPReferer(), + 'msg' => '批量删除成功', + ]; + + return $this->jsonSuccess($content); + } + } diff --git a/app/Http/Admin/Controllers/ReviewController.php b/app/Http/Admin/Controllers/ReviewController.php index b76c569e..3013dd78 100644 --- a/app/Http/Admin/Controllers/ReviewController.php +++ b/app/Http/Admin/Controllers/ReviewController.php @@ -23,8 +23,10 @@ class ReviewController extends Controller $reviewService = new ReviewService(); $publishTypes = $reviewService->getPublishTypes(); + $xmCourses = $reviewService->getXmCourses(); $this->view->setVar('publish_types', $publishTypes); + $this->view->setVar('xm_courses', $xmCourses); } /** @@ -56,8 +58,10 @@ class ReviewController extends Controller $reviewService = new ReviewService(); $review = $reviewService->getReview($id); + $publishTypes = $reviewService->getPublishTypes(); $this->view->setVar('review', $review); + $this->view->setVar('publish_types', $publishTypes); } /** @@ -135,9 +139,47 @@ class ReviewController extends Controller return $this->jsonSuccess($content); } + $reasons = $reviewService->getReasons(); $review = $reviewService->getReviewInfo($id); + $this->view->setVar('reasons', $reasons); $this->view->setVar('review', $review); } + /** + * @Post("/moderate/batch", name="admin.review.batch_moderate") + */ + public function batchModerateAction() + { + $reviewService = new ReviewService(); + + $reviewService->batchModerate(); + + $location = $this->url->get(['for' => 'admin.mod.reviews']); + + $content = [ + 'location' => $location, + 'msg' => '批量审核成功', + ]; + + return $this->jsonSuccess($content); + } + + /** + * @Post("/delete/batch", name="admin.review.batch_delete") + */ + public function batchDeleteAction() + { + $reviewService = new ReviewService(); + + $reviewService->batchDelete(); + + $content = [ + 'location' => $this->request->getHTTPReferer(), + 'msg' => '批量删除成功', + ]; + + return $this->jsonSuccess($content); + } + } diff --git a/app/Http/Admin/Controllers/StudentController.php b/app/Http/Admin/Controllers/StudentController.php deleted file mode 100644 index 324c6943..00000000 --- a/app/Http/Admin/Controllers/StudentController.php +++ /dev/null @@ -1,141 +0,0 @@ -request->getQuery('course_id', 'int', 0); - - $studentService = new StudentService(); - - $sourceTypes = $studentService->getSourceTypes(); - - $xmCourses = $studentService->getXmCourses('all', $courseId); - - $this->view->setVar('source_types', $sourceTypes); - $this->view->setVar('xm_courses', $xmCourses); - } - - /** - * @Get("/list", name="admin.student.list") - */ - public function listAction() - { - $courseId = $this->request->getQuery('course_id', 'int', 0); - - $studentService = new StudentService(); - - $pager = $studentService->getRelations(); - - $course = null; - - if ($courseId > 0) { - $course = $studentService->getCourse($courseId); - } - - $this->view->setVar('pager', $pager); - $this->view->setVar('course', $course); - } - - /** - * @Get("/add", name="admin.student.add") - */ - public function addAction() - { - $courseId = $this->request->getQuery('course_id', 'int', 0); - - $studentService = new StudentService(); - - $xmCourses = $studentService->getXmCourses('all', $courseId); - - $this->view->setVar('xm_courses', $xmCourses); - } - - /** - * @Post("/create", name="admin.student.create") - */ - public function createAction() - { - $studentService = new StudentService(); - - $student = $studentService->createRelation(); - - $location = $this->url->get( - ['for' => 'admin.student.list'], - ['course_id' => $student->course_id] - ); - - $content = [ - 'location' => $location, - 'msg' => '添加学员成功', - ]; - - return $this->jsonSuccess($content); - } - - /** - * @Get("/edit", name="admin.student.edit") - */ - public function editAction() - { - $relationId = $this->request->getQuery('relation_id', 'int'); - - $studentService = new StudentService(); - - $relation = $studentService->getRelation($relationId); - $course = $studentService->getCourse($relation->course_id); - $student = $studentService->getStudent($relation->user_id); - - $this->view->setVar('relation', $relation); - $this->view->setVar('course', $course); - $this->view->setVar('student', $student); - } - - /** - * @Post("/update", name="admin.student.update") - */ - public function updateAction() - { - $studentService = new StudentService(); - - $studentService->updateRelation(); - - $location = $this->url->get(['for' => 'admin.student.list']); - - $content = [ - 'location' => $location, - 'msg' => '更新学员成功', - ]; - - return $this->jsonSuccess($content); - } - - /** - * @Get("/learning", name="admin.student.learning") - */ - public function learningAction() - { - $studentService = new StudentService(); - - $pager = $studentService->getLearnings(); - - $this->view->setVar('pager', $pager); - } - -} diff --git a/app/Http/Admin/Controllers/VipController.php b/app/Http/Admin/Controllers/VipController.php new file mode 100644 index 00000000..047070b6 --- /dev/null +++ b/app/Http/Admin/Controllers/VipController.php @@ -0,0 +1,126 @@ +getVips(); + + $this->view->setVar('pager', $pager); + } + + /** + * @Get("/add", name="admin.vip.add") + */ + public function addAction() + { + + } + + /** + * @Post("/create", name="admin.vip.create") + */ + public function createAction() + { + $vipService = new VipService(); + + $vipService->createVip(); + + $location = $this->url->get(['for' => 'admin.vip.list']); + + $content = [ + 'location' => $location, + 'msg' => '创建套餐成功', + ]; + + return $this->jsonSuccess($content); + } + + /** + * @Get("/{id:[0-9]+}/edit", name="admin.vip.edit") + */ + public function editAction($id) + { + $vipService = new VipService(); + + $vip = $vipService->getVip($id); + + $this->view->setVar('vip', $vip); + } + + /** + * @Post("/{id:[0-9]+}/update", name="admin.vip.update") + */ + public function updateAction($id) + { + $vipService = new VipService(); + + $vipService->updateVip($id); + + $location = $this->url->get(['for' => 'admin.vip.list']); + + $content = [ + 'location' => $location, + 'msg' => '更新套餐成功', + ]; + + return $this->jsonSuccess($content); + } + + /** + * @Post("/{id:[0-9]+}/delete", name="admin.vip.delete") + */ + public function deleteAction($id) + { + $vipService = new VipService(); + + $vipService->deleteVip($id); + + $location = $this->request->getHTTPReferer(); + + $content = [ + 'location' => $location, + 'msg' => '删除套餐成功', + ]; + + return $this->jsonSuccess($content); + } + + /** + * @Post("/{id:[0-9]+}/restore", name="admin.vip.restore") + */ + public function restoreAction($id) + { + $vipService = new VipService(); + + $vipService->restoreVip($id); + + $location = $this->request->getHTTPReferer(); + + $content = [ + 'location' => $location, + 'msg' => '还原套餐成功', + ]; + + return $this->jsonSuccess($content); + } + +} diff --git a/app/Http/Admin/Services/Answer.php b/app/Http/Admin/Services/Answer.php index 1b2f527a..c705c432 100644 --- a/app/Http/Admin/Services/Answer.php +++ b/app/Http/Admin/Services/Answer.php @@ -213,30 +213,15 @@ class Answer extends Service $reason = $this->request->getPost('reason', ['trim', 'string']); $answer = $this->findOrFail($id); - - $validator = new AnswerValidator(); - - if ($type == 'approve') { - $answer->published = AnswerModel::PUBLISH_APPROVED; - } elseif ($type == 'reject') { - $validator->checkRejectReason($reason); - $answer->published = AnswerModel::PUBLISH_REJECTED; - } - - $answer->update(); - $question = $this->findQuestion($answer->question_id); - - $this->recountQuestionAnswers($question); - $owner = $this->findUser($answer->owner_id); - - $this->recountUserAnswers($owner); - $sender = $this->getLoginUser(); if ($type == 'approve') { + $answer->published = AnswerModel::PUBLISH_APPROVED; + $answer->update(); + if ($answer->owner_id != $question->owner_id) { $this->handleAnswerPostPoint($answer); $this->handleQuestionAnsweredNotice($answer); @@ -248,17 +233,17 @@ class Answer extends Service } elseif ($type == 'reject') { - $options = ReasonModel::answerRejectOptions(); - - if (array_key_exists($reason, $options)) { - $reason = $options[$reason]; - } + $answer->published = AnswerModel::PUBLISH_REJECTED; + $answer->update(); $this->handleAnswerRejectedNotice($answer, $sender, $reason); $this->eventsManager->fire('Answer:afterReject', $this, $answer); } + $this->recountQuestionAnswers($question); + $this->recountUserAnswers($owner); + return $answer; } @@ -298,6 +283,78 @@ class Answer extends Service $this->recountUserAnswers($user); } + public function batchModerate() + { + $type = $this->request->getQuery('type', ['trim', 'string']); + $ids = $this->request->getPost('ids', ['trim', 'int']); + + $answerRepo = new AnswerRepo(); + + $answers = $answerRepo->findByIds($ids); + + if ($answers->count() == 0) return; + + $sender = $this->getLoginUser(); + + foreach ($answers as $answer) { + + $question = $this->findQuestion($answer->question_id); + $owner = $this->findUser($answer->owner_id); + + if ($type == 'approve') { + + $answer->published = AnswerModel::PUBLISH_APPROVED; + $answer->update(); + + if ($answer->owner_id != $question->owner_id) { + $this->handleAnswerPostPoint($answer); + $this->handleQuestionAnsweredNotice($answer); + } + + $this->handleAnswerApprovedNotice($answer, $sender); + + } elseif ($type == 'reject') { + + $answer->published = AnswerModel::PUBLISH_REJECTED; + $answer->update(); + + $this->handleAnswerRejectedNotice($answer, $sender, ''); + } + + $this->recountQuestionAnswers($question); + $this->recountUserAnswers($owner); + } + } + + public function batchDelete() + { + $ids = $this->request->getPost('ids', ['trim', 'int']); + + $answerRepo = new AnswerRepo(); + + $answers = $answerRepo->findByIds($ids); + + if ($answers->count() == 0) return; + + $sender = $this->getLoginUser(); + + foreach ($answers as $answer) { + + $answer->deleted = 1; + $answer->update(); + + $this->handleAnswerDeletedNotice($answer, $sender); + + $question = $this->findQuestion($answer->question_id); + + $this->recountQuestionAnswers($question); + + $owner = $this->findUser($answer->owner_id); + + $this->recountUserAnswers($owner); + } + } + protected function findOrFail($id) { $validator = new AnswerValidator(); @@ -390,7 +447,7 @@ class Answer extends Service $notice->handle($answer, $sender); } - protected function handleAnswerRejectedNotice(AnswerModel $answer, UserModel $sender, $reason) + protected function handleAnswerRejectedNotice(AnswerModel $answer, UserModel $sender, $reason = '') { $notice = new AnswerRejectedNotice(); @@ -398,6 +455,11 @@ class Answer extends Service } + protected function handleAnswerDeletedNotice(AnswerModel $answer, UserModel $sender, $reason = '') + { + + } + protected function handleAnswerPostPoint(AnswerModel $answer) { $service = new AnswerPostPointHistory(); diff --git a/app/Http/Admin/Services/Article.php b/app/Http/Admin/Services/Article.php index 42cc02a1..fb9c0b03 100644 --- a/app/Http/Admin/Services/Article.php +++ b/app/Http/Admin/Services/Article.php @@ -18,9 +18,9 @@ use App\Models\Reason as ReasonModel; use App\Models\Report as ReportModel; 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\User as UserRepo; +use App\Services\Category as CategoryService; use App\Services\Logic\Article\ArticleDataTrait; use App\Services\Logic\Article\ArticleInfo as ArticleInfoService; use App\Services\Logic\Article\XmTagList as XmTagListService; @@ -42,16 +42,11 @@ class Article extends Service return $service->handle($id); } - public function getCategories() + public function getCategoryOptions() { - $categoryRepo = new CategoryRepo(); + $categoryService = new CategoryService(); - return $categoryRepo->findAll([ - 'type' => CategoryModel::TYPE_ARTICLE, - 'level' => 1, - 'published' => 1, - 'deleted' => 0, - ]); + return $categoryService->getCategoryOptions(CategoryModel::TYPE_ARTICLE); } public function getPublishTypes() @@ -161,15 +156,18 @@ class Article extends Service $data = []; - if (isset($post['category_id'])) { - $category = $validator->checkCategory($post['category_id']); - $data['category_id'] = $category->id; - } - if (isset($post['title'])) { $data['title'] = $validator->checkTitle($post['title']); } + if (isset($post['cover'])) { + $data['cover'] = $validator->checkCover($post['cover']); + } + + if (isset($post['summary'])) { + $data['summary'] = $validator->checkSummary($post['summary']); + } + if (isset($post['keywords'])) { $data['keywords'] = $validator->checkKeywords($post['keywords']); } @@ -186,22 +184,23 @@ class Article extends Service } } - if (isset($post['closed'])) { - $data['closed'] = $validator->checkCloseStatus($post['closed']); - } - - if (isset($post['private'])) { - $data['private'] = $validator->checkPrivateStatus($post['private']); - } - if (isset($post['featured'])) { $data['featured'] = $validator->checkFeatureStatus($post['featured']); } + if (isset($post['closed'])) { + $data['closed'] = $validator->checkCloseStatus($post['closed']); + } + if (isset($post['published'])) { $data['published'] = $validator->checkPublishStatus($post['published']); } + if (isset($post['category_id'])) { + $category = $validator->checkCategory($post['category_id']); + $data['category_id'] = $category->id; + } + if (isset($post['xm_tag_ids'])) { $this->saveTags($article, $post['xm_tag_ids']); } @@ -266,31 +265,12 @@ class Article extends Service $reason = $this->request->getPost('reason', ['trim', 'string']); $article = $this->findOrFail($id); - - $validator = new ArticleValidator(); + $sender = $this->getLoginUser(); if ($type == 'approve') { $article->published = ArticleModel::PUBLISH_APPROVED; - - } elseif ($type == 'reject') { - - $validator->checkRejectReason($reason); - - $article->published = ArticleModel::PUBLISH_REJECTED; - } - - $article->update(); - - $owner = $this->findUser($article->owner_id); - - $this->rebuildArticleCache($article); - $this->rebuildArticleIndex($article); - $this->recountUserArticles($owner); - - $sender = $this->getLoginUser(); - - if ($type == 'approve') { + $article->update(); $this->handleArticlePostPoint($article); $this->handleArticleApprovedNotice($article, $sender); @@ -299,17 +279,20 @@ class Article extends Service } elseif ($type == 'reject') { - $options = ReasonModel::articleRejectOptions(); - - if (array_key_exists($reason, $options)) { - $reason = $options[$reason]; - } + $article->published = ArticleModel::PUBLISH_REJECTED; + $article->update(); $this->handleArticleRejectedNotice($article, $sender, $reason); $this->eventsManager->fire('Article:afterReject', $this, $article); } + $owner = $this->findUser($article->owner_id); + + $this->rebuildArticleCache($article); + $this->rebuildArticleIndex($article); + $this->recountUserArticles($owner); + return $article; } @@ -347,6 +330,72 @@ class Article extends Service $this->recountUserArticles($owner); } + public function batchModerate() + { + $type = $this->request->getQuery('type', ['trim', 'string']); + $ids = $this->request->getPost('ids', ['trim', 'int']); + + $articleRepo = new ArticleRepo(); + + $articles = $articleRepo->findByIds($ids); + + if ($articles->count() == 0) return; + + $sender = $this->getLoginUser(); + + foreach ($articles as $article) { + + if ($type == 'approve') { + + $article->published = ArticleModel::PUBLISH_APPROVED; + $article->update(); + + $this->handleArticlePostPoint($article); + $this->handleArticleApprovedNotice($article, $sender); + + } elseif ($type == 'reject') { + + $article->published = ArticleModel::PUBLISH_REJECTED; + $article->update(); + + $this->handleArticleRejectedNotice($article, $sender); + } + + $owner = $this->findUser($article->owner_id); + + $this->recountUserArticles($owner); + $this->rebuildArticleCache($article); + $this->rebuildArticleIndex($article); + } + } + + public function batchDelete() + { + $ids = $this->request->getPost('ids', ['trim', 'int']); + + $articleRepo = new ArticleRepo(); + + $articles = $articleRepo->findByIds($ids); + + if ($articles->count() == 0) return; + + $sender = $this->getLoginUser(); + + foreach ($articles as $article) { + + $article->deleted = 1; + $article->update(); + + $this->handleArticleDeletedNotice($article, $sender); + + $owner = $this->findUser($article->owner_id); + + $this->recountUserArticles($owner); + $this->rebuildArticleCache($article); + $this->rebuildArticleIndex($article); + } + } + protected function findOrFail($id) { $validator = new ArticleValidator(); @@ -402,13 +451,18 @@ class Article extends Service $notice->handle($article, $sender); } - protected function handleArticleRejectedNotice(ArticleModel $article, UserModel $sender, $reason) + protected function handleArticleRejectedNotice(ArticleModel $article, UserModel $sender, $reason = '') { $notice = new ArticleRejectedNotice(); $notice->handle($article, $sender, $reason); } + protected function handleArticleDeletedNotice(ArticleModel $article, UserModel $sender, $reason = '') + { + + } + protected function handleArticles($pager) { if ($pager->total_items > 0) { diff --git a/app/Http/Admin/Services/AuthNode.php b/app/Http/Admin/Services/AuthNode.php index 35c59e85..319c1f2d 100644 --- a/app/Http/Admin/Services/AuthNode.php +++ b/app/Http/Admin/Services/AuthNode.php @@ -55,6 +55,80 @@ class AuthNode extends Service ], ], ], + [ + 'id' => '1-6', + 'title' => '文章管理', + 'type' => 'menu', + 'children' => [ + [ + 'id' => '1-6-1', + 'title' => '文章列表', + 'type' => 'menu', + 'route' => 'admin.article.list', + ], + [ + 'id' => '1-6-2', + 'title' => '搜索文章', + 'type' => 'menu', + 'route' => 'admin.article.search', + ], + [ + 'id' => '1-6-3', + 'title' => '添加文章', + 'type' => 'menu', + 'route' => 'admin.article.add', + ], + [ + 'id' => '1-6-4', + 'title' => '编辑文章', + 'type' => 'button', + 'route' => 'admin.article.edit', + ], + [ + 'id' => '1-6-5', + 'title' => '删除文章', + 'type' => 'button', + 'route' => 'admin.article.delete', + ], + [ + 'id' => '1-6-6', + 'title' => '文章详情', + 'type' => 'button', + 'route' => 'admin.article.show', + ], + [ + 'id' => '1-6-7', + 'title' => '审核文章', + 'type' => 'button', + 'route' => 'admin.article.moderate', + ], + [ + 'id' => '1-6-8', + 'title' => '审核举报', + 'type' => 'button', + 'route' => 'admin.article.report', + ], + ], + ], + [ + 'id' => '1-7', + 'title' => '问答管理', + 'type' => 'menu', + 'children' => [ + [ + 'id' => '1-7-1', + 'title' => '问题列表', + 'type' => 'menu', + 'route' => 'admin.question.list', + ], + [ + 'id' => '1-7-2', + 'title' => '答案列表', + 'type' => 'menu', + 'route' => 'admin.answer.list', + ], + ], + ], [ 'id' => '1-2', 'title' => '导航管理', @@ -191,80 +265,6 @@ class AuthNode extends Service ], ], ], - [ - 'id' => '1-6', - 'title' => '文章管理', - 'type' => 'menu', - 'children' => [ - [ - 'id' => '1-6-1', - 'title' => '文章列表', - 'type' => 'menu', - 'route' => 'admin.article.list', - ], - [ - 'id' => '1-6-2', - 'title' => '搜索文章', - 'type' => 'menu', - 'route' => 'admin.article.search', - ], - [ - 'id' => '1-6-3', - 'title' => '添加文章', - 'type' => 'menu', - 'route' => 'admin.article.add', - ], - [ - 'id' => '1-6-4', - 'title' => '编辑文章', - 'type' => 'button', - 'route' => 'admin.article.edit', - ], - [ - 'id' => '1-6-5', - 'title' => '删除文章', - 'type' => 'button', - 'route' => 'admin.article.delete', - ], - [ - 'id' => '1-6-6', - 'title' => '文章详情', - 'type' => 'button', - 'route' => 'admin.article.show', - ], - [ - 'id' => '1-6-7', - 'title' => '审核文章', - 'type' => 'button', - 'route' => 'admin.article.moderate', - ], - [ - 'id' => '1-6-8', - 'title' => '审核举报', - 'type' => 'button', - 'route' => 'admin.article.report', - ], - ], - ], - [ - 'id' => '1-7', - 'title' => '问答管理', - 'type' => 'menu', - 'children' => [ - [ - 'id' => '1-7-1', - 'title' => '问题列表', - 'type' => 'menu', - 'route' => 'admin.question.list', - ], - [ - 'id' => '1-7-2', - 'title' => '答案列表', - 'type' => 'menu', - 'route' => 'admin.answer.list', - ], - ], - ], [ 'id' => '1-20', 'title' => '分类管理', @@ -624,7 +624,7 @@ class AuthNode extends Service 'id' => '2-2-1', 'title' => '会员套餐', 'type' => 'menu', - 'route' => 'admin.setting.vip', + 'route' => 'admin.vip.list', ], [ 'id' => '2-2-2', @@ -632,43 +632,6 @@ class AuthNode extends Service 'type' => 'menu', 'route' => 'admin.point_gift.list', ], - [ - 'id' => '2-2-3', - 'title' => '限时秒杀', - 'type' => 'menu', - 'route' => 'admin.flash_sale.list', - ], - ], - ], - [ - 'id' => '2-3', - 'title' => '学员管理', - 'type' => 'menu', - 'children' => [ - [ - 'id' => '2-3-1', - 'title' => '学员列表', - 'type' => 'menu', - 'route' => 'admin.student.list', - ], - [ - 'id' => '2-3-2', - 'title' => '搜索学员', - 'type' => 'menu', - 'route' => 'admin.student.search', - ], - [ - 'id' => '2-3-3', - 'title' => '添加学员', - 'type' => 'menu', - 'route' => 'admin.student.add', - ], - [ - 'id' => '2-3-4', - 'title' => '编辑学员', - 'type' => 'button', - 'route' => 'admin.student.edit', - ], ], ], [ @@ -901,38 +864,32 @@ class AuthNode extends Service ], [ 'id' => '2-21', - 'title' => '限时秒杀', + 'title' => '会员套餐', 'type' => 'button', 'children' => [ [ 'id' => '2-21-1', - 'title' => '商品列表', + 'title' => '套餐列表', 'type' => 'button', - 'route' => 'admin.flash_sale.list', + 'route' => 'admin.vip.list', ], [ 'id' => '2-21-2', - 'title' => '添加商品', + 'title' => '添加套餐', 'type' => 'button', - 'route' => 'admin.flash_sale.add', + 'route' => 'admin.vip.add', ], [ 'id' => '2-21-3', - 'title' => '搜索商品', + 'title' => '编辑套餐', 'type' => 'button', - 'route' => 'admin.flash_sale.search', + 'route' => 'admin.vip.edit', ], [ 'id' => '2-21-4', - 'title' => '编辑商品', + 'title' => '删除套餐', 'type' => 'button', - 'route' => 'admin.flash_sale.edit', - ], - [ - 'id' => '2-21-5', - 'title' => '删除商品', - 'type' => 'button', - 'route' => 'admin.flash_sale.delete', + 'route' => 'admin.vip.delete', ], ], ], diff --git a/app/Http/Admin/Services/Category.php b/app/Http/Admin/Services/Category.php index 92e8caf8..2401fa99 100644 --- a/app/Http/Admin/Services/Category.php +++ b/app/Http/Admin/Services/Category.php @@ -8,6 +8,7 @@ namespace App\Http\Admin\Services; use App\Caches\Category as CategoryCache; +use App\Caches\CategoryAllList as CategoryAllListCache; use App\Caches\CategoryList as CategoryListCache; use App\Caches\CategoryTreeList as CategoryTreeListCache; use App\Models\Category as CategoryModel; @@ -140,7 +141,6 @@ class Category extends Service $category->update(); $this->updateCategoryStats($category); - $this->rebuildCategoryCache($category); return $category; @@ -182,7 +182,6 @@ class Category extends Service $category->update($data); $this->updateCategoryStats($category); - $this->rebuildCategoryCache($category); return $category; @@ -201,7 +200,6 @@ class Category extends Service $category->update(); $this->updateCategoryStats($category); - $this->rebuildCategoryCache($category); return $category; @@ -216,7 +214,6 @@ class Category extends Service $category->update(); $this->updateCategoryStats($category); - $this->rebuildCategoryCache($category); return $category; @@ -250,6 +247,10 @@ class Category extends Service $cache = new CategoryTreeListCache(); $cache->rebuild($category->type); + + $cache = new CategoryAllListCache(); + + $cache->rebuild($category->type); } protected function enableChildCategories($parentId) diff --git a/app/Http/Admin/Services/Chapter.php b/app/Http/Admin/Services/Chapter.php index 5b01ce92..5df3290a 100644 --- a/app/Http/Admin/Services/Chapter.php +++ b/app/Http/Admin/Services/Chapter.php @@ -201,7 +201,9 @@ class Chapter extends Service } $lessonCount = $chapterRepo->countLessons($chapter->id); + $chapter->lesson_count = $lessonCount; + $chapter->update(); } diff --git a/app/Http/Admin/Services/Comment.php b/app/Http/Admin/Services/Comment.php index b97f29cd..6f48a764 100644 --- a/app/Http/Admin/Services/Comment.php +++ b/app/Http/Admin/Services/Comment.php @@ -13,6 +13,7 @@ use App\Library\Paginator\Query as PagerQuery; use App\Models\Comment as CommentModel; use App\Models\Reason as ReasonModel; use App\Models\Report as ReportModel; +use App\Models\User as UserModel; use App\Repos\Comment as CommentRepo; use App\Repos\Report as ReportRepo; use App\Repos\User as UserRepo; @@ -126,6 +127,12 @@ class Comment extends Service $this->decrUserCommentCount($owner); + $sender = $this->getLoginUser(); + + $this->handleCommentDeletedNotice($comment, $sender); + + $this->eventsManager->fire('Comment:afterDelete', $this, $comment); + return $comment; } @@ -164,23 +171,14 @@ class Comment extends Service $validator = new CommentValidator(); + $sender = $this->getLoginUser(); + if ($type == 'approve') { $comment->published = CommentModel::PUBLISH_APPROVED; - - } elseif ($type == 'reject') { - - $validator->checkRejectReason($reason); - - $comment->published = CommentModel::PUBLISH_REJECTED; - } - - $comment->update(); - - if ($type == 'approve') { + $comment->update(); $owner = $this->findUser($comment->owner_id); - $item = $validator->checkItem($comment->item_id, $comment->item_type); $this->incrItemCommentCount($item); @@ -197,11 +195,17 @@ class Comment extends Service } $this->handleCommentPostPoint($comment); + $this->handleCommentApprovedNotice($comment, $sender); $this->eventsManager->fire('Comment:afterApprove', $this, $comment); } elseif ($type == 'reject') { + $comment->published = CommentModel::PUBLISH_REJECTED; + $comment->update(); + + $this->handleCommentRejectedNotice($comment, $sender, $reason); + $this->eventsManager->fire('Comment:afterReject', $this, $comment); } @@ -236,6 +240,93 @@ class Comment extends Service $comment->update(); } + public function batchModerate() + { + $type = $this->request->getQuery('type', ['trim', 'string']); + $ids = $this->request->getPost('ids', ['trim', 'int']); + + $commentRepo = new CommentRepo(); + + $comments = $commentRepo->findByIds($ids); + + if ($comments->count() == 0) return; + + $validator = new CommentValidator(); + + $sender = $this->getLoginUser(); + + foreach ($comments as $comment) { + + if ($type == 'approve') { + + $owner = $this->findUser($comment->owner_id); + $item = $validator->checkItem($comment->item_id, $comment->item_type); + + $this->incrItemCommentCount($item); + $this->incrUserCommentCount($owner); + + $comment->published = CommentModel::PUBLISH_APPROVED; + $comment->update(); + + if ($comment->parent_id == 0) { + $this->handleItemCommentedNotice($item, $comment); + } + + if ($comment->parent_id > 0) { + $parent = $validator->checkParent($comment->parent_id); + $this->incrCommentReplyCount($parent); + $this->handleCommentRepliedNotice($comment); + } + + $this->handleCommentPostPoint($comment); + $this->handleCommentApprovedNotice($comment, $sender); + + } elseif ($type == 'reject') { + + $comment->published = CommentModel::PUBLISH_REJECTED; + $comment->update(); + + $this->handleCommentRejectedNotice($comment, $sender); + } + } + } + + public function batchDelete() + { + $ids = $this->request->getPost('ids', ['trim', 'int']); + + $commentRepo = new CommentRepo(); + + $comments = $commentRepo->findByIds($ids); + + if ($comments->count() == 0) return; + + $validator = new CommentValidator(); + + $sender = $this->getLoginUser(); + + foreach ($comments as $comment) { + + $comment->deleted = 1; + $comment->update(); + + if ($comment->parent_id > 0) { + $parent = $validator->checkParent($comment->parent_id); + $this->decrCommentReplyCount($parent); + } + + $this->handleCommentDeletedNotice($comment, $sender); + + $item = $validator->checkItem($comment->item_id, $comment->item_type); + + $this->decrItemCommentCount($item); + + $owner = $this->findUser($comment->owner_id); + + $this->decrUserCommentCount($owner); + } + } + protected function findOrFail($id) { $validator = new CommentValidator(); @@ -250,6 +341,21 @@ class Comment extends Service return $userRepo->findById($id); } + protected function handleCommentApprovedNotice(CommentModel $comment, UserModel $sender) + { + + } + + protected function handleCommentRejectedNotice(CommentModel $comment, UserModel $sender, $reason = '') + { + + } + + protected function handleCommentDeletedNotice(CommentModel $comment, UserModel $sender, $reason = '') + { + + } + protected function handleComments($pager) { if ($pager->total_items > 0) { diff --git a/app/Http/Admin/Services/Consult.php b/app/Http/Admin/Services/Consult.php index 4934ff69..44ae915c 100644 --- a/app/Http/Admin/Services/Consult.php +++ b/app/Http/Admin/Services/Consult.php @@ -9,9 +9,13 @@ namespace App\Http\Admin\Services; use App\Builders\ConsultList as ConsultListBuilder; use App\Library\Paginator\Query as PagerQuery; +use App\Library\Validators\Common as CommonValidator; use App\Models\Chapter as ChapterModel; use App\Models\Consult as ConsultModel; use App\Models\Course as CourseModel; +use App\Models\Reason as ReasonModel; +use App\Models\User as UserModel; +use App\Repos\Account as AccountRepo; use App\Repos\Chapter as ChapterRepo; use App\Repos\Consult as ConsultRepo; use App\Repos\Course as CourseRepo; @@ -27,6 +31,34 @@ class Consult extends Service return ConsultModel::publishTypes(); } + public function getReasons() + { + return ReasonModel::consultRejectOptions(); + } + + public function getXmCourses() + { + $courseRepo = new CourseRepo(); + + $items = $courseRepo->findAll([ + 'published' => 1, + 'deleted' => 0, + ]); + + if ($items->count() == 0) return []; + + $result = []; + + foreach ($items as $item) { + $result[] = [ + 'name' => sprintf('%s - %s(¥%0.2f)', $item->id, $item->title, $item->market_price), + 'value' => $item->id, + ]; + } + + return $result; + } + public function getConsults() { $pagerQuery = new PagerQuery(); @@ -35,6 +67,21 @@ class Consult extends Service $params['deleted'] = $params['deleted'] ?? 0; + $accountRepo = new AccountRepo(); + + /** + * 兼容用户编号|手机号码|邮箱地址查询 + */ + if (!empty($params['owner_id'])) { + if (CommonValidator::phone($params['owner_id'])) { + $account = $accountRepo->findByPhone($params['owner_id']); + $params['owner_id'] = $account ? $account->id : -1000; + } elseif (CommonValidator::email($params['owner_id'])) { + $account = $accountRepo->findByEmail($params['owner_id']); + $params['owner_id'] = $account ? $account->id : -1000; + } + } + $sort = $pagerQuery->getSort(); $page = $pagerQuery->getPage(); $limit = $pagerQuery->getLimit(); @@ -95,7 +142,6 @@ class Consult extends Service if (isset($post['published'])) { $data['published'] = $validator->checkPublishStatus($post['published']); - $this->handleItemConsults($consult); } $consult->update($data); @@ -104,6 +150,10 @@ class Consult extends Service $this->handleReplyNotice($consult); } + $this->recountItemConsults($consult); + + $this->eventsManager->fire('Consult:afterUpdate', $this, $consult); + return $consult; } @@ -115,7 +165,13 @@ class Consult extends Service $consult->update(); - $this->handleItemConsults($consult); + $this->recountItemConsults($consult); + + $sender = $this->getLoginUser(); + + $this->handleConsultDeletedNotice($consult, $sender); + + $this->eventsManager->fire('Consult:afterDelete', $this, $consult); } public function restoreConsult($id) @@ -126,52 +182,97 @@ class Consult extends Service $consult->update(); - $this->handleItemConsults($consult); + $this->recountItemConsults($consult); + + $this->eventsManager->fire('Consult:afterRestore', $this, $consult); } public function moderate($id) { $type = $this->request->getPost('type', ['trim', 'string']); + $reason = $this->request->getPost('reason', ['trim', 'string']); $consult = $this->findOrFail($id); + $sender = $this->getLoginUser(); if ($type == 'approve') { + $consult->published = ConsultModel::PUBLISH_APPROVED; - } elseif ($type == 'reject') { - $consult->published = ConsultModel::PUBLISH_REJECTED; - } + $consult->update(); - $consult->update(); + $this->handleConsultApprovedNotice($consult, $sender); - $this->handleItemConsults($consult); - - if ($type == 'approve') { $this->eventsManager->fire('Consult:afterApprove', $this, $consult); + } elseif ($type == 'reject') { + + $consult->published = ConsultModel::PUBLISH_REJECTED; + $consult->update(); + + $this->handleConsultRejectedNotice($consult, $sender, $reason); + $this->eventsManager->fire('Consult:afterReject', $this, $consult); } + $this->recountItemConsults($consult); + return $consult; } - protected function handleItemConsults(ConsultModel $consult) + public function batchModerate() { - if ($consult->course_id > 0) { - $course = $this->findCourse($consult->course_id); - $this->recountCourseConsults($course); - } + $type = $this->request->getQuery('type', ['trim', 'string']); + $ids = $this->request->getPost('ids', ['trim', 'int']); - if ($consult->chapter_id > 0) { - $chapter = $this->findChapter($consult->chapter_id); - $this->recountChapterConsults($chapter); + $consultRepo = new ConsultRepo(); + + $consults = $consultRepo->findByIds($ids); + + if ($consults->count() == 0) return; + + $sender = $this->getLoginUser(); + + foreach ($consults as $consult) { + + if ($type == 'approve') { + + $consult->published = ConsultModel::PUBLISH_APPROVED; + $consult->update(); + + $this->handleConsultApprovedNotice($consult, $sender); + + } elseif ($type == 'reject') { + + $consult->published = ConsultModel::PUBLISH_REJECTED; + $consult->update(); + + $this->handleConsultRejectedNotice($consult, $sender); + } + + $this->recountItemConsults($consult); } } - protected function handleReplyNotice(ConsultModel $consult) + public function batchDelete() { - $notice = new ConsultReplyNotice(); + $ids = $this->request->getPost('ids', ['trim', 'int']); - $notice->createTask($consult); + $consultRepo = new ConsultRepo(); + + $consults = $consultRepo->findByIds($ids); + + if ($consults->count() == 0) return; + + $sender = $this->getLoginUser(); + + foreach ($consults as $consult) { + + $consult->deleted = 1; + $consult->update(); + + $this->handleConsultDeletedNotice($consult, $sender); + $this->recountItemConsults($consult); + } } protected function findOrFail($id) @@ -195,6 +296,41 @@ class Consult extends Service return $chapterRepo->findById($id); } + protected function handleReplyNotice(ConsultModel $consult) + { + $notice = new ConsultReplyNotice(); + + $notice->createTask($consult); + } + + protected function handleConsultApprovedNotice(ConsultModel $review, UserModel $sender) + { + + } + + protected function handleConsultRejectedNotice(ConsultModel $review, UserModel $sender, $reason = '') + { + + } + + protected function handleConsultDeletedNotice(ConsultModel $review, UserModel $sender, $reason = '') + { + + } + + protected function recountItemConsults(ConsultModel $consult) + { + if ($consult->course_id > 0) { + $course = $this->findCourse($consult->course_id); + $this->recountCourseConsults($course); + } + + if ($consult->chapter_id > 0) { + $chapter = $this->findChapter($consult->chapter_id); + $this->recountChapterConsults($chapter); + } + } + protected function recountCourseConsults(CourseModel $course) { $courseRepo = new CourseRepo(); diff --git a/app/Http/Admin/Services/Course.php b/app/Http/Admin/Services/Course.php index 7e8bd99f..1d4ade92 100644 --- a/app/Http/Admin/Services/Course.php +++ b/app/Http/Admin/Services/Course.php @@ -10,22 +10,20 @@ namespace App\Http\Admin\Services; use App\Builders\CourseList as CourseListBuilder; use App\Builders\ResourceList as ResourceListBuilder; use App\Caches\Course as CourseCache; -use App\Caches\CourseCategoryList as CourseCategoryListCache; use App\Caches\CourseRelatedList as CourseRelatedListCache; -use App\Caches\CourseTeacherList as CourseTeacherListCache; use App\Library\Paginator\Query as PagerQuery; use App\Models\Category as CategoryModel; use App\Models\Course as CourseModel; -use App\Models\CourseCategory as CourseCategoryModel; use App\Models\CourseRelated as CourseRelatedModel; -use App\Models\CourseUser as CourseUserModel; -use App\Repos\Category as CategoryRepo; +use App\Models\CourseTag as CourseTagModel; use App\Repos\Chapter as ChapterRepo; use App\Repos\Course as CourseRepo; -use App\Repos\CourseCategory as CourseCategoryRepo; use App\Repos\CourseRelated as CourseRelatedRepo; -use App\Repos\CourseUser as CourseUserRepo; +use App\Repos\CourseTag as CourseTagRepo; +use App\Repos\Tag as TagRepo; use App\Repos\User as UserRepo; +use App\Services\Category as CategoryService; +use App\Services\Logic\Course\XmTagList as XmTagListService; use App\Services\Sync\CourseIndex as CourseIndexSync; use App\Validators\Course as CourseValidator; use App\Validators\CourseOffline as CourseOfflineValidator; @@ -39,12 +37,8 @@ class Course extends Service $params = $pagerQuery->getParams(); - if (!empty($params['xm_category_ids'])) { - $params['category_id'] = explode(',', $params['xm_category_ids']); - } - - if (!empty($params['xm_teacher_ids'])) { - $params['teacher_id'] = explode(',', $params['xm_teacher_ids']); + if (!empty($params['xm_tag_ids'])) { + $params['tag_id'] = explode(',', $params['xm_tag_ids']); } $params['deleted'] = $params['deleted'] ?? 0; @@ -155,10 +149,6 @@ class Course extends Service $data['refund_expiry'] = $validator->checkRefundExpiry($post['refund_expiry']); } - if (isset($post['origin_price'])) { - $data['origin_price'] = $validator->checkOriginPrice($post['origin_price']); - } - if (isset($post['market_price'])) { $data['market_price'] = $validator->checkMarketPrice($post['market_price']); } @@ -173,17 +163,20 @@ class Course extends Service if (isset($post['published'])) { $data['published'] = $validator->checkPublishStatus($post['published']); - if ($post['published'] == 1) { - $validator->checkPublishAbility($course); - } } - if (isset($post['xm_category_ids'])) { - $this->saveCategories($course, $post['xm_category_ids']); + if (isset($post['category_id'])) { + $category = $validator->checkCategory($post['category_id']); + $data['category_id'] = $category->id; } - if (isset($post['xm_teacher_ids'])) { - $this->saveTeachers($course, $post['xm_teacher_ids']); + if (isset($post['teacher_id'])) { + $teacher = $validator->checkTeacher($post['teacher_id']); + $data['teacher_id'] = $teacher->id; + } + + if (isset($post['xm_tag_ids'])) { + $this->saveTags($course, $post['xm_tag_ids']); } if (isset($post['xm_course_ids'])) { @@ -258,6 +251,33 @@ class Course extends Service return CourseModel::levelTypes(); } + public function getTeacherOptions() + { + $userRepo = new UserRepo(); + + $teachers = $userRepo->findTeachers(); + + if ($teachers->count() == 0) return []; + + $options = []; + + foreach ($teachers as $teacher) { + $options[] = [ + 'id' => $teacher->id, + 'name' => $teacher->name, + ]; + } + + return $options; + } + + public function getCategoryOptions() + { + $categoryService = new CategoryService(); + + return $categoryService->getCategoryOptions(CategoryModel::TYPE_COURSE); + } + public function getStudyExpiryOptions() { return CourseModel::studyExpiryOptions(); @@ -268,92 +288,11 @@ class Course extends Service return CourseModel::refundExpiryOptions(); } - public function getXmCategories($id) + public function getXmTags($id) { - $categoryRepo = new CategoryRepo(); + $service = new XmTagListService(); - $allCategories = $categoryRepo->findAll([ - 'type' => CategoryModel::TYPE_COURSE, - 'published' => 1, - 'deleted' => 0, - ]); - - if ($allCategories->count() == 0) return []; - - $courseCategoryIds = []; - - if ($id > 0) { - $courseRepo = new CourseRepo(); - $courseCategories = $courseRepo->findCategories($id); - if ($courseCategories->count() > 0) { - foreach ($courseCategories as $category) { - $courseCategoryIds[] = $category->id; - } - } - } - - $list = []; - - /** - * 没有二级分类的不显示 - */ - foreach ($allCategories as $category) { - if ($category->level == 1 && $category->child_count > 0) { - $list[$category->id] = [ - 'name' => $category->name, - 'value' => $category->id, - 'children' => [], - ]; - } - } - - foreach ($allCategories as $category) { - $selected = in_array($category->id, $courseCategoryIds); - $parentId = $category->parent_id; - if ($category->level == 2) { - $list[$parentId]['children'][] = [ - 'name' => $category->name, - 'value' => $category->id, - 'selected' => $selected, - ]; - } - } - - return array_values($list); - } - - public function getXmTeachers($id) - { - $userRepo = new UserRepo(); - - $allTeachers = $userRepo->findTeachers(); - - if ($allTeachers->count() == 0) return []; - - $courseTeacherIds = []; - - if ($id > 0) { - $courseRepo = new CourseRepo(); - $courseTeachers = $courseRepo->findTeachers($id); - if ($courseTeachers->count() > 0) { - foreach ($courseTeachers as $teacher) { - $courseTeacherIds[] = $teacher->id; - } - } - } - - $list = []; - - foreach ($allTeachers as $teacher) { - $selected = in_array($teacher->id, $courseTeacherIds); - $list[] = [ - 'name' => $teacher->name, - 'value' => $teacher->id, - 'selected' => $selected, - ]; - } - - return $list; + return $service->handle($id); } public function getXmCourses($id) @@ -409,7 +348,7 @@ class Course extends Service { $courseRepo = new CourseRepo(); - $resources = $courseRepo->findResources($id); + $resources = $courseRepo->findResources($id); if ($resources->count() == 0) return []; @@ -429,106 +368,65 @@ class Course extends Service return $validator->checkCourse($id); } - protected function saveTeachers(CourseModel $course, $teacherIds) + protected function saveTags(CourseModel $course, $tagIds) { - $courseRepo = new CourseRepo(); + /** + * 修改数据后,afterFetch设置的属性会失效,重新执行 + */ + $course->afterFetch(); - $courseTeachers = $courseRepo->findTeachers($course->id); + if (is_string($tagIds) && strlen($tagIds) > 0) { + $tagIds = explode(',', $tagIds); + } - $originTeacherIds = []; + $originTagIds = []; - if ($courseTeachers->count() > 0) { - foreach ($courseTeachers as $teacher) { - $originTeacherIds[] = $teacher->id; + if ($course->tags) { + $originTagIds = kg_array_column($course->tags, 'id'); + } + + $newTagIds = $tagIds ?: []; + $addedTagIds = array_diff($newTagIds, $originTagIds); + + if ($addedTagIds) { + foreach ($addedTagIds as $tagId) { + $courseTag = new CourseTagModel(); + $courseTag->course_id = $course->id; + $courseTag->tag_id = $tagId; + $courseTag->create(); + $this->recountTagCourses($tagId); } } - $newTeacherIds = $teacherIds ? explode(',', $teacherIds) : []; - $addedTeacherIds = array_diff($newTeacherIds, $originTeacherIds); + $deletedTagIds = array_diff($originTagIds, $newTagIds); - if ($addedTeacherIds) { - foreach ($addedTeacherIds as $teacherId) { - $courseTeacher = new CourseUserModel(); - $courseTeacher->course_id = $course->id; - $courseTeacher->user_id = $teacherId; - $courseTeacher->role_type = CourseUserModel::ROLE_TEACHER; - $courseTeacher->source_type = CourseUserModel::SOURCE_IMPORT; - $courseTeacher->create(); - } - } - - $deletedTeacherIds = array_diff($originTeacherIds, $newTeacherIds); - - if ($deletedTeacherIds) { - $courseUserRepo = new CourseUserRepo(); - foreach ($deletedTeacherIds as $teacherId) { - $courseTeacher = $courseUserRepo->findCourseTeacher($course->id, $teacherId); - if ($courseTeacher) { - $courseTeacher->delete(); + if ($deletedTagIds) { + $courseTagRepo = new CourseTagRepo(); + foreach ($deletedTagIds as $tagId) { + $courseTag = $courseTagRepo->findCourseTag($course->id, $tagId); + if ($courseTag) { + $courseTag->delete(); + $this->recountTagCourses($tagId); } } } - $teacherId = $newTeacherIds[0] ?? 0; + $courseTags = []; - if ($teacherId) { - $course->teacher_id = $teacherId; - $course->update(); - } - - $cache = new CourseTeacherListCache(); - - $cache->rebuild($course->id); - } - - protected function saveCategories(CourseModel $course, $categoryIds) - { - $courseRepo = new CourseRepo(); - - $courseCategories = $courseRepo->findCategories($course->id); - - $originCategoryIds = []; - - if ($courseCategories->count() > 0) { - foreach ($courseCategories as $category) { - $originCategoryIds[] = $category->id; - } - } - - $newCategoryIds = $categoryIds ? explode(',', $categoryIds) : []; - $addedCategoryIds = array_diff($newCategoryIds, $originCategoryIds); - - if ($addedCategoryIds) { - foreach ($addedCategoryIds as $categoryId) { - $courseCategory = new CourseCategoryModel(); - $courseCategory->course_id = $course->id; - $courseCategory->category_id = $categoryId; - $courseCategory->create(); - } - } - - $deletedCategoryIds = array_diff($originCategoryIds, $newCategoryIds); - - if ($deletedCategoryIds) { - $courseCategoryRepo = new CourseCategoryRepo(); - foreach ($deletedCategoryIds as $categoryId) { - $courseCategory = $courseCategoryRepo->findCourseCategory($course->id, $categoryId); - if ($courseCategory) { - $courseCategory->delete(); + if ($newTagIds) { + $tagRepo = new TagRepo(); + $tags = $tagRepo->findByIds($newTagIds); + if ($tags->count() > 0) { + foreach ($tags as $tag) { + $courseTags[] = ['id' => $tag->id, 'name' => $tag->name]; + $this->recountTagCourses($tag->id); } } } - $categoryId = $newCategoryIds[0] ?? 0; + $course->tags = $courseTags; - if ($categoryId) { - $course->category_id = $categoryId; - $course->update(); - } - - $cache = new CourseCategoryListCache(); - - $cache->rebuild($course->id); + $course->update(); } protected function saveRelatedCourses(CourseModel $course, $courseIds) @@ -608,6 +506,21 @@ class Course extends Service $sync->addItem($course->id); } + protected function recountTagCourses($tagId) + { + $tagRepo = new TagRepo(); + + $tag = $tagRepo->findById($tagId); + + if (!$tag) return; + + $courseCount = $tagRepo->countCourses($tagId); + + $tag->course_count = $courseCount; + + $tag->update(); + } + protected function handleCourses($pager) { if ($pager->total_items > 0) { diff --git a/app/Http/Admin/Services/CourseLearning.php b/app/Http/Admin/Services/CourseLearning.php new file mode 100644 index 00000000..02113df1 --- /dev/null +++ b/app/Http/Admin/Services/CourseLearning.php @@ -0,0 +1,64 @@ +findCourseOrFail($id); + + $pagerQuery = new PagerQuery(); + + $params = $pagerQuery->getParams(); + + $params['course_id'] = $course->id; + + $sort = $pagerQuery->getSort(); + $page = $pagerQuery->getPage(); + $limit = $pagerQuery->getLimit(); + + $learningRepo = new LearningRepo(); + + $pager = $learningRepo->paginate($params, $sort, $page, $limit); + + return $this->handleLearnings($pager); + } + + protected function findCourseOrFail($id) + { + $validator = new CourseValidator(); + + return $validator->checkCourse($id); + } + + protected function handleLearnings($pager) + { + if ($pager->total_items > 0) { + + $builder = new LearningListBuilder(); + + $pipeA = $pager->items->toArray(); + $pipeB = $builder->handleCourses($pipeA); + $pipeC = $builder->handleChapters($pipeB); + $pipeD = $builder->handleUsers($pipeC); + $pipeE = $builder->objects($pipeD); + + $pager->items = $pipeE; + } + + return $pager; + } + +} diff --git a/app/Http/Admin/Services/CourseUser.php b/app/Http/Admin/Services/CourseUser.php new file mode 100644 index 00000000..a3963d47 --- /dev/null +++ b/app/Http/Admin/Services/CourseUser.php @@ -0,0 +1,101 @@ +request->getPost(); + + $validator = new CourseUserValidator(); + + $course = $validator->checkCourse($id); + + $user = $validator->checkUser($post['user_id']); + + $expiryTime = $validator->checkExpiryTime($post['expiry_time']); + + $sourceType = CourseUserModel::SOURCE_MANUAL; + + return $this->assignUserCourse($course, $user, $expiryTime, $sourceType); + } + + public function getUsers($id) + { + $validator = new CourseUserValidator(); + + $course = $validator->checkCourse($id); + + $pagerQuery = new PagerQuery(); + + $params = $pagerQuery->getParams(); + + $params['course_id'] = $course->id; + $params['deleted'] = 0; + + $accountRepo = new AccountRepo(); + + /** + * 兼容用户编号|手机号码|邮箱地址查询 + */ + if (!empty($params['user_id'])) { + if (CommonValidator::phone($params['user_id'])) { + $account = $accountRepo->findByPhone($params['user_id']); + $params['user_id'] = $account ? $account->id : -1000; + } elseif (CommonValidator::email($params['user_id'])) { + $account = $accountRepo->findByEmail($params['user_id']); + $params['user_id'] = $account ? $account->id : -1000; + } + } + + $sort = $pagerQuery->getSort(); + $page = $pagerQuery->getPage(); + $limit = $pagerQuery->getLimit(); + + $repo = new CourseUserRepo(); + + $pager = $repo->paginate($params, $sort, $page, $limit); + + return $this->handleUsers($pager); + } + + protected function handleUsers($pager) + { + if ($pager->total_items > 0) { + + $builder = new CourseUserListBuilder(); + + $items = $pager->items->toArray(); + $pipeA = $builder->handleUsers($items); + $pipeB = $builder->objects($pipeA); + + $pager->items = $pipeB; + } + + return $pager; + } + +} diff --git a/app/Http/Admin/Services/FlashSale.php b/app/Http/Admin/Services/FlashSale.php deleted file mode 100644 index b903a6c6..00000000 --- a/app/Http/Admin/Services/FlashSale.php +++ /dev/null @@ -1,380 +0,0 @@ -findOrFail($id); - - $result = []; - - foreach ($schedules as $schedule) { - $result[] = [ - 'name' => $schedule['name'], - 'value' => $schedule['hour'], - 'selected' => in_array($schedule['hour'], $sale->schedules), - ]; - } - - return $result; - } - - public function getXmCourses() - { - $courseRepo = new CourseRepo(); - - $items = $courseRepo->findAll([ - 'free' => 0, - 'published' => 1, - 'deleted' => 0, - ]); - - if ($items->count() == 0) return []; - - $result = []; - - foreach ($items as $item) { - $result[] = [ - 'name' => sprintf('%s(¥%0.2f)', $item->title, $item->market_price), - 'value' => $item->id, - ]; - } - - return $result; - } - - public function getXmPackages() - { - $packageRepo = new PackageRepo(); - - $items = $packageRepo->findAll([ - 'published' => 1, - 'deleted' => 0, - ]); - - if ($items->count() == 0) return []; - - $result = []; - - foreach ($items as $item) { - $result[] = [ - 'name' => sprintf('%s(¥%0.2f)', $item->title, $item->market_price), - 'value' => $item->id, - ]; - } - - return $result; - } - - public function getXmVips() - { - $vipRepo = new VipRepo(); - - $items = $vipRepo->findAll(); - - if ($items->count() == 0) return []; - - $result = []; - - foreach ($items as $item) { - $result[] = [ - 'name' => sprintf('%s(¥%0.2f)', $item->title, $item->price), - 'value' => $item->id, - ]; - } - - return $result; - } - - public function getFlashSales() - { - $pagerQuery = new PagerQuery(); - - $params = $pagerQuery->getParams(); - - $params['deleted'] = $params['deleted'] ?? 0; - - $sort = $pagerQuery->getSort(); - $page = $pagerQuery->getPage(); - $limit = $pagerQuery->getLimit(); - - $saleRepo = new FlashSaleRepo(); - - return $saleRepo->paginate($params, $sort, $page, $limit); - } - - public function getFlashSale($id) - { - return $this->findOrFail($id); - } - - public function createFlashSale() - { - $post = $this->request->getPost(); - - $validator = new FlashSaleValidator(); - - $post['item_type'] = $validator->checkItemType($post['item_type']); - - $sale = new FlashSaleModel(); - - switch ($post['item_type']) { - case FlashSaleModel::ITEM_COURSE: - $sale = $this->createCourseFlashSale($post); - break; - case FlashSaleModel::ITEM_PACKAGE: - $sale = $this->createPackageFlashSale($post); - break; - case FlashSaleModel::ITEM_VIP: - $sale = $this->createVipFlashSale($post); - break; - } - - $this->rebuildFlashSaleCache($sale); - - return $sale; - } - - public function updateFlashSale($id) - { - $sale = $this->findOrFail($id); - - $post = $this->request->getPost(); - - $originInfo = $this->getOriginInfo($sale->item_id, $sale->item_type); - - $validator = new FlashSaleValidator(); - - $data = []; - - $data['item_info'] = $originInfo['item_info']; - - if (isset($post['start_time']) && isset($post['end_time'])) { - $data['start_time'] = $validator->checkStartTime($post['start_time']); - $data['end_time'] = $validator->checkEndTime($post['end_time']); - $validator->checkTimeRange($data['start_time'], $data['end_time']); - } - - if (isset($post['xm_schedules'])) { - $data['schedules'] = $validator->checkSchedules($post['xm_schedules']); - } - - if (isset($post['stock'])) { - $data['stock'] = $validator->checkStock($post['stock']); - } - - if (isset($post['price'])) { - $data['price'] = $validator->checkPrice($originInfo['item_price'], $post['price']); - } - - if (isset($post['published'])) { - $data['published'] = $validator->checkPublishStatus($post['published']); - } - - $sale->update($data); - - $this->initFlashSaleQueue($sale); - $this->rebuildFlashSaleCache($sale); - - return $sale; - } - - public function deleteFlashSale($id) - { - $sale = $this->findOrFail($id); - - $sale->deleted = 1; - - $sale->update(); - - $this->rebuildFlashSaleCache($sale); - - return $sale; - } - - public function restoreFlashSale($id) - { - $sale = $this->findOrFail($id); - - $sale->deleted = 0; - - $sale->update(); - - $this->rebuildFlashSaleCache($sale); - - return $sale; - } - - protected function findOrFail($id) - { - $validator = new FlashSaleValidator(); - - return $validator->checkFlashSale($id); - } - - protected function initFlashSaleQueue(FlashSaleModel $sale) - { - $queue = new FlashSaleQueue(); - - $queue->init($sale->id); - } - - protected function rebuildFlashSaleCache(FlashSaleModel $sale) - { - $cache = new FlashSaleCache(); - - $cache->rebuild($sale->id); - } - - protected function createCourseFlashSale($post) - { - $validator = new FlashSaleValidator(); - - $course = $validator->checkCourse($post['xm_course_id']); - - $originInfo = $this->getOriginInfo($course->id, FlashSaleModel::ITEM_COURSE); - - $sale = new FlashSaleModel(); - - $sale->item_id = $course->id; - $sale->item_type = FlashSaleModel::ITEM_COURSE; - $sale->item_info = $originInfo['item_info']; - - $sale->create(); - - return $sale; - } - - protected function createPackageFlashSale($post) - { - $validator = new FlashSaleValidator(); - - $package = $validator->checkPackage($post['xm_package_id']); - - $originInfo = $this->getOriginInfo($package->id, FlashSaleModel::ITEM_PACKAGE); - - $sale = new FlashSaleModel(); - - $sale->item_id = $package->id; - $sale->item_type = FlashSaleModel::ITEM_PACKAGE; - $sale->item_info = $originInfo['item_info']; - - $sale->create(); - - return $sale; - } - - protected function createVipFlashSale($post) - { - $validator = new FlashSaleValidator(); - - $vip = $validator->checkVip($post['xm_vip_id']); - - $originInfo = $this->getOriginInfo($vip->id, FlashSaleModel::ITEM_VIP); - - $sale = new FlashSaleModel(); - - $sale->item_id = $vip->id; - $sale->item_type = FlashSaleModel::ITEM_VIP; - $sale->item_info = $originInfo['item_info']; - - $sale->create(); - - return $sale; - } - - protected function getOriginInfo($itemId, $itemType) - { - $result = [ - 'item_info' => [], - 'item_price' => 0.00, - ]; - - if ($itemType == FlashSaleModel::ITEM_COURSE) { - - $courseRepo = new CourseRepo(); - - $course = $courseRepo->findById($itemId); - - $result = [ - 'item_info' => [ - 'course' => [ - 'id' => $course->id, - 'title' => $course->title, - 'cover' => CourseModel::getCoverPath($course->cover), - 'market_price' => $course->market_price, - ], - ], - 'item_price' => $course->market_price, - ]; - - } elseif ($itemType == FlashSaleModel::ITEM_PACKAGE) { - - $packageRepo = new PackageRepo(); - - $package = $packageRepo->findById($itemId); - - $result = [ - 'item_info' => [ - 'package' => [ - 'id' => $package->id, - 'title' => $package->title, - 'cover' => PackageModel::getCoverPath($package->cover), - 'market_price' => $package->market_price, - ], - ], - 'item_price' => $package->market_price, - ]; - - } elseif ($itemType == FlashSaleModel::ITEM_VIP) { - - $vipRepo = new VipRepo(); - - $vip = $vipRepo->findById($itemId); - - $result = [ - 'item_info' => [ - 'vip' => [ - 'id' => $vip->id, - 'title' => $vip->title, - 'cover' => VipModel::getCoverPath($vip->cover), - 'expiry' => $vip->expiry, - 'price' => $vip->price, - ], - ], - 'item_price' => $vip->price, - ]; - } - - return $result; - } - -} diff --git a/app/Http/Admin/Services/Order.php b/app/Http/Admin/Services/Order.php index 995cf065..b69745d9 100644 --- a/app/Http/Admin/Services/Order.php +++ b/app/Http/Admin/Services/Order.php @@ -9,6 +9,7 @@ namespace App\Http\Admin\Services; use App\Builders\OrderList as OrderListBuilder; use App\Library\Paginator\Query as PaginateQuery; +use App\Library\Validators\Common as CommonValidator; use App\Models\Order as OrderModel; use App\Repos\Account as AccountRepo; use App\Repos\Order as OrderRepo; @@ -36,6 +37,30 @@ class Order extends Service $params['deleted'] = $params['deleted'] ?? 0; + /** + * 兼容订单编号或订单序号查询 + */ + if (isset($params['id']) && strlen($params['id']) > 10) { + $orderRepo = new OrderRepo(); + $order = $orderRepo->findBySn($params['id']); + $params['id'] = $order ? $order->id : -1000; + } + + $accountRepo = new AccountRepo(); + + /** + * 兼容用户编号|手机号码|邮箱地址查询 + */ + if (!empty($params['owner_id'])) { + if (CommonValidator::phone($params['owner_id'])) { + $account = $accountRepo->findByPhone($params['owner_id']); + $params['owner_id'] = $account ? $account->id : -1000; + } elseif (CommonValidator::email($params['owner_id'])) { + $account = $accountRepo->findByEmail($params['owner_id']); + $params['owner_id'] = $account ? $account->id : -1000; + } + } + $sort = $pageQuery->getSort(); $page = $pageQuery->getPage(); $limit = $pageQuery->getLimit(); diff --git a/app/Http/Admin/Services/Question.php b/app/Http/Admin/Services/Question.php index ad1450b7..e17a687d 100644 --- a/app/Http/Admin/Services/Question.php +++ b/app/Http/Admin/Services/Question.php @@ -16,10 +16,10 @@ use App\Models\Question as QuestionModel; use App\Models\Reason as ReasonModel; use App\Models\Report as ReportModel; 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\User as UserRepo; +use App\Services\Category as CategoryService; use App\Services\Logic\Notice\Internal\QuestionApproved as QuestionApprovedNotice; use App\Services\Logic\Notice\Internal\QuestionRejected as QuestionRejectedNotice; use App\Services\Logic\Point\History\QuestionPost as QuestionPostPointHistory; @@ -41,16 +41,11 @@ class Question extends Service return $service->handle($id); } - public function getCategories() + public function getCategoryOptions() { - $categoryRepo = new CategoryRepo(); + $categoryService = new CategoryService(); - return $categoryRepo->findAll([ - 'type' => CategoryModel::TYPE_QUESTION, - 'level' => 1, - 'published' => 1, - 'deleted' => 0, - ]); + return $categoryService->getCategoryOptions(CategoryModel::TYPE_QUESTION); } public function getPublishTypes() @@ -155,11 +150,6 @@ class Question extends Service $data = []; - if (isset($post['category_id'])) { - $category = $validator->checkCategory($post['category_id']); - $data['category_id'] = $category->id; - } - if (isset($post['title'])) { $data['title'] = $validator->checkTitle($post['title']); } @@ -172,10 +162,18 @@ class Question extends Service $data['keywords'] = $validator->checkKeywords($post['keywords']); } + if (isset($post['summary'])) { + $data['summary'] = $validator->checkSummary($post['keywords']); + } + if (isset($post['anonymous'])) { $data['anonymous'] = $validator->checkAnonymousStatus($post['anonymous']); } + if (isset($post['featured'])) { + $data['featured'] = $validator->checkFeatureStatus($post['featured']); + } + if (isset($post['closed'])) { $data['closed'] = $validator->checkCloseStatus($post['closed']); } @@ -184,6 +182,11 @@ class Question extends Service $data['published'] = $validator->checkPublishStatus($post['published']); } + if (isset($post['category_id'])) { + $category = $validator->checkCategory($post['category_id']); + $data['category_id'] = $category->id; + } + if (isset($post['xm_tag_ids'])) { $this->saveTags($question, $post['xm_tag_ids']); } @@ -210,6 +213,10 @@ class Question extends Service $question->update(); + $sender = $this->getLoginUser(); + + $this->handleQuestionDeletedNotice($question, $sender); + $owner = $this->findUser($question->owner_id); $this->saveDynamicAttrs($question); @@ -247,28 +254,13 @@ class Question extends Service $reason = $this->request->getPost('reason', ['trim', 'string']); $question = $this->findOrFail($id); - - $validator = new QuestionValidator(); - - if ($type == 'approve') { - $question->published = QuestionModel::PUBLISH_APPROVED; - } elseif ($type == 'reject') { - $validator->checkRejectReason($reason); - $question->published = QuestionModel::PUBLISH_REJECTED; - } - - $question->update(); - - $owner = $this->findUser($question->owner_id); - - $this->rebuildQuestionCache($question); - $this->rebuildQuestionIndex($question); - $this->recountUserQuestions($owner); - $sender = $this->getLoginUser(); if ($type == 'approve') { + $question->published = QuestionModel::PUBLISH_APPROVED; + $question->update(); + $this->handleQuestionPostPoint($question); $this->handleQuestionApprovedNotice($question, $sender); @@ -276,17 +268,20 @@ class Question extends Service } elseif ($type == 'reject') { - $options = ReasonModel::questionRejectOptions(); - - if (array_key_exists($reason, $options)) { - $reason = $options[$reason]; - } + $question->published = QuestionModel::PUBLISH_REJECTED; + $question->update(); $this->handleQuestionRejectedNotice($question, $sender, $reason); $this->eventsManager->fire('Question:afterReject', $this, $question); } + $owner = $this->findUser($question->owner_id); + + $this->recountUserQuestions($owner); + $this->rebuildQuestionCache($question); + $this->rebuildQuestionIndex($question); + return $question; } @@ -324,6 +319,72 @@ class Question extends Service $this->recountUserQuestions($owner); } + public function batchModerate() + { + $type = $this->request->getQuery('type', ['trim', 'string']); + $ids = $this->request->getPost('ids', ['trim', 'int']); + + $questionRepo = new QuestionRepo(); + + $questions = $questionRepo->findByIds($ids); + + if ($questions->count() == 0) return; + + $sender = $this->getLoginUser(); + + foreach ($questions as $question) { + + if ($type == 'approve') { + + $question->published = QuestionModel::PUBLISH_APPROVED; + $question->update(); + + $this->handleQuestionPostPoint($question); + $this->handleQuestionApprovedNotice($question, $sender); + + } elseif ($type == 'reject') { + + $question->published = QuestionModel::PUBLISH_REJECTED; + $question->update(); + + $this->handleQuestionRejectedNotice($question, $sender); + } + + $owner = $this->findUser($question->owner_id); + + $this->recountUserQuestions($owner); + $this->rebuildQuestionCache($question); + $this->rebuildQuestionIndex($question); + } + } + + public function batchDelete() + { + $ids = $this->request->getPost('ids', ['trim', 'int']); + + $questionRepo = new QuestionRepo(); + + $questions = $questionRepo->findByIds($ids); + + if ($questions->count() == 0) return; + + $sender = $this->getLoginUser(); + + foreach ($questions as $question) { + + $question->deleted = 1; + $question->update(); + + $this->handleQuestionDeletedNotice($question, $sender); + + $owner = $this->findUser($question->owner_id); + + $this->recountUserQuestions($owner); + $this->rebuildQuestionCache($question); + $this->rebuildQuestionIndex($question); + } + } + protected function findOrFail($id) { $validator = new QuestionValidator(); @@ -379,13 +440,18 @@ class Question extends Service $notice->handle($question, $sender); } - protected function handleQuestionRejectedNotice(QuestionModel $question, UserModel $sender, $reason) + protected function handleQuestionRejectedNotice(QuestionModel $question, UserModel $sender, $reason = '') { $notice = new QuestionRejectedNotice(); $notice->handle($question, $sender, $reason); } + protected function handleQuestionDeletedNotice(QuestionModel $question, UserModel $sender, $reason = '') + { + + } + protected function handleQuestions($pager) { if ($pager->total_items > 0) { diff --git a/app/Http/Admin/Services/Refund.php b/app/Http/Admin/Services/Refund.php index 6c21711a..ed8aeed0 100644 --- a/app/Http/Admin/Services/Refund.php +++ b/app/Http/Admin/Services/Refund.php @@ -9,6 +9,7 @@ namespace App\Http\Admin\Services; use App\Builders\RefundList as RefundListBuilder; use App\Library\Paginator\Query as PaginateQuery; +use App\Library\Validators\Common as CommonValidator; use App\Models\Refund as RefundModel; use App\Models\Task as TaskModel; use App\Repos\Account as AccountRepo; @@ -43,6 +44,21 @@ class Refund extends Service $params['order_id'] = $order ? $order->id : -1000; } + $accountRepo = new AccountRepo(); + + /** + * 兼容用户编号|手机号码|邮箱地址查询 + */ + if (!empty($params['owner_id'])) { + if (CommonValidator::phone($params['owner_id'])) { + $account = $accountRepo->findByPhone($params['owner_id']); + $params['owner_id'] = $account ? $account->id : -1000; + } elseif (CommonValidator::email($params['owner_id'])) { + $account = $accountRepo->findByEmail($params['owner_id']); + $params['owner_id'] = $account ? $account->id : -1000; + } + } + $sort = $pageQuery->getSort(); $page = $pageQuery->getPage(); $limit = $pageQuery->getLimit(); diff --git a/app/Http/Admin/Services/Review.php b/app/Http/Admin/Services/Review.php index 14bc5aa7..26922213 100644 --- a/app/Http/Admin/Services/Review.php +++ b/app/Http/Admin/Services/Review.php @@ -9,8 +9,12 @@ namespace App\Http\Admin\Services; use App\Builders\ReviewList as ReviewListBuilder; use App\Library\Paginator\Query as PagerQuery; +use App\Library\Validators\Common as CommonValidator; use App\Models\Course as CourseModel; +use App\Models\Reason as ReasonModel; use App\Models\Review as ReviewModel; +use App\Models\User as UserModel; +use App\Repos\Account as AccountRepo; use App\Repos\Course as CourseRepo; use App\Repos\Review as ReviewRepo; use App\Services\CourseStat as CourseStatService; @@ -25,6 +29,34 @@ class Review extends Service return ReviewModel::publishTypes(); } + public function getReasons() + { + return ReasonModel::reviewRejectOptions(); + } + + public function getXmCourses() + { + $courseRepo = new CourseRepo(); + + $items = $courseRepo->findAll([ + 'published' => 1, + 'deleted' => 0, + ]); + + if ($items->count() == 0) return []; + + $result = []; + + foreach ($items as $item) { + $result[] = [ + 'name' => sprintf('%s - %s(¥%0.2f)', $item->id, $item->title, $item->market_price), + 'value' => $item->id, + ]; + } + + return $result; + } + public function getReviews() { $pagerQuery = new PagerQuery(); @@ -33,6 +65,21 @@ class Review extends Service $params['deleted'] = $params['deleted'] ?? 0; + $accountRepo = new AccountRepo(); + + /** + * 兼容用户编号|手机号码|邮箱地址查询 + */ + if (!empty($params['owner_id'])) { + if (CommonValidator::phone($params['owner_id'])) { + $account = $accountRepo->findByPhone($params['owner_id']); + $params['owner_id'] = $account ? $account->id : -1000; + } elseif (CommonValidator::email($params['owner_id'])) { + $account = $accountRepo->findByEmail($params['owner_id']); + $params['owner_id'] = $account ? $account->id : -1000; + } + } + $sort = $pagerQuery->getSort(); $page = $pagerQuery->getPage(); $limit = $pagerQuery->getLimit(); @@ -91,6 +138,10 @@ class Review extends Service $data['rating3'] = $validator->checkRating($post['rating3']); } + if (isset($post['anonymous'])) { + $data['anonymous'] = $validator->checkAnonymous($post['anonymous']); + } + if (isset($post['published'])) { $data['published'] = $validator->checkPublishStatus($post['published']); $this->recountCourseReviews($course); @@ -99,6 +150,7 @@ class Review extends Service $review->update($data); $this->updateCourseRating($course); + $this->recountCourseReviews($course); $this->eventsManager->fire('Review:afterUpdate', $this, $review); @@ -117,6 +169,12 @@ class Review extends Service $this->recountCourseReviews($course); + $this->updateCourseRating($course); + + $sender = $this->getLoginUser(); + + $this->handleReviewDeletedNotice($review, $sender); + $this->eventsManager->fire('Review:afterReview', $this, $review); } @@ -138,30 +196,102 @@ class Review extends Service public function moderate($id) { $type = $this->request->getPost('type', ['trim', 'string']); + $reason = $this->request->getPost('reason', ['trim', 'string']); $review = $this->findOrFail($id); - if ($type == 'approve') { - $review->published = ReviewModel::PUBLISH_APPROVED; - } elseif ($type == 'reject') { - $review->published = ReviewModel::PUBLISH_REJECTED; - } + $sender = $this->getLoginUser(); - $review->update(); + if ($type == 'approve') { + + $review->published = ReviewModel::PUBLISH_APPROVED; + $review->update(); + + $this->handleReviewApprovedNotice($review, $sender); + + $this->eventsManager->fire('Review:afterApprove', $this, $review); + + } elseif ($type == 'reject') { + + $review->published = ReviewModel::PUBLISH_REJECTED; + $review->update(); + + $this->handleReviewRejectedNotice($review, $sender, $reason); + + $this->eventsManager->fire('Review:afterReject', $this, $review); + } $course = $this->findCourse($review->course_id); $this->recountCourseReviews($course); - - if ($type == 'approve') { - $this->eventsManager->fire('Review:afterApprove', $this, $review); - } elseif ($type == 'reject') { - $this->eventsManager->fire('Review:afterReject', $this, $review); - } + $this->updateCourseRating($course); return $review; } + public function batchModerate() + { + $type = $this->request->getQuery('type', ['trim', 'string']); + $ids = $this->request->getPost('ids', ['trim', 'int']); + + $reviewRepo = new ReviewRepo(); + + $reviews = $reviewRepo->findByIds($ids); + + if ($reviews->count() == 0) return; + + $sender = $this->getLoginUser(); + + foreach ($reviews as $review) { + + if ($type == 'approve') { + + $review->published = ReviewModel::PUBLISH_APPROVED; + $review->update(); + + $this->handleReviewApprovedNotice($review, $sender); + + } elseif ($type == 'reject') { + + $review->published = ReviewModel::PUBLISH_REJECTED; + $review->update(); + + $this->handleReviewRejectedNotice($review, $sender); + } + + $course = $this->findCourse($review->course_id); + + $this->recountCourseReviews($course); + $this->updateCourseRating($course); + } + } + + public function batchDelete() + { + $ids = $this->request->getPost('ids', ['trim', 'int']); + + $reviewRepo = new ReviewRepo(); + + $reviews = $reviewRepo->findByIds($ids); + + if ($reviews->count() == 0) return; + + $sender = $this->getLoginUser(); + + foreach ($reviews as $review) { + + $review->deleted = 1; + $review->update(); + + $this->handleReviewDeletedNotice($review, $sender); + + $course = $this->findCourse($review->course_id); + + $this->recountCourseReviews($course); + $this->updateCourseRating($course); + } + } + protected function findOrFail($id) { $validator = new ReviewValidator(); @@ -176,6 +306,21 @@ class Review extends Service return $courseRepo->findById($id); } + protected function handleReviewApprovedNotice(ReviewModel $review, UserModel $sender) + { + + } + + protected function handleReviewRejectedNotice(ReviewModel $review, UserModel $sender, $reason = '') + { + + } + + protected function handleReviewDeletedNotice(ReviewModel $review, UserModel $sender, $reason = '') + { + + } + protected function recountCourseReviews(CourseModel $course) { $courseRepo = new CourseRepo(); diff --git a/app/Http/Admin/Services/Role.php b/app/Http/Admin/Services/Role.php index e6e50b2e..3899d6cd 100644 --- a/app/Http/Admin/Services/Role.php +++ b/app/Http/Admin/Services/Role.php @@ -140,6 +140,9 @@ class Role extends Service $list[] = str_replace('.edit', '.list', $route); } elseif (strpos($route, '.delete')) { $list[] = str_replace('.delete', '.restore', $route); + $list[] = str_replace('.delete', '.batch_delete', $route); + } elseif (strpos($route, '.moderate')) { + $list[] = str_replace('.moderate', '.batch_moderate', $route); } elseif (strpos($route, '.search')) { $list[] = str_replace('.search', '.list', $route); } diff --git a/app/Http/Admin/Services/Student.php b/app/Http/Admin/Services/Student.php deleted file mode 100644 index 1743e513..00000000 --- a/app/Http/Admin/Services/Student.php +++ /dev/null @@ -1,223 +0,0 @@ - 1, - 'deleted' => 0, - ]; - - /** - * 过滤付费课程 - */ - if ($scope == 'charge') { - $where['free'] = 0; - } - - $items = $courseRepo->findAll($where); - - if ($items->count() == 0) return []; - - $result = []; - - foreach ($items as $item) { - $result[] = [ - 'name' => sprintf('%s - %s(¥%0.2f)', $item->id, $item->title, $item->market_price), - 'value' => $item->id, - 'selected' => $item->id == $courseId, - ]; - } - - return $result; - } - - public function getSourceTypes() - { - return CourseUserModel::sourceTypes(); - } - - public function getCourse($id) - { - $repo = new CourseRepo(); - - return $repo->findById($id); - } - - public function getStudent($id) - { - $repo = new UserRepo(); - - return $repo->findById($id); - } - - public function getRelations() - { - $pagerQuery = new PagerQuery(); - - $params = $pagerQuery->getParams(); - - $params['role_type'] = CourseUserModel::ROLE_STUDENT; - - $validator = new CourseUserValidator(); - - if (!empty($params['xm_course_id'])) { - $course = $validator->checkCourse($params['xm_course_id']); - $params['course_id'] = $course->id; - } - - if (!empty($params['xm_user_id'])) { - $user = $validator->checkUser($params['xm_user_id']); - $params['user_id'] = $user->id; - } - - $sort = $pagerQuery->getSort(); - $page = $pagerQuery->getPage(); - $limit = $pagerQuery->getLimit(); - - $courseUserRepo = new CourseUserRepo(); - - $pager = $courseUserRepo->paginate($params, $sort, $page, $limit); - - return $this->handleRelations($pager); - } - - public function getLearnings() - { - $pagerQuery = new PagerQuery(); - - $params = $pagerQuery->getParams(); - - $sort = $pagerQuery->getSort(); - $page = $pagerQuery->getPage(); - $limit = $pagerQuery->getLimit(); - - $learningRepo = new LearningRepo(); - - $pager = $learningRepo->paginate($params, $sort, $page, $limit); - - return $this->handleLearnings($pager); - } - - public function getRelation($id) - { - return $this->findOrFail($id); - } - - public function createRelation() - { - $post = $this->request->getPost(); - - $validator = new CourseUserValidator(); - - $data = [ - 'role_type' => CourseUserModel::ROLE_STUDENT, - 'source_type' => CourseUserModel::SOURCE_IMPORT, - ]; - - $course = $validator->checkCourse($post['xm_course_id']); - $user = $validator->checkUser($post['xm_user_id']); - $expiryTime = $validator->checkExpiryTime($post['expiry_time']); - - $data['course_id'] = $course->id; - $data['user_id'] = $user->id; - $data['expiry_time'] = $expiryTime; - - $validator->checkIfImported($course->id, $user->id); - - $courseUser = new CourseUserModel(); - - $courseUser->create($data); - - $course->user_count += 1; - $course->update(); - - $user->course_count += 1; - $user->update(); - - return $courseUser; - } - - public function updateRelation() - { - $post = $this->request->getPost(); - - $relation = $this->findOrFail($post['relation_id']); - - $validator = new CourseUserValidator(); - - $data = []; - - if (isset($post['expiry_time'])) { - $data['expiry_time'] = $validator->checkExpiryTime($post['expiry_time']); - } - - $relation->update($data); - - return $relation; - } - - protected function findOrFail($id) - { - $validator = new CourseUserValidator(); - - return $validator->checkRelation($id); - } - - protected function handleRelations($pager) - { - if ($pager->total_items > 0) { - - $builder = new CourseUserListBuilder(); - - $pipeA = $pager->items->toArray(); - $pipeB = $builder->handleCourses($pipeA); - $pipeC = $builder->handleUsers($pipeB); - $pipeD = $builder->objects($pipeC); - - $pager->items = $pipeD; - } - - return $pager; - } - - protected function handleLearnings($pager) - { - if ($pager->total_items > 0) { - - $builder = new LearningListBuilder(); - - $pipeA = $pager->items->toArray(); - $pipeB = $builder->handleCourses($pipeA); - $pipeC = $builder->handleChapters($pipeB); - $pipeD = $builder->handleUsers($pipeC); - $pipeE = $builder->objects($pipeD); - - $pager->items = $pipeE; - } - - return $pager; - } - -} diff --git a/app/Http/Admin/Services/Trade.php b/app/Http/Admin/Services/Trade.php index 42616281..3023e9ae 100644 --- a/app/Http/Admin/Services/Trade.php +++ b/app/Http/Admin/Services/Trade.php @@ -9,6 +9,7 @@ namespace App\Http\Admin\Services; use App\Builders\TradeList as TradeListBuilder; use App\Library\Paginator\Query as PaginateQuery; +use App\Library\Validators\Common as CommonValidator; use App\Models\Refund as RefundModel; use App\Models\Trade as TradeModel; use App\Repos\Account as AccountRepo; @@ -46,6 +47,21 @@ class Trade extends Service $params['order_id'] = $order ? $order->id : -1000; } + $accountRepo = new AccountRepo(); + + /** + * 兼容用户编号|手机号码|邮箱地址查询 + */ + if (!empty($params['owner_id'])) { + if (CommonValidator::phone($params['owner_id'])) { + $account = $accountRepo->findByPhone($params['owner_id']); + $params['owner_id'] = $account ? $account->id : -1000; + } elseif (CommonValidator::email($params['owner_id'])) { + $account = $accountRepo->findByEmail($params['owner_id']); + $params['owner_id'] = $account ? $account->id : -1000; + } + } + $sort = $pageQuery->getSort(); $page = $pageQuery->getPage(); $limit = $pageQuery->getLimit(); diff --git a/app/Http/Admin/Services/User.php b/app/Http/Admin/Services/User.php index 7a15e29f..be2f4039 100644 --- a/app/Http/Admin/Services/User.php +++ b/app/Http/Admin/Services/User.php @@ -335,11 +335,12 @@ class User extends Service $items = $pager->items->toArray(); $pipeA = $builder->handleUsers($items); - $pipeB = $builder->handleAdminRoles($pipeA); - $pipeC = $builder->handleEduRoles($pipeB); - $pipeD = $builder->objects($pipeC); + $pipeB = $builder->handleAccounts($pipeA); + $pipeC = $builder->handleAdminRoles($pipeB); + $pipeD = $builder->handleEduRoles($pipeC); + $pipeE = $builder->objects($pipeD); - $pager->items = $pipeD; + $pager->items = $pipeE; } return $pager; diff --git a/app/Http/Admin/Services/Util.php b/app/Http/Admin/Services/Util.php index b9352de6..552f235b 100644 --- a/app/Http/Admin/Services/Util.php +++ b/app/Http/Admin/Services/Util.php @@ -7,8 +7,7 @@ namespace App\Http\Admin\Services; -use App\Caches\IndexSlideList as IndexSlideListCache; -use App\Services\Utils\IndexCourseCache as IndexCourseCacheUtil; +use App\Services\Utils\IndexPageCache as IndexPageCacheUtil; class Util extends Service { @@ -17,29 +16,25 @@ class Util extends Service { $items = $this->request->getPost('items'); - if ($items['slide'] == 1) { - $cache = new IndexSlideListCache(); - $cache->rebuild(); + $sections = [ + 'slide', + 'featured_course', + 'new_course', + 'free_course', + 'vip_course', + ]; + + if (empty($items)) { + $items = $sections; } - $util = new IndexCourseCacheUtil(); + $util = new IndexPageCacheUtil(); - if ($items['featured_course'] == 1) { - $util->rebuild('featured_course'); + foreach ($sections as $section) { + if (in_array($section, $items)) { + $util->rebuild($section); + } } - - if ($items['new_course'] == 1) { - $util->rebuild('new_course'); - } - - if ($items['free_course'] == 1) { - $util->rebuild('free_course'); - } - - if ($items['vip_course'] == 1) { - $util->rebuild('vip_course'); - } - } } diff --git a/app/Http/Admin/Services/Vip.php b/app/Http/Admin/Services/Vip.php new file mode 100644 index 00000000..a926aba7 --- /dev/null +++ b/app/Http/Admin/Services/Vip.php @@ -0,0 +1,120 @@ +getParams(); + + $params['deleted'] = $params['deleted'] ?? 0; + + $sort = $pagerQuery->getSort(); + $page = $pagerQuery->getPage(); + $limit = $pagerQuery->getLimit(); + + $vipRepo = new VipRepo(); + + return $vipRepo->paginate($params, $sort, $page, $limit); + } + + public function getVip($id) + { + return $this->findOrFail($id); + } + + public function createVip() + { + $post = $this->request->getPost(); + + $validator = new VipValidator(); + + $data = []; + + $data['expiry'] = $validator->checkExpiry($post['expiry']); + $data['price'] = $validator->checkPrice($post['price']); + $data['title'] = sprintf('%s个月', $data['expiry']); + + $vip = new VipModel(); + + $vip->create($data); + + return $vip; + } + + public function updateVip($id) + { + $vip = $this->findOrFail($id); + + $post = $this->request->getPost(); + + $validator = new VipValidator(); + + $data = []; + + if (isset($post['cover'])) { + $data['cover'] = $validator->checkCover($post['cover']); + } + + if (isset($post['expiry'])) { + $data['expiry'] = $validator->checkExpiry($post['expiry']); + $data['title'] = sprintf('%s个月', $data['expiry']); + } + + if (isset($post['price'])) { + $data['price'] = $validator->checkPrice($post['price']); + } + + if (isset($post['published'])) { + $data['published'] = $validator->checkPublishStatus($post['published']); + } + + $vip->update($data); + + return $vip; + } + + public function deleteVip($id) + { + $vip = $this->findOrFail($id); + + $vip->deleted = 1; + + $vip->update(); + + return $vip; + } + + public function restoreVip($id) + { + $vip = $this->findOrFail($id); + + $vip->deleted = 0; + + $vip->update(); + + return $vip; + } + + protected function findOrFail($id) + { + $validator = new VipValidator(); + + return $validator->checkVip($id); + } + +} diff --git a/app/Http/Admin/Views/answer/edit.volt b/app/Http/Admin/Views/answer/edit.volt index 9f5d83a5..3e354819 100644 --- a/app/Http/Admin/Views/answer/edit.volt +++ b/app/Http/Admin/Views/answer/edit.volt @@ -7,16 +7,27 @@ 编辑答案
-
- + +
+
{{ question.title }}
-
+ +
-
+
+ +
+ {% for value,title in publish_types %} + {% set checked = value == answer.published ? 'checked="checked"' : '' %} + + {% endfor %} +
+
+
diff --git a/app/Http/Admin/Views/answer/list.volt b/app/Http/Admin/Views/answer/list.volt index a2fb6054..7bbaf4d6 100644 --- a/app/Http/Admin/Views/answer/list.volt +++ b/app/Http/Admin/Views/answer/list.volt @@ -5,12 +5,17 @@ {{ partial('macros/answer') }} {% set search_url = url({'for':'admin.answer.search'}) %} + {% set batch_delete_url = url({'for':'admin.answer.batch_delete'}) %}
+ {% if request.get('course_id') > 0 %} + 返回 + {% endif %} 回答管理 + 批量删除
- +
+ + @@ -29,7 +36,9 @@ - + + + @@ -46,10 +55,15 @@ {% set restore_url = url({'for':'admin.answer.restore','id':item.id}) %} {% set moderate_url = url({'for':'admin.answer.moderate','id':item.id}) %} + + diff --git a/app/Http/Admin/Views/answer/moderate.volt b/app/Http/Admin/Views/answer/moderate.volt index 703cebd4..4dec226a 100644 --- a/app/Http/Admin/Views/answer/moderate.volt +++ b/app/Http/Admin/Views/answer/moderate.volt @@ -37,8 +37,8 @@
diff --git a/app/Http/Admin/Views/answer/report.volt b/app/Http/Admin/Views/answer/report.volt index f0b06c78..62b8bba0 100644 --- a/app/Http/Admin/Views/answer/report.volt +++ b/app/Http/Admin/Views/answer/report.volt @@ -23,13 +23,13 @@
{{ answer.question.title }}
{{ answer.owner.name }} - {{ date('Y-m-d H:i',answer.create_time) }} + {{ date('Y-m-d H:i:s',answer.create_time) }}
{{ answer.content }}
-
信息作者信息问答信息 评论 点赞 状态
-

问题:{{ item.question.title }}

-

回答:{{ substr(item.summary,0,32) }}

-

作者:{{ item.owner.name }} 创建:{{ date('Y-m-d',item.create_time) }}

+

昵称:{{ item.owner.name }}

+

编号:{{ item.owner.id }}

+
+

问题:{{ item.question.title }}({{ item.question.id }})

+

回答:{{ item.summary }}({{ item.id }})

+

创建:{{ date('Y-m-d',item.create_time) }}

{{ item.comment_count }} {{ item.like_count }}
+
@@ -73,7 +73,7 @@
- +
diff --git a/app/Http/Admin/Views/answer/search.volt b/app/Http/Admin/Views/answer/search.volt index cd0e7b6f..945fb5d7 100644 --- a/app/Http/Admin/Views/answer/search.volt +++ b/app/Http/Admin/Views/answer/search.volt @@ -24,21 +24,24 @@ +
+ +
+ +
+
-
+
+ +
+
{% for value,title in publish_types %} - + {% endfor %}
-
- -
- - -
-
@@ -55,4 +58,24 @@
+{% endblock %} + +{% block inline_js %} + + + {% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/article/edit.volt b/app/Http/Admin/Views/article/edit.volt index 041fd3b6..1046feeb 100644 --- a/app/Http/Admin/Views/article/edit.volt +++ b/app/Http/Admin/Views/article/edit.volt @@ -2,6 +2,8 @@ {% block content %} + {% set update_url = url({'for':'admin.article.update','id':article.id}) %} +
编辑文章
@@ -9,12 +11,16 @@
  • 基本信息
  • +
  • 搜索优化
  • 文章内容
{{ partial('article/edit_basic') }}
+
+ {{ partial('article/edit_seo') }} +
{{ partial('article/edit_desc') }}
@@ -29,6 +35,7 @@ {{ js_include('lib/kindeditor/kindeditor.min.js') }} {{ js_include('lib/kindeditor/lang/zh-CN.js') }} {{ js_include('admin/js/content.editor.js') }} + {{ js_include('admin/js/cover.upload.js') }} {% endblock %} diff --git a/app/Http/Admin/Views/article/edit_basic.volt b/app/Http/Admin/Views/article/edit_basic.volt index d76f9e88..39af9867 100644 --- a/app/Http/Admin/Views/article/edit_basic.volt +++ b/app/Http/Admin/Views/article/edit_basic.volt @@ -1,6 +1,16 @@ {% set source_url_display = article.source_type == 1 ? 'display:none' : 'display:block' %} -
+ +
+ +
+ + +
+
+ +
+
@@ -8,15 +18,21 @@
- +
-
+
- +
- +
@@ -35,6 +51,22 @@
+
+ +
+ {% for value,title in publish_types %} + {% set checked = value == article.published ? 'checked="checked"' : '' %} + + {% endfor %} +
+
+
+ +
+ + +
+
@@ -42,17 +74,10 @@
-
- -
- - -
-
- +
diff --git a/app/Http/Admin/Views/article/edit_desc.volt b/app/Http/Admin/Views/article/edit_desc.volt index f3b32586..bd0b4927 100644 --- a/app/Http/Admin/Views/article/edit_desc.volt +++ b/app/Http/Admin/Views/article/edit_desc.volt @@ -1,4 +1,4 @@ - +
diff --git a/app/Http/Admin/Views/article/edit_seo.volt b/app/Http/Admin/Views/article/edit_seo.volt new file mode 100644 index 00000000..5dfa0d94 --- /dev/null +++ b/app/Http/Admin/Views/article/edit_seo.volt @@ -0,0 +1,21 @@ + +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + +
+
+ \ No newline at end of file diff --git a/app/Http/Admin/Views/article/list.volt b/app/Http/Admin/Views/article/list.volt index 13269e08..19cbc66d 100644 --- a/app/Http/Admin/Views/article/list.volt +++ b/app/Http/Admin/Views/article/list.volt @@ -6,14 +6,20 @@ {% set add_url = url({'for':'admin.article.add'}) %} {% set search_url = url({'for':'admin.article.search'}) %} + {% set category_url = url({'for':'admin.article.category'}) %} + {% set batch_delete_url = url({'for':'admin.article.batch_delete'}) %}
文章管理 + 批量删除
-
+
- - + @@ -37,11 +42,10 @@ - - - - - + + + + @@ -59,29 +63,35 @@ {% set moderate_url = url({'for':'admin.article.moderate','id':item.id}) %} {% set comment_url = url({'for':'admin.comment.list'},{'item_id':item.id,'item_type':2}) %} + + - - - - + - - + +
文章浏览评论点赞收藏作者信息文章信息统计信息 状态 推荐 关闭
+

昵称:{{ item.owner.name }}

+

编号:{{ item.owner.id }}

+

标题:{{ item.title }}({{ item.id }})

{% if item.category.id is defined %} 分类:{{ item.category.name }} {% endif %} - {% if item.tags %} - 标签:{{ tags_info(item.tags) }} - {% endif %} -

-

- 来源:{{ source_type(item.source_type) }} - 作者:{{ item.owner.name }} 创建:{{ date('Y-m-d',item.create_time) }}

{{ item.view_count }}{{ item.comment_count }}{{ item.like_count }}{{ item.favorite_count }} +

+ 浏览:{{ item.view_count }} + 评论:{{ item.comment_count }} +

+

+ 点赞:{{ item.like_count }} + 收藏:{{ item.favorite_count }} +

+
{{ publish_status(item.published) }}
@@ -115,64 +125,11 @@ diff --git a/app/Http/Admin/Views/audit/search.volt b/app/Http/Admin/Views/audit/search.volt index 2167810e..7a8ce8c4 100644 --- a/app/Http/Admin/Views/audit/search.volt +++ b/app/Http/Admin/Views/audit/search.volt @@ -35,7 +35,7 @@
-
-
+
-
diff --git a/app/Http/Admin/Views/category/list.volt b/app/Http/Admin/Views/category/list.volt index 2b79388e..7e2efff7 100644 --- a/app/Http/Admin/Views/category/list.volt +++ b/app/Http/Admin/Views/category/list.volt @@ -22,7 +22,7 @@
- +
@@ -54,20 +54,21 @@ {% set restore_url = url({'for':'admin.category.restore','id':item.id}) %} - - {% if item.type == 1 %} + + {% if item.type in [1,3,4] %} {% if item.level == 1 %} {% else %} {% endif %} - {% elseif item.type == 2 %} + {% else %} {% endif %} - +
{{ item.id }}{{ item.name }}{{ item.name }} {{ item.name }}{{ item.name }}{{ item.name }}{{ item.level }} {{ item.child_count }}
diff --git a/app/Http/Admin/Views/chapter/lessons_live.volt b/app/Http/Admin/Views/chapter/lessons_live.volt index 6871a304..0ff808d0 100644 --- a/app/Http/Admin/Views/chapter/lessons_live.volt +++ b/app/Http/Admin/Views/chapter/lessons_live.volt @@ -17,7 +17,7 @@ {% endif %} {%- endmacro %} - +
diff --git a/app/Http/Admin/Views/chapter/lessons_offline.volt b/app/Http/Admin/Views/chapter/lessons_offline.volt index 91b9fa67..dae91e84 100644 --- a/app/Http/Admin/Views/chapter/lessons_offline.volt +++ b/app/Http/Admin/Views/chapter/lessons_offline.volt @@ -7,7 +7,7 @@ {% endif %} {%- endmacro %} -
+
diff --git a/app/Http/Admin/Views/chapter/lessons_read.volt b/app/Http/Admin/Views/chapter/lessons_read.volt index b2125d94..317c5908 100644 --- a/app/Http/Admin/Views/chapter/lessons_read.volt +++ b/app/Http/Admin/Views/chapter/lessons_read.volt @@ -1,4 +1,4 @@ -
+
diff --git a/app/Http/Admin/Views/chapter/lessons_vod.volt b/app/Http/Admin/Views/chapter/lessons_vod.volt index 7f31d3d1..4a2018f8 100644 --- a/app/Http/Admin/Views/chapter/lessons_vod.volt +++ b/app/Http/Admin/Views/chapter/lessons_vod.volt @@ -12,7 +12,7 @@ {% endif %} {%- endmacro %} -
+
diff --git a/app/Http/Admin/Views/comment/list.volt b/app/Http/Admin/Views/comment/list.volt index 539ebbd9..eec11649 100644 --- a/app/Http/Admin/Views/comment/list.volt +++ b/app/Http/Admin/Views/comment/list.volt @@ -4,20 +4,36 @@ {{ partial('macros/common') }} -
+ {% set batch_delete_url = url({'for':'admin.comment.batch_delete'}) %} + +
+
+ + {% if request.get('item_id') > 0 %} + 返回 + {% endif %} + 评论管理 + + 批量删除 +
+
+ +
+ - + + + - - + @@ -28,9 +44,12 @@ {% set delete_url = url({'for':'admin.comment.delete','id':item.id}) %} {% set restore_url = url({'for':'admin.comment.restore','id':item.id}) %} - + + + -
评论作者内容回复 点赞用户时间创建 操作
{{ item.content }}{{ item.owner.name }}({{ item.owner.id }}) +

{{ item.content }}

+
{{ item.reply_count }} {{ item.like_count }}{{ item.owner.name }} {{ date('Y-m-d',item.create_time) }} {% if item.deleted == 0 %} diff --git a/app/Http/Admin/Views/comment/moderate.volt b/app/Http/Admin/Views/comment/moderate.volt index d34bbe26..d78e7500 100644 --- a/app/Http/Admin/Views/comment/moderate.volt +++ b/app/Http/Admin/Views/comment/moderate.volt @@ -37,8 +37,8 @@
@@ -46,7 +46,7 @@
- +
diff --git a/app/Http/Admin/Views/comment/report.volt b/app/Http/Admin/Views/comment/report.volt index da53925a..75bfb15a 100644 --- a/app/Http/Admin/Views/comment/report.volt +++ b/app/Http/Admin/Views/comment/report.volt @@ -22,13 +22,13 @@
{{ comment.owner.name }} - {{ date('Y-m-d H:i',comment.create_time) }} + {{ date('Y-m-d H:i:s',comment.create_time) }}
{{ comment.content }}
- +
@@ -47,7 +47,7 @@ - + {% endfor %} @@ -72,7 +72,7 @@
- +
diff --git a/app/Http/Admin/Views/consult/edit.volt b/app/Http/Admin/Views/consult/edit.volt index d556935b..f01813fc 100644 --- a/app/Http/Admin/Views/consult/edit.volt +++ b/app/Http/Admin/Views/consult/edit.volt @@ -18,6 +18,22 @@ +
+ +
+ {% for value,title in publish_types %} + {% set checked = value == consult.published ? 'checked="checked"' : '' %} + + {% endfor %} +
+
+
+ +
+ + +
+
diff --git a/app/Http/Admin/Views/consult/list.volt b/app/Http/Admin/Views/consult/list.volt index 2b025356..5aa25265 100644 --- a/app/Http/Admin/Views/consult/list.volt +++ b/app/Http/Admin/Views/consult/list.volt @@ -2,19 +2,20 @@ {% block content %} -{{ partial('macros/consult') }} + {{ partial('macros/consult') }} {% set search_url = url({'for':'admin.consult.search'}) %} + {% set batch_delete_url = url({'for':'admin.consult.batch_delete'}) %}
- 返回 - {% if course %} - {{ course.title }} + {% if request.get('course_id') > 0 %} + 返回 {% endif %} 咨询管理 + 批量删除
-
{{ item.owner.name }} {{ item.reason }}{{ date('Y-m-d',item.create_time) }}{{ date('Y-m-d H:i:s',item.create_time) }}
+
+ + @@ -33,42 +36,47 @@ - + + + {% for item in pager.items %} {% 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_user_url = url({'for':'admin.consult.list'},{'owner_id':item.owner.id}) %} + {% set course_url = url({'for':'home.course.show','id':item.course.id}) %} + {% set owner_url = url({'for':'home.user.show','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 update_url = url({'for':'admin.consult.update','id':item.id}) %} {% set delete_url = url({'for':'admin.consult.delete','id':item.id}) %} {% set restore_url = url({'for':'admin.consult.restore','id':item.id}) %} + + - + - - + + - + @@ -48,11 +52,12 @@ {% set restore_url = url({'for':'admin.help.restore','id':item.id}) %} - + - - + + - + diff --git a/app/Http/Admin/Views/macros/answer.volt b/app/Http/Admin/Views/macros/answer.volt index 05de2d9f..a395e01a 100644 --- a/app/Http/Admin/Views/macros/answer.volt +++ b/app/Http/Admin/Views/macros/answer.volt @@ -6,6 +6,6 @@ {% elseif type == 3 %} 未通过 {% else %} - 未知 + N/A {% endif %} {%- endmacro %} \ No newline at end of file diff --git a/app/Http/Admin/Views/macros/article.volt b/app/Http/Admin/Views/macros/article.volt index fa74535e..91a8eb3a 100644 --- a/app/Http/Admin/Views/macros/article.volt +++ b/app/Http/Admin/Views/macros/article.volt @@ -6,7 +6,7 @@ {% elseif type == 3 %} 未通过 {% else %} - 未知 + N/A {% endif %} {%- endmacro %} @@ -20,11 +20,4 @@ {% else %} N/A {% endif %} -{%- endmacro %} - -{%- macro tags_info(items) %} - {% for item in items %} - {% set comma = loop.last ? '' : ',' %} - {{ item.name ~ comma }} - {% endfor %} {%- endmacro %} \ No newline at end of file diff --git a/app/Http/Admin/Views/macros/comment.volt b/app/Http/Admin/Views/macros/comment.volt index 05de2d9f..a395e01a 100644 --- a/app/Http/Admin/Views/macros/comment.volt +++ b/app/Http/Admin/Views/macros/comment.volt @@ -6,6 +6,6 @@ {% elseif type == 3 %} 未通过 {% else %} - 未知 + N/A {% endif %} {%- endmacro %} \ No newline at end of file diff --git a/app/Http/Admin/Views/macros/consult.volt b/app/Http/Admin/Views/macros/consult.volt index ce3c3a92..3210346a 100644 --- a/app/Http/Admin/Views/macros/consult.volt +++ b/app/Http/Admin/Views/macros/consult.volt @@ -6,7 +6,7 @@ {% elseif type == 3 %} 未通过 {% else %} - 未知 + N/A {% endif %} {%- endmacro %} diff --git a/app/Http/Admin/Views/macros/course.volt b/app/Http/Admin/Views/macros/course.volt index bb716a69..2617aa2b 100644 --- a/app/Http/Admin/Views/macros/course.volt +++ b/app/Http/Admin/Views/macros/course.volt @@ -8,7 +8,7 @@ {% elseif value == 4 %} 面授 {% else %} - 未知 + N/A {% endif %} {%- endmacro %} @@ -22,6 +22,6 @@ {% elseif value == 4 %} 高级 {% else %} - 未知 + N/A {% endif %} {%- endmacro %} \ No newline at end of file diff --git a/app/Http/Admin/Views/macros/course_user.volt b/app/Http/Admin/Views/macros/course_user.volt new file mode 100644 index 00000000..0f3cb9db --- /dev/null +++ b/app/Http/Admin/Views/macros/course_user.volt @@ -0,0 +1,19 @@ +{%- macro source_type(value) %} + {% if value == 1 %} + 免费 + {% elseif value == 2 %} + 付费 + {% elseif value == 3 %} + 畅学 + {% elseif value == 4 %} + 分配 + {% elseif value == 5 %} + 积分兑换 + {% elseif value == 6 %} + 抽奖兑换 + {% elseif value == 10 %} + 试听 + {% else %} + N/A + {% endif %} +{%- endmacro %} \ No newline at end of file diff --git a/app/Http/Admin/Views/macros/question.volt b/app/Http/Admin/Views/macros/question.volt index 6593e6ea..a395e01a 100644 --- a/app/Http/Admin/Views/macros/question.volt +++ b/app/Http/Admin/Views/macros/question.volt @@ -6,13 +6,6 @@ {% elseif type == 3 %} 未通过 {% else %} - 未知 + N/A {% endif %} -{%- endmacro %} - -{%- macro tags_info(items) %} - {% for item in items %} - {% set comma = loop.last ? '' : ',' %} - {{ item.name ~ comma }} - {% endfor %} {%- endmacro %} \ No newline at end of file diff --git a/app/Http/Admin/Views/macros/review.volt b/app/Http/Admin/Views/macros/review.volt index 05de2d9f..a395e01a 100644 --- a/app/Http/Admin/Views/macros/review.volt +++ b/app/Http/Admin/Views/macros/review.volt @@ -6,6 +6,6 @@ {% elseif type == 3 %} 未通过 {% else %} - 未知 + N/A {% endif %} {%- endmacro %} \ No newline at end of file diff --git a/app/Http/Admin/Views/moderation/answers.volt b/app/Http/Admin/Views/moderation/answers.volt index 24d18077..11d4e9bc 100644 --- a/app/Http/Admin/Views/moderation/answers.volt +++ b/app/Http/Admin/Views/moderation/answers.volt @@ -4,26 +4,32 @@ {{ partial('macros/answer') }} + {% set batch_moderate_url = url({'for':'admin.answer.batch_moderate'}) %} +
回答审核 + 批量通过 + 批量拒绝
-
问答 用户内容 时间 状态私密 操作
-

课程:{{ item.course.title }}({{ item.course.id }}){{ private_info(item.private) }}

+

昵称:{{ item.owner.name }}

+

编号:{{ item.owner.id }}

+
+

课程:{{ item.course.title }}({{ item.course.id }})

提问:{{ item.question }}

回复:{{ item.answer }}

-

昵称:{{ item.owner.name }}

-

编号:{{ item.owner.id }}

-
-

提问:{{ date('Y-m-d H:i:s',item.create_time) }}

+

提问:{{ date('Y-m-d',item.create_time) }}

{% if item.reply_time > 0 %} -

回复:{{ date('Y-m-d H:i:s',item.reply_time) }}

+

回复:{{ date('Y-m-d',item.reply_time) }}

{% else %}

回复:N/A

{% endif %}
{{ publish_status(item.published) }}
diff --git a/app/Http/Admin/Views/consult/moderate.volt b/app/Http/Admin/Views/consult/moderate.volt index 04345558..7016a4be 100644 --- a/app/Http/Admin/Views/consult/moderate.volt +++ b/app/Http/Admin/Views/consult/moderate.volt @@ -7,22 +7,12 @@
- {% if consult.course.id is defined %} -
- -
-
{{ consult.course.title }}
-
+
+ +
+
{{ consult.course.title }}
- {% endif %} - {% if consult.chapter.id is defined %} -
- -
-
{{ consult.chapter.title }}
-
-
- {% endif %} +
@@ -45,13 +35,50 @@
+
- +
+{% endblock %} + +{% block inline_js %} + + + {% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/consult/search.volt b/app/Http/Admin/Views/consult/search.volt index bc683c0c..bc9f476c 100644 --- a/app/Http/Admin/Views/consult/search.volt +++ b/app/Http/Admin/Views/consult/search.volt @@ -13,22 +13,32 @@
- +
- +
- +
- +
+
+
+
+ +
+ +
+
-
+
+
{% for value,title in publish_types %} - + {% endfor %}
@@ -55,4 +65,41 @@ +{% endblock %} + +{% block include_js %} + + {{ js_include('lib/xm-select.js') }} + +{% endblock %} + +{% block inline_js %} + + + {% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/student/add.volt b/app/Http/Admin/Views/course/add_user.volt similarity index 54% rename from app/Http/Admin/Views/student/add.volt rename to app/Http/Admin/Views/course/add_user.volt index 40dbcd56..f6731e94 100644 --- a/app/Http/Admin/Views/student/add.volt +++ b/app/Http/Admin/Views/course/add_user.volt @@ -2,20 +2,23 @@ {% block content %} -
-
- 添加学员 -
+ {% set create_url = url({'for':'admin.course.create_user','id':course.id}) %} + +
+ 添加学员 +
+ +
- +
-
+
{{ course.title }}
- +
- +
@@ -35,12 +38,6 @@ {% endblock %} -{% block include_js %} - - {{ js_include('lib/xm-select.js') }} - -{% endblock %} - {% block inline_js %} diff --git a/app/Http/Admin/Views/course/edit_basic.volt b/app/Http/Admin/Views/course/edit_basic.volt index bf0f5709..5f13ce69 100644 --- a/app/Http/Admin/Views/course/edit_basic.volt +++ b/app/Http/Admin/Views/course/edit_basic.volt @@ -1,10 +1,4 @@ - -
- -
- -
-
+
@@ -15,25 +9,63 @@
+
+ +
+ +
+
-
+
-
+ +
+
+
+ +
+
- - - - + {% for value,title in level_types %} + {% set checked = course.level == value ? 'checked="checked"' : '' %} + + {% endfor %} +
+
+
+ +
+ + +
+
+
+ +
+ +
diff --git a/app/Http/Admin/Views/course/edit_desc.volt b/app/Http/Admin/Views/course/edit_desc.volt index 0c9893c3..a1a511fd 100644 --- a/app/Http/Admin/Views/course/edit_desc.volt +++ b/app/Http/Admin/Views/course/edit_desc.volt @@ -1,4 +1,4 @@ - +
diff --git a/app/Http/Admin/Views/course/edit_offline.volt b/app/Http/Admin/Views/course/edit_offline.volt index 2ec4f202..f82fba81 100644 --- a/app/Http/Admin/Views/course/edit_offline.volt +++ b/app/Http/Admin/Views/course/edit_offline.volt @@ -1,4 +1,4 @@ - +
diff --git a/app/Http/Admin/Views/course/edit_related.volt b/app/Http/Admin/Views/course/edit_related.volt index 739b1085..6d72aaf0 100644 --- a/app/Http/Admin/Views/course/edit_related.volt +++ b/app/Http/Admin/Views/course/edit_related.volt @@ -1,4 +1,4 @@ - +
@@ -8,7 +8,7 @@
- +
diff --git a/app/Http/Admin/Views/course/edit_sale.volt b/app/Http/Admin/Views/course/edit_sale.volt index d08ff074..4991243c 100644 --- a/app/Http/Admin/Views/course/edit_sale.volt +++ b/app/Http/Admin/Views/course/edit_sale.volt @@ -1,4 +1,4 @@ - +
diff --git a/app/Http/Admin/Views/course/learnings.volt b/app/Http/Admin/Views/course/learnings.volt new file mode 100644 index 00000000..62b64093 --- /dev/null +++ b/app/Http/Admin/Views/course/learnings.volt @@ -0,0 +1,48 @@ +{% extends 'templates/main.volt' %} + +{% block content %} + + {{ partial('macros/common') }} + + {% if pager.total_pages > 0 %} + + + + + + + + + + + + + + + + + + + {% for item in pager.items %} + {% set duration = item.duration > 0 ? item.duration|duration : 'N/A' %} + {% set active_time = item.active_time > 0 ? date('Y-m-d H:i:s',item.active_time) : 'N/A' %} + + + + + + + + {% endfor %} + +
章节名称终端类型终端地址学习时长最近学习
{{ item.chapter.title }}({{ item.chapter.id }}){{ client_type(item.client_type) }}{{ item.client_ip }}{{ duration }}{{ active_time }}
+ {{ partial('partials/pager') }} + {% endif %} + +{% endblock %} + +{% block include_js %} + + {{ js_include('admin/js/ip2region.js') }} + +{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/course/list.volt b/app/Http/Admin/Views/course/list.volt index 0b17998e..4203088b 100644 --- a/app/Http/Admin/Views/course/list.volt +++ b/app/Http/Admin/Views/course/list.volt @@ -27,13 +27,8 @@
- +
- - - - - @@ -43,14 +38,9 @@ - - - - - - - - + + + @@ -63,13 +53,13 @@ {% set update_url = url({'for':'admin.course.update','id':item.id}) %} {% set delete_url = url({'for':'admin.course.delete','id':item.id}) %} {% set restore_url = url({'for':'admin.course.restore','id':item.id}) %} - {% set catalog_url = url({'for':'admin.course.chapters','id':item.id}) %} - {% set student_url = url({'for':'admin.student.list'},{'course_id':item.id}) %} - {% set review_url = url({'for':'admin.review.list'},{'course_id':item.id}) %} - {% set consult_url = url({'for':'admin.consult.list'},{'course_id':item.id}) %} + {% set chapters_url = url({'for':'admin.course.chapters','id':item.id}) %} + {% set users_url = url({'for':'admin.course.users','id':item.id}) %} + {% set reviews_url = url({'for':'admin.review.list'},{'course_id':item.id}) %} + {% set consults_url = url({'for':'admin.consult.list'},{'course_id':item.id}) %} - - - - - - - - + + + @@ -127,45 +124,4 @@ {{ partial('partials/pager') }} -{% endblock %} - -{% block inline_js %} - - - {% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/course/search.volt b/app/Http/Admin/Views/course/search.volt index bded8418..6a807e3b 100644 --- a/app/Http/Admin/Views/course/search.volt +++ b/app/Http/Admin/Views/course/search.volt @@ -7,34 +7,54 @@ 搜索课程
- +
- +
- +
-
+
- +
-
+ +
+
+
+ +
+ +
+
-
+
+
{% for value,title in model_types %} - + {% endfor %}
@@ -42,7 +62,7 @@
{% for value,title in level_types %} - + {% endfor %}
@@ -85,36 +105,20 @@ {% endblock %} -{% block include_js %} - - {{ js_include('lib/xm-select.js') }} - -{% endblock %} - {% block inline_js %} diff --git a/app/Http/Admin/Views/course/search_user.volt b/app/Http/Admin/Views/course/search_user.volt new file mode 100644 index 00000000..68dde0bf --- /dev/null +++ b/app/Http/Admin/Views/course/search_user.volt @@ -0,0 +1,103 @@ +{% extends 'templates/main.volt' %} + +{% block content %} + + {% set target = request.get('target','string','search') %} + {% set count = request.get('count','int',-1) %} + + {% if target == 'search' %} + {% set action_url = url({'for':'admin.course.users','id':course.id}) %} + {% set title = '搜索学员' %} + {% else %} + {% set action_url = url({'for':'admin.course.export_user','id':course.id}) %} + {% set title = '导出学员' %} + {% endif %} + + +
+ {{ title }} +
+
+ +
+
{{ course.title }}
+
+
+
+ +
+ +
+
+
+ +
+ {% for value,title in source_types %} + + {% endfor %} +
+
+
+ +
+ +
+
-
+
+ +
+
+
+ +
+ + + + +
+
+ + +{% endblock %} + +{% block inline_js %} + + + +{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/course/users.volt b/app/Http/Admin/Views/course/users.volt new file mode 100644 index 00000000..2222791f --- /dev/null +++ b/app/Http/Admin/Views/course/users.volt @@ -0,0 +1,100 @@ +{% extends 'templates/main.volt' %} + +{% block content %} + + {{ partial('macros/course_user') }} + + {% set add_url = url({'for':'admin.course.add_user','id':course.id}) %} + {% set search_url = url({'for':'admin.course.search_user','id':course.id}) %} + + + +
课程课时课件学员收藏咨询评价价格基本信息统计信息价格信息 推荐 发布 操作
-

标题:{{ item.title }}({{ item.id }})

+

标题:{{ item.title }}({{ item.id }})

{% if item.category.id is defined %} 分类:{{ item.category.name }} @@ -85,19 +75,26 @@ 创建:{{ date('Y-m-d',item.create_time) }}

{{ item.lesson_count }}{{ item.resource_count }}{{ item.user_count }}{{ item.favorite_count }}{{ item.consult_count }}{{ item.review_count }} -

原始:{{ '¥%0.2f'|format(item.origin_price) }}

-

市场:{{ '¥%0.2f'|format(item.market_price) }}

-

会员:{{ '¥%0.2f'|format(item.vip_price) }}

+

+ 学员:{{ item.user_count }} + 咨询:{{ item.consult_count }} + 评价:{{ item.review_count }} +

+

+ 课时:{{ item.lesson_count }} + 课件:{{ item.resource_count }} + 收藏:{{ item.favorite_count }} +

+

市场价:{{ '¥%0.2f'|format(item.market_price) }}

+

会员价:{{ '¥%0.2f'|format(item.vip_price) }}

+
+ + + + + + + + + + + + + + + + + + + + + + {% for item in pager.items %} + {% set learnings_url = url({'for':'admin.course.learnings','id':item.course_id},{'user_id':item.user_id,'plan_id':item.plan_id}) %} + {% set user_url = url({'for':'home.user.show','id':item.user_id}) %} + {% set expiry_time = item.expiry_time > 0 ? date('Y-m-d H:i:s',item.expiry_time) : 'N/A' %} + {% set active_time = item.active_time > 0 ? date('Y-m-d H:i:s',item.active_time) : 'N/A' %} + + + + + + + + + + {% endfor %} + +
用户信息学习情况来源类型加入时间过期时间最近学习操作
{{ item.user.name }}({{ item.user.id }}) +

进度:{{ item.progress }}%

+

时长:{{ item.duration|duration }}

+
{{ source_type(item.source_type) }}{{ date('Y-m-d H:i:s',item.create_time) }}{{ expiry_time }}{{ active_time }} + 学习记录 +
+ + {{ partial('partials/pager') }} + +{% endblock %} + +{% block inline_js %} + + + +{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/flash_sale/add.volt b/app/Http/Admin/Views/flash_sale/add.volt deleted file mode 100644 index abfa320a..00000000 --- a/app/Http/Admin/Views/flash_sale/add.volt +++ /dev/null @@ -1,105 +0,0 @@ -{% extends 'templates/main.volt' %} - -{% block content %} - -
-
- 添加商品 -
-
- -
- {% for value,title in item_types %} - - {% endfor %} -
-
- - - -
- -
- - -
-
-
- -{% endblock %} - -{% block include_js %} - - {{ js_include('lib/xm-select.js') }} - -{% endblock %} - -{% block inline_js %} - - - -{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/flash_sale/edit.volt b/app/Http/Admin/Views/flash_sale/edit.volt deleted file mode 100644 index 6142bac2..00000000 --- a/app/Http/Admin/Views/flash_sale/edit.volt +++ /dev/null @@ -1,103 +0,0 @@ -{% extends 'templates/main.volt' %} - -{% block content %} - - {{ partial('macros/flash_sale') }} - - {% set sale.item_info = array_object(sale.item_info) %} - {% set sale.start_time = sale.start_time > 0 ? date('Y-m-d H:i:s',sale.start_time) : '' %} - {% set sale.end_time = sale.end_time > 0 ? date('Y-m-d H:i:s',sale.end_time) : '' %} - -
-
- 编辑商品 -
-
- -
- {{ item_full_info(sale.item_type,sale.item_info) }} -
-
-
- -
- -
-
-
- -
- -
-
-
- -
-
-
-
-
- -
- -
-
-
- -
- -
-
-
- -
- - -
-
-
- -
- - -
-
-
- -{% endblock %} - -{% block include_js %} - - {{ js_include('lib/xm-select.js') }} - -{% endblock %} - -{% block inline_js %} - - - -{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/flash_sale/search.volt b/app/Http/Admin/Views/flash_sale/search.volt deleted file mode 100644 index 0036dd70..00000000 --- a/app/Http/Admin/Views/flash_sale/search.volt +++ /dev/null @@ -1,46 +0,0 @@ -{% extends 'templates/main.volt' %} - -{% block content %} - -
-
- 搜索商品 -
-
- -
- -
-
-
- -
- {% for value,title in item_types %} - - {% endfor %} -
-
-
- -
- - -
-
-
- -
- - -
-
-
- -
- - -
-
-
- -{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/help/list.volt b/app/Http/Admin/Views/help/list.volt index 6f1af71c..7be5ae54 100644 --- a/app/Http/Admin/Views/help/list.volt +++ b/app/Http/Admin/Views/help/list.volt @@ -3,6 +3,7 @@ {% block content %} {% set add_url = url({'for':'admin.help.add'}) %} + {% set category_url = url({'for':'admin.help.category'}) %}
@@ -11,6 +12,9 @@
编号标题 分类标题 浏览 排序 发布
{{ item.id }}{{ item.title }} {{ item.category.name }}{{ item.title }} {{ item.view_count }}
diff --git a/app/Http/Admin/Views/index/main_app_info.volt b/app/Http/Admin/Views/index/main_app_info.volt index 7b59198e..eaa4b24e 100644 --- a/app/Http/Admin/Views/index/main_app_info.volt +++ b/app/Http/Admin/Views/index/main_app_info.volt @@ -12,7 +12,7 @@
当前版本{{ app_info.version }}{{ app_info.alias }} {{ app_info.version }}
获取渠道
+
- + + - - - + + + + @@ -33,14 +39,15 @@ {% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %} {% set moderate_url = url({'for':'admin.answer.moderate','id':item.id}) %} - + +
回答作者时间用户信息问答信息创建时间 操作
-

问题:{{ item.question.title }}

-

回答:{{ substr(item.summary,0,32) }}

-

昵称:{{ item.owner.name }}

编号:{{ item.owner.id }}

+

问题:{{ item.question.title }}

+

回答:{{ substr(item.summary,0,32) }}

+
{{ date('Y-m-d H:i:s',item.create_time) }} 详情 diff --git a/app/Http/Admin/Views/moderation/articles.volt b/app/Http/Admin/Views/moderation/articles.volt index cc1184a3..a5314447 100644 --- a/app/Http/Admin/Views/moderation/articles.volt +++ b/app/Http/Admin/Views/moderation/articles.volt @@ -4,16 +4,21 @@ {{ partial('macros/article') }} + {% set batch_moderate_url = url({'for':'admin.article.batch_moderate'}) %} +
文章审核 + 批量通过 + 批量拒绝
- +
+ @@ -21,9 +26,10 @@ - - - + + + + @@ -32,19 +38,20 @@ {% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %} {% set moderate_url = url({'for':'admin.article.moderate','id':item.id}) %} - + +
文章作者时间用户信息文章信息创建时间 操作
-

标题:{{ item.title }}

-

- 来源:{{ source_type(item.source_type) }} - {% if item.tags %} - 标签:{{ tags_info(item.tags) }} - {% endif %} -

-

昵称:{{ item.owner.name }}

编号:{{ item.owner.id }}

+

标题:{{ item.title }}

+

+ {% if item.category.id is defined %} + 分类:{{ item.category.name }} + {% endif %} + 来源:{{ source_type(item.source_type) }} +

+
{{ date('Y-m-d H:i:s',item.create_time) }} 详情 diff --git a/app/Http/Admin/Views/moderation/comments.volt b/app/Http/Admin/Views/moderation/comments.volt index 6100004d..f6b15afa 100644 --- a/app/Http/Admin/Views/moderation/comments.volt +++ b/app/Http/Admin/Views/moderation/comments.volt @@ -4,26 +4,32 @@ {{ partial('macros/comment') }} + {% set batch_moderate_url = url({'for':'admin.comment.batch_moderate'}) %} +
评论审核 + 批量通过 + 批量拒绝
- +
- + + - - - + + + + @@ -32,11 +38,12 @@ {% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %} {% set moderate_url = url({'for':'admin.comment.moderate','id':item.id}) %} - + +
评论作者时间用户信息评论信息创建时间 操作
{{ substr(item.content,0,32) }}

昵称:{{ item.owner.name }}

编号:{{ item.owner.id }}

{{ substr(item.content,0,32) }} {{ date('Y-m-d H:i:s',item.create_time) }} 详情 diff --git a/app/Http/Admin/Views/moderation/consults.volt b/app/Http/Admin/Views/moderation/consults.volt index 6009231d..c08c40b3 100644 --- a/app/Http/Admin/Views/moderation/consults.volt +++ b/app/Http/Admin/Views/moderation/consults.volt @@ -3,17 +3,21 @@ {% block content %} {% set search_url = url({'for':'admin.consult.search'}) %} + {% set batch_moderate_url = url({'for':'admin.consult.batch_moderate'}) %}
咨询审核 + 批量通过 + 批量拒绝
- +
+ @@ -21,9 +25,10 @@ - - - + + + + @@ -34,23 +39,16 @@ {% set course_url = url({'for':'home.course.show','id':item.course.id}) %} {% set moderate_url = url({'for':'admin.consult.moderate','id':item.id}) %} - + + diff --git a/app/Http/Admin/Views/moderation/questions.volt b/app/Http/Admin/Views/moderation/questions.volt index 71e922d3..1c7ed23f 100644 --- a/app/Http/Admin/Views/moderation/questions.volt +++ b/app/Http/Admin/Views/moderation/questions.volt @@ -4,16 +4,21 @@ {{ partial('macros/question') }} + {% set batch_moderate_url = url({'for':'admin.question.batch_moderate'}) %} +
问题审核 + 批量通过 + 批量拒绝
-
问答用户时间用户信息咨询信息创建时间 操作
-

课程:{{ item.course.title }}({{ item.course.id }})

-

提问:{{ item.question }}

-

回复:{{ item.answer }}

-

昵称:{{ item.owner.name }}

编号:{{ item.owner.id }}

-

提问:{{ date('Y-m-d H:i:s',item.create_time) }}

- {% if item.reply_time > 0 %} -

回复:{{ date('Y-m-d H:i:s',item.reply_time) }}

- {% else %} -

回复:N/A

- {% endif %} +

课程:{{ item.course.title }}({{ item.course.id }})

+

咨询:{{ item.question }}

{{ date('Y-m-d H:i:s',item.create_time) }} 详情
+
+ @@ -21,9 +26,10 @@ - - - + + + + @@ -32,18 +38,19 @@ {% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %} {% set moderate_url = url({'for':'admin.question.moderate','id':item.id}) %} - + +
问题作者时间用户信息问题信息创建时间 操作
-

标题:{{ item.title }}

-

- {% if item.tags %} - 标签:{{ tags_info(item.tags) }} - {% endif %} -

-

昵称:{{ item.owner.name }}

编号:{{ item.owner.id }}

+

标题:{{ item.title }}

+

+ {% if item.category.id is defined %} + 分类:{{ item.category.name }} + {% endif %} +

+
{{ date('Y-m-d H:i:s',item.create_time) }} 详情 diff --git a/app/Http/Admin/Views/moderation/reviews.volt b/app/Http/Admin/Views/moderation/reviews.volt index f3cc40c3..da90d9a7 100644 --- a/app/Http/Admin/Views/moderation/reviews.volt +++ b/app/Http/Admin/Views/moderation/reviews.volt @@ -3,17 +3,21 @@ {% block content %} {% set search_url = url({'for':'admin.review.search'}) %} + {% set batch_moderate_url = url({'for':'admin.review.batch_moderate'}) %}
评价审核 + 批量通过 + 批量拒绝
- +
+ @@ -22,10 +26,11 @@ - - - - + + + + + @@ -35,6 +40,11 @@ {% set course_url = url({'for':'home.course.show','id':item.course.id}) %} {% set moderate_url = url({'for':'admin.review.moderate','id':item.id}) %} + + -
內容评分用户时间用户信息评价信息课程评分创建时间 操作
+

昵称:{{ item.owner.name }}

+

编号:{{ item.owner.id }}

+

课程:{{ item.course.title }}({{ item.course.id }})

评价:{{ item.content }}

@@ -44,10 +54,6 @@

通俗易懂:{{ item.rating2 }}

逻辑清晰:{{ item.rating3 }}

-

昵称:{{ item.owner.name }}

-

编号:{{ item.owner.id }}

-
{{ date('Y-m-d H:i:s',item.create_time) }} 详情 diff --git a/app/Http/Admin/Views/nav/list.volt b/app/Http/Admin/Views/nav/list.volt index 04788648..0781172b 100644 --- a/app/Http/Admin/Views/nav/list.volt +++ b/app/Http/Admin/Views/nav/list.volt @@ -38,7 +38,7 @@ - +
@@ -82,7 +82,8 @@ - + - - - + @@ -44,15 +42,14 @@ {% for item in pager.items %} {% set show_url = url({'for':'admin.order.show','id':item.id}) %} - - + diff --git a/app/Http/Admin/Views/order/macro.volt b/app/Http/Admin/Views/order/macro.volt index f2b4fc1a..b7ffb616 100644 --- a/app/Http/Admin/Views/order/macro.volt +++ b/app/Http/Admin/Views/order/macro.volt @@ -81,14 +81,4 @@ {% elseif value == 5 %} 已退款 {% endif %} -{%- endmacro %} - -{%- macro promotion_type(value) %} - {% if value == 1 %} - 秒杀 - {% elseif value == 2 %} - 折扣 - {% else %} - N/A - {% endif %} {%- endmacro %} \ No newline at end of file diff --git a/app/Http/Admin/Views/order/order_info.volt b/app/Http/Admin/Views/order/order_info.volt index 4cc52a4d..efe116e9 100644 --- a/app/Http/Admin/Views/order/order_info.volt +++ b/app/Http/Admin/Views/order/order_info.volt @@ -8,7 +8,6 @@ diff --git a/app/Http/Admin/Views/order/search.volt b/app/Http/Admin/Views/order/search.volt index 1f266a06..14f94fd1 100644 --- a/app/Http/Admin/Views/order/search.volt +++ b/app/Http/Admin/Views/order/search.volt @@ -6,12 +6,6 @@
搜索订单
-
- -
- -
-
@@ -19,10 +13,26 @@
- + +
+ +
+
+
+ +
+ +
+
-
+
+ +
+
+
+
{% for value,title in item_types %} - + {% endfor %}
@@ -30,20 +40,10 @@
{% for value,title in status_types %} - + {% endfor %}
-
- -
- -
-
-
-
- -
-
@@ -59,16 +59,14 @@ diff --git a/app/Http/Admin/Views/refund/list.volt b/app/Http/Admin/Views/refund/list.volt index ced2cf7e..f21e4301 100644 --- a/app/Http/Admin/Views/refund/list.volt +++ b/app/Http/Admin/Views/refund/list.volt @@ -30,8 +30,8 @@
- + @@ -42,14 +42,14 @@ {% for item in pager.items %} {% set show_url = url({'for':'admin.refund.show','id':item.id}) %} - + diff --git a/app/Http/Admin/Views/refund/search.volt b/app/Http/Admin/Views/refund/search.volt index eab5c260..e52077d3 100644 --- a/app/Http/Admin/Views/refund/search.volt +++ b/app/Http/Admin/Views/refund/search.volt @@ -13,29 +13,29 @@
- +
- + +
+
+
+ +
+ +
+
-
+
+
{% for value,title in status_types %} - + {% endfor %}
-
- -
- -
-
-
-
- -
-
@@ -51,16 +51,14 @@ diff --git a/app/Http/Admin/Views/review/search.volt b/app/Http/Admin/Views/review/search.volt index 048436df..29c5dc4a 100644 --- a/app/Http/Admin/Views/review/search.volt +++ b/app/Http/Admin/Views/review/search.volt @@ -13,25 +13,42 @@
- +
- +
- +
- +
+
+
+
+ +
+ +
+
-
+
+
{% for value,title in publish_types %} - + {% endfor %}
+
+ +
+ + +
+
@@ -48,4 +65,41 @@
+{% endblock %} + +{% block include_js %} + + {{ js_include('lib/xm-select.js') }} + +{% endblock %} + +{% block inline_js %} + + + {% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/role/add.volt b/app/Http/Admin/Views/role/add.volt index 837f6094..7e8d40ca 100644 --- a/app/Http/Admin/Views/role/add.volt +++ b/app/Http/Admin/Views/role/add.volt @@ -21,7 +21,7 @@
- +
diff --git a/app/Http/Admin/Views/role/edit.volt b/app/Http/Admin/Views/role/edit.volt index d54835c6..a8d6dcb2 100644 --- a/app/Http/Admin/Views/role/edit.volt +++ b/app/Http/Admin/Views/role/edit.volt @@ -43,7 +43,7 @@
- +
diff --git a/app/Http/Admin/Views/setting/point.volt b/app/Http/Admin/Views/setting/point.volt index 62568942..ba266dcb 100644 --- a/app/Http/Admin/Views/setting/point.volt +++ b/app/Http/Admin/Views/setting/point.volt @@ -36,7 +36,7 @@
行为奖励规则
-
{{ position_info(item.position) }} {{ target_info(item.target) }}
diff --git a/app/Http/Admin/Views/order/list.volt b/app/Http/Admin/Views/order/list.volt index 6e7ac38c..853805ac 100644 --- a/app/Http/Admin/Views/order/list.volt +++ b/app/Http/Admin/Views/order/list.volt @@ -26,14 +26,12 @@
商品信息 买家信息促销类型商品信息 订单金额 订单状态 创建时间
-

名称:{{ item.subject }}

-

单号:{{ item.sn }}

-

昵称:{{ item.owner.name }}

编号:{{ item.owner.id }}

{{ promotion_type(item.promotion_type) }} +

名称:{{ item.subject }}

+

单号:{{ item.sn }}

+
{{ '¥%0.2f'|format(item.amount) }} {{ order_status(item.status) }} {{ date('Y-m-d H:i:s',item.create_time) }}
订单编号:{{ order.sn }} - 促销类型:{{ promotion_type(order.promotion_type) }}
商品信息 买家信息商品信息 退款金额 退款状态 创建时间
-

商品:{{ item.order.subject }}

-

单号:{{ item.order.sn }}

-

昵称:{{ item.owner.name }}

编号:{{ item.owner.id }}

+

商品:{{ item.order.subject }}

+

单号:{{ item.order.sn }}

+
{{ '¥%0.2f'|format(item.amount) }} {{ refund_status(item.status) }} {{ date('Y-m-d H:i:s',item.create_time) }}
+
diff --git a/app/Http/Admin/Views/setting/sms.volt b/app/Http/Admin/Views/setting/sms.volt index f2d8b7a4..1969543b 100644 --- a/app/Http/Admin/Views/setting/sms.volt +++ b/app/Http/Admin/Views/setting/sms.volt @@ -29,7 +29,7 @@
模板配置
-
+
diff --git a/app/Http/Admin/Views/setting/vip.volt b/app/Http/Admin/Views/setting/vip.volt index 3631a9a2..a458e0b5 100644 --- a/app/Http/Admin/Views/setting/vip.volt +++ b/app/Http/Admin/Views/setting/vip.volt @@ -6,7 +6,7 @@
会员设置
-
+
diff --git a/app/Http/Admin/Views/setting/wechat_oa_menu.volt b/app/Http/Admin/Views/setting/wechat_oa_menu.volt index 0c34b148..0fff9af8 100644 --- a/app/Http/Admin/Views/setting/wechat_oa_menu.volt +++ b/app/Http/Admin/Views/setting/wechat_oa_menu.volt @@ -1,5 +1,5 @@ -
+
diff --git a/app/Http/Admin/Views/setting/wechat_oa_notice.volt b/app/Http/Admin/Views/setting/wechat_oa_notice.volt index 2040b9a1..7b86a162 100644 --- a/app/Http/Admin/Views/setting/wechat_oa_notice.volt +++ b/app/Http/Admin/Views/setting/wechat_oa_notice.volt @@ -1,7 +1,7 @@ {% set notice_template = oa.notice_template|json_decode %} -
+
diff --git a/app/Http/Admin/Views/slide/list.volt b/app/Http/Admin/Views/slide/list.volt index 2a3bbd0c..c69ca372 100644 --- a/app/Http/Admin/Views/slide/list.volt +++ b/app/Http/Admin/Views/slide/list.volt @@ -23,7 +23,7 @@ -
+
@@ -56,7 +56,8 @@ - +
{{ target_info(item.target) }} {{ target_attrs_info(item.target_attrs) }}
diff --git a/app/Http/Admin/Views/student/edit.volt b/app/Http/Admin/Views/student/edit.volt deleted file mode 100644 index 0fb3c08f..00000000 --- a/app/Http/Admin/Views/student/edit.volt +++ /dev/null @@ -1,67 +0,0 @@ -{% extends 'templates/main.volt' %} - -{% block content %} - - {% set expiry_editable = relation.source_type in [2,4,5,6] %} - - -
- 编辑学员 -
-
- -
-
{{ course.title }}
-
-
-
- -
-
{{ student.name }}
-
-
- {% if expiry_editable %} -
- -
- -
-
- {% else %} -
- -
-
{{ date('Y-m-d H:i:s',relation.expiry_time) }}
-
-
- {% endif %} -
- -
- - - -
-
- - -{% endblock %} - -{% block inline_js %} - - - -{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/student/learning.volt b/app/Http/Admin/Views/student/learning.volt deleted file mode 100644 index 314ef2c2..00000000 --- a/app/Http/Admin/Views/student/learning.volt +++ /dev/null @@ -1,61 +0,0 @@ -{% extends 'templates/main.volt' %} - -{% block content %} - - {%- macro client_type_info(value) %} - {% if value == 1 %} - desktop - {% elseif value == 2 %} - mobile - {% elseif value == 3 %} - app - {% elseif value == 4 %} - 小程序 - {% endif %} - {%- endmacro %} - - - - - - - - - - - - - - - - - - - {% for item in pager.items %} - {% set duration = item.duration > 0 ? item.duration|duration : 'N/A' %} - {% set active_time = item.active_time > 0 ? date('Y-m-d H:i:s',item.active_time) : 'N/A' %} - - - - - - - {% endfor %} - -
课时信息终端信息学习时长活跃时间
-

课程:{{ item.course.title }}

-

章节:{{ item.chapter.title }}

-
-

类型:{{ client_type_info(item.client_type) }}

-

地址:{{ item.client_ip }}

-
{{ duration }}{{ active_time }}
- - {{ partial('partials/pager') }} - -{% endblock %} - -{% block include_js %} - - {{ js_include('admin/js/ip2region.js') }} - -{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/student/list.volt b/app/Http/Admin/Views/student/list.volt deleted file mode 100644 index 7f3dfd71..00000000 --- a/app/Http/Admin/Views/student/list.volt +++ /dev/null @@ -1,135 +0,0 @@ -{% extends 'templates/main.volt' %} - -{% block content %} - - {%- macro source_type_info(value) %} - {% if value == 1 %} - 免费 - {% elseif value == 2 %} - 付费 - {% elseif value == 3 %} - 畅学 - {% elseif value == 4 %} - 导入 - {% elseif value == 5 %} - 积分 - {% elseif value == 6 %} - 抽奖 - {% endif %} - {%- endmacro %} - - {% if course %} - {% set add_url = url({'for':'admin.student.add'},{'course_id':course.id}) %} - {% set search_url = url({'for':'admin.student.search'},{'course_id':course.id}) %} - {% else %} - {% set add_url = url({'for':'admin.student.add'}) %} - {% set search_url = url({'for':'admin.student.search'}) %} - {% endif %} - -
-
- - 返回 - {% if course %} - {{ course.title }} - {% endif %} - 学员管理 - -
- -
- - - - - - - - - - - - - - - - - - - - - - {% for item in pager.items %} - {% set learning_url = url({'for':'admin.student.learning'},{'course_id':item.course_id,'user_id':item.user_id,'plan_id':item.plan_id}) %} - {% set course_url = url({'for':'home.course.show','id':item.course.id}) %} - {% set user_url = url({'for':'home.user.show','id':item.user_id}) %} - {% set edit_url = url({'for':'admin.student.edit'},{'relation_id':item.id}) %} - - - - - - - - - {% endfor %} - -
基本信息学习情况来源类型加入日期有效期限操作
-

课程:{{ item.course.title }}({{ item.course.id }})

-

学员:{{ item.user.name }}({{ item.user.id }})

-
-

进度:{{ item.progress }}%

-

时长:{{ item.duration|duration }}

-
{{ source_type_info(item.source_type) }}{{ date('Y-m-d',item.create_time) }} - {% if item.source_type in [1,3] %} - N/A - {% else %} -

开始:{{ date('Y-m-d',item.create_time) }}

-

结束:{{ date('Y-m-d',item.expiry_time) }}

- {% endif %} -
-
- - -
-
- - {{ partial('partials/pager') }} - -{% endblock %} - -{% block inline_js %} - - - -{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/student/search.volt b/app/Http/Admin/Views/student/search.volt deleted file mode 100644 index 66213406..00000000 --- a/app/Http/Admin/Views/student/search.volt +++ /dev/null @@ -1,63 +0,0 @@ -{% extends 'templates/main.volt' %} - -{% block content %} - -
-
- 搜索学员 -
-
- -
-
-
-
-
- -
- -
-
-
- -
- {% for value,title in source_types %} - - {% endfor %} -
-
-
- -
- - -
-
-
- -{% endblock %} - -{% block include_js %} - - {{ js_include('lib/xm-select.js') }} - -{% endblock %} - -{% block inline_js %} - - - -{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/tag/add.volt b/app/Http/Admin/Views/tag/add.volt index b2d30288..9b81ad04 100644 --- a/app/Http/Admin/Views/tag/add.volt +++ b/app/Http/Admin/Views/tag/add.volt @@ -15,7 +15,7 @@
- +
diff --git a/app/Http/Admin/Views/tag/edit.volt b/app/Http/Admin/Views/tag/edit.volt index d7a190c0..c6b4814f 100644 --- a/app/Http/Admin/Views/tag/edit.volt +++ b/app/Http/Admin/Views/tag/edit.volt @@ -49,7 +49,7 @@
- +
diff --git a/app/Http/Admin/Views/tag/list.volt b/app/Http/Admin/Views/tag/list.volt index 4ca7498e..e13c8f4e 100644 --- a/app/Http/Admin/Views/tag/list.volt +++ b/app/Http/Admin/Views/tag/list.volt @@ -21,7 +21,7 @@
- +
@@ -30,7 +30,6 @@ - @@ -38,7 +37,6 @@ - @@ -56,12 +54,11 @@ - - +
编号 图标 名称关注 课程 文章 问题{{ item.id }} {{ item.name }} {{ item.name }}{{ item.follow_count }} {{ item.course_count }} {{ item.article_count }} {{ item.question_count }} -
diff --git a/app/Http/Admin/Views/tag/search.volt b/app/Http/Admin/Views/tag/search.volt index c82bc7b0..70bb8ebe 100644 --- a/app/Http/Admin/Views/tag/search.volt +++ b/app/Http/Admin/Views/tag/search.volt @@ -7,17 +7,27 @@ 搜索标签
- +
- +
+
+ +
+ +
+
-
+
+ +
+
@@ -41,4 +51,24 @@
+{% endblock %} + +{% block inline_js %} + + + {% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/topic/add.volt b/app/Http/Admin/Views/topic/add.volt index 573ba53a..f57b584d 100644 --- a/app/Http/Admin/Views/topic/add.volt +++ b/app/Http/Admin/Views/topic/add.volt @@ -15,7 +15,7 @@
- +
diff --git a/app/Http/Admin/Views/topic/edit.volt b/app/Http/Admin/Views/topic/edit.volt index a450e8ee..cd1bfdd7 100644 --- a/app/Http/Admin/Views/topic/edit.volt +++ b/app/Http/Admin/Views/topic/edit.volt @@ -2,7 +2,7 @@ {% block content %} - {% set action_url = url({'for':'admin.topic.update','id':topic.id}) %} + {% set update_url = url({'for':'admin.topic.update','id':topic.id}) %}
编辑专题 diff --git a/app/Http/Admin/Views/topic/edit_basic.volt b/app/Http/Admin/Views/topic/edit_basic.volt index 31285bae..f959bd9a 100644 --- a/app/Http/Admin/Views/topic/edit_basic.volt +++ b/app/Http/Admin/Views/topic/edit_basic.volt @@ -1,10 +1,4 @@ -
-
- -
- -
-
+
@@ -15,6 +9,12 @@
+
+ +
+ +
+
@@ -31,7 +31,7 @@
- +
diff --git a/app/Http/Admin/Views/topic/edit_course.volt b/app/Http/Admin/Views/topic/edit_course.volt index 19443fde..f1262ae4 100644 --- a/app/Http/Admin/Views/topic/edit_course.volt +++ b/app/Http/Admin/Views/topic/edit_course.volt @@ -1,4 +1,4 @@ - +
@@ -8,7 +8,7 @@
- +
diff --git a/app/Http/Admin/Views/topic/list.volt b/app/Http/Admin/Views/topic/list.volt index 1e49e4f9..3d60758b 100644 --- a/app/Http/Admin/Views/topic/list.volt +++ b/app/Http/Admin/Views/topic/list.volt @@ -21,23 +21,19 @@
- +
- - - - - + @@ -50,12 +46,11 @@ {% set delete_url = url({'for':'admin.topic.delete','id':item.id}) %} {% set restore_url = url({'for':'admin.topic.restore','id':item.id}) %} - - + - - - + + - - + + @@ -44,16 +44,16 @@ {% for item in pager.items %} {% set show_url = url({'for':'admin.trade.show','id':item.id}) %} - - + +
编号 标题 课程数创建时间更新时间创建 发布 操作
{{ item.id }}{{ item.title }}{{ item.title }}({{ item.id }}) {{ item.course_count }}{{ date('Y-m-d H:i:s',item.create_time) }}{{ date('Y-m-d H:i:s',item.update_time) }}{{ date('Y-m-d',item.create_time) }}
diff --git a/app/Http/Admin/Views/topic/search.volt b/app/Http/Admin/Views/topic/search.volt index 96577795..3d1a4fc0 100644 --- a/app/Http/Admin/Views/topic/search.volt +++ b/app/Http/Admin/Views/topic/search.volt @@ -7,17 +7,27 @@ 搜索专题
- +
- +
+
+ +
+ +
+
-
+
+ +
+
@@ -41,4 +51,24 @@
+{% endblock %} + +{% block inline_js %} + + + {% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/trade/list.volt b/app/Http/Admin/Views/trade/list.volt index a8177d81..d3a35689 100644 --- a/app/Http/Admin/Views/trade/list.volt +++ b/app/Http/Admin/Views/trade/list.volt @@ -31,10 +31,10 @@
商品信息 买家信息交易金额商品信息 交易平台交易金额 交易状态 创建时间 操作
-

商品:{{ item.order.subject }}

-

单号:{{ item.order.sn }}

-

昵称:{{ item.owner.name }}

编号:{{ item.owner.id }}

{{ '¥%0.2f'|format(item.amount) }} +

商品:{{ item.order.subject }}

+

单号:{{ item.order.sn }}

+
{{ channel_type(item.channel) }}{{ '¥%0.2f'|format(item.amount) }} {{ trade_status(item.status) }} {{ date('Y-m-d H:i:s',item.create_time) }} diff --git a/app/Http/Admin/Views/trade/search.volt b/app/Http/Admin/Views/trade/search.volt index d8bc32f2..dfd0f483 100644 --- a/app/Http/Admin/Views/trade/search.volt +++ b/app/Http/Admin/Views/trade/search.volt @@ -13,16 +13,26 @@
- +
- + +
+
+
+ +
+ +
+
-
+
+
{% for value,title in channel_types %} - + {% endfor %}
@@ -30,20 +40,10 @@
{% for value,title in status_types %} - + {% endfor %}
-
- -
- -
-
-
-
- -
-
@@ -59,16 +59,14 @@ + {% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/vip/add.volt b/app/Http/Admin/Views/vip/add.volt new file mode 100644 index 00000000..9e8d9583 --- /dev/null +++ b/app/Http/Admin/Views/vip/add.volt @@ -0,0 +1,35 @@ +{% extends 'templates/main.volt' %} + +{% block content %} + +
+
+ 添加套餐 +
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + +
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/vip/edit.volt b/app/Http/Admin/Views/vip/edit.volt new file mode 100644 index 00000000..b60be3e4 --- /dev/null +++ b/app/Http/Admin/Views/vip/edit.volt @@ -0,0 +1,43 @@ +{% extends 'templates/main.volt' %} + +{% block content %} + +
+
+ 编辑套餐 +
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/app/Http/Admin/Views/flash_sale/list.volt b/app/Http/Admin/Views/vip/list.volt similarity index 52% rename from app/Http/Admin/Views/flash_sale/list.volt rename to app/Http/Admin/Views/vip/list.volt index 9960be4c..36ea6781 100644 --- a/app/Http/Admin/Views/flash_sale/list.volt +++ b/app/Http/Admin/Views/vip/list.volt @@ -2,64 +2,54 @@ {% block content %} - {{ partial('macros/flash_sale') }} - - {% set add_url = url({'for':'admin.flash_sale.add'}) %} - {% set search_url = url({'for':'admin.flash_sale.search'}) %} + {% set add_url = url({'for':'admin.vip.add'}) %} - - +
+ - - + - - - - - + + + + {% for item in pager.items %} - {% set edit_url = url({'for':'admin.flash_sale.edit','id':item.id}) %} - {% set update_url = url({'for':'admin.flash_sale.update','id':item.id}) %} - {% set delete_url = url({'for':'admin.flash_sale.delete','id':item.id}) %} - {% set restore_url = url({'for':'admin.flash_sale.restore','id':item.id}) %} + {% set edit_url = url({'for':'admin.vip.edit','id':item.id}) %} + {% set update_url = url({'for':'admin.vip.update','id':item.id}) %} + {% set delete_url = url({'for':'admin.vip.delete','id':item.id}) %} + {% set restore_url = url({'for':'admin.vip.restore','id':item.id}) %} - + + + - - - - + + + {% if resource.me.owned == 1 %} + + {% else %} + + {% endif %} + + {% endfor %} +
商品信息秒杀价格秒杀库存秒杀时间参与场次编号套餐名称套餐期限(月)套餐价格 发布 操作
{{ item_full_info(item.item_type,item.item_info) }}{{ item.id }}{{ item.title }}{{ item.expiry }} {{ '¥%0.2f'|format(item.price) }}{{ item.stock }} -

开始:{{ date('Y-m-d H:i:s',item.start_time) }}

-

结束:{{ date('Y-m-d H:i:s',item.end_time) }}

+
{{ schedules_info(item.schedules) }}
diff --git a/app/Http/Api/Controllers/ArticleController.php b/app/Http/Api/Controllers/ArticleController.php index c61ac491..af7b9d74 100644 --- a/app/Http/Api/Controllers/ArticleController.php +++ b/app/Http/Api/Controllers/ArticleController.php @@ -14,7 +14,6 @@ use App\Services\Logic\Article\ArticleFavorite as ArticleFavoriteService; use App\Services\Logic\Article\ArticleInfo as ArticleInfoService; use App\Services\Logic\Article\ArticleLike as ArticleLikeService; use App\Services\Logic\Article\ArticleList as ArticleListService; -use App\Services\Logic\Article\ArticlePrivate as ArticlePrivateService; use App\Services\Logic\Article\CategoryList as CategoryListService; use App\Services\Logic\Article\CommentList as CommentListService; @@ -63,16 +62,11 @@ class ArticleController extends Controller $approved = $article['published'] == ArticleModel::PUBLISH_APPROVED; $owned = $article['me']['owned'] == 1; - $private = $article['private'] == 1; if (!$approved && !$owned) { $this->notFound(); } - if ($private && !$owned) { - $this->forbidden(); - } - return $this->jsonSuccess(['article' => $article]); } @@ -114,20 +108,6 @@ class ArticleController extends Controller return $this->jsonSuccess(['msg' => $msg]); } - /** - * @Post("/{id:[0-9]+}/private", name="home.article.private") - */ - public function privateAction($id) - { - $service = new ArticlePrivateService(); - - $article = $service->handle($id); - - $msg = $article->private == 1 ? '开启仅我可见成功' : '关闭仅我可见成功'; - - return $this->jsonSuccess(['msg' => $msg]); - } - /** * @Post("/{id:[0-9]+}/favorite", name="api.article.favorite") */ diff --git a/app/Http/Api/Controllers/FlashSaleController.php b/app/Http/Api/Controllers/FlashSaleController.php deleted file mode 100644 index b6b7f46d..00000000 --- a/app/Http/Api/Controllers/FlashSaleController.php +++ /dev/null @@ -1,48 +0,0 @@ -handle(); - - return $this->jsonSuccess(['sales' => $sales]); - } - - /** - * @Post("/order", name="api.flash_sale.order") - */ - public function orderAction() - { - $service = new OrderCreateService(); - - $order = $service->handle(); - - $service = new OrderInfoService(); - - $order = $service->handle($order->sn); - - return $this->jsonSuccess(['order' => $order]); - } - -} diff --git a/app/Http/Api/Controllers/IndexController.php b/app/Http/Api/Controllers/IndexController.php index d6efa30c..b288df8c 100644 --- a/app/Http/Api/Controllers/IndexController.php +++ b/app/Http/Api/Controllers/IndexController.php @@ -84,18 +84,6 @@ class IndexController extends Controller return $this->jsonSuccess(['teachers' => $teachers]); } - /** - * @Get("/flash/sales", name="api.index.flash_sales") - */ - public function flashSalesAction() - { - $cache = new IndexFlashSaleList(); - - $sales = $cache->get(); - - return $this->jsonSuccess(['sales' => $sales]); - } - /** * @Get("/courses/featured", name="api.index.featured_courses") */ diff --git a/app/Http/Home/Controllers/ArticleController.php b/app/Http/Home/Controllers/ArticleController.php index e22dc7fa..f6effe5a 100644 --- a/app/Http/Home/Controllers/ArticleController.php +++ b/app/Http/Home/Controllers/ArticleController.php @@ -18,7 +18,6 @@ use App\Services\Logic\Article\ArticleFavorite as ArticleFavoriteService; use App\Services\Logic\Article\ArticleInfo as ArticleInfoService; use App\Services\Logic\Article\ArticleLike as ArticleLikeService; use App\Services\Logic\Article\ArticleList as ArticleListService; -use App\Services\Logic\Article\ArticlePrivate as ArticlePrivateService; use App\Services\Logic\Article\ArticleUpdate as ArticleUpdateService; use App\Services\Logic\Article\RelatedArticleList as RelatedArticleListService; use Phalcon\Mvc\View; @@ -43,11 +42,15 @@ class ArticleController extends Controller $service = new ArticleQueryService(); + $topCategories = $service->handleTopCategories(); + $subCategories = $service->handleSubCategories(); $sorts = $service->handleSorts(); $params = $service->getParams(); $this->seo->prependTitle('专栏'); + $this->view->setVar('top_categories', $topCategories); + $this->view->setVar('sub_categories', $subCategories); $this->view->setVar('sorts', $sorts); $this->view->setVar('params', $params); } @@ -74,16 +77,18 @@ class ArticleController extends Controller { $service = new ArticleService(); - $sourceTypes = $service->getSourceTypes(); $article = $service->getArticleModel(); + $categoryOptions = $service->getCategoryOptions(); + $sourceTypes = $service->getSourceTypes(); $xmTags = $service->getXmTags(0); $this->seo->prependTitle('撰写文章'); $this->view->pick('article/edit'); + $this->view->setVar('article', $article); + $this->view->setVar('category_options', $categoryOptions); $this->view->setVar('source_types', $sourceTypes); $this->view->setVar('xm_tags', $xmTags); - $this->view->setVar('article', $article); } /** @@ -93,14 +98,16 @@ class ArticleController extends Controller { $service = new ArticleService(); + $categoryOptions = $service->getCategoryOptions(); $sourceTypes = $service->getSourceTypes(); $article = $service->getArticle($id); $xmTags = $service->getXmTags($id); $this->seo->prependTitle('编辑文章'); - $this->view->setVar('source_types', $sourceTypes); $this->view->setVar('article', $article); + $this->view->setVar('category_options', $categoryOptions); + $this->view->setVar('source_types', $sourceTypes); $this->view->setVar('xm_tags', $xmTags); } @@ -126,16 +133,11 @@ class ArticleController extends Controller $approved = $article['published'] == ArticleModel::PUBLISH_APPROVED; $owned = $article['me']['owned'] == 1; - $private = $article['private'] == 1; if (!$approved && !$owned) { $this->notFound(); } - if ($private && !$owned) { - $this->forbidden(); - } - $this->seo->prependTitle(['专栏', $article['title']]); $this->seo->setDescription($article['summary']); @@ -238,20 +240,6 @@ class ArticleController extends Controller return $this->jsonSuccess(['msg' => $msg]); } - /** - * @Post("/{id:[0-9]+}/private", name="home.article.private") - */ - public function privateAction($id) - { - $service = new ArticlePrivateService(); - - $article = $service->handle($id); - - $msg = $article->private == 1 ? '开启仅我可见成功' : '关闭仅我可见成功'; - - return $this->jsonSuccess(['msg' => $msg]); - } - /** * @Post("/{id:[0-9]+}/favorite", name="home.article.favorite") */ diff --git a/app/Http/Home/Controllers/CourseController.php b/app/Http/Home/Controllers/CourseController.php index 6047b3e9..b80acb00 100644 --- a/app/Http/Home/Controllers/CourseController.php +++ b/app/Http/Home/Controllers/CourseController.php @@ -15,7 +15,6 @@ use App\Services\Logic\Course\CourseFavorite as CourseFavoriteService; use App\Services\Logic\Course\CourseInfo as CourseInfoService; use App\Services\Logic\Course\CourseList as CourseListService; use App\Services\Logic\Course\PackageList as CoursePackageListService; -use App\Services\Logic\Course\RecommendedList as CourseRecommendedListService; use App\Services\Logic\Course\RelatedList as CourseRelatedListService; use App\Services\Logic\Course\ResourceList as CourseResourceListService; use App\Services\Logic\Course\ReviewList as CourseReviewListService; @@ -168,23 +167,10 @@ class CourseController extends Controller { $service = new CourseResourceListService(); - $items = $service->handle($id); + $resources = $service->handle($id); $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW); - $this->view->setVar('items', $items); - } - - /** - * @Get("/{id:[0-9]+}/recommended", name="home.course.recommended") - */ - public function recommendedAction($id) - { - $service = new CourseRecommendedListService(); - - $courses = $service->handle($id); - - $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW); - $this->view->setVar('courses', $courses); + $this->view->setVar('resources', $resources); } /** diff --git a/app/Http/Home/Controllers/DanmuController.php b/app/Http/Home/Controllers/DanmuController.php deleted file mode 100644 index 16e3a0e9..00000000 --- a/app/Http/Home/Controllers/DanmuController.php +++ /dev/null @@ -1,35 +0,0 @@ -handle(); - - $service = new DanmuInfoService(); - - $danmu = $service->handle($danmu->id); - - return $this->jsonSuccess(['danmu' => $danmu]); - } - -} diff --git a/app/Http/Home/Controllers/FlashSaleController.php b/app/Http/Home/Controllers/FlashSaleController.php deleted file mode 100644 index d5d26620..00000000 --- a/app/Http/Home/Controllers/FlashSaleController.php +++ /dev/null @@ -1,63 +0,0 @@ -authUser->id == 0) { - $this->response->redirect(['for' => 'home.account.login']); - return false; - } - - return true; - } - - /** - * @Get("/", name="home.flash_sale.index") - */ - public function indexAction() - { - $this->seo->prependTitle('秒杀'); - - $service = new SaleListService(); - - $sales = $service->handle(); - - $this->view->setVar('sales', $sales); - } - - /** - * @Post("/order", name="home.flash_sale.order") - */ - public function orderAction() - { - $service = new OrderCreateService(); - - $order = $service->handle(); - - $location = $this->url->get( - ['for' => 'home.order.pay'], - ['sn' => $order->sn] - ); - - return $this->jsonSuccess(['location' => $location]); - } - -} diff --git a/app/Http/Home/Controllers/QuestionController.php b/app/Http/Home/Controllers/QuestionController.php index a9f8526a..eeb603e4 100644 --- a/app/Http/Home/Controllers/QuestionController.php +++ b/app/Http/Home/Controllers/QuestionController.php @@ -42,11 +42,15 @@ class QuestionController extends Controller $service = new QuestionQueryService(); + $topCategories = $service->handleTopCategories(); + $subCategories = $service->handleSubCategories(); $sorts = $service->handleSorts(); $params = $service->getParams(); $this->seo->prependTitle('问答'); + $this->view->setVar('top_categories', $topCategories); + $this->view->setVar('sub_categories', $subCategories); $this->view->setVar('sorts', $sorts); $this->view->setVar('params', $params); } @@ -74,13 +78,14 @@ class QuestionController extends Controller $service = new QuestionService(); $question = $service->getQuestionModel(); - + $categoryOptions = $service->getCategoryOptions(); $xmTags = $service->getXmTags(0); $this->seo->prependTitle('提问'); $this->view->pick('question/edit'); $this->view->setVar('question', $question); + $this->view->setVar('category_options', $categoryOptions); $this->view->setVar('xm_tags', $xmTags); } @@ -92,12 +97,13 @@ class QuestionController extends Controller $service = new QuestionService(); $question = $service->getQuestion($id); - + $categoryOptions = $service->getCategoryOptions(); $xmTags = $service->getXmTags($id); $this->seo->prependTitle('编辑问题'); $this->view->setVar('question', $question); + $this->view->setVar('category_options', $categoryOptions); $this->view->setVar('xm_tags', $xmTags); } diff --git a/app/Http/Home/Controllers/TeacherController.php b/app/Http/Home/Controllers/TeacherController.php index 5260f285..6dfc10c6 100644 --- a/app/Http/Home/Controllers/TeacherController.php +++ b/app/Http/Home/Controllers/TeacherController.php @@ -8,7 +8,9 @@ namespace App\Http\Home\Controllers; use App\Http\Home\Services\FullH5Url as FullH5UrlService; +use App\Services\Logic\Teacher\CourseList as TeacherCourseListService; use App\Services\Logic\Teacher\TeacherList as TeacherListService; +use App\Services\Logic\User\UserInfo as UserInfoService; use Phalcon\Mvc\View; /** @@ -59,11 +61,34 @@ class TeacherController extends Controller return $this->response->redirect($location); } - $this->dispatcher->forward([ - 'controller' => 'user', - 'action' => 'show', - 'params' => ['id' => $id], - ]); + $service = new UserInfoService(); + + $user = $service->handle($id); + + if ($user['deleted'] == 1) { + $this->notFound(); + } + + $this->seo->prependTitle(['讲师', $user['name']]); + + $this->view->setVar('user', $user); + } + + /** + * @Get("/{id:[0-9]+}/courses", name="home.teacher.courses") + */ + public function coursesAction($id) + { + $model = $this->request->getQuery('model', 'trim', 'vod'); + + $service = new TeacherCourseListService(); + + $pager = $service->handle($id); + + $pager->target = "tab-{$model}"; + + $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW); + $this->view->setVar('pager', $pager); } } diff --git a/app/Http/Home/Controllers/UserController.php b/app/Http/Home/Controllers/UserController.php index 7e141f01..a1bb9b61 100644 --- a/app/Http/Home/Controllers/UserController.php +++ b/app/Http/Home/Controllers/UserController.php @@ -11,8 +11,6 @@ use App\Http\Home\Services\FullH5Url as FullH5UrlService; 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; @@ -112,36 +110,4 @@ class UserController extends Controller $this->view->setVar('pager', $pager); } - /** - * @Get("/{id:[0-9]+}/friends", name="home.user.friends") - */ - public function friendsAction($id) - { - $service = new UserFriendListService(); - - $pager = $service->handle($id); - - $pager->target = 'tab-friends'; - - $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW); - $this->view->pick('user/friends'); - $this->view->setVar('pager', $pager); - } - - /** - * @Get("/{id:[0-9]+}/groups", name="home.user.groups") - */ - public function groupsAction($id) - { - $service = new UserGroupListService(); - - $pager = $service->handle($id); - - $pager->target = 'tab-groups'; - - $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW); - $this->view->pick('user/groups'); - $this->view->setVar('pager', $pager); - } - } diff --git a/app/Http/Home/Controllers/WidgetController.php b/app/Http/Home/Controllers/WidgetController.php index 1d558745..f7dd3843 100644 --- a/app/Http/Home/Controllers/WidgetController.php +++ b/app/Http/Home/Controllers/WidgetController.php @@ -9,6 +9,7 @@ namespace App\Http\Home\Controllers; use App\Caches\FeaturedArticleList as FeaturedArticleListCache; use App\Caches\FeaturedCourseList as FeaturedCourseListCache; +use App\Caches\FeaturedQuestionList as FeaturedQuestionListCache; use App\Services\Logic\Article\TopAuthorList as TopAuthorListService; use App\Services\Logic\Question\HotQuestionList as HotQuestionListService; use App\Services\Logic\Question\TopAnswererList as TopAnswererListService; @@ -63,6 +64,20 @@ class WidgetController extends Controller $this->view->setVar('articles', $articles); } + /** + * @Get("/featured/questions", name="home.widget.featured_questions") + */ + public function featuredQuestionsAction() + { + $cache = new FeaturedQuestionListCache(); + + $questions = $cache->get(); + + $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW); + $this->view->pick('widget/featured_questions'); + $this->view->setVar('questions', $questions); + } + /** * @Get("/hot/questions", name="home.widget.hot_questions") */ diff --git a/app/Http/Home/Services/Article.php b/app/Http/Home/Services/Article.php index 7264c9d4..496e4f47 100644 --- a/app/Http/Home/Services/Article.php +++ b/app/Http/Home/Services/Article.php @@ -9,8 +9,7 @@ namespace App\Http\Home\Services; 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\Services\Category as CategoryService; use App\Services\Logic\Article\XmTagList as XmTagListService; use App\Services\Logic\ArticleTrait; @@ -35,15 +34,11 @@ class Article extends Service return $service->handle($id); } - public function getCategories() + public function getCategoryOptions() { - $categoryRepo = new CategoryRepo(); + $categoryService = new CategoryService(); - return $categoryRepo->findAll([ - 'type' => CategoryModel::TYPE_ARTICLE, - 'level' => 1, - 'published' => 1, - ]); + return $categoryService->getCategoryOptions(CategoryModel::TYPE_ARTICLE); } public function getSourceTypes() @@ -51,11 +46,6 @@ class Article extends Service return ArticleModel::sourceTypes(); } - public function getReportReasons() - { - return ReasonModel::reportOptions(); - } - public function getArticle($id) { return $this->checkArticle($id); diff --git a/app/Http/Home/Services/ArticleQuery.php b/app/Http/Home/Services/ArticleQuery.php index 2ae41942..fe898d92 100644 --- a/app/Http/Home/Services/ArticleQuery.php +++ b/app/Http/Home/Services/ArticleQuery.php @@ -22,12 +22,16 @@ class ArticleQuery extends Service $this->baseUrl = $this->url->get(['for' => 'home.article.list']); } - public function handleCategories() + public function handleTopCategories() { $params = $this->getParams(); - if (isset($params['category_id'])) { - unset($params['category_id']); + if (isset($params['tc'])) { + unset($params['tc']); + } + + if (isset($params['sc'])) { + unset($params['sc']); } $defaultItem = [ @@ -44,8 +48,50 @@ class ArticleQuery extends Service $topCategories = $categoryService->getChildCategories(CategoryModel::TYPE_ARTICLE, 0); - foreach ($topCategories as $key => $category) { - $params['category_id'] = $category['id']; + foreach ($topCategories as $category) { + $params['tc'] = $category['id']; + $result[] = [ + 'id' => $category['id'], + 'name' => $category['name'], + 'url' => $this->baseUrl . $this->buildParams($params), + ]; + } + + return $result; + } + + public function handleSubCategories() + { + $params = $this->getParams(); + + if (empty($params['tc'])) { + return []; + } + + $categoryService = new CategoryService(); + + $subCategories = $categoryService->getChildCategories(CategoryModel::TYPE_ARTICLE, $params['tc']); + + if (empty($subCategories)) { + return []; + } + + if (isset($params['sc'])) { + unset($params['sc']); + } + + $defaultItem = [ + 'id' => 'all', + 'name' => '全部', + 'url' => $this->baseUrl . $this->buildParams($params), + ]; + + $result = []; + + $result[] = $defaultItem; + + foreach ($subCategories as $category) { + $params['sc'] = $category['id']; $result[] = [ 'id' => $category['id'], 'name' => $category['name'], @@ -84,19 +130,23 @@ class ArticleQuery extends Service $validator = new ArticleQueryValidator(); - if (isset($query['category_id']) && $query['category_id'] != 'all') { - $validator->checkCategory($query['category_id']); - $params['category_id'] = $query['category_id']; + if (isset($query['tag_id'])) { + $tag = $validator->checkTag($query['tag_id']); + $params['tag_id'] = $tag->id; } - if (isset($query['tag_id'])) { - $validator->checkTag($query['tag_id']); - $params['tag_id'] = $query['tag_id']; + if (isset($query['tc']) && $query['tc'] != 'all') { + $category = $validator->checkCategory($query['tc']); + $params['tc'] = $category->id; + } + + if (isset($query['sc']) && $query['sc'] != 'all') { + $category = $validator->checkCategory($query['sc']); + $params['sc'] = $category->id; } if (isset($query['sort'])) { - $validator->checkSort($query['sort']); - $params['sort'] = $query['sort']; + $params['sort'] = $validator->checkSort($query['sort']);; } return $params; diff --git a/app/Http/Home/Services/CourseQuery.php b/app/Http/Home/Services/CourseQuery.php index 11db94bb..6c0d8fe2 100644 --- a/app/Http/Home/Services/CourseQuery.php +++ b/app/Http/Home/Services/CourseQuery.php @@ -7,7 +7,6 @@ namespace App\Http\Home\Services; -use App\Caches\Category as CategoryCache; use App\Models\Category as CategoryModel; use App\Models\Course as CourseModel; use App\Services\Category as CategoryService; @@ -187,32 +186,6 @@ class CourseQuery extends Service return $result; } - public function handleCategoryPaths($categoryId) - { - $result = []; - - $cache = new CategoryCache(); - - $subCategory = $cache->get($categoryId); - $topCategory = $cache->get($subCategory->parent_id); - - $topParams = ['tc' => $topCategory->id]; - - $result['top'] = [ - 'name' => $topCategory->name, - 'url' => $this->baseUrl . $this->buildParams($topParams), - ]; - - $subParams = ['tc' => $topCategory->id, 'sc' => $subCategory->id]; - - $result['sub'] = [ - 'name' => $subCategory->name, - 'url' => $this->baseUrl . $this->buildParams($subParams), - ]; - - return $result; - } - public function getParams() { $query = $this->request->getQuery(); @@ -221,29 +194,31 @@ class CourseQuery extends Service $validator = new CourseQueryValidator(); + if (isset($query['tag_id'])) { + $tag = $validator->checkTag($query['tag_id']); + $params['tag_id'] = $tag->id; + } + if (isset($query['tc']) && $query['tc'] != 'all') { - $validator->checkTopCategory($query['tc']); - $params['tc'] = $query['tc']; + $category = $validator->checkCategory($query['tc']); + $params['tc'] = $category->id; } if (isset($query['sc']) && $query['sc'] != 'all') { - $validator->checkSubCategory($query['sc']); - $params['sc'] = $query['sc']; + $category = $validator->checkCategory($query['sc']); + $params['sc'] = $category->id; } if (isset($query['model']) && $query['model'] != 'all') { - $validator->checkModel($query['model']); - $params['model'] = $query['model']; + $params['model'] = $validator->checkModel($query['model']); } if (isset($query['level']) && $query['level'] != 'all') { - $validator->checkLevel($query['level']); - $params['level'] = $query['level']; + $params['level'] = $validator->checkLevel($query['level']); } if (isset($query['sort'])) { - $validator->checkSort($query['sort']); - $params['sort'] = $query['sort']; + $params['sort'] = $validator->checkSort($query['sort']); } return $params; diff --git a/app/Http/Home/Services/Question.php b/app/Http/Home/Services/Question.php index 3e541ac0..bfcdea34 100644 --- a/app/Http/Home/Services/Question.php +++ b/app/Http/Home/Services/Question.php @@ -9,7 +9,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\Services\Category as CategoryService; use App\Services\Logic\Question\XmTagList as XmTagListService; use App\Services\Logic\QuestionTrait; use App\Services\Logic\Service as LogicService; @@ -28,15 +28,11 @@ class Question extends LogicService return $question; } - public function getCategories() + public function getCategoryOptions() { - $categoryRepo = new CategoryRepo(); + $categoryService = new CategoryService(); - return $categoryRepo->findAll([ - 'type' => CategoryModel::TYPE_ARTICLE, - 'level' => 1, - 'published' => 1, - ]); + return $categoryService->getCategoryOptions(CategoryModel::TYPE_QUESTION); } public function getXmTags($id) diff --git a/app/Http/Home/Services/QuestionQuery.php b/app/Http/Home/Services/QuestionQuery.php index d4b99971..4a71dad1 100644 --- a/app/Http/Home/Services/QuestionQuery.php +++ b/app/Http/Home/Services/QuestionQuery.php @@ -22,12 +22,16 @@ class QuestionQuery extends Service $this->baseUrl = $this->url->get(['for' => 'home.question.list']); } - public function handleCategories() + public function handleTopCategories() { $params = $this->getParams(); - if (isset($params['category_id'])) { - unset($params['category_id']); + if (isset($params['tc'])) { + unset($params['tc']); + } + + if (isset($params['sc'])) { + unset($params['sc']); } $defaultItem = [ @@ -44,8 +48,50 @@ class QuestionQuery extends Service $topCategories = $categoryService->getChildCategories(CategoryModel::TYPE_QUESTION, 0); - foreach ($topCategories as $key => $category) { - $params['category_id'] = $category['id']; + foreach ($topCategories as $category) { + $params['tc'] = $category['id']; + $result[] = [ + 'id' => $category['id'], + 'name' => $category['name'], + 'url' => $this->baseUrl . $this->buildParams($params), + ]; + } + + return $result; + } + + public function handleSubCategories() + { + $params = $this->getParams(); + + if (empty($params['tc'])) { + return []; + } + + $categoryService = new CategoryService(); + + $subCategories = $categoryService->getChildCategories(CategoryModel::TYPE_QUESTION, $params['tc']); + + if (empty($subCategories)) { + return []; + } + + if (isset($params['sc'])) { + unset($params['sc']); + } + + $defaultItem = [ + 'id' => 'all', + 'name' => '全部', + 'url' => $this->baseUrl . $this->buildParams($params), + ]; + + $result = []; + + $result[] = $defaultItem; + + foreach ($subCategories as $category) { + $params['sc'] = $category['id']; $result[] = [ 'id' => $category['id'], 'name' => $category['name'], @@ -84,19 +130,23 @@ class QuestionQuery extends Service $validator = new QuestionQueryValidator(); - if (isset($query['category_id']) && $query['category_id'] != 'all') { - $validator->checkCategory($query['category_id']); - $params['category_id'] = $query['category_id']; + if (isset($query['tag_id'])) { + $tag = $validator->checkTag($query['tag_id']); + $params['tag_id'] = $tag->id; } - if (isset($query['tag_id'])) { - $validator->checkTag($query['tag_id']); - $params['tag_id'] = $query['tag_id']; + if (isset($query['tc']) && $query['tc'] != 'all') { + $category = $validator->checkCategory($query['tc']); + $params['tc'] = $category->id; + } + + if (isset($query['sc']) && $query['sc'] != 'all') { + $category = $validator->checkCategory($query['sc']); + $params['sc'] = $category->id; } if (isset($query['sort'])) { - $validator->checkSort($query['sort']); - $params['sort'] = $query['sort']; + $params['sort'] = $validator->checkSort($query['sort']);; } return $params; diff --git a/app/Http/Home/Views/article/edit.volt b/app/Http/Home/Views/article/edit.volt index 911072bb..3049e516 100644 --- a/app/Http/Home/Views/article/edit.volt +++ b/app/Http/Home/Views/article/edit.volt @@ -2,7 +2,7 @@ {% block content %} - {% set title = article.id > 0 ? '编辑文章' : '撰写文章' %} + {% set title = article.id > 0 ? '编辑文章' : '发布文章' %} {% set action_url = article.id > 0 ? url({'for':'home.article.update','id':article.id}) : url({'for':'home.article.create'}) %} {% set source_url_display = article.source_type == 1 ? 'display:none;' : 'display:block;' %} @@ -28,12 +28,28 @@
-
- -
-
+ {% if category_options|length > 0 %} +
+ +
+ +
-
+ {% endif %} + {% if xm_tags|length > 0 %} +
+ +
+
+
+
+ {% endif %}
diff --git a/app/Http/Home/Views/article/list.volt b/app/Http/Home/Views/article/list.volt index 11fe75e8..16a1859e 100644 --- a/app/Http/Home/Views/article/list.volt +++ b/app/Http/Home/Views/article/list.volt @@ -2,17 +2,14 @@ {% block content %} - {% set sort_val = request.get('sort','trim','latest') %} + {% if top_categories|length > 1 %} + {{ partial('article/list_filter') }} + {% endif %} + + {% set post_url = url({'for':'home.article.add'}) %} {% set pager_url = url({'for':'home.article.pager'}, params) %} {% set top_authors_url = url({'for':'home.widget.top_authors'},{'limit':5}) %} - {% set my_tags_url = url({'for':'home.widget.my_tags'},{'type':'article'}) %} - - + {% set sort_val = request.get('sort','trim','latest') %}
@@ -33,9 +30,9 @@
- {% if auth_user.id > 0 %} - - {% endif %} +
@@ -44,6 +41,7 @@ {% block include_js %} + {{ js_include('home/js/list.filter.js') }} {{ js_include('home/js/article.list.js') }} {% endblock %} \ No newline at end of file diff --git a/app/Http/Home/Views/article/list_filter.volt b/app/Http/Home/Views/article/list_filter.volt new file mode 100644 index 00000000..c38d092c --- /dev/null +++ b/app/Http/Home/Views/article/list_filter.volt @@ -0,0 +1,32 @@ +{% set tc_val = request.get('tc','int','all') %} +{% set sc_val = request.get('sc','int','all') %} +{% set sort_val = request.get('sort','trim','latest') %} + +
+ +
+ +
+ {% if top_categories %} +
+
方向
+
+ {% for category in top_categories %} + {% set class = tc_val == category.id ? 'layui-btn layui-btn-xs' : 'none' %} + {{ category.name }} + {% endfor %} +
+
+ {% endif %} + {% if sub_categories %} +
+
分类
+
+ {% for category in sub_categories %} + {% set class = sc_val == category.id ? 'layui-btn layui-btn-xs' : 'none' %} + {{ category.name }} + {% endfor %} +
+
+ {% endif %} +
diff --git a/app/Http/Home/Views/article/show.volt b/app/Http/Home/Views/article/show.volt index 98dbb75c..6f128ead 100644 --- a/app/Http/Home/Views/article/show.volt +++ b/app/Http/Home/Views/article/show.volt @@ -8,7 +8,6 @@ {% set qrcode_url = url({'for':'home.qrcode'},{'text':share_url}) %} {% set article_edit_url = url({'for':'home.article.edit','id':article.id}) %} {% set article_delete_url = url({'for':'home.article.delete','id':article.id}) %} - {% set article_private_url = url({'for':'home.article.private','id':article.id}) %} {% set article_close_url = url({'for':'home.article.close','id':article.id}) %} {% set article_owner_url = url({'for':'home.user.show','id':article.owner.id}) %} {% set article_related_url = url({'for':'home.article.related','id':article.id}) %} @@ -21,9 +20,10 @@ 详情
@@ -44,17 +44,12 @@
举报 - {% if auth_user.id == article.owner.id %} + {% if article.me.owned == 1 %} {% if article.closed == 0 %} 关闭 {% else %} 打开 {% endif %} - {% if article.private == 0 %} - 私密 - {% else %} - 共享 - {% endif %} 编辑 删除 {% endif %} @@ -121,8 +116,10 @@ {% block include_js %} + {{ js_include('lib/clipboard.min.js') }} {{ js_include('home/js/article.show.js') }} {{ js_include('home/js/article.share.js') }} {{ js_include('home/js/comment.js') }} + {{ js_include('home/js/copy.js') }} {% endblock %} \ No newline at end of file diff --git a/app/Http/Home/Views/chapter/live/active.volt b/app/Http/Home/Views/chapter/live/active.volt index 6e7b6d35..393d7e69 100644 --- a/app/Http/Home/Views/chapter/live/active.volt +++ b/app/Http/Home/Views/chapter/live/active.volt @@ -53,9 +53,9 @@
- +
@@ -71,11 +71,13 @@ {% block include_js %} + {{ js_include('lib/clipboard.min.js') }} {{ js_include('lib/dplayer/flv.min.js') }} {{ js_include('lib/dplayer/DPlayer.min.js') }} {{ js_include('home/js/chapter.live.player.js') }} {{ js_include('home/js/chapter.live.chat.js') }} {{ js_include('home/js/chapter.show.js') }} {{ js_include('home/js/course.share.js') }} + {{ js_include('home/js/copy.js') }} {% endblock %} \ No newline at end of file diff --git a/app/Http/Home/Views/chapter/read.volt b/app/Http/Home/Views/chapter/read.volt index 9624486a..b2380bbe 100644 --- a/app/Http/Home/Views/chapter/read.volt +++ b/app/Http/Home/Views/chapter/read.volt @@ -12,9 +12,10 @@ 返回课程
@@ -42,8 +43,8 @@
- +
@@ -63,9 +64,11 @@ {% block include_js %} + {{ js_include('lib/clipboard.min.js') }} {{ js_include('home/js/course.share.js') }} {{ js_include('home/js/chapter.read.js') }} {{ js_include('home/js/chapter.show.js') }} {{ js_include('home/js/comment.js') }} + {{ js_include('home/js/copy.js') }} {% endblock %} \ No newline at end of file diff --git a/app/Http/Home/Views/chapter/vod.volt b/app/Http/Home/Views/chapter/vod.volt index 0226cd4d..2bdde288 100644 --- a/app/Http/Home/Views/chapter/vod.volt +++ b/app/Http/Home/Views/chapter/vod.volt @@ -13,9 +13,10 @@ {{ chapter.title }}
@@ -43,10 +44,11 @@
- - + + +
@@ -60,11 +62,13 @@ {% block include_js %} + {{ js_include('lib/clipboard.min.js') }} {{ js_include('lib/dplayer/hls.min.js') }} {{ js_include('lib/dplayer/DPlayer.min.js') }} {{ js_include('home/js/course.share.js') }} {{ js_include('home/js/chapter.show.js') }} {{ js_include('home/js/chapter.vod.player.js') }} {{ js_include('home/js/comment.js') }} + {{ js_include('home/js/copy.js') }} {% endblock %} \ No newline at end of file diff --git a/app/Http/Home/Views/course/list.volt b/app/Http/Home/Views/course/list.volt index 59134b89..fbedd877 100644 --- a/app/Http/Home/Views/course/list.volt +++ b/app/Http/Home/Views/course/list.volt @@ -2,7 +2,9 @@ {% block content %} - {{ partial('course/list_filter') }} + {% if top_categories|length > 1 %} + {{ partial('course/list_filter') }} + {% endif %} {% set pager_url = url({'for':'home.course.pager'}, params) %} @@ -12,6 +14,7 @@ {% block include_js %} + {{ js_include('home/js/list.filter.js') }} {{ js_include('home/js/course.list.js') }} {% endblock %} \ No newline at end of file diff --git a/app/Http/Home/Views/course/list_filter.volt b/app/Http/Home/Views/course/list_filter.volt index 4f919e64..2f71026c 100644 --- a/app/Http/Home/Views/course/list_filter.volt +++ b/app/Http/Home/Views/course/list_filter.volt @@ -8,16 +8,18 @@
-
-
-
方向
-
- {% for category in top_categories %} - {% set class = tc_val == category.id ? 'layui-btn layui-btn-xs' : 'none' %} - {{ category.name }} - {% endfor %} +
+ {% if top_categories %} +
+
方向
+
+ {% for category in top_categories %} + {% set class = tc_val == category.id ? 'layui-btn layui-btn-xs' : 'none' %} + {{ category.name }} + {% endfor %} +
-
+ {% endif %} {% if sub_categories %}
分类
@@ -49,7 +51,7 @@
-
+
{% for sort in sorts %} {% set class = sort_val == sort.id ? 'layui-btn layui-btn-xs' : 'none' %} {{ sort.name }} diff --git a/app/Http/Home/Views/course/recommended.volt b/app/Http/Home/Views/course/recommended.volt deleted file mode 100644 index 7ecdda61..00000000 --- a/app/Http/Home/Views/course/recommended.volt +++ /dev/null @@ -1,12 +0,0 @@ -{{ partial('macros/course') }} - -{% if courses %} -
-
推荐课程
-
- {% for course in courses %} - {{ sidebar_course_card(course) }} - {% endfor %} -
-
-{% endif %} \ No newline at end of file diff --git a/app/Http/Home/Views/course/resources.volt b/app/Http/Home/Views/course/resources.volt index a500b8bb..efd2fd64 100644 --- a/app/Http/Home/Views/course/resources.volt +++ b/app/Http/Home/Views/course/resources.volt @@ -1,20 +1,22 @@ -{% if items|length > 0 %} - - - - - - - {% for item in items %} +{% if resources|length > 0 %} +
名称大小操作
- - - {% if item.me.owned == 1 and auth_user.id > 0 %} - - {% else %} - - {% endif %} + + + - {% endfor %} -
{{ item.name }}{{ item.size|human_size }}下载下载名称大小操作
+ {% for resource in resources %} +
{{ resource.name }}{{ resource.size|human_size }}下载下载
+{% else %} +
没有相关记录
{% endif %} \ No newline at end of file diff --git a/app/Http/Home/Views/course/reviews.volt b/app/Http/Home/Views/course/reviews.volt index 352573c3..0949507d 100644 --- a/app/Http/Home/Views/course/reviews.volt +++ b/app/Http/Home/Views/course/reviews.volt @@ -3,18 +3,24 @@ {% if pager.total_pages > 0 %}
{% for item in pager.items %} - {% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %} + {% if item.anonymous == 0 %} + {% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %} + {% set owner_name = item.owner.name %} + {% else %} + {% set owner_url = 'javascript:' %} + {% set owner_name = '匿名用户' %} + {% endif %} {% set like_url = url({'for':'home.review.like','id':item.id}) %}
{{ star_info(item.rating) }}
{{ item.content }}
@@ -78,7 +79,6 @@
{% set show_sidebar_topics = 1 %} - {% set show_sidebar_recommended = 1 %} {% set show_sidebar_related = 1 %}
@@ -88,10 +88,6 @@ {% set topics_url = url({'for':'home.course.topics','id':course.id}) %} {% endif %} - {% if show_sidebar_recommended %} - {% set recommended_url = url({'for':'home.course.recommended','id':course.id}) %} - - {% endif %} {% if show_sidebar_related %} {% set related_url = url({'for':'home.course.related','id':course.id}) %} @@ -121,7 +117,9 @@ {% block include_js %} + {{ js_include('lib/clipboard.min.js') }} {{ js_include('home/js/course.show.js') }} {{ js_include('home/js/course.share.js') }} + {{ js_include('home/js/copy.js') }} {% endblock %} \ No newline at end of file diff --git a/app/Http/Home/Views/course/show_order.volt b/app/Http/Home/Views/course/show_order.volt index f5ab79d3..0aba8192 100644 --- a/app/Http/Home/Views/course/show_order.volt +++ b/app/Http/Home/Views/course/show_order.volt @@ -6,7 +6,7 @@ {% elseif course.me.allow_order == 1 %} {% set order_url = url({'for':'home.order.confirm'},{'item_id':course.id,'item_type':1}) %} {% endif %} diff --git a/app/Http/Home/Views/course/show_teacher.volt b/app/Http/Home/Views/course/show_teacher.volt index cbe0dfc3..e10b581c 100644 --- a/app/Http/Home/Views/course/show_teacher.volt +++ b/app/Http/Home/Views/course/show_teacher.volt @@ -1,22 +1,21 @@ -{% if course.teachers %} +{% if course.teacher %} + {% set teacher = course.teacher %}