diff --git a/app/Builders/Builder.php b/app/Builders/Builder.php index a9b7ab93..02cd4f2f 100644 --- a/app/Builders/Builder.php +++ b/app/Builders/Builder.php @@ -2,9 +2,9 @@ namespace App\Builders; -use Phalcon\Mvc\User\Component as UserComponent; +use Phalcon\Mvc\User\Component; -class Builder extends UserComponent +class Builder extends Component { public function arrayToObject($array) diff --git a/app/Builders/CategoryList.php b/app/Builders/CategoryTreeList.php similarity index 96% rename from app/Builders/CategoryList.php rename to app/Builders/CategoryTreeList.php index 61104863..25735823 100644 --- a/app/Builders/CategoryList.php +++ b/app/Builders/CategoryTreeList.php @@ -2,7 +2,7 @@ namespace App\Builders; -class CategoryList extends Builder +class CategoryTreeList extends Builder { public function handleTreeList($categories) diff --git a/app/Builders/ChapterList.php b/app/Builders/ChapterTreeList.php similarity index 97% rename from app/Builders/ChapterList.php rename to app/Builders/ChapterTreeList.php index d7ee5c1e..afc2c29e 100644 --- a/app/Builders/ChapterList.php +++ b/app/Builders/ChapterTreeList.php @@ -4,7 +4,7 @@ namespace App\Builders; use App\Models\Course as CourseModel; -class ChapterList extends Builder +class ChapterTreeList extends Builder { /** diff --git a/app/Builders/CommentList.php b/app/Builders/CommentList.php new file mode 100644 index 00000000..a3e3bcbb --- /dev/null +++ b/app/Builders/CommentList.php @@ -0,0 +1,99 @@ +getCourses($comments); + + foreach ($comments as $key => $comment) { + $comments[$key]['course'] = $courses[$comment['course_id']] ?? []; + } + + return $comments; + } + + public function handleChapters($comments) + { + $chapters = $this->getChapters($comments); + + foreach ($comments as $key => $comment) { + $comments[$key]['chapter'] = $chapters[$comment['chapter_id']] ?? []; + } + + return $comments; + } + + public function handleUsers($comments) + { + $users = $this->getUsers($comments); + + foreach ($comments as $key => $comment) { + $comments[$key]['user'] = $users[$comment['user_id']] ?? []; + } + + return $comments; + } + + public function getCourses($comments) + { + $ids = kg_array_column($comments, '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($comments) + { + $ids = kg_array_column($comments, '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($comments) + { + $ids = kg_array_column($comments, 'user_id'); + + $userRepo = new UserRepo(); + + $users = $userRepo->findByIds($ids, ['id', 'name', 'avatar']); + + $imgBaseUrl = kg_img_base_url(); + + $result = []; + + foreach ($users->toArray() as $user) { + $user['avatar'] = $imgBaseUrl . $user['avatar']; + $result[$user['id']] = $user; + } + + return $result; + } + +} diff --git a/app/Builders/ConsultList.php b/app/Builders/ConsultList.php new file mode 100644 index 00000000..0ec526a1 --- /dev/null +++ b/app/Builders/ConsultList.php @@ -0,0 +1,70 @@ +getCourses($consults); + + foreach ($consults as $key => $consult) { + $consults[$key]['course'] = $courses[$consult['course_id']] ?? []; + } + + return $consults; + } + + public function handleUsers($consults) + { + $users = $this->getUsers($consults); + + foreach ($consults as $key => $consult) { + $consults[$key]['user'] = $users[$consult['user_id']] ?? []; + } + + return $consults; + } + + public function getCourses($consults) + { + $ids = kg_array_column($consults, '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 getUsers($consults) + { + $ids = kg_array_column($consults, 'user_id'); + + $userRepo = new UserRepo(); + + $users = $userRepo->findByIds($ids, ['id', 'name', 'avatar']); + + $imgBaseUrl = kg_img_base_url(); + + $result = []; + + foreach ($users->toArray() as $user) { + $user['avatar'] = $imgBaseUrl . $user['avatar']; + $result[$user['id']] = $user; + } + + return $result; + } + +} diff --git a/app/Builders/CourseFavoriteList.php b/app/Builders/CourseFavoriteList.php new file mode 100644 index 00000000..57eb88b8 --- /dev/null +++ b/app/Builders/CourseFavoriteList.php @@ -0,0 +1,80 @@ +getCourses($relations); + + foreach ($relations as $key => $value) { + $relations[$key]['course'] = $courses[$value['course_id']]; + } + + return $relations; + } + + public function handleUsers($relations) + { + $users = $this->getUsers($relations); + + foreach ($relations as $key => $value) { + $relations[$key]['user'] = $users[$value['user_id']]; + } + + return $relations; + } + + public function getCourses($relations) + { + $ids = kg_array_column($relations, 'course_id'); + + $courseRepo = new CourseRepo(); + + $columns = [ + 'id', 'title', 'cover', 'summary', + 'market_price', 'vip_price', 'model', 'level', 'attrs', + 'user_count', 'lesson_count', 'review_count', 'favorite_count', + ]; + + $courses = $courseRepo->findByIds($ids, $columns); + + $imgBaseUrl = kg_img_base_url(); + + $result = []; + + foreach ($courses->toArray() as $course) { + $course['cover'] = $imgBaseUrl . $course['cover']; + $course['attrs'] = json_decode($course['attrs'], true); + $result[$course['id']] = $course; + } + + return $result; + } + + public function getUsers($relations) + { + $ids = kg_array_column($relations, 'user_id'); + + $userRepo = new UserRepo(); + + $users = $userRepo->findByIds($ids, ['id', 'name', 'avatar']); + + $imgBaseUrl = kg_img_base_url(); + + $result = []; + + foreach ($users->toArray() as $user) { + $user['avatar'] = $imgBaseUrl . $user['avatar']; + $result[$user['id']] = $user; + } + + return $result; + } + +} diff --git a/app/Builders/CourseList.php b/app/Builders/CourseList.php index 20dc5010..cdbbf9f2 100644 --- a/app/Builders/CourseList.php +++ b/app/Builders/CourseList.php @@ -13,7 +13,7 @@ class CourseList extends Builder { $imgBaseUrl = kg_img_base_url(); - $result = []; + $list = []; foreach ($courses as $course) { @@ -36,13 +36,13 @@ class CourseList extends Builder 'categories' => $course['categories'], 'user_count' => $course['user_count'], 'lesson_count' => $course['lesson_count'], - 'thread_count' => $course['thread_count'], + 'comment_count' => $course['comment_count'], 'review_count' => $course['review_count'], 'favorite_count' => $course['favorite_count'], ]; } - return $result; + return $list; } public function handleCategories($courses) diff --git a/app/Builders/CourseUserList.php b/app/Builders/CourseUserList.php index 8188ee96..a333d3ad 100644 --- a/app/Builders/CourseUserList.php +++ b/app/Builders/CourseUserList.php @@ -30,34 +30,47 @@ class CourseUserList extends Builder return $relations; } - protected function getCourses($relations) + public function getCourses($relations) { $ids = kg_array_column($relations, 'course_id'); $courseRepo = new CourseRepo(); - $courses = $courseRepo->findByIds($ids, ['id', 'title', 'cover'])->toArray(); + $columns = [ + 'id', 'title', 'cover', 'summary', + 'market_price', 'vip_price', 'model', 'level', 'attrs', + 'user_count', 'lesson_count', 'review_count', 'favorite_count', + ]; + + $courses = $courseRepo->findByIds($ids, $columns); + + $imgBaseUrl = kg_img_base_url(); $result = []; - foreach ($courses as $course) { + foreach ($courses->toArray() as $course) { + $course['cover'] = $imgBaseUrl . $course['cover']; + $course['attrs'] = json_decode($course['attrs'], true); $result[$course['id']] = $course; } return $result; } - protected function getUsers($relations) + public function getUsers($relations) { $ids = kg_array_column($relations, 'user_id'); $userRepo = new UserRepo(); - $users = $userRepo->findByIds($ids, ['id', 'name', 'avatar'])->toArray(); + $users = $userRepo->findByIds($ids, ['id', 'name', 'avatar']); + + $imgBaseUrl = kg_img_base_url(); $result = []; - foreach ($users as $user) { + foreach ($users->toArray() as $user) { + $user['avatar'] = $imgBaseUrl . $user['avatar']; $result[$user['id']] = $user; } diff --git a/app/Builders/LearningList.php b/app/Builders/LearningList.php index ab695d8e..4afedb21 100644 --- a/app/Builders/LearningList.php +++ b/app/Builders/LearningList.php @@ -48,11 +48,11 @@ class LearningList extends Builder $courseRepo = new CourseRepo(); - $courses = $courseRepo->findByIds($ids, ['id', 'title', 'cover'])->toArray(); + $courses = $courseRepo->findByIds($ids, ['id', 'title', 'cover']); $result = []; - foreach ($courses as $course) { + foreach ($courses->toArray() as $course) { $result[$course['id']] = $course; } @@ -65,11 +65,11 @@ class LearningList extends Builder $chapterRepo = new ChapterRepo(); - $chapters = $chapterRepo->findByIds($ids, ['id', 'title'])->toArray(); + $chapters = $chapterRepo->findByIds($ids, ['id', 'title']); $result = []; - foreach ($chapters as $chapter) { + foreach ($chapters->toArray() as $chapter) { $result[$chapter['id']] = $chapter; } @@ -82,11 +82,11 @@ class LearningList extends Builder $userRepo = new UserRepo(); - $users = $userRepo->findByIds($ids, ['id', 'name', 'avatar'])->toArray(); + $users = $userRepo->findByIds($ids, ['id', 'name', 'avatar']); $result = []; - foreach ($users as $user) { + foreach ($users->toArray() as $user) { $result[$user['id']] = $user; } diff --git a/app/Builders/NavList.php b/app/Builders/NavTreeList.php similarity index 97% rename from app/Builders/NavList.php rename to app/Builders/NavTreeList.php index 01706498..1d2decee 100644 --- a/app/Builders/NavList.php +++ b/app/Builders/NavTreeList.php @@ -2,7 +2,7 @@ namespace App\Builders; -class NavList extends Builder +class NavTreeList extends Builder { public function handleTreeList($navs) diff --git a/app/Builders/OrderList.php b/app/Builders/OrderList.php index c4c9a557..14e95e73 100644 --- a/app/Builders/OrderList.php +++ b/app/Builders/OrderList.php @@ -7,6 +7,7 @@ use App\Repos\User as UserRepo; class OrderList extends Builder { + protected $imgBaseUrl; public function __construct() @@ -14,28 +15,64 @@ class OrderList extends Builder $this->imgBaseUrl = kg_img_base_url(); } - public function handleItems($orders) + /** + * @param array $orders + * @return array + */ + public function handleUsers(array $orders) { - $itemInfo = []; + $users = $this->getUsers($orders); foreach ($orders as $key => $order) { - switch ($order['item_type']) { - case OrderModel::TYPE_COURSE: - $itemInfo = $this->handleCourseInfo($order['item_info']); - break; - case OrderModel::TYPE_PACKAGE: - $itemInfo = $this->handlePackageInfo($order['item_info']); - break; - case OrderModel::TYPE_REWARD: - $itemInfo = $this->handleRewardInfo($order['item_info']); - break; - } + $orders[$key]['user'] = $users[$order['user_id']]; + } + + return $orders; + } + + /** + * @param array $orders + * @return array + */ + public function handleItems(array $orders) + { + foreach ($orders as $key => $order) { + + $itemInfo = $this->handleItem($order); + $orders[$key]['item_info'] = $itemInfo; } return $orders; } + /** + * @param array $order + * @return array|mixed + */ + public function handleItem(array $order) + { + $itemInfo = []; + + switch ($order['item_type']) { + case OrderModel::ITEM_COURSE: + $itemInfo = $this->handleCourseInfo($order['item_info']); + break; + case OrderModel::ITEM_PACKAGE: + $itemInfo = $this->handlePackageInfo($order['item_info']); + break; + case OrderModel::ITEM_VIP: + $itemInfo = $this->handleVipInfo($order['item_info']); + break; + } + + return $itemInfo; + } + + /** + * @param string $itemInfo + * @return mixed + */ protected function handleCourseInfo($itemInfo) { if (!empty($itemInfo) && is_string($itemInfo)) { @@ -46,6 +83,10 @@ class OrderList extends Builder return $itemInfo; } + /** + * @param string $itemInfo + * @return mixed + */ protected function handlePackageInfo($itemInfo) { if (!empty($itemInfo) && is_string($itemInfo)) { @@ -58,6 +99,10 @@ class OrderList extends Builder return $itemInfo; } + /** + * @param string $itemInfo + * @return mixed + */ protected function handleRewardInfo($itemInfo) { if (!empty($itemInfo) && is_string($itemInfo)) { @@ -68,28 +113,34 @@ class OrderList extends Builder return $itemInfo; } - public function handleUsers($orders) + /** + * @param string $itemInfo + * @return mixed + */ + protected function handleVipInfo($itemInfo) { - $users = $this->getUsers($orders); - - foreach ($orders as $key => $order) { - $orders[$key]['user'] = $users[$order['user_id']]; + if (!empty($itemInfo) && is_string($itemInfo)) { + $itemInfo = json_decode($itemInfo, true); } - return $orders; + return $itemInfo; } - protected function getUsers($orders) + /** + * @param array $orders + * @return array + */ + protected function getUsers(array $orders) { $ids = kg_array_column($orders, 'user_id'); $userRepo = new UserRepo(); - $users = $userRepo->findByIds($ids, ['id', 'name', 'avatar'])->toArray(); + $users = $userRepo->findByIds($ids, ['id', 'name']); $result = []; - foreach ($users as $user) { + foreach ($users->toArray() as $user) { $result[$user['id']] = $user; } diff --git a/app/Builders/RefundList.php b/app/Builders/RefundList.php index d55daf4c..17e56a9b 100644 --- a/app/Builders/RefundList.php +++ b/app/Builders/RefundList.php @@ -2,11 +2,23 @@ namespace App\Builders; +use App\Repos\Order as OrderRepo; use App\Repos\User as UserRepo; class RefundList extends Builder { + public function handleOrders($trades) + { + $orders = $this->getOrders($trades); + + foreach ($trades as $key => $trade) { + $trades[$key]['order'] = $orders[$trade['order_id']]; + } + + return $trades; + } + public function handleUsers($refunds) { $users = $this->getUsers($refunds); @@ -18,22 +30,34 @@ class RefundList extends Builder return $refunds; } - protected function getUsers($refunds) + public function getOrders($trades) + { + $ids = kg_array_column($trades, 'order_id'); + + $orderRepo = new OrderRepo(); + + $orders = $orderRepo->findByIds($ids, ['id', 'sn', 'subject', 'amount']); + + $result = []; + + foreach ($orders->toArray() as $order) { + $result[$order['id']] = $order; + } + + return $result; + } + + public function getUsers($refunds) { $ids = kg_array_column($refunds, 'user_id'); $userRepo = new UserRepo(); - $users = $userRepo->findByIds($ids, ['id', 'name', 'avatar']); + $users = $userRepo->findByIds($ids, ['id', 'name']); $result = []; - $imgBaseUrl = kg_img_base_url(); - foreach ($users->toArray() as $user) { - - $user['avatar'] = $imgBaseUrl . $user['avatar']; - $result[$user['id']] = $user; } diff --git a/app/Builders/ReviewList.php b/app/Builders/ReviewList.php index c48e5826..8714fc21 100644 --- a/app/Builders/ReviewList.php +++ b/app/Builders/ReviewList.php @@ -30,7 +30,7 @@ class ReviewList extends Builder return $reviews; } - protected function getCourses($reviews) + public function getCourses($reviews) { $ids = kg_array_column($reviews, 'course_id'); @@ -47,7 +47,7 @@ class ReviewList extends Builder return $result; } - protected function getUsers($reviews) + public function getUsers($reviews) { $ids = kg_array_column($reviews, 'user_id'); @@ -55,10 +55,10 @@ class ReviewList extends Builder $users = $userRepo->findByIds($ids, ['id', 'name', 'avatar']); - $result = []; - $imgBaseUrl = kg_img_base_url(); + $result = []; + foreach ($users->toArray() as $user) { $user['avatar'] = $imgBaseUrl . $user['avatar']; $result[$user['id']] = $user; diff --git a/app/Builders/TradeList.php b/app/Builders/TradeList.php index 909463e2..f878ffc1 100644 --- a/app/Builders/TradeList.php +++ b/app/Builders/TradeList.php @@ -2,11 +2,23 @@ namespace App\Builders; +use App\Repos\Order as OrderRepo; use App\Repos\User as UserRepo; class TradeList extends Builder { + public function handleOrders($trades) + { + $orders = $this->getOrders($trades); + + foreach ($trades as $key => $trade) { + $trades[$key]['order'] = $orders[$trade['order_id']]; + } + + return $trades; + } + public function handleUsers($trades) { $users = $this->getUsers($trades); @@ -18,17 +30,34 @@ class TradeList extends Builder return $trades; } - protected function getUsers($trades) + public function getOrders($trades) + { + $ids = kg_array_column($trades, 'order_id'); + + $orderRepo = new OrderRepo(); + + $orders = $orderRepo->findByIds($ids, ['id', 'sn', 'subject', 'amount']); + + $result = []; + + foreach ($orders->toArray() as $order) { + $result[$order['id']] = $order; + } + + return $result; + } + + public function getUsers($trades) { $ids = kg_array_column($trades, 'user_id'); $userRepo = new UserRepo(); - $users = $userRepo->findByIds($ids, ['id', 'name', 'avatar'])->toArray(); + $users = $userRepo->findByIds($ids, ['id', 'name']); $result = []; - foreach ($users as $user) { + foreach ($users->toArray() as $user) { $result[$user['id']] = $user; } diff --git a/app/Builders/UserList.php b/app/Builders/UserList.php index 1bca819f..20d19a04 100644 --- a/app/Builders/UserList.php +++ b/app/Builders/UserList.php @@ -32,7 +32,7 @@ class UserList extends Builder public function handleEduRoles($users) { - $roles = $this->getEduRoles($users); + $roles = $this->getEduRoles(); foreach ($users as $key => $user) { $users[$key]['edu_role'] = $roles[$user['edu_role']] ?? ['id' => 0, 'name' => 'N/A']; @@ -41,24 +41,24 @@ class UserList extends Builder return $users; } - private function getAdminRoles($users) + protected function getAdminRoles($users) { $ids = kg_array_column($users, 'admin_role'); $roleRepo = new RoleRepo(); - $roles = $roleRepo->findByIds($ids, ['id', 'name'])->toArray(); + $roles = $roleRepo->findByIds($ids, ['id', 'name']); $result = []; - foreach ($roles as $role) { + foreach ($roles->toArray() as $role) { $result[$role['id']] = $role; } return $result; } - private function getEduRoles() + protected function getEduRoles() { $result = [ UserModel::EDU_ROLE_STUDENT => [ diff --git a/app/Caches/Cache.php b/app/Caches/Cache.php index 4db6c76c..f0e43e8b 100644 --- a/app/Caches/Cache.php +++ b/app/Caches/Cache.php @@ -2,11 +2,14 @@ namespace App\Caches; -abstract class Cache extends \Phalcon\Mvc\User\Component +use Phalcon\Cache\Backend\Redis as RedisCache; +use Phalcon\Mvc\User\Component; + +abstract class Cache extends Component { /** - * @var \Phalcon\Cache\Backend\Redis + * @var RedisCache */ protected $cache; diff --git a/app/Caches/CategoryList.php b/app/Caches/CategoryList.php index a44f708d..0c792f9d 100644 --- a/app/Caches/CategoryList.php +++ b/app/Caches/CategoryList.php @@ -3,6 +3,7 @@ namespace App\Caches; use App\Models\Category as CategoryModel; +use Phalcon\Mvc\Model\Resultset; class CategoryList extends Cache { @@ -25,6 +26,9 @@ class CategoryList extends Cache */ public function getContent($id = null) { + /** + * @var Resultset $categories + */ $categories = CategoryModel::query() ->columns(['id', 'parent_id', 'name', 'priority', 'level', 'path']) ->where('published = 1 AND deleted = 0') diff --git a/app/Caches/CategoryTreeList.php b/app/Caches/CategoryTreeList.php index b14ed69e..6ae7eb71 100644 --- a/app/Caches/CategoryTreeList.php +++ b/app/Caches/CategoryTreeList.php @@ -2,8 +2,9 @@ namespace App\Caches; -use App\Builders\CategoryList as CategoryTreeListBuilder; +use App\Builders\CategoryTreeList as CategoryTreeListBuilder; use App\Models\Category as CategoryModel; +use Phalcon\Mvc\Model\Resultset; class CategoryTreeList extends Cache { @@ -17,11 +18,14 @@ class CategoryTreeList extends Cache public function getKey($id = null) { - return 'category_tree'; + return 'category_tree_list'; } public function getContent($id = null) { + /** + * @var Resultset $categories + */ $categories = CategoryModel::query() ->where('published = 1 AND deleted = 0') ->execute(); @@ -34,7 +38,7 @@ class CategoryTreeList extends Cache } /** - * @param \App\Models\Category[] $categories + * @param Resultset $categories * @return array */ protected function handleContent($categories) diff --git a/app/Caches/ChapterCounter.php b/app/Caches/ChapterCounter.php deleted file mode 100644 index 4a8e1278..00000000 --- a/app/Caches/ChapterCounter.php +++ /dev/null @@ -1,40 +0,0 @@ -lifetime; - } - - public function getKey($id = null) - { - return "chapter_counter:{$id}"; - } - - public function getContent($id = null) - { - $chapterRepo = new ChapterRepo(); - - $chapter = $chapterRepo->findById($id); - - if (!$chapter) return []; - - $content = [ - 'lesson_count' => $chapter->lesson_count, - 'user_count' => $chapter->user_count, - 'comment_count' => $chapter->comment_count, - 'like_count' => $chapter->like_count, - ]; - - return $content; - } - -} diff --git a/app/Caches/CourseChapterList.php b/app/Caches/ChapterTreeList.php similarity index 69% rename from app/Caches/CourseChapterList.php rename to app/Caches/ChapterTreeList.php index abdf924c..e1221404 100644 --- a/app/Caches/CourseChapterList.php +++ b/app/Caches/ChapterTreeList.php @@ -2,10 +2,11 @@ namespace App\Caches; -use App\Builders\ChapterList as ChapterListBuilder; +use App\Builders\ChapterTreeList as ChapterTreeListBuilder; use App\Repos\Course as CourseRepo; +use Phalcon\Mvc\Model\Resultset; -class CourseChapterList extends Cache +class ChapterTreeList extends Cache { protected $lifetime = 7 * 86400; @@ -17,13 +18,16 @@ class CourseChapterList extends Cache public function getKey($id = null) { - return "course_chapter_list:{$id}"; + return "chapter_tree_list:{$id}"; } public function getContent($id = null) { $courseRepo = new CourseRepo(); + /** + * @var Resultset $chapters + */ $chapters = $courseRepo->findChapters($id); if ($chapters->count() == 0) { @@ -34,14 +38,14 @@ class CourseChapterList extends Cache } /** - * @param \App\Models\Chapter[] $chapters + * @param Resultset $chapters * @return array */ protected function handleContent($chapters) { $items = $chapters->toArray(); - $builder = new ChapterListBuilder(); + $builder = new ChapterTreeListBuilder(); $content = $builder->handleTreeList($items); diff --git a/app/Caches/Counter.php b/app/Caches/Counter.php index 3e915d51..340783ce 100644 --- a/app/Caches/Counter.php +++ b/app/Caches/Counter.php @@ -2,11 +2,14 @@ namespace App\Caches; -abstract class Counter extends \Phalcon\Mvc\User\Component +use App\Library\Cache\Backend\Redis as RedisCache; +use Phalcon\Mvc\User\Component; + +abstract class Counter extends Component { /** - * @var \App\Library\Cache\Backend\Redis + * @var RedisCache */ protected $cache; @@ -40,16 +43,6 @@ abstract class Counter extends \Phalcon\Mvc\User\Component $lifetime = $this->getLifetime(); - /** - * 原始内容为空,设置较短的生存时间,简单防止穿透 - */ - if (!$content) { - - $lifetime = 5 * 60; - - $content = ['default' => 0]; - } - $this->redis->hMSet($key, $content); $this->redis->expire($key, $lifetime); @@ -82,17 +75,47 @@ abstract class Counter extends \Phalcon\Mvc\User\Component $this->get($id); } - public function increment($id, $hashKey, $value = 1) + public function hGet($id, $hashKey) { $key = $this->getKey($id); + if (!$this->redis->exists($key)) { + $this->get($id); + } + + $value = $this->redis->hGet($key, $hashKey); + + return $value; + } + + public function hDel($id, $hashKey) + { + $key = $this->getKey($id); + + $value = $this->redis->hDel($key, $hashKey); + + return $value; + } + + public function hIncrBy($id, $hashKey, $value = 1) + { + $key = $this->getKey($id); + + if (!$this->redis->exists($key)) { + $this->get($id); + } + $this->redis->hIncrBy($key, $hashKey, $value); } - public function decrement($id, $hashKey, $value = 1) + public function hDecrBy($id, $hashKey, $value = 1) { $key = $this->getKey($id); + if (!$this->redis->exists($key)) { + $this->get($id); + } + $this->redis->hIncrBy($key, $hashKey, 0 - $value); } diff --git a/app/Caches/Course.php b/app/Caches/Course.php index ee0f7009..dd81374e 100644 --- a/app/Caches/Course.php +++ b/app/Caches/Course.php @@ -25,6 +25,8 @@ class Course extends Cache $course = $courseRepo->findById($id); + $course->cover = kg_img_url($course->cover); + if (!$course) { return new \stdClass(); } diff --git a/app/Caches/CourseCategoryList.php b/app/Caches/CourseCategoryList.php index 3b72400f..f3d0d173 100644 --- a/app/Caches/CourseCategoryList.php +++ b/app/Caches/CourseCategoryList.php @@ -3,6 +3,7 @@ namespace App\Caches; use App\Repos\Course as CourseRepo; +use Phalcon\Mvc\Model\Resultset; class CourseCategoryList extends Cache { @@ -23,6 +24,9 @@ class CourseCategoryList extends Cache { $courseRepo = new CourseRepo(); + /** + * @var Resultset $categories + */ $categories = $courseRepo->findCategories($id); if ($categories->count() == 0) { @@ -33,7 +37,7 @@ class CourseCategoryList extends Cache } /** - * @param \App\Models\Category[] $categories + * @param Resultset $categories * @return array */ public function handleContent($categories) diff --git a/app/Caches/CourseCounter.php b/app/Caches/CourseCounter.php deleted file mode 100644 index 301065fe..00000000 --- a/app/Caches/CourseCounter.php +++ /dev/null @@ -1,41 +0,0 @@ -lifetime; - } - - public function getKey($id = null) - { - return "course_counter:{$id}"; - } - - public function getContent($id = null) - { - $courseRepo = new CourseRepo(); - - $course = $courseRepo->findById($id); - - if (!$course) return []; - - $content = [ - 'user_count' => $course->user_count, - 'lesson_count' => $course->lesson_count, - 'comment_count' => $course->comment_count, - 'review_count' => $course->review_count, - 'favorite_count' => $course->favorite_count, - ]; - - return $content; - } - -} diff --git a/app/Caches/CoursePackageList.php b/app/Caches/CoursePackageList.php index 4c7e48a2..81b2101d 100644 --- a/app/Caches/CoursePackageList.php +++ b/app/Caches/CoursePackageList.php @@ -2,7 +2,10 @@ namespace App\Caches; +use App\Models\Package as PackageModel; use App\Repos\Course as CourseRepo; +use App\Repos\Package as PackageRepo; +use Phalcon\Mvc\Model\Resultset; class CoursePackageList extends Cache { @@ -23,6 +26,9 @@ class CoursePackageList extends Cache { $courseRepo = new CourseRepo(); + /** + * @var Resultset $packages + */ $packages = $courseRepo->findPackages($id); if ($packages->count() == 0) { @@ -33,7 +39,7 @@ class CoursePackageList extends Cache } /** - * @param \App\Models\Package[] $packages + * @param PackageModel[] $packages * @return array */ protected function handleContent($packages) @@ -64,15 +70,21 @@ class CoursePackageList extends Cache $result = []; + $imgBaseUrl = kg_img_base_url(); + foreach ($courses as $course) { + + $course->cover = $imgBaseUrl . $course->cover; + $result[] = [ 'id' => $course->id, - 'model' => $course->model, 'title' => $course->title, - 'summary' => $course->summary, 'cover' => $course->cover, + 'summary' => $course->summary, 'market_price' => $course->market_price, 'vip_price' => $course->vip_price, + 'model' => $course->model, + 'level' => $course->level, ]; } diff --git a/app/Caches/CourseRelatedList.php b/app/Caches/CourseRelatedList.php index 54a8c53a..8d75adff 100644 --- a/app/Caches/CourseRelatedList.php +++ b/app/Caches/CourseRelatedList.php @@ -2,7 +2,9 @@ namespace App\Caches; +use App\Models\Course as CourseModel; use App\Repos\Course as CourseRepo; +use Phalcon\Mvc\Model\Resultset; class CourseRelatedList extends Cache { @@ -23,6 +25,9 @@ class CourseRelatedList extends Cache { $courseRepo = new CourseRepo(); + /** + * @var Resultset $courses + */ $courses = $courseRepo->findRelatedCourses($id); if ($courses->count() == 0) { @@ -34,22 +39,28 @@ class CourseRelatedList extends Cache /** - * @param \App\Models\Course[] $courses + * @param CourseModel[] $courses * @return array */ public function handleContent($courses) { $result = []; + $imgBaseUrl = kg_img_base_url(); + foreach ($courses as $course) { + + $course->cover = $imgBaseUrl . $course->cover; + $result[] = [ 'id' => $course->id, - 'model' => $course->model, 'title' => $course->title, 'cover' => $course->cover, 'summary' => $course->summary, 'market_price' => $course->market_price, 'vip_price' => $course->vip_price, + 'model' => $course->model, + 'level' => $course->level, ]; } diff --git a/app/Caches/CourseTeacherList.php b/app/Caches/CourseTeacherList.php index a8d34d9d..41fb85cc 100644 --- a/app/Caches/CourseTeacherList.php +++ b/app/Caches/CourseTeacherList.php @@ -2,7 +2,9 @@ namespace App\Caches; +use App\Models\User as UserModel; use App\Repos\Course as CourseRepo; +use Phalcon\Mvc\Model\Resultset; class CourseTeacherList extends Cache { @@ -23,6 +25,9 @@ class CourseTeacherList extends Cache { $courseRepo = new CourseRepo(); + /** + * @var Resultset $users + */ $users = $courseRepo->findTeachers($id); if ($users->count() == 0) { @@ -33,14 +38,19 @@ class CourseTeacherList extends Cache } /** - * @param \App\Models\User[] $users + * @param UserModel[] $users * @return array */ public function handleContent($users) { $result = []; + $imgBaseUrl = kg_img_base_url(); + foreach ($users as $user) { + + $user->avatar = $imgBaseUrl . $user->avatar; + $result[] = [ 'id' => $user->id, 'name' => $user->name, diff --git a/app/Caches/HotCourseList.php b/app/Caches/HotCourseList.php index 09e5e374..4e4e9cd9 100644 --- a/app/Caches/HotCourseList.php +++ b/app/Caches/HotCourseList.php @@ -2,12 +2,14 @@ namespace App\Caches; +use App\Models\Course as CourseModel; use App\Repos\Course as CourseRepo; +use Phalcon\Mvc\Model\Resultset; class HotCourseList extends Cache { - protected $lifetime = 7 * 86400; + protected $lifetime = 86400; public function getLifetime() { @@ -23,6 +25,9 @@ class HotCourseList extends Cache { $courseRepo = new CourseRepo(); + /** + * @var Resultset $courses + */ $courses = $courseRepo->findRelatedCourses($id); if ($courses->count() == 0) { @@ -32,9 +37,8 @@ class HotCourseList extends Cache return $this->handleContent($courses); } - /** - * @param \App\Models\Course[] $courses + * @param CourseModel[] $courses * @return array */ public function handleContent($courses) @@ -44,12 +48,13 @@ class HotCourseList extends Cache foreach ($courses as $course) { $result[] = [ 'id' => $course->id, - 'model' => $course->model, 'title' => $course->title, 'summary' => $course->summary, 'cover' => $course->cover, 'market_price' => $course->market_price, 'vip_price' => $course->vip_price, + 'model' => $course->model, + 'level' => $course->level, ]; } diff --git a/app/Caches/LatestCourseList.php b/app/Caches/LatestCourseList.php index 3f715e72..8874dc11 100644 --- a/app/Caches/LatestCourseList.php +++ b/app/Caches/LatestCourseList.php @@ -2,7 +2,9 @@ namespace App\Caches; +use App\Models\Course as CourseModel; use App\Repos\Course as CourseRepo; +use Phalcon\Mvc\Model\Resultset; class LatestCourseList extends Cache { @@ -23,6 +25,9 @@ class LatestCourseList extends Cache { $courseRepo = new CourseRepo(); + /** + * @var Resultset $courses + */ $courses = $courseRepo->findRelatedCourses($id); if ($courses->count() == 0) { @@ -34,22 +39,28 @@ class LatestCourseList extends Cache /** - * @param \App\Models\Course[] $courses + * @param CourseModel[] $courses * @return array */ public function handleContent($courses) { $result = []; + $imgBaseUrl = kg_img_base_url(); + foreach ($courses as $course) { + + $course->cover = $imgBaseUrl . $course->cover; + $result[] = [ 'id' => $course->id, - 'model' => $course->model, 'title' => $course->title, 'summary' => $course->summary, 'cover' => $course->cover, 'market_price' => $course->market_price, 'vip_price' => $course->vip_price, + 'model' => $course->model, + 'level' => $course->level, ]; } diff --git a/app/Caches/NavTreeList.php b/app/Caches/NavTreeList.php index 2aaf88ef..32260510 100644 --- a/app/Caches/NavTreeList.php +++ b/app/Caches/NavTreeList.php @@ -2,8 +2,9 @@ namespace App\Caches; -use App\Builders\NavList as NavListBuilder; +use App\Builders\NavTreeList as NavTreeListBuilder; use App\Models\Nav as NavModel; +use Phalcon\Mvc\Model\Resultset; class NavTreeList extends Cache { @@ -22,6 +23,9 @@ class NavTreeList extends Cache public function getContent($id = null) { + /** + * @var Resultset $navs + */ $navs = NavModel::query() ->where('published = 1 AND deleted = 0') ->orderBy('position ASC, priority ASC') @@ -35,7 +39,7 @@ class NavTreeList extends Cache } /** - * @param \App\Models\Nav[] $navs + * @param Resultset $navs * @return array */ protected function handleContent($navs) @@ -53,7 +57,7 @@ class NavTreeList extends Cache } } - $builder = new NavListBuilder(); + $builder = new NavTreeListBuilder(); $content = [ 'top' => $builder->handleTreeList($list['top']), diff --git a/app/Caches/SlideList.php b/app/Caches/SlideList.php index 91cd6f53..91f962ba 100644 --- a/app/Caches/SlideList.php +++ b/app/Caches/SlideList.php @@ -3,6 +3,7 @@ namespace App\Caches; use App\Models\Slide as SlideModel; +use Phalcon\Mvc\Model\Resultset; class SlideList extends Cache { @@ -21,6 +22,9 @@ class SlideList extends Cache public function getContent($id = null) { + /** + * @var Resultset $slides + */ $slides = SlideModel::query() ->columns(['id', 'title', 'cover', 'summary', 'target', 'content']) ->where('published = 1 AND deleted = 0') @@ -35,7 +39,7 @@ class SlideList extends Cache } /** - * @param \App\Models\Slide[] $slides + * @param SlideModel[] $slides * @return array */ protected function handleContent($slides) diff --git a/app/Caches/UserCounter.php b/app/Caches/UserCounter.php deleted file mode 100644 index 3fc5c30c..00000000 --- a/app/Caches/UserCounter.php +++ /dev/null @@ -1,38 +0,0 @@ -lifetime; - } - - public function getKey($id = null) - { - return "user_counter:{$id}"; - } - - public function getContent($id = null) - { - $userRepo = new UserRepo(); - - $user = $userRepo->findById($id); - - if (!$user) return []; - - $content = [ - 'notice_count' => $user->notice_count, - 'msg_count' => $user->msg_count, - ]; - - return $content; - } - -} diff --git a/app/Caches/UserDailyCounter.php b/app/Caches/UserDailyCounter.php new file mode 100644 index 00000000..f2b8a55b --- /dev/null +++ b/app/Caches/UserDailyCounter.php @@ -0,0 +1,40 @@ + 0, + 'comment_count' => 0, + 'consult_count' => 0, + 'order_count' => 0, + 'chapter_vote_count' => 0, + 'comment_vote_count' => 0, + 'consult_vote_count' => 0, + 'review_vote_count' => 0, + ]; + + return $content; + } + +} diff --git a/app/Console/Tasks/AvatarSyncTask.php b/app/Console/Tasks/AvatarSyncTask.php deleted file mode 100644 index de212a28..00000000 --- a/app/Console/Tasks/AvatarSyncTask.php +++ /dev/null @@ -1,91 +0,0 @@ -where('edu_role = 1') - ->limit($limit, $offset) - ->execute(); - - if ($users->count() > 0) { - $this->handleUsers($users); - } - } - } - - protected function handleUsers($users) - { - $storage = new Storage(); - - foreach ($users as $user) { - - $avatar = $user->avatar; - - if (!$avatar) { - continue; - } - - if (Text::startsWith($avatar, '/img/avatar')) { - continue; - } - - if (Text::startsWith($avatar, '//')) { - $avatar = 'http:' . $avatar; - } - - $url = str_replace(['-40-40', '-80-80', '-140-140', '-160-160'], '-200-200', $avatar); - - $fileName = parse_url($url, PHP_URL_PATH); - $filePath = tmp_path('avatar') . $fileName; - - $content = file_get_contents($url); - - if ($content === false) { - echo "get user {$user->id} avatar failed" . PHP_EOL; - continue; - } - - $put = file_put_contents($filePath, $content); - - if ($put === false) { - echo "put user {$user->id} cover failed" . PHP_EOL; - continue; - } - - $keyName = $this->getKeyName($filePath); - $remoteUrl = $storage->putFile($keyName, $filePath); - - if ($remoteUrl) { - $user->avatar = $keyName; - $user->deleted = 2; - $user->update(); - echo "upload avatar of user {$user->id} success" . PHP_EOL; - } else { - echo "upload avatar of user {$user->id} failed" . PHP_EOL; - } - } - } - - protected function getKeyName($filePath) - { - $ext = pathinfo($filePath, PATHINFO_EXTENSION); - return '/img/avatar/' . date('YmdHis') . rand(1000, 9999) . '.' . $ext; - } - -} diff --git a/app/Console/Tasks/ClassSpiderTask.php b/app/Console/Tasks/ClassSpiderTask.php deleted file mode 100644 index 5e3797fb..00000000 --- a/app/Console/Tasks/ClassSpiderTask.php +++ /dev/null @@ -1,511 +0,0 @@ - ['div.shizhan-course-wrap > a', 'href'], - 'course_cover' => ['div.img-box > img.shizhan-course-img', 'src'], - 'course_title' => ['div.img-box > img.shizhan-course-img', 'alt'], - ]); - - $this->handleList($ql); - } - - protected function handleList($ql) - { - foreach (range(1, 6) as $page) { - - $url = "https://coding.imooc.com/?sort=0&unlearn=0&page={$page}"; - - echo "============== Page {$page} =================" . PHP_EOL; - - $data = $ql->get($url)->query()->getData(); - - if ($data->count() == 0) { - break; - } - - foreach ($data->all() as $item) { - - $courseData = [ - 'class_id' => $this->getCourseId($item['course_link']), - 'title' => $item['course_title'], - 'cover' => $item['course_cover'], - ]; - - //print_r($courseData); - - if ($courseData['class_id']) { - $course = CourseModel::findFirstByClassId($courseData['class_id']); - if (!$course) { - $course = new CourseModel(); - $course->create($courseData); - } - } - } - - } - - $ql->destruct(); - } - - public function courseAction() - { - $courses = CourseModel::query() - ->where('class_id > 114') - ->orderBy('class_id ASC') - ->execute(); - - foreach ($courses as $course) { - $this->handleCourse($course); - sleep(5); - } - } - - public function chapterAction() - { - $ql = QueryList::rules([ - 'chapter_title' => ['.chapter-bd > h5.name', 'text'], - 'chapter_summary' => ['.chapter-bd > p.desc', 'text'], - 'lesson_html' => ['.chapter-bd > ul', 'html'], - ]); - - $courses = CourseModel::query() - ->where('class_id > 114') - ->orderBy('class_id ASC') - ->execute(); - - foreach ($courses as $course) { - $this->handleChapter($ql, $course); - sleep(5); - } - } - - protected function handleChapter(QueryList $ql, $course) - { - echo " course id: {$course->id} , class_id :{$course->class_id} " . PHP_EOL; - - $url = "https://coding.imooc.com/class/chapter/{$course->class_id}.html"; - - $data = $ql->get($url)->query()->getData(); - - if ($data->count() == 0) { - return; - } - - $lesson_ql = QueryList::rules([ - 'lesson_title' => ['span.title_info', 'text'], - 'lesson_free' => ['span.watch-free', 'text'], - ]); - - foreach ($data->all() as $item) { - - $chapterData = [ - 'course_id' => $course->id, - 'title' => trim($item['chapter_title']), - 'summary' => trim($item['chapter_summary']), - ]; - - $chapter = new ChapterModel(); - $chapter->create($chapterData); - - $this->handleLesson($chapter, $lesson_ql, $item['lesson_html']); - } - - $ql->destruct(); - } - - protected function handleLesson($chapter, QueryList $lesson_ql, $html) - { - - $lessons = $lesson_ql->html($html)->query()->getData(); - - if ($lessons->count() == 0) { - return; - } - - foreach ($lessons->all() as $item) { - $data = [ - 'course_id' => $chapter->course_id, - 'parent_id' => $chapter->id, - 'title' => $item['lesson_title'], - 'free' => $item['lesson_free'] ? 1 : 0, - ]; - - $model = new ChapterModel(); - $model->create($data); - } - - $lesson_ql->destruct(); - } - - public function consultAction() - { - $courses = CourseModel::query() - ->where('class_id > 0') - ->orderBy('class_id ASC') - ->execute(); - - foreach ($courses as $course) { - $this->handleConsult($course); - sleep(5); - } - } - - protected function handleConsult($course) - { - - foreach (range(1, 20) as $page) { - - echo "course {$course->id}, page {$page}" . PHP_EOL; - - $url = "https://coding.imooc.com/class/ajaxconsultsearch?cid={$course->class_id}&page={$page}&pagesize=15"; - - $content = file_get_contents($url); - - $json = json_decode($content, true); - - $consults = $json['data']['data_adv']; - - if (empty($consults)) { - break; - } - - foreach ($consults as $item) { - $data = [ - 'question' => $item['content'], - 'answer' => $item['answer'], - 'like_count' => $item['praise'], - 'created_at' => strtotime($item['create_time']), - ]; - $consult = new ConsultModel(); - $consult->create($data); - } - - } - - } - - public function reviewAction() - { - $ql = QueryList::rules([ - 'review_content' => ['p.cmt-txt', 'text'], - 'review_rating' => ['div.stars > span', 'text'], - ]); - - $courses = CourseModel::query() - ->where('class_id > 0') - ->orderBy('class_id ASC') - ->execute(); - - foreach ($courses as $course) { - $this->handleReview($ql, $course); - sleep(5); - } - } - - protected function handleReview($ql, $course) - { - foreach (range(1, 10) as $page) { - - $url = "https://coding.imooc.com/class/evaluation/{$course->class_id}.html?page={$page}"; - - echo "============== Course {$course->id}, Page {$page} =================" . PHP_EOL; - - $data = $ql->get($url)->query()->getData(); - - if ($data->count() == 0) { - break; - } - - foreach ($data->all() as $item) { - - $reviewData = [ - 'course_id' => $course->id, - 'content' => $item['review_content'], - 'rating' => $this->getReviewRating($item['review_rating']), - ]; - - $review = new ReviewModel(); - $review->create($reviewData); - } - } - - $ql->destruct(); - } - - public function packageAction() - { - $ql = QueryList::rules([ - 'id' => ['a.js-buy-package', 'data-cid'], - 'title' => ['p.package-title', 'text'], - 'price' => ['p.package-price', 'text'], - 'other_html' => ['div.other-course-wrap', 'html'], - ]); - - $courses = CourseModel::query() - ->where('class_id > 0') - ->orderBy('class_id ASC') - ->execute(); - - foreach ($courses as $course) { - $this->handlePackage($ql, $course); - sleep(5); - } - } - - protected function handlePackage(QueryList $ql, $course) - { - echo " course id: {$course->id} , class_id :{$course->class_id} " . PHP_EOL; - - $url = "https://coding.imooc.com/class/package/{$course->class_id}.html"; - - $data = $ql->get($url)->query()->getData(); - - if ($data->count() == 0) { - return; - } - - $other_ql = QueryList::rules([ - 'href' => ['a.course-item', 'href'], - ]); - - foreach ($data->all() as $item) { - - $packageData = [ - 'id' => trim($item['id']), - 'title' => trim($item['title']), - 'market_price' => $this->getMarketPrice($item['price']), - ]; - - $package = PackageModel::findFirst($packageData['id']); - - if (!$package) { - $package = new PackageModel(); - $package->create($packageData); - } - - $cpRepo = new CoursePackageRepo(); - - $cp = $cpRepo->findCoursePackage($course->id, $package->id); - - if (!$cp) { - $cp = new CoursePackageModel(); - $cp->course_id = $course->id; - $cp->package_id = $package->id; - $cp->create(); - } - - $this->handleOtherPackageCourse($package, $other_ql, $item['other_html']); - } - - $ql->destruct(); - } - - protected function handleOtherPackageCourse($package, QueryList $other_ql, $html) - { - $courses = $other_ql->html($html)->query()->getData(); - - if ($courses->count() == 0) { - return; - } - - foreach ($courses->all() as $item) { - - $courseId = str_replace(['//coding.imooc.com/class/', '.html'], '', $item['href']); - - $cpRepo = new CoursePackageRepo(); - - $cp = $cpRepo->findCoursePackage($courseId, $package->id); - - if (!$cp) { - $cp = new CoursePackageModel(); - $cp->course_id = (int)$courseId; - $cp->package_id = $package->id; - $cp->create(); - } - } - - $other_ql->destruct(); - } - - protected function handleCourse($course) - { - echo " =============== class id {$course->class_id} ============" . PHP_EOL; - - $url = "https://coding.imooc.com/class/{$course->class_id}.html"; - - $ql = QueryList::getInstance()->get($url); - - $summary = $ql->find('div.info-desc')->text(); - $userLink = $ql->find('div.teacher > a')->attr('href'); - $marketPrice = $ql->find('div.ori-price')->text(); - $level = $ql->find('div.info-bar > span:eq(1)')->text(); - $duration = $ql->find('div.info-bar > span:eq(3)')->text(); - $userCount = $ql->find('div.info-bar > span:eq(5)')->text(); - $score = $ql->find('div.info-bar > span:eq(7)')->text(); - - $courseData = [ - 'summary' => trim($summary), - 'user_count' => intval($userCount), - 'market_price' => $this->getMarketPrice($marketPrice), - 'level' => $this->getLevel($level), - 'score' => $this->getScore($score), - 'attrs' => [ - 'duration' => $this->getCourseDuration($duration), - ], - ]; - - $course->update($courseData); - - $ql->destruct(); - - $userId = $this->getUserId($userLink); - - $user = UserModel::findFirst($userId); - - if ($user) { - - $user->edu_role = UserModel::EDU_ROLE_TEACHER; - $user->update(); - - $cuRepo = new \App\Repos\CourseUser(); - - $row = $cuRepo->findCourseTeacher($course->id, $user->id); - - if (!$row) { - $courseUser = new CourseUserModel(); - $courseUser->course_id = $course->id; - $courseUser->user_id = $user->id; - $courseUser->role_type = CourseUserModel::ROLE_TEACHER; - $courseUser->expire_time = strtotime('+15 years'); - $courseUser->create(); - } - } - - $this->handleTeacherInfo($userId); - - } - - protected function handleTeacherInfo($id) - { - $url = 'http://www.imooc.com/t/' . $id; - - $ql = QueryList::getInstance()->get($url); - - $data = []; - - $data['id'] = $id; - $data['avatar'] = $ql->find('img.tea-header')->attr('src'); - $data['name'] = $ql->find('p.tea-nickname')->text(); - $data['title'] = $ql->find('p.tea-professional')->text(); - $data['about'] = $ql->find('p.tea-desc')->text(); - - $user = UserModel::findFirst($id); - - if (!$user) { - $user = new UserModel(); - $user->create($data); - } - - $ql->destruct(); - } - - protected function getUserId($userLink) - { - $result = str_replace(['http://www.imooc.com/u/'], '', $userLink); - - return trim($result); - } - - protected function getCourseId($courseLink) - { - if (!strpos($courseLink, '.html')) { - return false; - } - - $result = str_replace(['/class/', '.html'], '', $courseLink); - - return trim($result); - } - - protected function getMarketPrice($price) - { - $price = str_replace('¥', '', $price); - return floatval(trim($price)); - } - - protected function getScore($score) - { - return floatval(trim($score) * 10); - } - - protected function getCourseDuration($duration) - { - $hours = 0; - $minutes = 0; - - if (preg_match('/(.*?)小时(.*?)分/s', $duration, $matches)) { - $hours = trim($matches[1]); - $minutes = trim($matches[2]); - } elseif (preg_match('/(.*?)小时/s', $duration, $matches)) { - $hours = trim($matches[1]); - } elseif (preg_match('/(.*?)分/s', $duration, $matches)) { - $minutes = trim($matches[1]); - } - - return 3600 * $hours + 60 * $minutes; - } - - protected function getChapterDuration($duration) - { - if (strpos($duration, ':') === false) { - return 0; - } - - list($minutes, $seconds) = explode(':', trim($duration)); - - return 60 * $minutes + $seconds; - } - - protected function getLevel($type) - { - $mapping = [ - '入门' => CourseModel::LEVEL_ENTRY, - '初级' => CourseModel::LEVEL_JUNIOR, - '中级' => CourseModel::LEVEL_MEDIUM, - '高级' => CourseModel::LEVEL_SENIOR, - ]; - - return $mapping[$type] ?? CourseModel::LEVEL_ENTRY; - } - - protected function getReviewRating($type) - { - $mapping = [ - '好评' => 10, - '中评' => 8, - '差评' => 6, - ]; - - return $mapping[$type] ?? 8; - } - -} diff --git a/app/Console/Tasks/CleanLogTask.php b/app/Console/Tasks/CleanLogTask.php index 5fe91b98..9f0f5926 100644 --- a/app/Console/Tasks/CleanLogTask.php +++ b/app/Console/Tasks/CleanLogTask.php @@ -11,6 +11,7 @@ class CleanLogTask extends Task { $this->cleanCommonLog(); $this->cleanConsoleLog(); + $this->cleanHttpLog(); $this->cleanSqlLog(); $this->cleanListenerLog(); $this->cleanCaptchaLog(); @@ -19,7 +20,7 @@ class CleanLogTask extends Task $this->cleanVodLog(); $this->cleanStorageLog(); $this->cleanAlipayLog(); - $this->cleanWxpayLog(); + $this->cleanWechatLog(); $this->cleanRefundLog(); } @@ -31,6 +32,14 @@ class CleanLogTask extends Task $this->cleanLog('common', 7); } + /** + * 清理Http日志 + */ + protected function cleanHttpLog() + { + $this->cleanLog('http', 7); + } + /** * 清理Console日志 */ @@ -106,9 +115,9 @@ class CleanLogTask extends Task /** * 清理微信支付服务日志 */ - protected function cleanWxpayLog() + protected function cleanWechatLog() { - $this->cleanLog('wxpay', 30); + $this->cleanLog('wechat', 30); } /** diff --git a/app/Console/Tasks/CloseOrderTask.php b/app/Console/Tasks/CloseOrderTask.php index 9ebbe234..f925f0dd 100644 --- a/app/Console/Tasks/CloseOrderTask.php +++ b/app/Console/Tasks/CloseOrderTask.php @@ -4,6 +4,8 @@ namespace App\Console\Tasks; use App\Models\Order as OrderModel; use Phalcon\Cli\Task; +use Phalcon\Mvc\Model\Resultset; +use Phalcon\Mvc\Model\ResultsetInterface; class CloseOrderTask extends Task { @@ -26,7 +28,7 @@ class CloseOrderTask extends Task * 查找待关闭订单 * * @param int $limit - * @return \Phalcon\Mvc\Model\ResultsetInterface + * @return ResultsetInterface|Resultset|OrderModel[] */ protected function findOrders($limit = 1000) { diff --git a/app/Console/Tasks/CloseSlideTask.php b/app/Console/Tasks/CloseSlideTask.php deleted file mode 100644 index c3b16e75..00000000 --- a/app/Console/Tasks/CloseSlideTask.php +++ /dev/null @@ -1,40 +0,0 @@ -findSlides(); - - if ($slides->count() == 0) { - return; - } - - foreach ($slides as $slide) { - $slide->published = 0; - $slide->update(); - } - } - - /** - * 查找待关闭轮播 - * - * @return \Phalcon\Mvc\Model\ResultsetInterface - */ - protected function findSlides() - { - $Slides = SlideModel::query() - ->where('published = 1') - ->andWhere('end_time < :end_time:', ['end_time' => time()]) - ->execute(); - - return $Slides; - } - -} diff --git a/app/Console/Tasks/CloseTradeTask.php b/app/Console/Tasks/CloseTradeTask.php index 5907ab1f..3855f420 100644 --- a/app/Console/Tasks/CloseTradeTask.php +++ b/app/Console/Tasks/CloseTradeTask.php @@ -4,7 +4,10 @@ namespace App\Console\Tasks; use App\Models\Trade as TradeModel; use App\Services\Alipay as AlipayService; +use App\Services\Wechat as WechatService; use Phalcon\Cli\Task; +use Phalcon\Mvc\Model\Resultset; +use Phalcon\Mvc\Model\ResultsetInterface; class CloseTradeTask extends Task { @@ -20,8 +23,8 @@ class CloseTradeTask extends Task foreach ($trades as $trade) { if ($trade->channel == TradeModel::CHANNEL_ALIPAY) { $this->closeAlipayTrade($trade); - } elseif ($trade->channel == TradeModel::CHANNEL_WXPAY) { - $this->closeWxpayTrade($trade); + } elseif ($trade->channel == TradeModel::CHANNEL_WECHAT) { + $this->closeWechatTrade($trade); } } } @@ -53,9 +56,9 @@ class CloseTradeTask extends Task * * @param TradeModel $trade */ - protected function closeWxpayTrade($trade) + protected function closeWechatTrade($trade) { - $service = new WxpayService(); + $service = new WechatService(); $wxOrder = $service->findOrder($trade->sn); @@ -74,7 +77,7 @@ class CloseTradeTask extends Task * 查找待关闭交易 * * @param int $limit - * @return \Phalcon\Mvc\Model\ResultsetInterface + * @return Resultset|ResultsetInterface */ protected function findTrades($limit = 5) { diff --git a/app/Console/Tasks/CountCourseTask.php b/app/Console/Tasks/CountCourseTask.php index 61687c82..dfcd3e4f 100644 --- a/app/Console/Tasks/CountCourseTask.php +++ b/app/Console/Tasks/CountCourseTask.php @@ -2,6 +2,7 @@ namespace App\Console\Tasks; +use App\Models\Category as CategoryModel; use App\Repos\Category as CategoryRepo; use Phalcon\Cli\Task; @@ -14,6 +15,9 @@ class CountCourseTask extends Task $mapping = []; + /** + * @var CategoryModel[] $subCategories + */ $subCategories = $categoryRepo->findAll(['level' => 2, 'deleted' => 0]); foreach ($subCategories as $category) { @@ -31,6 +35,9 @@ class CountCourseTask extends Task } } + /** + * @var CategoryModel[] $topCategories + */ $topCategories = $categoryRepo->findAll(['level' => 1, 'deleted' => 0]); foreach ($topCategories as $category) { diff --git a/app/Console/Tasks/ImageSyncTask.php b/app/Console/Tasks/ImageSyncTask.php deleted file mode 100644 index ba158793..00000000 --- a/app/Console/Tasks/ImageSyncTask.php +++ /dev/null @@ -1,66 +0,0 @@ -where('id > 1155') - ->execute(); - - $storage = new Storage(); - - foreach ($courses as $course) { - - $cover = $course->cover; - - if (Text::startsWith($cover, '//')) { - $cover = 'http:' . $cover; - } - - $url = str_replace('-360-202', '', $cover); - - $fileName = parse_url($url, PHP_URL_PATH); - $filePath = tmp_path() . $fileName; - $content = file_get_contents($url); - - if ($content === false) { - echo "get course {$course->id} cover failed" . PHP_EOL; - return; - } - - $put = file_put_contents($filePath, $content); - - if ($put === false) { - echo "put course {$course->id} cover failed" . PHP_EOL; - return; - } - - $keyName = $this->getKeyName($filePath); - $remoteUrl = $storage->putFile($keyName, $filePath); - - if ($remoteUrl) { - $course->cover = $keyName; - $course->update(); - echo "upload cover of course {$course->id} success" . PHP_EOL; - } else { - echo "upload cover of course {$course->id} failed" . PHP_EOL; - } - } - } - - protected function getKeyName($filePath) - { - $ext = pathinfo($filePath, PATHINFO_EXTENSION); - return '/img/cover/' . date('YmdHis') . rand(1000, 9999) . '.' . $ext; - } - -} diff --git a/app/Console/Tasks/LearningTask.php b/app/Console/Tasks/LearningTask.php index 59a5d700..150635d3 100644 --- a/app/Console/Tasks/LearningTask.php +++ b/app/Console/Tasks/LearningTask.php @@ -2,6 +2,7 @@ namespace App\Console\Tasks; +use App\Library\Cache\Backend\Redis as RedisCache; use App\Models\Course as CourseModel; use App\Models\Learning as LearningModel; use App\Repos\Chapter as ChapterRepo; @@ -9,88 +10,109 @@ use App\Repos\ChapterUser as ChapterUserRepo; use App\Repos\Course as CourseRepo; use App\Repos\CourseUser as CourseUserRepo; use App\Repos\Learning as LearningRepo; +use App\Services\LearningSyncer; use Phalcon\Cli\Task; class LearningTask extends Task { /** - * @var \App\Library\Cache\Backend\Redis + * @var RedisCache */ protected $cache; + /** + * @var \Redis + */ + protected $redis; + public function mainAction() { $this->cache = $this->getDI()->get('cache'); - $keys = $this->cache->queryKeys('learning:'); + $this->redis = $this->cache->getRedis(); - if (!$keys) return; + $syncer = new LearningSyncer(); - $keys = array_slice($keys, 0, 500); + $syncKey = $syncer->getSyncKey(); - foreach ($keys as $key) { - $lastKey = $this->cache->getRawKeyName($key); - $this->handleLearning($lastKey); + $requestIds = $this->redis->sMembers($syncKey); + + if (!$requestIds) return; + + foreach ($requestIds as $requestId) { + $itemKey = $syncer->getItemKey($requestId); + $this->handleLearning($itemKey); } + + $this->redis->sRem($syncKey, ...$requestIds); } - protected function handleLearning($key) + /** + * @param string $itemKey + */ + protected function handleLearning($itemKey) { - $content = $this->cache->get($key); + /** + * @var LearningModel $cacheLearning + */ + $cacheLearning = $this->cache->get($itemKey); - if (!$content) return; + if (!$cacheLearning) return; $learningRepo = new LearningRepo(); - $learning = $learningRepo->findByRequestId($content['request_id']); + $dbLearning = $learningRepo->findByRequestId($cacheLearning->request_id); - if (!$learning) { - $learning = new LearningModel(); - $learning->create($content); + if (!$dbLearning) { + $cacheLearning->create(); } else { - $learning->duration += $content['duration']; - $learning->update(); + $dbLearning->duration += $cacheLearning->duration; + $dbLearning->update(); } - $this->updateChapterUser($content['chapter_id'], $content['user_id'], $content['duration'], $content['position']); + $this->updateChapterUser($dbLearning); - $this->cache->delete($key); + $this->cache->delete($itemKey); } - protected function updateChapterUser($chapterId, $userId, $duration = 0, $position = 0) + /** + * @param LearningModel $learning + */ + protected function updateChapterUser(LearningModel $learning) { $chapterUserRepo = new ChapterUserRepo(); - $chapterUser = $chapterUserRepo->findChapterUser($chapterId, $userId); + $chapterUser = $chapterUserRepo->findChapterUser($learning->chapter_id, $learning->user_id); if (!$chapterUser) return; $chapterRepo = new ChapterRepo(); - $chapter = $chapterRepo->findById($chapterId); + $chapter = $chapterRepo->findById($learning->chapter_id); if (!$chapter) return; $chapterModel = $chapter->attrs['model']; - $chapterUser->duration += $duration; + $chapterUser->duration += $learning->duration; /** * 消费规则 + * * 1.点播观看时间大于时长30% * 2.直播观看时间超过10分钟 * 3.图文浏览即消费 */ if ($chapterModel == CourseModel::MODEL_VOD) { - $chapterDuration = $chapter->attrs['duration'] ?: 300; + $duration = $chapter->attrs['duration'] ?: 300; - $progress = floor(100 * $chapterUser->duration / $chapterDuration); + $progress = floor(100 * $chapterUser->duration / $duration); - $chapterUser->position = floor($position); + $chapterUser->position = floor($learning->position); $chapterUser->progress = $progress < 100 ? $progress : 100; - $chapterUser->consumed = $chapterUser->duration > 0.3 * $chapterDuration ? 1 : 0; + $chapterUser->consumed = $chapterUser->duration > 0.3 * $duration ? 1 : 0; } elseif ($chapterModel == CourseModel::MODEL_LIVE) { @@ -108,6 +130,10 @@ class LearningTask extends Task } } + /** + * @param int $courseId + * @param int $userId + */ protected function updateCourseUser($courseId, $userId) { $courseRepo = new CourseRepo(); @@ -142,9 +168,11 @@ class LearningTask extends Task $courseUser = $courseUserRepo->findCourseUser($courseId, $userId); - $courseUser->progress = $progress; - $courseUser->duration = $duration; - $courseUser->update(); + if ($courseUser) { + $courseUser->progress = $progress; + $courseUser->duration = $duration; + $courseUser->update(); + } } } diff --git a/app/Console/Tasks/ManageCourseIndexTask.php b/app/Console/Tasks/ManageCourseIndexTask.php index 5584be01..b2e459cd 100644 --- a/app/Console/Tasks/ManageCourseIndexTask.php +++ b/app/Console/Tasks/ManageCourseIndexTask.php @@ -3,9 +3,11 @@ namespace App\Console\Tasks; use App\Models\Course as CourseModel; -use App\Searchers\CourseDocumenter; -use App\Searchers\CourseSearcher; +use App\Searchers\CourseDocument; +use App\Searchers\CourseSearch; use Phalcon\Cli\Task; +use Phalcon\Mvc\Model\Resultset; +use Phalcon\Mvc\Model\ResultsetInterface; class ManageCourseIndexTask extends Task { @@ -55,7 +57,7 @@ class ManageCourseIndexTask extends Task */ protected function cleanCourseIndex() { - $searcher = new CourseSearcher(); + $searcher = new CourseSearch(); $index = $searcher->getXS()->getIndex(); @@ -77,9 +79,9 @@ class ManageCourseIndexTask extends Task return; } - $searcher = new CourseSearcher(); + $searcher = new CourseSearch(); - $documenter = new CourseDocumenter(); + $documenter = new CourseDocument(); $index = $searcher->getXS()->getIndex(); @@ -106,7 +108,7 @@ class ManageCourseIndexTask extends Task */ protected function searchCourses($query) { - $searcher = new CourseSearcher(); + $searcher = new CourseSearch(); $result = $searcher->search($query); @@ -116,7 +118,7 @@ class ManageCourseIndexTask extends Task /** * 查找课程 * - * @return \Phalcon\Mvc\Model\ResultsetInterface + * @return Resultset|ResultsetInterface */ protected function findCourses() { diff --git a/app/Console/Tasks/ProcessOrderTask.php b/app/Console/Tasks/ProcessOrderTask.php new file mode 100644 index 00000000..27536c4b --- /dev/null +++ b/app/Console/Tasks/ProcessOrderTask.php @@ -0,0 +1,190 @@ +findTasks(); + + if ($tasks->count() == 0) { + return; + } + + $orderRepo = new OrderRepo(); + + foreach ($tasks as $task) { + + try { + + /** + * @var array $itemInfo + */ + $itemInfo = $task->item_info; + + $order = $orderRepo->findById($itemInfo['order']['id']); + + switch ($order->item_type) { + case OrderModel::ITEM_COURSE: + $this->handleCourseOrder($order); + break; + case OrderModel::ITEM_PACKAGE: + $this->handlePackageOrder($order); + break; + case OrderModel::ITEM_VIP: + $this->handleVipOrder($order); + break; + } + + } catch (\Exception $e) { + + $task->try_count += 1; + $task->priority += 1; + + if ($task->try_count > self::TRY_COUNT) { + $task->status = TaskModel::STATUS_FAILED; + } + + $task->update(); + } + } + } + + /** + * @param OrderModel $order + */ + protected function handleCourseOrder(OrderModel $order) + { + /** + * @var array $itemInfo + */ + $itemInfo = $order->item_info; + + $data = [ + 'user_id' => $order->user_id, + 'course_id' => $order->item_id, + 'expiry_time' => $itemInfo['course']['expiry_time'], + 'role_type' => CourseUserModel::ROLE_STUDENT, + 'source_type' => CourseUserModel::SOURCE_CHARGE, + ]; + + $courseUser = new CourseUserModel(); + + if ($courseUser->create($data) === false) { + throw new \RuntimeException('Create Course User Failed'); + } + + $this->handleCourseHistory($data['course_id'], $data['user_id']); + } + + /** + * @param OrderModel $order + */ + protected function handlePackageOrder(OrderModel $order) + { + /** + * @var array $itemInfo + */ + $itemInfo = $order->item_info; + + foreach ($itemInfo['courses'] as $course) { + + $data = [ + 'user_id' => $order->user_id, + 'course_id' => $course['id'], + 'expiry_time' => $course['expiry_time'], + 'role_type' => CourseUserModel::ROLE_STUDENT, + 'source_type' => CourseUserModel::SOURCE_CHARGE, + ]; + + $courseUser = new CourseUserModel(); + + if ($courseUser->create($data) === false) { + throw new \RuntimeException('Create Course User Failed'); + } + + $this->handleCourseHistory($data['course_id'], $data['user_id']); + } + } + + /** + * @param OrderModel $order + */ + protected function handleVipOrder(OrderModel $order) + { + $userRepo = new UserRepo(); + + $user = $userRepo->findById($order->user_id); + + /** + * @var array $itemInfo + */ + $itemInfo = $order->item_info; + + $user->vip_expiry_time = $itemInfo['vip']['expiry_time']; + + if ($user->update() === false) { + throw new \RuntimeException('Update Vip Expiry Failed'); + } + } + + /** + * @param int $courseId + * @param int $userId + */ + protected function handleCourseHistory($courseId, $userId) + { + $courseUserRepo = new CourseUserRepo(); + + $courseUser = $courseUserRepo->findCourseStudent($courseId, $userId); + + if ($courseUser) { + $courseUser->update(['deleted' => 1]); + } + + $courseRepo = new CourseRepo(); + + $userLearnings = $courseRepo->findUserLearnings($courseId, $userId); + + if ($userLearnings->count() > 0) { + $userLearnings->update(['deleted' => 1]); + } + } + + /** + * @param int $limit + * @return ResultsetInterface|Resultset|TaskModel[] + */ + protected function findTasks($limit = 100) + { + $itemType = TaskModel::TYPE_PROCESS_ORDER; + $status = TaskModel::STATUS_PENDING; + $tryCount = self::TRY_COUNT; + + $tasks = TaskModel::query() + ->where('item_type = :item_type:', ['item_type' => $itemType]) + ->andWhere('status = :status:', ['status' => $status]) + ->andWhere('try_count < :try_count:', ['try_count' => $tryCount]) + ->orderBy('priority ASC') + ->limit($limit) + ->execute(); + + return $tasks; + } + +} diff --git a/app/Console/Tasks/RebuildChapterCacheTask.php b/app/Console/Tasks/RebuildChapterCacheTask.php index 6757e723..7eefc278 100644 --- a/app/Console/Tasks/RebuildChapterCacheTask.php +++ b/app/Console/Tasks/RebuildChapterCacheTask.php @@ -6,6 +6,7 @@ use App\Caches\Chapter as ChapterCache; use App\Caches\ChapterCounter as ChapterCounterCache; use App\Repos\Chapter as ChapterRepo; use App\Services\ChapterCacheSyncer; +use Phalcon\Mvc\Model\Resultset; class RebuildChapterCacheTask extends Task { @@ -39,6 +40,9 @@ class RebuildChapterCacheTask extends Task $chapterRepo = new ChapterRepo(); + /** + * @var Resultset $chapters + */ $chapters = $chapterRepo->findByIds($chapterIds); if ($chapters->count() == 0) { diff --git a/app/Console/Tasks/RebuildCourseCacheTask.php b/app/Console/Tasks/RebuildCourseCacheTask.php index fc9abf66..cb55d9a7 100644 --- a/app/Console/Tasks/RebuildCourseCacheTask.php +++ b/app/Console/Tasks/RebuildCourseCacheTask.php @@ -4,14 +4,17 @@ namespace App\Console\Tasks; use App\Caches\Course as CourseCache; use App\Caches\CourseCounter as CourseCounterCache; +use App\Library\Cache\Backend\Redis as RedisCache; +use App\Models\Course as CourseModel; use App\Repos\Course as CourseRepo; use App\Services\CourseCacheSyncer; +use Phalcon\Mvc\Model\Resultset; class RebuildCourseCacheTask extends Task { /** - * @var \App\Library\Cache\Backend\Redis + * @var RedisCache */ protected $cache; @@ -39,6 +42,9 @@ class RebuildCourseCacheTask extends Task $courseRepo = new CourseRepo(); + /** + * @var Resultset|CourseModel[] $courses + */ $courses = $courseRepo->findByIds($courseIds); if ($courses->count() == 0) { @@ -49,10 +55,12 @@ class RebuildCourseCacheTask extends Task $counterCache = new CourseCounterCache(); foreach ($courses as $course) { + $course->user_count = $courseRepo->countUsers($course->id); $course->comment_count = $courseRepo->countComments($course->id); $course->review_count = $courseRepo->countReviews($course->id); $course->favorite_count = $courseRepo->countFavorites($course->id); + $course->update(); $courseCache->rebuild($course->id); diff --git a/app/Console/Tasks/RebuildCourseIndexTask.php b/app/Console/Tasks/RebuildCourseIndexTask.php index a7b885d0..64ba22df 100644 --- a/app/Console/Tasks/RebuildCourseIndexTask.php +++ b/app/Console/Tasks/RebuildCourseIndexTask.php @@ -2,16 +2,17 @@ namespace App\Console\Tasks; +use App\Library\Cache\Backend\Redis as RedisCache; use App\Repos\Course as CourseRepo; -use App\Searchers\CourseDocumenter; -use App\Searchers\CourseSearcher; +use App\Searchers\CourseDocument; +use App\Searchers\CourseSearch; use App\Services\CourseIndexSyncer; class RebuildCourseIndexTask extends Task { /** - * @var \App\Library\Cache\Backend\Redis + * @var RedisCache */ protected $cache; @@ -31,7 +32,7 @@ class RebuildCourseIndexTask extends Task protected function rebuild() { - $key = $this->getCacheKey(); + $key = $this->getSyncKey(); $courseIds = $this->redis->sRandMember($key, 100); @@ -45,16 +46,18 @@ class RebuildCourseIndexTask extends Task return; } - $document = new CourseDocumenter(); + $document = new CourseDocument(); - $searcher = new CourseSearcher(); + $searcher = new CourseSearch(); $index = $searcher->getXS()->getIndex(); $index->openBuffer(); foreach ($courses as $course) { + $doc = $document->setDocument($course); + if ($course->published == 1) { $index->update($doc); } else { @@ -67,11 +70,11 @@ class RebuildCourseIndexTask extends Task $this->redis->sRem($key, ...$courseIds); } - protected function getCacheKey() + protected function getSyncKey() { $syncer = new CourseIndexSyncer(); - return $syncer->getCacheKey(); + return $syncer->getSyncKey(); } } diff --git a/app/Console/Tasks/RefundTask.php b/app/Console/Tasks/RefundTask.php index cc274e5b..d0df4c6a 100644 --- a/app/Console/Tasks/RefundTask.php +++ b/app/Console/Tasks/RefundTask.php @@ -10,13 +10,19 @@ use App\Repos\CourseUser as CourseUserRepo; use App\Repos\Order as OrderRepo; use App\Repos\Refund as RefundRepo; use App\Repos\Trade as TradeRepo; +use App\Repos\User as UserRepo; use App\Services\Alipay as AlipayService; -use App\Services\Wxpay as WxpayService; +use App\Services\Wechat as WechatService; +use Phalcon\Mvc\Model\Resultset; +use Phalcon\Mvc\Model\ResultsetInterface; class RefundTask extends Task { - const TRY_COUNT = 5; + /** + * 重试次数 + */ + const TRY_COUNT = 3; public function mainAction() { @@ -34,15 +40,21 @@ class RefundTask extends Task foreach ($tasks as $task) { - $refund = $refundRepo->findBySn($task->item_info['refund']['sn']); - $trade = $tradeRepo->findBySn($task->item_info['refund']['trade_sn']); - $order = $orderRepo->findBySn($task->item_info['refund']['order_sn']); + /** + * @var array $itemInfo + */ + $itemInfo = $task->item_info; + + $refund = $refundRepo->findById($itemInfo['refund']['id']); + $trade = $tradeRepo->findById($itemInfo['refund']['trade_id']); + $order = $orderRepo->findById($itemInfo['refund']['order_id']); try { $this->db->begin(); $this->handleTradeRefund($trade, $refund); + $this->handleOrderRefund($order); $refund->status = RefundModel::STATUS_FINISHED; @@ -76,6 +88,7 @@ class RefundTask extends Task $this->db->rollback(); $task->try_count += 1; + $task->priority += 1; if ($task->try_count > self::TRY_COUNT) { $task->status = TaskModel::STATUS_FAILED; @@ -104,18 +117,23 @@ class RefundTask extends Task $response = false; if ($trade->channel == TradeModel::CHANNEL_ALIPAY) { + $alipay = new AlipayService(); + $response = $alipay->refundOrder([ 'out_trade_no' => $trade->sn, 'out_request_no' => $refund->sn, 'refund_amount' => $refund->amount, ]); - } elseif ($trade->channel == TradeModel::CHANNEL_WXPAY) { - $wxpay = new WxpayService(); - $response = $wxpay->refundOrder([ + + } elseif ($trade->channel == TradeModel::CHANNEL_WECHAT) { + + $wechat = new WechatService(); + + $response = $wechat->refundOrder([ 'out_trade_no' => $trade->sn, 'out_refund_no' => $refund->sn, - 'total_fee' => 100 * $trade->order_amount, + 'total_fee' => 100 * $trade->amount, 'refund_fee' => 100 * $refund->amount, ]); } @@ -133,19 +151,16 @@ class RefundTask extends Task protected function handleOrderRefund(OrderModel $order) { switch ($order->item_type) { - case OrderModel::TYPE_COURSE: + case OrderModel::ITEM_COURSE: $this->handleCourseOrderRefund($order); break; - case OrderModel::TYPE_PACKAGE: + case OrderModel::ITEM_PACKAGE: $this->handlePackageOrderRefund($order); break; - case OrderModel::TYPE_REWARD: - $this->handleRewardOrderRefund($order); - break; - case OrderModel::TYPE_VIP: + case OrderModel::ITEM_VIP: $this->handleVipOrderRefund($order); break; - case OrderModel::TYPE_TEST: + case OrderModel::ITEM_TEST: $this->handleTestOrderRefund($order); break; } @@ -179,8 +194,15 @@ class RefundTask extends Task { $courseUserRepo = new CourseUserRepo(); - foreach ($order->item_info['courses'] as $course) { + /** + * @var array $itemInfo + */ + $itemInfo = $order->item_info; + + foreach ($itemInfo['courses'] as $course) { + $courseUser = $courseUserRepo->findCourseStudent($course['id'], $order->user_id); + if ($courseUser) { $courseUser->deleted = 1; if ($courseUser->update() === false) { @@ -201,24 +223,17 @@ class RefundTask extends Task $user = $userRepo->findById($order->user_id); - $baseTime = $user->vip_expiry; + /** + * @var array $itemInfo + */ + $itemInfo = $order->item_info; - switch ($order->item_info['vip']['duration']) { - case 'one_month': - $user->vip_expiry = strtotime('-1 months', $baseTime); - break; - case 'three_month': - $user->vip_expiry = strtotime('-3 months', $baseTime); - break; - case 'six_month': - $user->vip_expiry = strtotime('-6 months', $baseTime); - break; - case 'twelve_month': - $user->vip_expiry = strtotime('-12 months', $baseTime); - break; - } + $diffTime = "-{$itemInfo['vip']['expiry']} months"; + $baseTime = $itemInfo['vip']['expiry_time']; - if ($user->vip_expiry < time()) { + $user->vip_expiry_time = strtotime($diffTime, $baseTime); + + if ($user->vip_expiry_time < time()) { $user->vip = 0; } @@ -227,16 +242,6 @@ class RefundTask extends Task } } - /** - * 处理打赏订单退款 - * - * @param OrderModel $order - */ - protected function handleRewardOrderRefund(OrderModel $order) - { - - } - /** * 处理测试订单退款 * @@ -247,6 +252,10 @@ class RefundTask extends Task } + /** + * @param int $limit + * @return ResultsetInterface|Resultset|TaskModel[] + */ protected function findTasks($limit = 5) { $itemType = TaskModel::TYPE_REFUND; @@ -257,7 +266,7 @@ class RefundTask extends Task ->where('item_type = :item_type:', ['item_type' => $itemType]) ->andWhere('status = :status:', ['status' => $status]) ->andWhere('try_count < :try_count:', ['try_count' => $tryCount]) - ->orderBy('priority ASC,try_count DESC') + ->orderBy('priority ASC') ->limit($limit) ->execute(); diff --git a/app/Console/Tasks/ReplySpiderTask.php b/app/Console/Tasks/ReplySpiderTask.php deleted file mode 100644 index 6527fe61..00000000 --- a/app/Console/Tasks/ReplySpiderTask.php +++ /dev/null @@ -1,156 +0,0 @@ -columns(['id']) - ->where('id > 59429') - ->orderBy('id ASC') - ->execute(); - - $ql = $this->getRules(); - - foreach ($threads as $thread) { - $this->handleList($ql, $thread->id); - sleep(5); - } - } - - protected function getRules() - { - $ql = QueryList::getInstance()->rules([ - 'thread_content' => ['div.qa-disscus', 'html'], - 'user_link' => ['div.qa-comment-author > a', 'href'], - 'user_img' => ['div.qa-comment-author > a > img', 'src'], - 'user_name' => ['span.qa-comment-nick', 'text'], - 'reply_id' => ['div.qa-comment', 'data-cid'], - 'reply_content' => ['div.qa-comment-c > div.rich-text', 'html'], - 'reply_time' => ['span.qa-comment-time', 'text'], - ]); - - return $ql; - } - - protected function handleList($ql, $threadId) - { - - $thread = ThreadModel::findFirst($threadId); - - $first = true; - - foreach (range(1, 10) as $page) { - - $url = "https://www.imooc.com/qadetail/{$threadId}?page={$page}"; - - echo "============== Thread {$threadId}, Page {$page} =================" . PHP_EOL; - - $data = $ql->get($url)->query()->getData(); - - if ($data->count() == 0) { - break; - } - - foreach ($data->all() as $item) { - - if ($first) { - $threadContent = $this->getThreadContent($item['thread_content']); - if ($threadContent) { - $thread->update(['content' => $threadContent]); - } - $first = false; - } - - $userData = [ - 'id' => $this->getUserId($item['user_link']), - 'name' => $this->getUserName($item['user_name']), - 'avatar' => $item['user_img'], - ]; - - $user = UserModel::findFirst($userData['id']); - - if (!$user) { - $user = new UserModel(); - $user->create($userData); - } - - $replyData = [ - 'thread_id' => $threadId, - 'author_id' => $user->id, - 'id' => $item['reply_id'], - 'content' => $this->getReplyContent($item['reply_content']), - 'created_at' => $this->getReplyTime($item['reply_time']), - ]; - - $reply = ReplyModel::findFirst($replyData['id']); - - if (!$reply && $replyData['content']) { - $reply = new ReplyModel(); - $reply->create($replyData); - } - } - } - - $ql->destruct(); - } - - protected function getUserId($userLink) - { - $result = str_replace(['/u/', '/bbs'], '', $userLink); - - return trim($result); - } - - protected function getUserName($userName) - { - $result = mb_substr($userName, 0, 30); - - return $result; - } - - protected function getThreadContent($content) - { - $content = str_replace('  ', ' ', $content); - if (mb_strlen($content) > 3000) { - return false; - } - $result = mb_substr($content, 0, 3000); - return $result; - } - - protected function getReplyContent($content) - { - $content = str_replace('  ', ' ', $content); - if (mb_strlen($content) > 1500) { - return false; - } - $result = mb_substr($content, 0, 1500); - return $result; - } - - protected function getReplyTime($time) - { - $date = $this->filter->sanitize($time, ['trim', 'string']); - - if (strpos($date, '天')) { - $days = str_replace(['天前'], '', $date); - $days = intval($days); - $result = strtotime("-{$days} days"); - } else { - $result = strtotime(trim($date)); - } - - return $result; - } - -} diff --git a/app/Console/Tasks/ReviewSpiderTask.php b/app/Console/Tasks/ReviewSpiderTask.php deleted file mode 100644 index 8f7df3bc..00000000 --- a/app/Console/Tasks/ReviewSpiderTask.php +++ /dev/null @@ -1,117 +0,0 @@ -columns(['id']) - ->where('id > 778') - ->orderBy('id ASC') - ->execute(); - - $ql = $this->getRules(); - - foreach ($courses as $course) { - $this->handleList($ql, $course->id); - sleep(5); - } - } - - protected function getRules() - { - $ql = QueryList::rules([ - 'user_link' => ['a.img-box', 'href'], - 'user_img' => ['a.img-box > img', 'src'], - 'user_name' => ['a.img-box > img', 'alt'], - 'review_content' => ['p.content', 'text'], - 'review_rating' => ['div.star-box > span', 'text'], - ]); - - return $ql; - } - - protected function handleList($ql, $courseId) - { - - foreach (range(1, 7) as $page) { - - $url = "https://www.imooc.com/course/coursescore/id/{$courseId}?page={$page}"; - - echo "============== Course {$courseId}, Page {$page} =================" . PHP_EOL; - - $data = $ql->get($url)->query()->getData(); - - if ($data->count() == 0) { - continue; - } - - foreach ($data->all() as $item) { - - $userData = [ - 'id' => $this->getUserId($item['user_link']), - 'name' => $item['user_name'], - 'avatar' => $item['user_img'], - ]; - - $user = UserModel::findFirst($userData['id']); - - if (!$user) { - $user = new UserModel(); - $user->create($userData); - } - - $reviewData = [ - 'user_id' => $user->id, - 'course_id' => $courseId, - 'content' => $this->getReviewContent($item['review_content']), - 'rating' => $this->getReviewRating($item['review_rating']), - ]; - - $reviewRepo = new ReviewRepo(); - - $reviewExist = $reviewRepo->findReview($courseId, $user->id); - - if (!$reviewExist) { - $review = new ReviewModel(); - $review->create($reviewData); - } - } - } - - $ql->destruct(); - } - - protected function getUserId($userLink) - { - $result = str_replace(['/u/', '/courses'], '', $userLink); - - return trim($result); - } - - protected function getReviewRating($rating) - { - $result = str_replace(['分'], '', $rating); - - return intval($result); - } - - protected function getReviewContent($content) - { - $result = $this->filter->sanitize($content, ['trim', 'string']); - - return $result; - } -} diff --git a/app/Console/Tasks/RevokeVipTask.php b/app/Console/Tasks/RevokeVipTask.php new file mode 100644 index 00000000..ca743909 --- /dev/null +++ b/app/Console/Tasks/RevokeVipTask.php @@ -0,0 +1,46 @@ +findUsers(); + + if ($users->count() == 0) { + return; + } + + foreach ($users as $user) { + $user->vip = 0; + $user->update(); + } + } + + /** + * 查找待解锁用户 + * + * @param int $limit + * @return UserModel[]|Resultset|ResultsetInterface + */ + protected function findUsers($limit = 1000) + { + $time = time(); + + $users = UserModel::query() + ->where('vip = 1') + ->andWhere('vip_expiry < :time:', ['time' => $time]) + ->limit($limit) + ->execute(); + + return $users; + } + +} diff --git a/app/Console/Tasks/SpiderTask.php b/app/Console/Tasks/SpiderTask.php deleted file mode 100644 index 586fecc4..00000000 --- a/app/Console/Tasks/SpiderTask.php +++ /dev/null @@ -1,438 +0,0 @@ -where('class_id = 0') - ->execute(); - - foreach ($courses as $course) { - - $url = "http://www.imooc.com/learn/{$course->id}"; - - $ql = QueryList::getInstance()->get($url); - - $userId = $ql->find('img.js-usercard-dialog')->attr('data-userid'); - - if ($userId) { - $user = UserModel::findFirst($userId); - if (!$user || !$user->avatar) { - $this->handleUserInfo2($course->id, $userId); - } - } - - $ql->destruct(); - - echo "finished course " . $course->id . PHP_EOL; - } - } - - public function user2Action() - { - $users = UserModel::query() - ->where('edu_role = 2') - ->andWhere('name = :name:', ['name' => '']) - ->execute(); - - foreach ($users as $user) { - $this->handleUserInfo($user->id); - echo "finished user: {$user->id}" . PHP_EOL; - } - } - - public function courseListAction($params) - { - $category = $params[0] ?? 'html'; - $page = $params[1] ?? 1; - - $categoryId = $this->getCategoryId($category); - - if (empty($categoryId)) { - throw new \Exception('invalid category'); - } - - $url = "http://www.imooc.com/course/list?c={$category}&page={$page}"; - - $data = QueryList::get($url)->rules([ - 'link' => ['a.course-card', 'href'], - 'title' => ['h3.course-card-name', 'text'], - 'cover' => ['img.course-banner', 'data-original'], - 'summary' => ['p.course-card-desc', 'text'], - 'level' => ['.course-card-info>span:even', 'text'], - 'user_count' => ['.course-card-info>span:odd', 'text'], - ])->query()->getData(); - - if ($data->count() == 0) { - return false; - } - - foreach ($data->all() as $item) { - $course = [ - 'id' => substr($item['link'], 7), - 'category_id' => $categoryId, - 'title' => $item['title'], - 'cover' => $item['cover'], - 'summary' => $item['summary'], - 'user_count' => $item['user_count'], - 'level' => $this->getLevel($item['level']), - ]; - $model = new CourseModel(); - $model->save($course); - } - - echo sprintf("saved: %d course", $data->count()); - } - - public function courseAction() - { - $courses = CourseModel::query() - ->where('id = 762') - ->orderBy('id asc') - ->execute(); - - $instance = QueryList::getInstance(); - - foreach ($courses as $course) { - - $url = "http://www.imooc.com/learn/{$course->id}"; - - $ql = $instance->get($url); - - //$this->handleCourseInfo($course, $ql); - - $this->handleCourseChapters($course, $ql); - - //$ql->destruct(); - - echo "finished course " . $course->id . PHP_EOL; - } - } - - public function teacherAction() - { - $users = UserModel::query() - ->where('edu_role = 2') - ->execute(); - - foreach ($users as $user) { - try { - $this->handleTeacherInfo2($user); - echo "finished teacher: {$user->id}" . PHP_EOL; - } catch (\Exception $e) { - echo $e->getMessage() . PHP_EOL; - } - } - } - - protected function handleTeacherInfo2(UserModel $user) - { - $url = "http://www.imooc.com/t/{$user->id}"; - - $ql = QueryList::getInstance()->get($url); - - $data = []; - - $data['avatar'] = $ql->find('img.tea-header')->attr('src'); - $data['name'] = $ql->find('p.tea-nickname')->text(); - $data['title'] = $ql->find('p.tea-professional')->text(); - $data['about'] = $ql->find('p.tea-desc')->text(); - - $user->update($data); - } - - public function userAction() - { - $users = UserModel::query() - ->where('edu_role = 1') - ->execute(); - - foreach ($users as $user) { - $this->handleUserInfo($user->id); - echo "finished user: {$user->id}" . PHP_EOL; - } - } - - protected function handleUserInfo($id) - { - $url = 'https://www.imooc.com/u/' . $id; - - $user = UserModel::findFirst($id); - - try { - - $ql = QueryList::getInstance()->get($url); - - $data = []; - - $data['avatar'] = $ql->find('.user-pic-bg>img')->attr('src'); - $data['name'] = $ql->find('h3.user-name>span')->text(); - $data['about'] = $ql->find('p.user-desc')->text(); - - print_r($data); - - $user->update($data); - - $ql->destruct(); - - } catch (\Exception $e) { - - $user->update(['deleted' => 1]); - - echo "user {$id} not found" . PHP_EOL; - } - } - - protected function handleUserInfo2($courseId, $userId) - { - $url = 'https://www.imooc.com/u/' . $userId; - - $user = UserModel::findFirst($userId); - - try { - - $ql = QueryList::getInstance()->get($url); - - $data = []; - - $data['avatar'] = $ql->find('.user-pic-bg>img')->attr('src'); - $data['name'] = $ql->find('h3.user-name>span')->text(); - $data['about'] = $ql->find('p.user-desc')->text(); - $data['edu_role'] = UserModel::EDU_ROLE_TEACHER; - - if ($user) { - $user->update($data); - } else { - $user = new UserModel(); - $user->create($data); - } - - $cuRepo = new CourseUserRepo(); - - $courseUser = $cuRepo->findCourseUser($courseId, $userId); - - if (!$courseUser) { - $courseUser = new CourseUserModel(); - $courseUser->course_id = $courseId; - $courseUser->user_id = $userId; - $courseUser->role_type = CourseUserModel::ROLE_TEACHER; - $courseUser->expire_time = strtotime('+15 years'); - $courseUser->create(); - } - - echo "teacher {$userId} off " . PHP_EOL; - - $ql->destruct(); - - } catch (\Exception $e) { - - $user->update(['deleted' => 1]); - - echo "user {$userId} not found" . PHP_EOL; - } - } - - protected function handleTeacherInfo($courseId, $userId) - { - $url = "http://www.imooc.com/t/{$userId}"; - - $ql = QueryList::getInstance()->get($url); - - $data = []; - - $data['id'] = $userId; - $data['avatar'] = $ql->find('img.tea-header')->attr('src'); - $data['name'] = $ql->find('p.tea-nickname')->text(); - $data['title'] = $ql->find('p.tea-professional')->text(); - $data['about'] = $ql->find('p.tea-desc')->text(); - $data['edu_role'] = UserModel::EDU_ROLE_TEACHER; - - $user = UserModel::findFirst($userId); - - if ($user) { - $user->update($data); - } else { - $user = new UserModel(); - $user->create($data); - } - - $cuRepo = new CourseUserRepo(); - - $courseUser = $cuRepo->findCourseUser($courseId, $userId); - - if (!$courseUser) { - $courseUser = new CourseUserModel(); - $courseUser->course_id = $courseId; - $courseUser->user_id = $userId; - $courseUser->role_type = CourseUserModel::ROLE_TEACHER; - $courseUser->expire_time = strtotime('+15 years'); - $courseUser->create(); - } - - $ql->destruct(); - - echo "teacher ok" . PHP_EOL; - } - - protected function handleCourseInfo(CourseModel $course, QueryList $ql) - { - $data = []; - - $data['user_id'] = $ql->find('img.js-usercard-dialog')->attr('data-userid'); - $data['description'] = $ql->find('.course-description')->text(); - $data['duration'] = $ql->find('.static-item:eq(1)>.meta-value')->text(); - $data['score'] = $ql->find('.score-btn>.meta-value')->text(); - - $data['attrs']['duration'] = $this->getCourseDuration($data['duration']); - - $course->update($data); - - if ($data['user_id']) { - $this->handleTeacherInfo($course->id, $data['user_id']); - } - - echo "course info ok" . PHP_EOL; - } - - protected function handleCourseChapters(CourseModel $course, QueryList $ql) - { - echo "top chapter" . PHP_EOL; - - $topChapters = $ql->rules([ - 'title' => ['.chapter > h3', 'text'], - 'sub_chapter_html' => ['.chapter > .video', 'html'], - ])->query()->getData(); - - - if ($topChapters->count() == 0) { - return false; - } - - foreach ($topChapters->all() as $item) { - - $data = [ - 'course_id' => $course->id, - 'title' => $item['title'], - ]; - - // create top chapter - $chapter = new ChapterModel(); - $chapter->create($data); - - // create sub chapter - if (!empty($item['sub_chapter_html'])) { - $this->handleSubChapters($chapter, $item['sub_chapter_html']); - } - } - } - - protected function handleSubChapters(ChapterModel $topChapter, $subChapterHtml) - { - $ql = QueryList::html($subChapterHtml); - - $chapters = $ql->find('li')->texts(); - - if ($chapters->count() == 0) { - return false; - } - - foreach ($chapters->all() as $item) { - - /** - * - * preg_match('/(\d{1,}-\d{1,})\s{1,}(.*?)\((.*?)\)/s', $item, $matches); - * - * if (!isset($matches[3]) || empty($matches[3])) { - * continue; - * } - * - * $data = [ - * 'title' => $matches[2], - * 'duration' => $this->getChapterDuration($matches[3]), - * ]; - */ - - $title = str_replace(["开始学习", "\r", "\n", "\t", " "], "", $item); - $title = preg_replace('/\(\d{2}:\d{2}\)/', '', $title); - - $data = []; - $data['course_id'] = $topChapter->course_id; - $data['parent_id'] = $topChapter->id; - $data['title'] = trim($title); - - $model = new ChapterModel(); - $model->create($data); - } - } - - protected function getCourseDuration($duration) - { - $hours = 0; - $minutes = 0; - - if (preg_match('/(.*?)小时(.*?)分/s', $duration, $matches)) { - $hours = trim($matches[1]); - $minutes = trim($matches[2]); - } elseif (preg_match('/(.*?)小时/s', $duration, $matches)) { - $hours = trim($matches[1]); - } elseif (preg_match('/(.*?)分/s', $duration, $matches)) { - $minutes = trim($matches[1]); - } - - return 3600 * $hours + 60 * $minutes; - } - - protected function getChapterDuration($duration) - { - if (strpos($duration, ':') === false) { - return 0; - } - - list($minutes, $seconds) = explode(':', trim($duration)); - - return 60 * $minutes + $seconds; - } - - protected function getLevel($type) - { - $mapping = [ - '入门' => CourseModel::LEVEL_ENTRY, - '初级' => CourseModel::LEVEL_JUNIOR, - '中级' => CourseModel::LEVEL_MEDIUM, - '高级' => CourseModel::LEVEL_SENIOR, - ]; - - return $mapping[$type] ?? CourseModel::LEVEL_ENTRY; - } - - protected function getCategoryId($type) - { - $mapping = [ - 'html' => 1, 'javascript' => 2, 'vuejs' => 10, 'reactjs' => 19, - 'angular' => 18, 'nodejs' => 16, 'jquery' => 15, - 'bootstrap' => 17, 'sassless' => 21, 'webapp' => 22, 'fetool' => 23, - 'html5' => 13, 'css3' => 14, - 'php' => 24, 'java' => 25, 'python' => 26, 'c' => 27, 'cplusplus' => 28, 'ruby' => 29, 'go' => 30, 'csharp' => 31, - 'android' => 32, 'ios' => 33, - 'mysql' => 36, 'mongodb' => 37, 'redis' => 38, 'oracle' => 39, 'pgsql' => 40, - 'cloudcomputing' => 42, 'bigdata' => 43, - 'unity3d' => 34, 'cocos2dx' => 35, - 'dxdh' => 46, 'uitool' => 47, 'uijc' => 48, - ]; - - return $mapping[$type] ?? 0; - } - -} diff --git a/app/Console/Tasks/ThreadSpiderTask.php b/app/Console/Tasks/ThreadSpiderTask.php deleted file mode 100644 index 14a1f481..00000000 --- a/app/Console/Tasks/ThreadSpiderTask.php +++ /dev/null @@ -1,145 +0,0 @@ -columns(['id']) - ->where('id > 494') - ->orderBy('id ASC') - ->execute(); - - $ql = $this->getRules(); - - foreach ($courses as $course) { - $this->handleList($ql, $course->id); - sleep(5); - } - } - - protected function getRules() - { - $ql = QueryList::rules([ - 'user_link' => ['a.media', 'href'], - 'user_img' => ['a.media > img', 'src'], - 'user_name' => ['a.media', 'title'], - //'chapter_link' => ['div.l-box > a:eq(1)', 'href'], - 'thread_link' => ['a.qa-tit', 'href'], - 'thread_title' => ['a.qa-tit', 'text'], - 'thread_time' => ['em.r', 'text'], - ]); - - return $ql; - } - - protected function handleList($ql, $courseId) - { - - foreach (range(1, 10) as $page) { - - $url = "https://www.imooc.com/course/qa/id/{$courseId}/t/2?page={$page}"; - - echo "============== Course {$courseId}, Page {$page} =================" . PHP_EOL; - - $data = $ql->get($url)->query()->getData(); - - if ($data->count() == 0) { - break; - } - - foreach ($data->all() as $item) { - - $userData = [ - 'id' => $this->getUserId($item['user_link']), - 'name' => $this->getUserName($item['user_name']), - 'avatar' => $item['user_img'], - ]; - - $user = UserModel::findFirst($userData['id']); - - if (!$user) { - $user = new UserModel(); - $user->create($userData); - } - - $threadData = [ - 'course_id' => $courseId, - 'author_id' => $user->id, - 'id' => $this->getThreadId($item['thread_link']), - 'title' => $this->getThreadTitle($item['thread_title']), - 'created_at' => $this->getThreadTime($item['thread_time']), - ]; - - $thread = ThreadModel::findFirst($threadData['id']); - - if (!$thread) { - $thread = new ThreadModel(); - $thread->create($threadData); - } - } - } - - $ql->destruct(); - } - - protected function getUserId($userLink) - { - $result = str_replace(['/u/', '/courses'], '', $userLink); - - return trim($result); - } - - protected function getUserName($userName) - { - $result = mb_substr($userName, 0, 30); - - return $result; - } - - protected function getChapterId($chapterLink) - { - $result = str_replace(['/video/'], '', $chapterLink); - - return trim($result); - } - - protected function getThreadId($threadLink) - { - $result = str_replace(['/qadetail/'], '', $threadLink); - - return trim($result); - } - - protected function getThreadTitle($title) - { - $title = $this->filter->sanitize($title, ['trim']); - $result = mb_substr($title, 0, 120); - return $result; - } - - protected function getThreadTime($time) - { - $date = $this->filter->sanitize($time, ['trim', 'string']); - - if (strpos($date, '天')) { - $days = str_replace(['天前'], '', $date); - $days = intval($days); - $result = strtotime("-{$days} days"); - } else { - $result = strtotime(trim($date)); - } - - return $result; - } - -} diff --git a/app/Console/Tasks/TopicSpiderTask.php b/app/Console/Tasks/TopicSpiderTask.php deleted file mode 100644 index 845911e7..00000000 --- a/app/Console/Tasks/TopicSpiderTask.php +++ /dev/null @@ -1,67 +0,0 @@ -columns(['id']) - ->where('id > 810') - ->orderBy('id ASC') - ->execute(); - - foreach ($courses as $course) { - $this->handleList($course->id); - sleep(5); - } - } - - protected function handleList($courseId) - { - $url = "https://www.imooc.com/course/ajaxskillcourse?cid={$courseId}"; - - $content = file_get_contents($url); - - $result = json_decode($content, true); - - $topics = $result['data']; - - echo "============== Course {$courseId} =================" . PHP_EOL; - - if (empty($topics)) { - return; - } - - foreach ($topics as $item) { - - $topicData = [ - 'id' => $item['subject_id'], - 'title' => $item['title'], - 'alias' => $this->getAlias($item['url']), - ]; - - $topic = TopicModel::findFirst($topicData['id']); - - if (!$topic) { - $topic = new TopicModel(); - $topic->create($topicData); - } - } - - } - - protected function getAlias($url) - { - $result = str_replace('//www.imooc.com/topic/', '', $url); - return trim($result); - } - - -} diff --git a/app/Console/Tasks/UnlockUserTask.php b/app/Console/Tasks/UnlockUserTask.php index 47722d55..ee316cf1 100644 --- a/app/Console/Tasks/UnlockUserTask.php +++ b/app/Console/Tasks/UnlockUserTask.php @@ -4,6 +4,8 @@ namespace App\Console\Tasks; use App\Models\User as UserModel; use Phalcon\Cli\Task; +use Phalcon\Mvc\Model\Resultset; +use Phalcon\Mvc\Model\ResultsetInterface; class UnlockUserTask extends Task { @@ -18,7 +20,6 @@ class UnlockUserTask extends Task foreach ($users as $user) { $user->locked = 0; - $user->lock_expiry = 0; $user->update(); } } @@ -27,7 +28,7 @@ class UnlockUserTask extends Task * 查找待解锁用户 * * @param int $limit - * @return \Phalcon\Mvc\Model\ResultsetInterface + * @return UserModel[]|Resultset|ResultsetInterface */ protected function findUsers($limit = 1000) { diff --git a/app/Http/Admin/Controllers/ChapterController.php b/app/Http/Admin/Controllers/ChapterController.php index ac8f2870..d050cd72 100644 --- a/app/Http/Admin/Controllers/ChapterController.php +++ b/app/Http/Admin/Controllers/ChapterController.php @@ -101,9 +101,9 @@ class ChapterController extends Controller switch ($course->model) { case CourseModel::MODEL_VOD: $vod = $contentService->getChapterVod($chapter->id); - $vodFiles = $contentService->getVodFiles($chapter->id); + $playUrls = $contentService->getPlayUrls($chapter->id); $this->view->setVar('vod', $vod); - $this->view->setVar('vod_files', $vodFiles); + $this->view->setVar('play_urls', $playUrls); break; case CourseModel::MODEL_LIVE: $live = $contentService->getChapterLive($chapter->id); diff --git a/app/Http/Admin/Controllers/CommentController.php b/app/Http/Admin/Controllers/CommentController.php new file mode 100644 index 00000000..5271ec20 --- /dev/null +++ b/app/Http/Admin/Controllers/CommentController.php @@ -0,0 +1,121 @@ +request->getQuery('course_id', 'int', 0); + $chapterId = $this->request->getQuery('chapter_id', 'int', 0); + + $commentService = new CommentService(); + + $pager = $commentService->getComments(); + + $chapter = null; + + if ($chapterId > 0) { + $chapter = $commentService->getChapter($chapterId); + $courseId = $chapter->course_id; + } + + $course = null; + + if ($courseId > 0) { + $course = $commentService->getCourse($courseId); + } + + $this->view->setVar('pager', $pager); + $this->view->setVar('course', $course); + $this->view->setVar('chapter', $chapter); + } + + /** + * @Get("/{id:[0-9]+}/edit", name="admin.comment.edit") + */ + public function editAction($id) + { + $commentService = new CommentService(); + + $comment = $commentService->getComment($id); + + $this->view->setVar('comment', $comment); + } + + /** + * @Post("/{id:[0-9]+}/update", name="admin.comment.update") + */ + public function updateAction($id) + { + $commentService = new CommentService(); + + $commentService->update($id); + + $location = $this->request->getHTTPReferer(); + + $content = [ + 'location' => $location, + 'msg' => '更新评论成功', + ]; + + return $this->ajaxSuccess($content); + } + + /** + * @Post("/{id:[0-9]+}/delete", name="admin.comment.delete") + */ + public function deleteAction($id) + { + $commentService = new CommentService(); + + $commentService->deleteComment($id); + + $location = $this->request->getHTTPReferer(); + + $content = [ + 'location' => $location, + 'msg' => '删除评论成功', + ]; + + return $this->ajaxSuccess($content); + } + + + /** + * @Post("/{id:[0-9]+}/restore", name="admin.comment.restore") + */ + public function restoreAction($id) + { + $commentService = new CommentService(); + + $commentService->restoreComment($id); + + $location = $this->request->getHTTPReferer(); + + $content = [ + 'location' => $location, + 'msg' => '还原评论成功', + ]; + + return $this->ajaxSuccess($content); + } + +} diff --git a/app/Http/Admin/Controllers/ConfigController.php b/app/Http/Admin/Controllers/ConfigController.php index b41d4eb0..b08ad249 100644 --- a/app/Http/Admin/Controllers/ConfigController.php +++ b/app/Http/Admin/Controllers/ConfigController.php @@ -157,10 +157,10 @@ class ConfigController extends Controller } else { $alipay = $configService->getSectionConfig('payment.alipay'); - $wxpay = $configService->getSectionConfig('payment.wxpay'); + $wechat = $configService->getSectionConfig('payment.wechat'); $this->view->setVar('alipay', $alipay); - $this->view->setVar('wxpay', $wxpay); + $this->view->setVar('wechat', $wechat); } } @@ -252,23 +252,21 @@ class ConfigController extends Controller */ public function vipAction() { - $section = 'vip'; - $configService = new ConfigService(); if ($this->request->isPost()) { - $data = $this->request->getPost(); + $data = $this->request->getPost('vip'); - $configService->updateSectionConfig($section, $data); + $configService->updateVipConfig($data); return $this->ajaxSuccess(['msg' => '更新配置成功']); } else { - $vip = $configService->getSectionConfig($section); + $vips = $configService->getVipConfig(); - $this->view->setVar('vip', $vip); + $this->view->setVar('vips', $vips); } } diff --git a/app/Http/Admin/Controllers/ConsultController.php b/app/Http/Admin/Controllers/ConsultController.php new file mode 100644 index 00000000..94524ea3 --- /dev/null +++ b/app/Http/Admin/Controllers/ConsultController.php @@ -0,0 +1,108 @@ +request->getQuery('course_id', 'int', 0); + + $consultService = new ConsultService(); + + $pager = $consultService->getConsults(); + + $course = null; + + if ($courseId > 0) { + $course = $consultService->getCourse($courseId); + } + + $this->view->setVar('pager', $pager); + $this->view->setVar('course', $course); + } + + /** + * @Get("/{id:[0-9]+}/edit", name="admin.consult.edit") + */ + public function editAction($id) + { + $consultService = new ConsultService(); + + $consult = $consultService->getConsult($id); + + $this->view->setVar('consult', $consult); + } + + /** + * @Post("/{id:[0-9]+}/update", name="admin.consult.update") + */ + public function updateAction($id) + { + $consultService = new ConsultService(); + + $consultService->updateConsult($id); + + $content = [ + 'msg' => '更新咨询成功', + ]; + + return $this->ajaxSuccess($content); + } + + /** + * @Post("/{id:[0-9]+}/delete", name="admin.consult.delete") + */ + public function deleteAction($id) + { + $consultService = new ConsultService(); + + $consultService->deleteConsult($id); + + $location = $this->request->getHTTPReferer(); + + $content = [ + 'location' => $location, + 'msg' => '删除咨询成功', + ]; + + return $this->ajaxSuccess($content); + } + + /** + * @Post("/{id:[0-9]+}/restore", name="admin.consult.restore") + */ + public function restoreAction($id) + { + $consultService = new ConsultService(); + + $consultService->restoreConsult($id); + + $location = $this->request->getHTTPReferer(); + + $content = [ + 'location' => $location, + 'msg' => '还原咨询成功', + ]; + + return $this->ajaxSuccess($content); + } + +} diff --git a/app/Http/Admin/Controllers/CourseController.php b/app/Http/Admin/Controllers/CourseController.php index d011beb5..23fe8a4d 100644 --- a/app/Http/Admin/Controllers/CourseController.php +++ b/app/Http/Admin/Controllers/CourseController.php @@ -75,11 +75,15 @@ class CourseController extends Controller $xmTeachers = $courseService->getXmTeachers($id); $xmCategories = $courseService->getXmCategories($id); $xmCourses = $courseService->getXmCourses($id); + $studyExpiryOptions = $courseService->getStudyExpiryOptions(); + $refundExpiryOptions = $courseService->getRefundExpiryOptions(); $this->view->setVar('course', $course); $this->view->setVar('xm_teachers', $xmTeachers); $this->view->setVar('xm_categories', $xmCategories); $this->view->setVar('xm_courses', $xmCourses); + $this->view->setVar('study_expiry_options', $studyExpiryOptions); + $this->view->setVar('refund_expiry_options', $refundExpiryOptions); } /** diff --git a/app/Http/Admin/Controllers/OrderController.php b/app/Http/Admin/Controllers/OrderController.php index 37648e91..8e3bbf9d 100644 --- a/app/Http/Admin/Controllers/OrderController.php +++ b/app/Http/Admin/Controllers/OrderController.php @@ -38,8 +38,8 @@ class OrderController extends Controller $orderService = new OrderService(); $order = $orderService->getOrder($id); - $trades = $orderService->getTrades($order->sn); - $refunds = $orderService->getRefunds($order->sn); + $trades = $orderService->getTrades($order->id); + $refunds = $orderService->getRefunds($order->id); $account = $orderService->getAccount($order->user_id); $user = $orderService->getUser($order->user_id); diff --git a/app/Http/Admin/Controllers/RefundController.php b/app/Http/Admin/Controllers/RefundController.php index 1f087576..26e66a20 100644 --- a/app/Http/Admin/Controllers/RefundController.php +++ b/app/Http/Admin/Controllers/RefundController.php @@ -38,8 +38,8 @@ class RefundController extends Controller $refundService = new RefundService(); $refund = $refundService->getRefund($id); - $order = $refundService->getOrder($refund->order_sn); - $trade = $refundService->getTrade($refund->trade_sn); + $order = $refundService->getOrder($refund->order_id); + $trade = $refundService->getTrade($refund->trade_id); $account = $refundService->getAccount($trade->user_id); $user = $refundService->getUser($trade->user_id); diff --git a/app/Http/Admin/Controllers/StudentController.php b/app/Http/Admin/Controllers/StudentController.php index 2e96caba..1244d99e 100644 --- a/app/Http/Admin/Controllers/StudentController.php +++ b/app/Http/Admin/Controllers/StudentController.php @@ -2,7 +2,7 @@ namespace App\Http\Admin\Controllers; -use App\Http\Admin\Services\CourseStudent as CourseStudentService; +use App\Http\Admin\Services\Student as StudentService; /** * @RoutePrefix("/admin/student") @@ -23,14 +23,20 @@ class StudentController extends Controller */ public function listAction() { - $courseId = $this->request->getQuery('course_id', 'int', ''); + $courseId = $this->request->getQuery('course_id', 'int', 0); - $courseStudentService = new CourseStudentService(); + $studentService = new StudentService(); - $pager = $courseStudentService->getCourseStudents(); + $pager = $studentService->getPlans(); + + $course = null; + + if ($courseId > 0) { + $course = $studentService->getCourse($courseId); + } $this->view->setVar('pager', $pager); - $this->view->setVar('course_id', $courseId); + $this->view->setVar('course', $course); } /** @@ -38,9 +44,17 @@ class StudentController extends Controller */ public function addAction() { - $courseId = $this->request->getQuery('course_id', 'int', ''); + $courseId = $this->request->getQuery('course_id', 'int', 0); - $this->view->setVar('course_id', $courseId); + $studentService = new StudentService(); + + $course = null; + + if ($courseId > 0) { + $course = $studentService->getCourse($courseId); + } + + $this->view->setVar('course', $course); } /** @@ -48,9 +62,9 @@ class StudentController extends Controller */ public function createAction() { - $courseStudentService = new CourseStudentService(); + $studentService = new StudentService(); - $student = $courseStudentService->createCourseStudent(); + $student = $studentService->createPlan(); $location = $this->url->get( ['for' => 'admin.student.list'], @@ -70,16 +84,15 @@ class StudentController extends Controller */ public function editAction() { - $courseId = $this->request->getQuery('course_id', 'int'); - $userId = $this->request->getQuery('user_id', 'int'); + $planId = $this->request->getQuery('plan_id'); - $courseStudentService = new CourseStudentService(); + $studentService = new StudentService(); - $courseStudent = $courseStudentService->getCourseStudent($courseId, $userId); - $course = $courseStudentService->getCourse($courseId); - $student = $courseStudentService->getStudent($userId); + $plan = $studentService->getPlan($planId); + $course = $studentService->getCourse($plan->course_id); + $student = $studentService->getStudent($plan->user_id); - $this->view->setVar('course_student', $courseStudent); + $this->view->setVar('plan', $plan); $this->view->setVar('course', $course); $this->view->setVar('student', $student); } @@ -89,14 +102,11 @@ class StudentController extends Controller */ public function updateAction() { - $courseStudentService = new CourseStudentService(); + $studentService = new StudentService(); - $student = $courseStudentService->updateCourseStudent(); + $studentService->updatePlan(); - $location = $this->url->get( - ['for' => 'admin.student.list'], - ['course_id' => $student->course_id] - ); + $location = $this->url->get(['for' => 'admin.student.list']); $content = [ 'location' => $location, @@ -111,9 +121,9 @@ class StudentController extends Controller */ public function learningAction() { - $courseStudentService = new CourseStudentService(); + $studentService = new StudentService(); - $pager = $courseStudentService->getCourseLearnings(); + $pager = $studentService->getLearnings(); $this->view->setVar('pager', $pager); } diff --git a/app/Http/Admin/Controllers/TestController.php b/app/Http/Admin/Controllers/TestController.php index 92e376e8..75699b37 100644 --- a/app/Http/Admin/Controllers/TestController.php +++ b/app/Http/Admin/Controllers/TestController.php @@ -165,7 +165,7 @@ class TestController extends Controller $this->db->rollback(); } - $this->view->pick('config/alipay_test'); + $this->view->pick('config/payment_alipay_test'); $this->view->setVar('trade', $trade); $this->view->setVar('qrcode', $qrcode); } diff --git a/app/Http/Admin/Controllers/TradeController.php b/app/Http/Admin/Controllers/TradeController.php index d547df2f..d180abb8 100644 --- a/app/Http/Admin/Controllers/TradeController.php +++ b/app/Http/Admin/Controllers/TradeController.php @@ -38,8 +38,8 @@ class TradeController extends Controller $tradeService = new TradeService(); $trade = $tradeService->getTrade($id); - $refunds = $tradeService->getRefunds($trade->sn); - $order = $tradeService->getOrder($trade->order_sn); + $refunds = $tradeService->getRefunds($trade->id); + $order = $tradeService->getOrder($trade->order_id); $account = $tradeService->getAccount($trade->user_id); $user = $tradeService->getUser($trade->user_id); diff --git a/app/Http/Admin/Controllers/StorageController.php b/app/Http/Admin/Controllers/UploadController.php similarity index 80% rename from app/Http/Admin/Controllers/StorageController.php rename to app/Http/Admin/Controllers/UploadController.php index 48294581..196c098f 100644 --- a/app/Http/Admin/Controllers/StorageController.php +++ b/app/Http/Admin/Controllers/UploadController.php @@ -5,13 +5,13 @@ namespace App\Http\Admin\Controllers; use App\Services\Storage as StorageService; /** - * @RoutePrefix("/admin/storage") + * @RoutePrefix("/admin/upload") */ -class StorageController extends Controller +class UploadController extends Controller { /** - * @Post("/cover/img/upload", name="admin.storage.cover.img.upload") + * @Post("/cover/img", name="admin.upload.cover.img") */ public function uploadCoverImageAction() { @@ -29,7 +29,7 @@ class StorageController extends Controller } /** - * @Post("/content/img/upload", name="admin.content.img.upload") + * @Post("/content/img", name="admin.upload.content.img") */ public function uploadContentImageAction() { diff --git a/app/Http/Admin/Controllers/UserController.php b/app/Http/Admin/Controllers/UserController.php index 8b068691..51011de7 100644 --- a/app/Http/Admin/Controllers/UserController.php +++ b/app/Http/Admin/Controllers/UserController.php @@ -81,9 +81,11 @@ class UserController extends Controller $userService = new UserService(); $user = $userService->getUser($id); + $account = $userService->getAccount($id); $roles = $userService->getRoles(); $this->view->setVar('user', $user); + $this->view->setVar('account', $account); $this->view->setVar('roles', $roles); } @@ -92,9 +94,15 @@ class UserController extends Controller */ public function updateAction($id) { + $type = $this->request->getPost('type'); + $userService = new UserService(); - $userService->updateUser($id); + if ($type == 'user') { + $userService->updateUser($id); + } else { + $userService->updateAccount($id); + } $location = $this->url->get(['for' => 'admin.user.list']); diff --git a/app/Http/Admin/Controllers/VodController.php b/app/Http/Admin/Controllers/VodController.php index a85a8f06..0f63c89c 100644 --- a/app/Http/Admin/Controllers/VodController.php +++ b/app/Http/Admin/Controllers/VodController.php @@ -18,9 +18,9 @@ class VodController extends Controller */ public function uploadSignatureAction() { - $service = new VodService(); + $vodService = new VodService(); - $signature = $service->getUploadSignature(); + $signature = $vodService->getUploadSignature(); return $this->ajaxSuccess(['signature' => $signature]); } @@ -30,7 +30,6 @@ class VodController extends Controller */ public function playerAction() { - $courseId = $this->request->getQuery('course_id'); $chapterId = $this->request->getQuery('chapter_id'); $playUrl = $this->request->getQuery('play_url'); @@ -38,7 +37,6 @@ class VodController extends Controller $this->view->pick('public/vod_player'); - $this->view->setVar('course_id', $courseId); $this->view->setVar('chapter_id', $chapterId); $this->view->setVar('play_url', urldecode($playUrl)); } @@ -54,13 +52,12 @@ class VodController extends Controller $learning->user_id = $this->authUser->id; $learning->request_id = $query['request_id']; - $learning->course_id = $query['course_id']; $learning->chapter_id = $query['chapter_id']; $learning->position = $query['position']; $syncerService = new LearningSyncerService(); - $syncerService->save($learning, $query['timeout']); + $syncerService->addItem($learning, $query['timeout']); return $this->ajaxSuccess(); } diff --git a/app/Http/Admin/Services/AlipayTest.php b/app/Http/Admin/Services/AlipayTest.php index c61ea9bf..09c49653 100644 --- a/app/Http/Admin/Services/AlipayTest.php +++ b/app/Http/Admin/Services/AlipayTest.php @@ -26,7 +26,9 @@ class AlipayTest extends PaymentTest ]; $alipayService = new AlipayService(); + $qrcode = $alipayService->getQrCode($outOrder); + $result = $qrcode ?: false; return $result; @@ -40,12 +42,15 @@ class AlipayTest extends PaymentTest public function cancelTestOrder($sn) { $tradeRepo = new TradeRepo(); + $trade = $tradeRepo->findBySn($sn); $orderRepo = new OrderRepo(); - $order = $orderRepo->findBySn($trade->order_sn); + + $order = $orderRepo->findById($trade->order_id); $alipayService = new AlipayService(); + $response = $alipayService->cancelOrder($trade->sn); if ($response) { diff --git a/app/Http/Admin/Services/AuthMenu.php b/app/Http/Admin/Services/AuthMenu.php index 31a13654..449309f3 100644 --- a/app/Http/Admin/Services/AuthMenu.php +++ b/app/Http/Admin/Services/AuthMenu.php @@ -2,9 +2,9 @@ namespace App\Http\Admin\Services; -use Phalcon\Mvc\User\Component as UserComponent; +use Phalcon\Mvc\User\Component; -class AuthMenu extends UserComponent +class AuthMenu extends Component { diff --git a/app/Http/Admin/Services/AuthNode.php b/app/Http/Admin/Services/AuthNode.php index 384fe6e2..d7757568 100644 --- a/app/Http/Admin/Services/AuthNode.php +++ b/app/Http/Admin/Services/AuthNode.php @@ -154,6 +154,68 @@ class AuthNode extends Service ], ], ], + [ + 'id' => '1-5', + 'label' => '单页管理', + 'type' => 'menu', + 'child' => [ + [ + 'id' => '1-5-1', + 'label' => '单页列表', + 'type' => 'menu', + 'route' => 'admin.page.list', + ], + [ + 'id' => '1-5-2', + 'label' => '添加单页', + 'type' => 'menu', + 'route' => 'admin.page.add', + ], + [ + 'id' => '1-5-3', + 'label' => '编辑单页', + 'type' => 'button', + 'route' => 'admin.page.edit', + ], + [ + 'id' => '1-5-4', + 'label' => '删除单页', + 'type' => 'button', + 'route' => 'admin.page.delete', + ], + ], + ], + [ + 'id' => '1-6', + 'label' => '帮助管理', + 'type' => 'menu', + 'child' => [ + [ + 'id' => '1-6-1', + 'label' => '帮助列表', + 'type' => 'menu', + 'route' => 'admin.help.list', + ], + [ + 'id' => '1-6-2', + 'label' => '添加帮助', + 'type' => 'menu', + 'route' => 'admin.help.add', + ], + [ + 'id' => '1-6-3', + 'label' => '编辑帮助', + 'type' => 'button', + 'route' => 'admin.help.edit', + ], + [ + 'id' => '1-6-4', + 'label' => '删除帮助', + 'type' => 'button', + 'route' => 'admin.help.delete', + ], + ], + ], ], ]; @@ -167,30 +229,30 @@ class AuthNode extends Service 'label' => '运营管理', 'child' => [ [ - 'id' => '2-5', + 'id' => '2-1', 'label' => '学员管理', 'type' => 'menu', 'child' => [ [ - 'id' => '2-5-1', + 'id' => '2-1-1', 'label' => '学员列表', 'type' => 'menu', 'route' => 'admin.student.list', ], [ - 'id' => '2-5-2', + 'id' => '2-1-2', 'label' => '搜索学员', 'type' => 'menu', 'route' => 'admin.student.search', ], [ - 'id' => '2-5-3', + 'id' => '2-1-3', 'label' => '添加学员', 'type' => 'menu', 'route' => 'admin.student.add', ], [ - 'id' => '2-5-4', + 'id' => '2-1-4', 'label' => '编辑学员', 'type' => 'button', 'route' => 'admin.student.edit', @@ -198,30 +260,61 @@ class AuthNode extends Service ], ], [ - 'id' => '2-1', + 'id' => '2-2', + 'label' => '咨询管理', + 'type' => 'menu', + 'child' => [ + [ + 'id' => '2-2-1', + 'label' => '咨询列表', + 'type' => 'menu', + 'route' => 'admin.consult.list', + ], + [ + 'id' => '2-2-2', + 'label' => '搜索咨询', + 'type' => 'menu', + 'route' => 'admin.consult.search', + ], + [ + 'id' => '2-2-3', + 'label' => '编辑咨询', + 'type' => 'button', + 'route' => 'admin.consult.edit', + ], + [ + 'id' => '2-2-4', + 'label' => '删除咨询', + 'type' => 'button', + 'route' => 'admin.consult.delete', + ], + ], + ], + [ + 'id' => '2-3', 'label' => '评价管理', 'type' => 'menu', 'child' => [ [ - 'id' => '2-1-1', + 'id' => '2-3-1', 'label' => '评价列表', 'type' => 'menu', 'route' => 'admin.review.list', ], [ - 'id' => '2-1-2', + 'id' => '2-3-2', 'label' => '搜索评价', 'type' => 'menu', 'route' => 'admin.review.search', ], [ - 'id' => '2-1-3', + 'id' => '2-3-3', 'label' => '编辑评价', 'type' => 'button', 'route' => 'admin.review.edit', ], [ - 'id' => '2-1-4', + 'id' => '2-3-4', 'label' => '删除评价', 'type' => 'button', 'route' => 'admin.review.delete', @@ -229,67 +322,67 @@ class AuthNode extends Service ], ], [ - 'id' => '2-3', + 'id' => '2-4', + 'label' => '评论管理', + 'type' => 'menu', + 'child' => [ + [ + 'id' => '2-4-1', + 'label' => '评论列表', + 'type' => 'menu', + 'route' => 'admin.comment.list', + ], + [ + 'id' => '2-4-2', + 'label' => '搜索评论', + 'type' => 'menu', + 'route' => 'admin.comment.search', + ], + [ + 'id' => '2-4-3', + 'label' => '编辑评论', + 'type' => 'button', + 'route' => 'admin.comment.edit', + ], + [ + 'id' => '2-4-4', + 'label' => '删除评论', + 'type' => 'button', + 'route' => 'admin.comment.delete', + ], + ], + ], + [ + 'id' => '2-5', 'label' => '轮播管理', 'type' => 'menu', 'child' => [ [ - 'id' => '2-3-1', + 'id' => '2-5-1', 'label' => '轮播列表', 'type' => 'menu', 'route' => 'admin.slide.list', ], [ - 'id' => '2-3-2', + 'id' => '2-5-2', 'label' => '添加轮播', 'type' => 'menu', 'route' => 'admin.slide.add', ], [ - 'id' => '2-3-3', + 'id' => '2-5-3', 'label' => '编辑轮播', 'type' => 'button', 'route' => 'admin.slide.edit', ], [ - 'id' => '2-3-4', + 'id' => '2-5-4', 'label' => '删除轮播', 'type' => 'button', 'route' => 'admin.slide.delete', ], ], ], - [ - 'id' => '2-4', - 'label' => '单页管理', - 'type' => 'menu', - 'child' => [ - [ - 'id' => '2-4-1', - 'label' => '单页列表', - 'type' => 'menu', - 'route' => 'admin.page.list', - ], - [ - 'id' => '2-4-2', - 'label' => '添加单页', - 'type' => 'menu', - 'route' => 'admin.page.add', - ], - [ - 'id' => '2-4-3', - 'label' => '编辑单页', - 'type' => 'button', - 'route' => 'admin.page.edit', - ], - [ - 'id' => '2-4-4', - 'label' => '删除单页', - 'type' => 'button', - 'route' => 'admin.page.delete', - ], - ], - ], [ 'id' => '2-6', 'label' => '导航管理', @@ -321,37 +414,6 @@ class AuthNode extends Service ], ], ], - [ - 'id' => '2-7', - 'label' => '帮助管理', - 'type' => 'menu', - 'child' => [ - [ - 'id' => '2-7-1', - 'label' => '帮助列表', - 'type' => 'menu', - 'route' => 'admin.help.list', - ], - [ - 'id' => '2-7-2', - 'label' => '添加帮助', - 'type' => 'menu', - 'route' => 'admin.help.add', - ], - [ - 'id' => '2-7-3', - 'label' => '编辑帮助', - 'type' => 'button', - 'route' => 'admin.help.edit', - ], - [ - 'id' => '2-7-4', - 'label' => '删除帮助', - 'type' => 'button', - 'route' => 'admin.help.delete', - ], - ], - ], ], ]; diff --git a/app/Http/Admin/Services/AuthUser.php b/app/Http/Admin/Services/AuthUser.php index 5623d0f9..03e28620 100644 --- a/app/Http/Admin/Services/AuthUser.php +++ b/app/Http/Admin/Services/AuthUser.php @@ -5,8 +5,9 @@ namespace App\Http\Admin\Services; use App\Models\Role as RoleModel; use App\Models\User as UserModel; use App\Repos\Role as RoleRepo; +use Phalcon\Mvc\User\Component; -class AuthUser extends \Phalcon\Mvc\User\Component +class AuthUser extends Component { /** diff --git a/app/Http/Admin/Services/Category.php b/app/Http/Admin/Services/Category.php index 3d2ee3e6..5ff4782a 100644 --- a/app/Http/Admin/Services/Category.php +++ b/app/Http/Admin/Services/Category.php @@ -5,6 +5,7 @@ namespace App\Http\Admin\Services; use App\Models\Category as CategoryModel; use App\Repos\Category as CategoryRepo; use App\Validators\Category as CategoryValidator; +use Phalcon\Mvc\Model\Resultset; class Category extends Service { @@ -179,6 +180,9 @@ class Category extends Service { $categoryRepo = new CategoryRepo(); + /** + * @var Resultset|CategoryModel[] $categories + */ $categories = $categoryRepo->findAll(['parent_id' => $parentId]); if ($categories->count() == 0) { @@ -195,6 +199,9 @@ class Category extends Service { $categoryRepo = new CategoryRepo(); + /** + * @var Resultset|CategoryModel[] $categories + */ $categories = $categoryRepo->findAll(['parent_id' => $parentId]); if ($categories->count() == 0) { diff --git a/app/Http/Admin/Services/Chapter.php b/app/Http/Admin/Services/Chapter.php index b96ab6ed..fd12c551 100644 --- a/app/Http/Admin/Services/Chapter.php +++ b/app/Http/Admin/Services/Chapter.php @@ -64,6 +64,8 @@ class Chapter extends Service $this->updateChapterStats($chapter); $this->updateCourseStats($chapter); + $this->eventsManager->fire('chapterAdmin:afterCreate', $this, $chapter); + return $chapter; } @@ -105,6 +107,8 @@ class Chapter extends Service $this->updateChapterStats($chapter); $this->updateCourseStats($chapter); + $this->eventsManager->fire('chapterAdmin:afterUpdate', $this, $chapter); + return $chapter; } @@ -123,6 +127,8 @@ class Chapter extends Service $this->updateChapterStats($chapter); $this->updateCourseStats($chapter); + $this->eventsManager->fire('chapterAdmin:afterDelete', $this, $chapter); + return $chapter; } @@ -137,6 +143,8 @@ class Chapter extends Service $this->updateChapterStats($chapter); $this->updateCourseStats($chapter); + $this->eventsManager->fire('chapterAdmin:afterRestore', $this, $chapter); + return $chapter; } diff --git a/app/Http/Admin/Services/ChapterContent.php b/app/Http/Admin/Services/ChapterContent.php index 38c8d109..b2597d33 100644 --- a/app/Http/Admin/Services/ChapterContent.php +++ b/app/Http/Admin/Services/ChapterContent.php @@ -43,13 +43,13 @@ class ChapterContent extends Service return $result; } - public function getVodFiles($chapterId) + public function getPlayUrls($chapterId) { $chapterVodService = new ChapterVodService(); - $vodFiles = $chapterVodService->getVodFiles($chapterId); + $playUrls = $chapterVodService->getPlayUrls($chapterId); - return kg_array_object($vodFiles); + return kg_array_object($playUrls); } public function updateChapterContent($chapterId) diff --git a/app/Http/Admin/Services/Comment.php b/app/Http/Admin/Services/Comment.php new file mode 100644 index 00000000..757a7a4d --- /dev/null +++ b/app/Http/Admin/Services/Comment.php @@ -0,0 +1,161 @@ +getParams(); + + $params['deleted'] = $params['deleted'] ?? 0; + + $sort = $pagerQuery->getSort(); + $page = $pagerQuery->getPage(); + $limit = $pagerQuery->getLimit(); + + $commentRepo = new CommentRepo(); + + $pager = $commentRepo->paginate($params, $sort, $page, $limit); + + $result = $this->handleComments($pager); + + return $result; + } + + public function getCourse($courseId) + { + $courseRepo = new CourseRepo(); + + $result = $courseRepo->findById($courseId); + + return $result; + } + + public function getChapter($chapterId) + { + $chapterRepo = new ChapterRepo(); + + $result = $chapterRepo->findById($chapterId); + + return $result; + } + + public function getComment($id) + { + $comment = $this->findOrFail($id); + + return $comment; + } + + public function updateComment($id) + { + $comment = $this->findOrFail($id); + + $post = $this->request->getPost(); + + $validator = new CommentValidator(); + + $data = []; + + if (isset($post['content'])) { + $data['content'] = $validator->checkContent($post['content']); + } + + if (isset($post['published'])) { + $data['published'] = $validator->checkPublishStatus($post['published']); + } + + $comment->update($data); + + return $comment; + } + + public function deleteComment($id) + { + $comment = $this->findOrFail($id); + + $comment->deleted = 1; + + $comment->update(); + + $chapterRepo = new ChapterRepo(); + + $chapter = $chapterRepo->findById($comment->chapter_id); + + $chapter->comment_count -= 1; + + $chapter->update(); + + $courseRepo = new CourseRepo(); + + $course = $courseRepo->findById($comment->course_id); + + $course->comment_count -= 1; + + $course->update(); + } + + public function restoreComment($id) + { + $comment = $this->findOrFail($id); + + $comment->deleted = 0; + + $comment->update(); + + $chapterRepo = new ChapterRepo(); + + $chapter = $chapterRepo->findById($comment->chapter_id); + + $chapter->comment_count += 1; + + $chapter->update(); + + $courseRepo = new CourseRepo(); + + $course = $courseRepo->findById($comment->course_id); + + $course->comment_count += 1; + + $course->update(); + } + + private function findOrFail($id) + { + $validator = new CommentValidator(); + + $result = $validator->checkComment($id); + + return $result; + } + + private function handleComments($pager) + { + if ($pager->total_items > 0) { + + $builder = new CommentListBuilder(); + + $pipeA = $pager->items->toArray(); + $pipeB = $builder->handleCourses($pipeA); + $pipeC = $builder->handleChapters($pipeB); + $pipeD = $builder->handleUsers($pipeC); + $pipeE = $builder->arrayToObject($pipeD); + + $pager->items = $pipeE; + } + + return $pager; + } + +} diff --git a/app/Http/Admin/Services/Config.php b/app/Http/Admin/Services/Config.php index 428c2f3f..e33ae55b 100644 --- a/app/Http/Admin/Services/Config.php +++ b/app/Http/Admin/Services/Config.php @@ -3,6 +3,7 @@ namespace App\Http\Admin\Services; use App\Repos\Config as ConfigRepo; +use App\Repos\Vip as VipRepo; class Config extends Service { @@ -108,4 +109,24 @@ class Config extends Service $this->updateSectionConfig($section, $config); } + public function getVipConfig() + { + $vipRepo = new VipRepo(); + + $config = $vipRepo->findAll(['deleted' => 0]); + + return $config; + } + + public function updateVipConfig($items) + { + $vipRepo = new VipRepo(); + + foreach ($items as $id => $price) { + $vip = $vipRepo->findById($id); + $vip->price = $price; + $vip->update(); + } + } + } diff --git a/app/Http/Admin/Services/Consult.php b/app/Http/Admin/Services/Consult.php new file mode 100644 index 00000000..8e2a862b --- /dev/null +++ b/app/Http/Admin/Services/Consult.php @@ -0,0 +1,136 @@ +getParams(); + + $params['deleted'] = $params['deleted'] ?? 0; + + $sort = $pagerQuery->getSort(); + $page = $pagerQuery->getPage(); + $limit = $pagerQuery->getLimit(); + + $consultRepo = new ConsultRepo(); + + $pager = $consultRepo->paginate($params, $sort, $page, $limit); + + return $this->handleConsults($pager); + } + + public function getCourse($courseId) + { + $courseRepo = new CourseRepo(); + + $result = $courseRepo->findById($courseId); + + return $result; + } + + public function getConsult($id) + { + $result = $this->findOrFail($id); + + return $result; + } + + public function updateConsult($id) + { + $consult = $this->findOrFail($id); + + $post = $this->request->getPost(); + + $validator = new ConsultValidator(); + + $data = []; + + if (isset($post['question'])) { + $data['question'] = $validator->checkQuestion($post['question']); + } + + if (isset($post['answer'])) { + $data['answer'] = $validator->checkAnswer($post['answer']); + } + + if (isset($post['published'])) { + $data['published'] = $validator->checkPublishStatus($post['published']); + } + + $consult->update($data); + + return $consult; + } + + public function deleteConsult($id) + { + $consult = $this->findOrFail($id); + + $consult->deleted = 1; + + $consult->update(); + + $courseRepo = new CourseRepo(); + + $course = $courseRepo->findById($consult->course_id); + + $course->consult_count -= 1; + + $course->update(); + } + + public function restoreConsult($id) + { + $consult = $this->findOrFail($id); + + $consult->deleted = 0; + + $consult->update(); + + $courseRepo = new CourseRepo(); + + $course = $courseRepo->findById($consult->course_id); + + $course->consult_count += 1; + + $course->update(); + } + + protected function findOrFail($id) + { + $validator = new ConsultValidator(); + + $result = $validator->checkConsult($id); + + return $result; + } + + protected function handleConsults($pager) + { + if ($pager->total_items > 0) { + + $builder = new ConsultListBuilder(); + + $pipeA = $pager->items->toArray(); + $pipeB = $builder->handleCourses($pipeA); + $pipeC = $builder->handleUsers($pipeB); + $pipeD = $builder->arrayToObject($pipeC); + + $pager->items = $pipeD; + } + + return $pager; + } + +} diff --git a/app/Http/Admin/Services/Course.php b/app/Http/Admin/Services/Course.php index fca9fdfc..bfaff11d 100644 --- a/app/Http/Admin/Services/Course.php +++ b/app/Http/Admin/Services/Course.php @@ -4,10 +4,12 @@ namespace App\Http\Admin\Services; use App\Builders\CourseList as CourseListBuilder; 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\Models\User as UserModel; use App\Repos\Category as CategoryRepo; use App\Repos\Chapter as ChapterRepo; use App\Repos\Course as CourseRepo; @@ -16,6 +18,7 @@ use App\Repos\CourseRelated as CourseRelatedRepo; use App\Repos\CourseUser as CourseUserRepo; use App\Repos\User as UserRepo; use App\Validators\Course as CourseValidator; +use Phalcon\Mvc\Model\Resultset; class Course extends Service { @@ -61,12 +64,13 @@ class Course extends Service $data['model'] = $validator->checkModel($post['model']); $data['title'] = $validator->checkTitle($post['title']); - $data['published'] = 0; $course = new CourseModel(); $course->create($data); + $this->eventsManager->fire('courseAdmin:afterCreate', $this, $course); + return $course; } @@ -111,7 +115,8 @@ class Course extends Service } else { $data['market_price'] = $validator->checkMarketPrice($post['market_price']); $data['vip_price'] = $validator->checkVipPrice($post['vip_price']); - $data['expiry'] = $validator->checkExpiry($post['expiry']); + $data['study_expiry'] = $validator->checkStudyExpiry($post['study_expiry']); + $data['refund_expiry'] = $validator->checkRefundExpiry($post['refund_expiry']); } } @@ -136,6 +141,8 @@ class Course extends Service $course->update($data); + $this->eventsManager->fire('courseAdmin:afterUpdate', $this, $course); + return $course; } @@ -147,6 +154,8 @@ class Course extends Service $course->update(); + $this->eventsManager->fire('courseAdmin:afterDelete', $this, $course); + return $course; } @@ -158,13 +167,32 @@ class Course extends Service $course->update(); + $this->eventsManager->fire('courseAdmin:afterRestore', $this, $course); + return $course; } + public function getStudyExpiryOptions() + { + $options = CourseModel::studyExpiryOptions(); + + return kg_array_object($options); + } + + public function getRefundExpiryOptions() + { + $options = CourseModel::refundExpiryOptions(); + + return kg_array_object($options); + } + public function getXmCategories($id) { $categoryRepo = new CategoryRepo(); + /** + * @var Resultset|CategoryModel[] $allCategories + */ $allCategories = $categoryRepo->findAll(['deleted' => 0]); if ($allCategories->count() == 0) { @@ -174,8 +202,14 @@ class Course extends Service $courseCategoryIds = []; if ($id > 0) { + $courseRepo = new CourseRepo(); + + /** + * @var Resultset|CategoryModel[] $courseCategories + */ $courseCategories = $courseRepo->findCategories($id); + if ($courseCategories->count() > 0) { foreach ($courseCategories as $category) { $courseCategoryIds[] = $category->id; @@ -214,6 +248,9 @@ class Course extends Service { $userRepo = new UserRepo(); + /** + * @var Resultset|UserModel[] $allTeachers + */ $allTeachers = $userRepo->findTeachers(); if ($allTeachers->count() == 0) { @@ -223,8 +260,14 @@ class Course extends Service $courseTeacherIds = []; if ($id > 0) { + $courseRepo = new CourseRepo(); + + /** + * @var Resultset|UserModel[] $courseTeachers + */ $courseTeachers = $courseRepo->findTeachers($id); + if ($courseTeachers->count() > 0) { foreach ($courseTeachers as $teacher) { $courseTeacherIds[] = $teacher->id; @@ -250,6 +293,9 @@ class Course extends Service { $courseRepo = new CourseRepo(); + /** + * @var Resultset|CourseModel[] $courses + */ $courses = $courseRepo->findRelatedCourses($id); $list = []; @@ -297,6 +343,9 @@ class Course extends Service { $courseRepo = new CourseRepo(); + /** + * @var Resultset|UserModel[] $courseTeachers + */ $courseTeachers = $courseRepo->findTeachers($course->id); $originTeacherIds = []; @@ -318,7 +367,7 @@ class Course extends Service 'user_id' => $teacherId, 'role_type' => CourseUserModel::ROLE_TEACHER, 'source_type' => CourseUserModel::SOURCE_IMPORT, - 'expire_time' => strtotime('+10 years'), + 'expiry_time' => strtotime('+10 years'), ]); } } @@ -340,6 +389,9 @@ class Course extends Service { $courseRepo = new CourseRepo(); + /** + * @var Resultset|CategoryModel[] $courseCategories + */ $courseCategories = $courseRepo->findCategories($course->id); $originCategoryIds = []; @@ -380,6 +432,9 @@ class Course extends Service { $courseRepo = new CourseRepo(); + /** + * @var Resultset|CourseModel[] $relatedCourses + */ $relatedCourses = $courseRepo->findRelatedCourses($course->id); $originRelatedIds = []; diff --git a/app/Http/Admin/Services/Nav.php b/app/Http/Admin/Services/Nav.php index 9e278681..b323e721 100644 --- a/app/Http/Admin/Services/Nav.php +++ b/app/Http/Admin/Services/Nav.php @@ -2,10 +2,11 @@ namespace App\Http\Admin\Services; -use App\Caches\NavList as NavListCache; +use App\Caches\NavTreeList as NavTreeListCache; use App\Models\Nav as NavModel; use App\Repos\Nav as NavRepo; use App\Validators\Nav as NavValidator; +use Phalcon\Mvc\Model\Resultset; class Nav extends Service { @@ -191,7 +192,7 @@ class Nav extends Service $nav->child_count = $childCount; $nav->update(); - $cache = new NavListCache(); + $cache = new NavTreeListCache(); $cache->rebuild(); } @@ -199,6 +200,9 @@ class Nav extends Service { $navRepo = new NavRepo(); + /** + * @var Resultset $navs + */ $navs = $navRepo->findAll(['parent_id' => $parentId]); if ($navs->count() == 0) { @@ -215,6 +219,9 @@ class Nav extends Service { $navRepo = new NavRepo(); + /** + * @var Resultset $navs + */ $navs = $navRepo->findAll(['parent_id' => $parentId]); if ($navs->count() == 0) { diff --git a/app/Http/Admin/Services/Order.php b/app/Http/Admin/Services/Order.php index 693e6b8d..052b76c3 100644 --- a/app/Http/Admin/Services/Order.php +++ b/app/Http/Admin/Services/Order.php @@ -88,7 +88,7 @@ class Order extends Service { $validator = new OrderValidator(); - $result = $validator->checkOrder($id); + $result = $validator->checkOrderById($id); return $result; } diff --git a/app/Http/Admin/Services/PaymentTest.php b/app/Http/Admin/Services/PaymentTest.php index 958f94f4..2f61e7a7 100644 --- a/app/Http/Admin/Services/PaymentTest.php +++ b/app/Http/Admin/Services/PaymentTest.php @@ -23,7 +23,8 @@ abstract class PaymentTest extends Service $order->subject = '测试 - 支付测试0.01元'; $order->amount = 0.01; $order->user_id = $authUser->id; - $order->item_type = OrderModel::TYPE_TEST; + $order->item_type = OrderModel::ITEM_TEST; + $order->create(); return $order; @@ -40,10 +41,11 @@ abstract class PaymentTest extends Service $trade = new TradeModel(); $trade->user_id = $order->user_id; - $trade->order_sn = $order->sn; + $trade->order_id = $order->id; $trade->subject = $order->subject; $trade->amount = $order->amount; $trade->channel = TradeModel::CHANNEL_ALIPAY; + $trade->create(); return $trade; diff --git a/app/Http/Admin/Services/Refund.php b/app/Http/Admin/Services/Refund.php index d5da8657..d4c8c16c 100644 --- a/app/Http/Admin/Services/Refund.php +++ b/app/Http/Admin/Services/Refund.php @@ -20,6 +20,16 @@ class Refund extends Service $pageQuery = new PaginateQuery(); $params = $pageQuery->getParams(); + + /** + * 兼容订单编号或订单序号查询 + */ + if (isset($params['order_id']) && strlen($params['order_id']) > 10) { + $orderRepo = new OrderRepo(); + $order = $orderRepo->findBySn($params['order_id']); + $params['order_id'] = $order ? $order->id : -1000; + } + $sort = $pageQuery->getSort(); $page = $pageQuery->getPage(); $limit = $pageQuery->getLimit(); @@ -38,29 +48,29 @@ class Refund extends Service return $refund; } - public function getTrade($sn) + public function getTrade($tradeId) { $tradeRepo = new TradeRepo(); - $trade = $tradeRepo->findBySn($sn); + $trade = $tradeRepo->findById($tradeId); return $trade; } - public function getOrder($sn) + public function getOrder($orderId) { $orderRepo = new OrderRepo(); - $order = $orderRepo->findBySn($sn); + $order = $orderRepo->findById($orderId); return $order; } - public function getUser($id) + public function getUser($userId) { $userRepo = new UserRepo(); - $user = $userRepo->findById($id); + $user = $userRepo->findById($userId); return $user; } @@ -121,9 +131,10 @@ class Refund extends Service $pipeA = $pager->items->toArray(); $pipeB = $builder->handleUsers($pipeA); - $pipeC = $builder->arrayToObject($pipeB); + $pipeC = $builder->handleOrders($pipeB); + $pipeD = $builder->arrayToObject($pipeC); - $pager->items = $pipeC; + $pager->items = $pipeD; } return $pager; diff --git a/app/Http/Admin/Services/Service.php b/app/Http/Admin/Services/Service.php index 11c6b75a..e6093909 100644 --- a/app/Http/Admin/Services/Service.php +++ b/app/Http/Admin/Services/Service.php @@ -2,7 +2,9 @@ namespace App\Http\Admin\Services; -class Service extends \Phalcon\Mvc\User\Component +use Phalcon\Mvc\User\Component; + +class Service extends Component { } diff --git a/app/Http/Admin/Services/Session.php b/app/Http/Admin/Services/Session.php index 1bf402ae..b022988b 100644 --- a/app/Http/Admin/Services/Session.php +++ b/app/Http/Admin/Services/Session.php @@ -9,7 +9,7 @@ class Session extends Service { /** - * @var \App\Http\Admin\Services\AuthUser + * @var AuthUser */ protected $auth; diff --git a/app/Http/Admin/Services/Slide.php b/app/Http/Admin/Services/Slide.php index df4b0d63..7fd0285d 100644 --- a/app/Http/Admin/Services/Slide.php +++ b/app/Http/Admin/Services/Slide.php @@ -57,10 +57,7 @@ class Slide extends Service $data['content'] = $validator->checkLink($post['content']); } - $data['start_time'] = strtotime(date('Y-m-d')); - $data['end_time'] = strtotime('+15 days', $data['start_time']); $data['priority'] = 10; - $data['published'] = 0; $slide = new SlideModel(); @@ -107,12 +104,6 @@ class Slide extends Service $data['priority'] = $validator->checkPriority($post['priority']); } - 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($post['start_time'], $post['end_time']); - } - if (isset($post['published'])) { $data['published'] = $validator->checkPublishStatus($post['published']); } diff --git a/app/Http/Admin/Services/CourseStudent.php b/app/Http/Admin/Services/Student.php similarity index 74% rename from app/Http/Admin/Services/CourseStudent.php rename to app/Http/Admin/Services/Student.php index 498689b0..2608ebed 100644 --- a/app/Http/Admin/Services/CourseStudent.php +++ b/app/Http/Admin/Services/Student.php @@ -10,9 +10,10 @@ use App\Repos\Course as CourseRepo; use App\Repos\CourseUser as CourseUserRepo; use App\Repos\Learning as LearningRepo; use App\Repos\User as UserRepo; +use App\Services\CourseStats as CourseStatsUpdater; use App\Validators\CourseUser as CourseUserValidator; -class CourseStudent extends Service +class Student extends Service { public function getCourse($courseId) @@ -29,7 +30,7 @@ class CourseStudent extends Service return $repo->findById($userId); } - public function getCourseStudents() + public function getPlans() { $pagerQuery = new PagerQuery(); @@ -46,10 +47,10 @@ class CourseStudent extends Service $pager = $courseUserRepo->paginate($params, $sort, $page, $limit); - return $this->handleCourseStudents($pager); + return $this->handlePlans($pager); } - public function getCourseLearnings() + public function getLearnings() { $pagerQuery = new PagerQuery(); @@ -63,17 +64,17 @@ class CourseStudent extends Service $pager = $learningRepo->paginate($params, $sort, $page, $limit); - return $this->handleCourseLearnings($pager); + return $this->handleLearnings($pager); } - public function getCourseStudent($courseId, $userId) + public function getPlan($id) { - $result = $this->findOrFail($courseId, $userId); + $result = $this->findOrFail($id); return $result; } - public function createCourseStudent() + public function createPlan() { $post = $this->request->getPost(); @@ -86,7 +87,7 @@ class CourseStudent extends Service $data['course_id'] = $validator->checkCourseId($post['course_id']); $data['user_id'] = $validator->checkUserId($post['user_id']); - $data['expire_time'] = $validator->checkExpireTime($post['expire_time']); + $data['expiry_time'] = $validator->checkExpiryTime($post['expiry_time']); $validator->checkIfJoined($post['course_id'], $post['user_id']); @@ -99,27 +100,23 @@ class CourseStudent extends Service return $courseUser; } - public function updateCourseStudent() + public function updatePlan() { $post = $this->request->getPost(); - $courseStudent = $this->findOrFail($post['course_id'], $post['user_id']); + $plan = $this->findOrFail($post['plan_id']); $validator = new CourseUserValidator(); $data = []; - if (isset($post['expire_time'])) { - $data['expire_time'] = $validator->checkExpireTime($post['expire_time']); + if (isset($post['expiry_time'])) { + $data['expiry_time'] = $validator->checkExpiryTime($post['expiry_time']); } - if (isset($post['locked'])) { - $data['locked'] = $validator->checkLockStatus($post['locked']); - } + $plan->update($data); - $courseStudent->update($data); - - return $courseStudent; + return $plan; } protected function updateUserCount($courseId) @@ -130,19 +127,19 @@ class CourseStudent extends Service $updater = new CourseStatsUpdater(); - $updater->updateUserCount($course); + $updater->updateUserCount($course->id); } - protected function findOrFail($courseId, $userId) + protected function findOrFail($id) { $validator = new CourseUserValidator(); - $result = $validator->checkCourseStudent($courseId, $userId); + $result = $validator->checkCourseUser($id); return $result; } - protected function handleCourseStudents($pager) + protected function handlePlans($pager) { if ($pager->total_items > 0) { @@ -159,7 +156,7 @@ class CourseStudent extends Service return $pager; } - protected function handleCourseLearnings($pager) + protected function handleLearnings($pager) { if ($pager->total_items > 0) { diff --git a/app/Http/Admin/Services/Trade.php b/app/Http/Admin/Services/Trade.php index 6f711e63..13d4c50d 100644 --- a/app/Http/Admin/Services/Trade.php +++ b/app/Http/Admin/Services/Trade.php @@ -20,6 +20,16 @@ class Trade extends Service $pageQuery = new PaginateQuery(); $params = $pageQuery->getParams(); + + /** + * 兼容订单编号或订单序号查询 + */ + if (isset($params['order_id']) && strlen($params['order_id']) > 10) { + $orderRepo = new OrderRepo(); + $order = $orderRepo->findBySn($params['order_id']); + $params['order_id'] = $order ? $order->id : -1000; + } + $sort = $pageQuery->getSort(); $page = $pageQuery->getPage(); $limit = $pageQuery->getLimit(); @@ -40,29 +50,29 @@ class Trade extends Service return $trade; } - public function getOrder($sn) + public function getOrder($orderId) { $orderRepo = new OrderRepo(); - $order = $orderRepo->findBySn($sn); + $order = $orderRepo->findById($orderId); return $order; } - public function getRefunds($sn) + public function getRefunds($tradeId) { $tradeRepo = new TradeRepo(); - $refunds = $tradeRepo->findRefunds($sn); + $refunds = $tradeRepo->findRefunds($tradeId); return $refunds; } - public function getUser($id) + public function getUser($userId) { $userRepo = new UserRepo(); - $user = $userRepo->findById($id); + $user = $userRepo->findById($userId); return $user; } @@ -103,9 +113,9 @@ class Trade extends Service $refund->subject = $trade->subject; $refund->amount = $trade->amount; $refund->user_id = $trade->user_id; - $refund->order_sn = $trade->order_sn; - $refund->trade_sn = $trade->sn; - $refund->apply_reason = '后台人工申请退款'; + $refund->order_id = $trade->order_id; + $refund->trade_id = $trade->sn; + $refund->apply_note = '后台人工申请退款'; $refund->create(); @@ -129,9 +139,10 @@ class Trade extends Service $pipeA = $pager->items->toArray(); $pipeB = $builder->handleUsers($pipeA); - $pipeC = $builder->arrayToObject($pipeB); + $pipeC = $builder->handleOrders($pipeB); + $pipeD = $builder->arrayToObject($pipeC); - $pager->items = $pipeC; + $pager->items = $pipeD; } return $pager; diff --git a/app/Http/Admin/Services/User.php b/app/Http/Admin/Services/User.php index 3c13bbf7..3967bc6c 100644 --- a/app/Http/Admin/Services/User.php +++ b/app/Http/Admin/Services/User.php @@ -4,10 +4,11 @@ namespace App\Http\Admin\Services; use App\Builders\UserList as UserListBuilder; use App\Library\Paginator\Query as PaginateQuery; -use App\Library\Util\Password as PasswordUtil; -use App\Models\User as UserModel; +use App\Models\Account as AccountModel; +use App\Repos\Account as AccountRepo; use App\Repos\Role as RoleRepo; use App\Repos\User as UserRepo; +use App\Validators\Account as AccountValidator; use App\Validators\User as UserValidator; class User extends Service @@ -47,33 +48,49 @@ class User extends Service return $user; } + public function getAccount($id) + { + $accountRepo = new AccountRepo(); + + $account = $accountRepo->findById($id); + + return $account; + } + public function createUser() { $post = $this->request->getPost(); - $validator = new UserValidator(); + $accountValidator = new AccountValidator(); - $name = $validator->checkName($post['name']); - $password = $validator->checkPassword($post['password']); - $eduRole = $validator->checkEduRole($post['edu_role']); - $adminRole = $validator->checkAdminRole($post['admin_role']); + $phone = $accountValidator->checkPhone($post['phone']); + $password = $accountValidator->checkPassword($post['password']); - $validator->checkIfNameTaken($name); + $accountValidator->checkIfPhoneTaken($post['phone']); - $data = []; + $userValidator = new UserValidator(); - $data['name'] = $name; - $data['salt'] = PasswordUtil::salt(); - $data['password'] = PasswordUtil::hash($password, $data['salt']); - $data['edu_role'] = $eduRole; - $data['admin_role'] = $adminRole; + $eduRole = $userValidator->checkEduRole($post['edu_role']); + $adminRole = $userValidator->checkAdminRole($post['admin_role']); - $user = new UserModel(); + $account = new AccountModel(); - $user->create($data); + $account->phone = $phone; + $account->password = $password; - if ($user->admin_role > 0) { - $this->updateAdminUserCount($user->admin_role); + $account->create(); + + $userRepo = new UserRepo(); + + $user = $userRepo->findById($account->id); + + $user->edu_role = $eduRole; + $user->admin_role = $adminRole; + + $user->update(); + + if ($adminRole > 0) { + $this->updateAdminUserCount($adminRole); } return $user; @@ -89,6 +106,13 @@ class User extends Service $data = []; + if (isset($post['name'])) { + $data['name'] = $validator->checkName($post['name']); + if ($post['name'] != $user->name) { + $validator->checkIfNameTaken($post['name']); + } + } + if (isset($post['title'])) { $data['title'] = $validator->checkTitle($post['title']); } @@ -105,13 +129,24 @@ class User extends Service $data['admin_role'] = $validator->checkAdminRole($post['admin_role']); } + if (isset($post['vip'])) { + $data['vip'] = $validator->checkVipStatus($post['vip']); + } + + if (isset($post['vip_expiry_time'])) { + $data['vip_expiry_time'] = $validator->checkVipExpiryTime($post['vip_expiry_time']); + if ($data['vip_expiry_time'] < time()) { + $data['vip'] = 0; + } + } + if (isset($post['locked'])) { $data['locked'] = $validator->checkLockStatus($post['locked']); } - if (isset($post['lock_expiry'])) { - $data['lock_expiry'] = $validator->checkLockExpiry($post['lock_expiry']); - if ($data['lock_expiry'] < time()) { + if (isset($post['lock_expiry_time'])) { + $data['lock_expiry_time'] = $validator->checkLockExpiryTime($post['lock_expiry_time']); + if ($data['lock_expiry_time'] < time()) { $data['locked'] = 0; } } @@ -131,6 +166,41 @@ class User extends Service return $user; } + public function updateAccount($id) + { + $post = $this->request->getPost(); + + $accountRepo = new AccountRepo(); + + $account = $accountRepo->findById($id); + + $validator = new AccountValidator(); + + $data = []; + + if (!empty($post['phone'])) { + $data['phone'] = $validator->checkPhone($post['phone']); + if ($post['phone'] != $account->phone) { + $validator->checkIfPhoneTaken($post['phone']); + } + } + + if (!empty($post['email'])) { + $data['email'] = $validator->checkEmail($post['email']); + if ($post['email'] != $account->email) { + $validator->checkIfEmailTaken($post['email']); + } + } + + if (!empty($post['password'])) { + $data['password'] = $validator->checkPassword($post['password']); + } + + $account->update($data); + + return $account; + } + protected function findOrFail($id) { $validator = new UserValidator(); @@ -146,9 +216,7 @@ class User extends Service $role = $roleRepo->findById($roleId); - if (!$role) { - return false; - } + if (!$role) return; $userCount = $roleRepo->countUsers($roleId); diff --git a/app/Http/Admin/Services/WechatTest.php b/app/Http/Admin/Services/WechatTest.php new file mode 100644 index 00000000..65e17820 --- /dev/null +++ b/app/Http/Admin/Services/WechatTest.php @@ -0,0 +1,66 @@ + $trade->sn, + 'total_fee' => 100 * $trade->amount, + 'body' => $trade->subject, + ]; + + $wechatService = new WechatService(); + + $qrcode = $wechatService->getQrCode($outOrder); + + $result = $qrcode ?: false; + + return $result; + } + + /** + * 取消测试订单 + * + * @param string $sn + */ + public function cancelTestOrder($sn) + { + $tradeRepo = new TradeRepo(); + + $trade = $tradeRepo->findBySn($sn); + + $orderRepo = new OrderRepo(); + + $order = $orderRepo->findById($trade->order_id); + + $wechatService = new WechatService(); + + $response = $wechatService->closeOrder($trade->sn); + + if ($response) { + $trade->status = TradeModel::STATUS_CLOSED; + $trade->update(); + if ($order->status != OrderModel::STATUS_PENDING) { + $order->status = OrderModel::STATUS_PENDING; + $order->update(); + } + } + } + +} diff --git a/app/Http/Admin/Services/WxpayTest.php b/app/Http/Admin/Services/WxpayTest.php deleted file mode 100644 index eb71c586..00000000 --- a/app/Http/Admin/Services/WxpayTest.php +++ /dev/null @@ -1,41 +0,0 @@ - $trade->sn, - 'total_fee' => 100 * $trade->amount, - 'body' => $trade->subject, - ]; - - $wxpayService = new WxpayService(); - $qrcode = $wxpayService->qrcode($outOrder); - $result = $qrcode ?: false; - - return $result; - } - - /** - * 取消测试订单 - * - * @param string $sn - */ - public function cancelTestOrder($sn) - { - - } - -} diff --git a/app/Http/Admin/Views/category/list.volt b/app/Http/Admin/Views/category/list.volt index deb1d702..88b2d030 100644 --- a/app/Http/Admin/Views/category/list.volt +++ b/app/Http/Admin/Views/category/list.volt @@ -101,7 +101,7 @@ var categoryId = $(this).attr('category-id'); var checked = $(this).is(':checked'); var published = checked ? 1 : 0; - var tips = published == 1 ? '确定要发布分类?' : '确定要下线分类?'; + var tips = published === 1 ? '确定要发布分类?' : '确定要下线分类?'; layer.confirm(tips, function () { $.ajax({ type: 'POST', diff --git a/app/Http/Admin/Views/chapter/edit_lesson_vod.volt b/app/Http/Admin/Views/chapter/edit_lesson_vod.volt index 6c871074..cc5f07e7 100644 --- a/app/Http/Admin/Views/chapter/edit_lesson_vod.volt +++ b/app/Http/Admin/Views/chapter/edit_lesson_vod.volt @@ -1,4 +1,4 @@ -{% if vod_files %} +{% if play_urls %}
视频信息
@@ -11,7 +11,7 @@ 大小 操作 - {% for item in vod_files %} + {% for item in play_urls %} {{ item.format }} {{ item.duration|play_duration }} @@ -19,7 +19,7 @@ {{ item.rate }}kbps {{ item.size }}M - 预览 + 预览 复制 diff --git a/app/Http/Admin/Views/chapter/lessons_vod.volt b/app/Http/Admin/Views/chapter/lessons_vod.volt index d1066163..721544fa 100644 --- a/app/Http/Admin/Views/chapter/lessons_vod.volt +++ b/app/Http/Admin/Views/chapter/lessons_vod.volt @@ -46,8 +46,10 @@ {{ file_status(item.attrs['file_status']) }} {{ item.attrs['duration']|play_duration }} - - + +
diff --git a/app/Http/Admin/Views/comment/edit.volt b/app/Http/Admin/Views/comment/edit.volt new file mode 100644 index 00000000..72e7cac3 --- /dev/null +++ b/app/Http/Admin/Views/comment/edit.volt @@ -0,0 +1,30 @@ +
+ 编辑评论 +
+ +
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
\ No newline at end of file diff --git a/app/Http/Admin/Views/comment/list.volt b/app/Http/Admin/Views/comment/list.volt new file mode 100644 index 00000000..7cd16708 --- /dev/null +++ b/app/Http/Admin/Views/comment/list.volt @@ -0,0 +1,114 @@ +
+
+ + 返回 + {% if course %} + {{ course.title }} + {% endif %} + {% if chapter %} + {{ chapter.title }} + {% endif %} + 评论管理 + +
+ +
+ + + + + + + + + + + + + + + + + + + + {% for item in pager.items %} + + + + + + + + {% endfor %} + +
评论用户时间发布操作
+

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

+ {% if item.chapter %} +

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

+ {% endif %} +

评论:{{ substr(item.content,0,25) }}

+
+

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

+

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

+
{{ date('Y-m-d H:i',item.created_at) }} +
+ + +
+
+ +{{ partial('partials/pager') }} + + \ No newline at end of file diff --git a/app/Http/Admin/Views/comment/search.volt b/app/Http/Admin/Views/comment/search.volt new file mode 100644 index 00000000..aed87846 --- /dev/null +++ b/app/Http/Admin/Views/comment/search.volt @@ -0,0 +1,67 @@ +
+ 搜索评论 +
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ + \ No newline at end of file diff --git a/app/Http/Admin/Views/config/live_push_test.volt b/app/Http/Admin/Views/config/live_push_test.volt index 73f7df7a..e17df224 100644 --- a/app/Http/Admin/Views/config/live_push_test.volt +++ b/app/Http/Admin/Views/config/live_push_test.volt @@ -2,8 +2,8 @@
-
-
+
+
@@ -38,23 +38,4 @@ -{{ partial('partials/clipboard_tips') }} - -{{ javascript_include('lib/jquery.min.js') }} -{{ javascript_include('lib/jquery.qrcode.min.js') }} - - \ No newline at end of file +{{ partial('partials/clipboard_tips') }} \ No newline at end of file diff --git a/app/Http/Admin/Views/config/payment.volt b/app/Http/Admin/Views/config/payment.volt index 0dbe13fa..9e739f9b 100644 --- a/app/Http/Admin/Views/config/payment.volt +++ b/app/Http/Admin/Views/config/payment.volt @@ -8,7 +8,7 @@ {{ partial('config/payment_alipay') }}
- {{ partial('config/payment_wxpay') }} + {{ partial('config/payment_wechat') }}
\ No newline at end of file diff --git a/app/Http/Admin/Views/config/alipay_test.volt b/app/Http/Admin/Views/config/payment_alipay_test.volt similarity index 100% rename from app/Http/Admin/Views/config/alipay_test.volt rename to app/Http/Admin/Views/config/payment_alipay_test.volt diff --git a/app/Http/Admin/Views/config/payment_wxpay.volt b/app/Http/Admin/Views/config/payment_wechat.volt similarity index 85% rename from app/Http/Admin/Views/config/payment_wxpay.volt rename to app/Http/Admin/Views/config/payment_wechat.volt index dc1651f3..1faf7cf2 100644 --- a/app/Http/Admin/Views/config/payment_wxpay.volt +++ b/app/Http/Admin/Views/config/payment_wechat.volt @@ -3,36 +3,36 @@
- - + +
- +
- +
- +
-
@@ -42,7 +42,7 @@
- +
@@ -71,7 +71,7 @@
- +
@@ -85,8 +85,8 @@ var $ = layui.jquery; var layer = layui.layer; - $('#show-wxpay-test').on('click', function () { - var url = '/admin/test/wxpay'; + $('#show-wechat-test').on('click', function () { + var url = '/admin/test/wechat'; layer.open({ type: 2, title: '微信 - 支付测试', diff --git a/app/Http/Admin/Views/config/wechat_test.volt b/app/Http/Admin/Views/config/payment_wechat_test.volt similarity index 97% rename from app/Http/Admin/Views/config/wechat_test.volt rename to app/Http/Admin/Views/config/payment_wechat_test.volt index 7e1a3e1b..d99401b4 100644 --- a/app/Http/Admin/Views/config/wechat_test.volt +++ b/app/Http/Admin/Views/config/payment_wechat_test.volt @@ -65,7 +65,7 @@ if (loopTime >= 300) { $.ajax({ type: 'POST', - url: '/admin/config/wxpay/test/cancel', + url: '/admin/config/wechat/test/cancel', data: {sn: sn}, success: function (res) { }, diff --git a/app/Http/Admin/Views/config/vip.volt b/app/Http/Admin/Views/config/vip.volt index a45a2a5a..59da0590 100644 --- a/app/Http/Admin/Views/config/vip.volt +++ b/app/Http/Admin/Views/config/vip.volt @@ -4,37 +4,15 @@ 会员设置 -
- -
- + {% for item in vips %} +
+ +
+ +
+
-
-
- -
- -
- -
-
-
- -
- -
- -
-
-
- -
- -
- -
-
-
+ {% endfor %}
diff --git a/app/Http/Admin/Views/config/wxpay_test.volt b/app/Http/Admin/Views/config/wxpay_test.volt deleted file mode 100644 index 5a32e29b..00000000 --- a/app/Http/Admin/Views/config/wxpay_test.volt +++ /dev/null @@ -1,85 +0,0 @@ -
- - {% if qrcode %} - -
- - - -
- 支付成功 -
- -
- 支付失败 -
- - {% else %} - -
- 生成二维码失败 -
- - {% endif %} - -
- -{% if qrcode %} - - {{ javascript_include('lib/jquery.min.js') }} - {{ javascript_include('lib/jquery.qrcode.min.js') }} - - - -{% endif %} \ No newline at end of file diff --git a/app/Http/Admin/Views/consult/edit.volt b/app/Http/Admin/Views/consult/edit.volt new file mode 100644 index 00000000..aac096f7 --- /dev/null +++ b/app/Http/Admin/Views/consult/edit.volt @@ -0,0 +1,37 @@ +
+ +
+ 编辑咨询 +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
\ No newline at end of file diff --git a/app/Http/Admin/Views/consult/list.volt b/app/Http/Admin/Views/consult/list.volt new file mode 100644 index 00000000..12106e61 --- /dev/null +++ b/app/Http/Admin/Views/consult/list.volt @@ -0,0 +1,111 @@ +
+
+ + 返回 + {% if course %} + {{ course.title }} + {% endif %} + 咨询管理 + +
+ +
+ + + + + + + + + + + + + + + + + + + + {% for item in pager.items %} + + + + + + + + {% endfor %} + +
问答用户时间发布操作
+

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

+

提问:{{ substr(item.question,0,25) }}

+ {% if item.answer %} +

回复:{{ substr(item.answer,0,25) }}

+ {% endif %} +
+

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

+

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

+
{{ date('Y-m-d H:i',item.created_at) }} +
+ + +
+
+ +{{ partial('partials/pager') }} + + \ No newline at end of file diff --git a/app/Http/Admin/Views/consult/search.volt b/app/Http/Admin/Views/consult/search.volt new file mode 100644 index 00000000..89bea2cc --- /dev/null +++ b/app/Http/Admin/Views/consult/search.volt @@ -0,0 +1,52 @@ +
+ +
+ 搜索咨询 +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
\ No newline at end of file diff --git a/app/Http/Admin/Views/course/edit_sale.volt b/app/Http/Admin/Views/course/edit_sale.volt index c3b14a0a..2b3271af 100644 --- a/app/Http/Admin/Views/course/edit_sale.volt +++ b/app/Http/Admin/Views/course/edit_sale.volt @@ -1,7 +1,5 @@ {% set free = course.market_price == 0 %} -{% set expiry_options = ['30':'一个月','90':'三个月','180':'半年','365':'一年','1095':'三年'] %} -
@@ -32,10 +30,18 @@
- +
- {% for key,value in expiry_options %} - + {% for key,value in study_expiry_options %} + + {% endfor %} +
+
+
+ +
+ {% for key,value in refund_expiry_options %} + {% endfor %}
@@ -53,7 +59,7 @@ \ No newline at end of file +{{ partial('partials/cover_uploader') }} \ No newline at end of file diff --git a/app/Http/Admin/Views/slide/list.volt b/app/Http/Admin/Views/slide/list.volt index ecbd2e09..c2b2f599 100644 --- a/app/Http/Admin/Views/slide/list.volt +++ b/app/Http/Admin/Views/slide/list.volt @@ -28,7 +28,6 @@ - @@ -36,7 +35,6 @@ 编号 标题 目标类型 - 有效期限 排序 发布 操作 @@ -48,10 +46,6 @@ {{ item.id }} {{ item.title }} {{ target_info(item.target) }} - -

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

-

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

- @@ -101,7 +95,7 @@ var slideId = $(this).attr('slide-id'); var checked = $(this).is(':checked'); var published = checked ? 1 : 0; - var tips = published == 1 ? '确定要发布轮播?' : '确定要下架轮播?'; + var tips = published === 1 ? '确定要发布轮播?' : '确定要下架轮播?'; layer.confirm(tips, function () { $.ajax({ diff --git a/app/Http/Admin/Views/student/add.volt b/app/Http/Admin/Views/student/add.volt index 4c7a5057..2557fc95 100644 --- a/app/Http/Admin/Views/student/add.volt +++ b/app/Http/Admin/Views/student/add.volt @@ -1,3 +1,5 @@ +{% set course_id = course ? course.id : '' %} +
@@ -21,7 +23,7 @@
- +
@@ -42,7 +44,7 @@ var laydate = layui.laydate; laydate.render({ - elem: 'input[name=expire_time]', + elem: 'input[name=expiry_time]', type: 'datetime' }); diff --git a/app/Http/Admin/Views/student/edit.volt b/app/Http/Admin/Views/student/edit.volt index 5ba6d356..ead53bfb 100644 --- a/app/Http/Admin/Views/student/edit.volt +++ b/app/Http/Admin/Views/student/edit.volt @@ -18,18 +18,10 @@
-
- -
- - -
-
-
- +
@@ -38,8 +30,7 @@
- - +
@@ -52,7 +43,7 @@ var laydate = layui.laydate; laydate.render({ - elem: 'input[name=expire_time]', + elem: 'input[name=expiry_time]', type: 'datetime' }); diff --git a/app/Http/Admin/Views/student/learning.volt b/app/Http/Admin/Views/student/learning.volt index 4f3e6e18..78cc047d 100644 --- a/app/Http/Admin/Views/student/learning.volt +++ b/app/Http/Admin/Views/student/learning.volt @@ -8,9 +8,9 @@ {%- macro last_active(created_at, updated_at) %} {% if updated_at > 0 %} - {{ date('Y-m-d H:i:s', updated_at) }} + {{ date('Y-m-d H:i', updated_at) }} {% else %} - {{ date('Y-m-d H:i:s', created_at) }} + {{ date('Y-m-d H:i', created_at) }} {% endif %} {%- endmacro %} diff --git a/app/Http/Admin/Views/student/list.volt b/app/Http/Admin/Views/student/list.volt index fc909e2a..2ebe9a89 100644 --- a/app/Http/Admin/Views/student/list.volt +++ b/app/Http/Admin/Views/student/list.volt @@ -1,7 +1,20 @@ +{%- macro source_type_info(value) %} + {% if value == 'free' %} + 免费 + {% elseif value == 'charge' %} + 付费 + {% elseif value == 'import' %} + 导入 + {% endif %} +{%- endmacro %} +
返回 + {% if course %} + {{ course.title }} + {% endif %} 学员管理
@@ -9,25 +22,32 @@ 搜索学员 - - 添加学员 - + {% if course %} + + 添加学员 + + {% else %} + + 添加学员 + + {% endif %}
- +
- + + + - @@ -35,25 +55,22 @@ {% for item in pager.items %} - - + + @@ -69,38 +86,6 @@ layui.use(['jquery', 'form'], function () { var $ = layui.jquery; - var form = layui.form; - - form.on('switch(switch-locked)', function (data) { - var courseId = $(this).attr('course-id'); - var userId = $(this).attr('user-id'); - var checked = $(this).is(':checked'); - var locked = checked ? 1 : 0; - var tips = locked == 1 ? '确定要锁定用户?' : '确定要解锁用户?'; - layer.confirm(tips, function () { - $.ajax({ - type: 'POST', - url: '/admin/student/update', - data: { - course_id: courseId, - user_id: userId, - locked: locked - }, - success: function (res) { - layer.msg(res.msg, {icon: 1}); - }, - error: function (xhr) { - var json = JSON.parse(xhr.responseText); - layer.msg(json.msg, {icon: 2}); - data.elem.checked = !checked; - form.render(); - } - }); - }, function () { - data.elem.checked = !checked; - form.render(); - }); - }); $('.kg-learning').on('click', function () { var url = $(this).attr('url'); diff --git a/app/Http/Admin/Views/topic/list.volt b/app/Http/Admin/Views/topic/list.volt index 68c15502..ab2a0a97 100644 --- a/app/Http/Admin/Views/topic/list.volt +++ b/app/Http/Admin/Views/topic/list.volt @@ -62,7 +62,7 @@ var topicId = $(this).attr('topic-id'); var checked = $(this).is(':checked'); var published = checked ? 1 : 0; - var tips = published == 1 ? '确定要发布话题?' : '确定要下架话题?'; + var tips = published === 1 ? '确定要发布话题?' : '确定要下架话题?'; layer.confirm(tips, function () { $.ajax({ type: 'POST', diff --git a/app/Http/Admin/Views/trade/list.volt b/app/Http/Admin/Views/trade/list.volt index 16031878..0de73f12 100644 --- a/app/Http/Admin/Views/trade/list.volt +++ b/app/Http/Admin/Views/trade/list.volt @@ -38,17 +38,17 @@ {% for item in pager.items %} - + diff --git a/app/Http/Admin/Views/trade/macro.volt b/app/Http/Admin/Views/trade/macro.volt index 65b269f5..9b9ee436 100644 --- a/app/Http/Admin/Views/trade/macro.volt +++ b/app/Http/Admin/Views/trade/macro.volt @@ -13,7 +13,7 @@ {%- macro channel_type(value) %} {% if value == 'alipay' %} 支付宝 - {% elseif value == 'wxpay' %} + {% elseif value == 'wechat' %} 微信 {% endif %} {%- endmacro %} \ No newline at end of file diff --git a/app/Http/Admin/Views/trade/search.volt b/app/Http/Admin/Views/trade/search.volt index d5f73660..2355b531 100644 --- a/app/Http/Admin/Views/trade/search.volt +++ b/app/Http/Admin/Views/trade/search.volt @@ -7,7 +7,7 @@
- +
@@ -22,7 +22,7 @@
- +
diff --git a/app/Http/Admin/Views/trade/show.volt b/app/Http/Admin/Views/trade/show.volt index a559d4ff..b9a84661 100644 --- a/app/Http/Admin/Views/trade/show.volt +++ b/app/Http/Admin/Views/trade/show.volt @@ -19,7 +19,7 @@ - +
基本信息 学习情况成员来源 有效期限锁定 操作
-

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

-

学员:{{ item.user.name }}

+

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

+

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

-
-
-
-
-
+

进度:{{ item.progress }}%

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

{{ date('Y-m-d H:i',item.expire_time) }}{{ source_type_info(item.source_type) }}{{ date('Y-m-d H:i',item.expiry_time) }}
-

商品:{{ item.subject }}

-

单号:{{ item.order_sn }}

+

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

+

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

-

名称:{{ item.user.name }}

+

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

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

¥{{ item.amount }} {{ channel_type(item.channel) }} {{ trade_status(item.status) }}{{ date('Y-m-d H:i:s',item.created_at) }}{{ date('Y-m-d H:i',item.created_at) }} 详情 ¥{{ trade.amount }} {{ channel_type(trade.channel) }} {{ trade_status(trade.status) }}{{ date('Y-m-d H:i:s',trade.created_at) }}{{ date('Y-m-d H:i',trade.created_at) }}
@@ -51,9 +51,9 @@ {{ item.sn }} ¥{{ item.amount }} - {{ substr(item.apply_reason,0,15) }} + {{ substr(item.apply_note,0,15) }} {{ refund_status(item) }} - {{ date('Y-m-d H:i:s',item.created_at) }} + {{ date('Y-m-d H:i',item.created_at) }} {% endfor %} @@ -78,7 +78,7 @@ {{ order.subject }} ¥{{ order.amount }} {{ order_status(order.status) }} - {{ date('Y-m-d H:i:s',order.created_at) }} + {{ date('Y-m-d H:i',order.created_at) }} diff --git a/app/Http/Admin/Views/user/add.volt b/app/Http/Admin/Views/user/add.volt index 25c57197..f89eb971 100644 --- a/app/Http/Admin/Views/user/add.volt +++ b/app/Http/Admin/Views/user/add.volt @@ -1,13 +1,13 @@ - +
添加用户
- +
- +
@@ -21,16 +21,16 @@
- +
- {% if auth_user.admin == 1 %} + {% if auth_user.root == 1 %}
- + {% for item in roles %} {% endfor %} diff --git a/app/Http/Admin/Views/user/edit.volt b/app/Http/Admin/Views/user/edit.volt index 4e32ba83..34883579 100644 --- a/app/Http/Admin/Views/user/edit.volt +++ b/app/Http/Admin/Views/user/edit.volt @@ -7,7 +7,7 @@
-
{{ user.name }}
+
@@ -33,7 +33,7 @@
- {% if auth_user.admin == 1 %} + {% if auth_user.root == 1 %}
@@ -45,18 +45,41 @@
{% endif %} +
+ +
+ + +
+
+ +
+ +
+ {% if user.vip_expiry_time > 0 %} + + {% else %} + + {% endif %} +
+
+
- - + +
- + {% if user.lock_expiry_time > 0 %} + + {% else %} + + {% endif %}
@@ -65,11 +88,54 @@
+
+{% if auth_user.root == 1 %} + +
+ +
+ 编辑帐号 +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ + + +
+
+ +
+ +{% endif %} +