1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-06-23 03:50:56 +08:00

Merge pull request #8 from xiaochong0302/develop

v1.2.0阶段性合并
This commit is contained in:
jacky huang 2020-11-27 09:53:00 +08:00 committed by GitHub
commit ec938d0a5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
151 changed files with 3305 additions and 726 deletions

1
.gitignore vendored
View File

@ -9,4 +9,5 @@
/db/migrations/schema.php /db/migrations/schema.php
/public/robots.txt /public/robots.txt
/public/sitemap.xml /public/sitemap.xml
/public/h5
*KgTest* *KgTest*

View File

@ -1,3 +1,7 @@
### [v1.2.0](https://gitee.com/koogua/course-tencent-cloud/releases/v1.2.0)(2020-11-25)
- 增加客户端api
- 代码优化以及问题修复
### [v1.1.0](https://gitee.com/koogua/course-tencent-cloud/releases/v1.1.0)(2020-10-08) ### [v1.1.0](https://gitee.com/koogua/course-tencent-cloud/releases/v1.1.0)(2020-10-08)
- 增加运营统计功能 - 增加运营统计功能

View File

@ -1,5 +0,0 @@
使用协议
1. 本系统属于强业务类型,非通用类库框架,不适合再次衍生发布。
2. 在保留我们版权标识的前提下,用户可以修改以满足自己的需求,可以用于商业用途。
3. 有限社区支持,用户对自己的行为负责。

View File

@ -1,24 +1,45 @@
## 酷瓜云课堂 ## 酷瓜云课堂
![酷瓜云网课GPL协议开源](https://images.gitee.com/uploads/images/2020/1127/092621_3805cf8f_23592.png)
#### 项目介绍 #### 项目介绍
酷瓜云课堂,依托腾讯云基础服务架构,采用 C 扩展框架 Phalcon 开发,致力网络教育软件。 酷瓜云课堂依托腾讯云基础服务架构采用C扩展框架Phalcon开发GPL-2.0开源协议,致力开源网课系统,开源网校系统,开源在线教育系统。
![](https://img.shields.io/static/v1?label=release&message=1.2.0&color=blue)
![](https://img.shields.io/static/v1?label=stars&message=101&color=blue)
![](https://img.shields.io/static/v1?label=forks&message=40&color=blue)
![](https://img.shields.io/static/v1?label=license&message=GPL-2.0&color=blue)
#### 系统功能 #### 系统功能
实现了点播、直播、专栏、会员、微聊等,是一个完整的产品,具体功能我也不想写一大堆,自己体验吧! 实现了点播、直播、专栏、会员、微聊等,是一个完整的产品,具体功能我也不想写一大堆,自己体验吧!
- [前台演示](https://ctc.koogua.com)
- [后台演示](https://ctc.koogua.com/admin)
帐号100015@163.com / 123456 (前后台通用)
友情提示: 友情提示:
- 系统配置低1核 1G 1M 跑多个容器),切莫压测 - 系统配置低1核 1G 1M 跑多个容器),切莫压测
- 课程数据来源于网络(无实质内容),切莫购买 - 课程数据来源于网络(无实质内容),切莫购买
- 管理后台已禁止数据提交,私密配置已过滤 - 管理后台已禁止数据提交,私密配置已过滤
演示帐号:**13507083515 / 123456** (前后台通用)
桌面端演示:
- [前台演示](https://ctc.koogua.com)
- [后台演示](https://ctc.koogua.com/admin)
移动端演示:
![移动端二维码](https://images.gitee.com/uploads/images/2020/1127/093203_265221a2_23592.png)
支付流程演示:
- [MySQL提升课程全面讲解MySQL架构设计0.01元)](https://ctc.koogua.com/order/confirm?item_id=1390&item_type=1)
- [Nginx入门到实践Nginx中间件0.01元)](https://ctc.koogua.com/order/confirm?item_id=1286&item_type=1)
- [数据库与中间件的基础必修课0.02元)](https://ctc.koogua.com/order/confirm?item_id=80&item_type=2)
Tips: 测试支付请用手机号注册一个新账户,以便接收订单通知,以及避免课程无法购买
#### 项目组件 #### 项目组件
- 后台框架:[phalcon 3.4.5](https://phalcon.io) - 后台框架:[phalcon 3.4.5](https://phalcon.io)
@ -27,14 +48,6 @@
- 即时通讯:[workerman 3.5.22](https://workerman.net) - 即时通讯:[workerman 3.5.22](https://workerman.net)
- 基础依赖:[php7.3](https://php.net) [mysql5.7](https://mysql.com) [redis5.0](https://redis.io) - 基础依赖:[php7.3](https://php.net) [mysql5.7](https://mysql.com) [redis5.0](https://redis.io)
#### 使用协议
虽然尝试了解过开源协议,但是理解的模棱两可,干脆用自己的协议吧。
1. 本系统属于强业务类型,非通用类库框架,不适合再次衍生发布。
2. 在保留我们版权标识的前提下,用户可以修改以满足自己的需求,可以用于商业用途。
3. 有限社区支持,用户对自己的行为负责。
#### 安装指南 #### 安装指南
- [运行环境搭建](https://gitee.com/koogua/course-tencent-cloud-docker) - [运行环境搭建](https://gitee.com/koogua/course-tencent-cloud-docker)
@ -43,20 +56,13 @@
#### 开发计划 #### 开发计划
- 桌面端:进行中 - 桌面端:进行中
- 移动端:待启动 - 移动端:进行中
- 小程序:待启动 - 小程序:待启动
#### 意见反馈 #### 意见反馈
- [在线反馈](https://gitee.com/koogua/course-tencent-cloud/issues)(推荐) - [在线反馈](https://gitee.com/koogua/course-tencent-cloud/issues)(推荐)
- QQ邮箱: 76632555@qq.com - QQ交流群: 787363898
- QQ群组: 787363898
#### 加入我们
这是一个创业项目,个人能力和精力有限,要兼顾产品规划以及开发,还要处理很多琐碎事情。目前在南山科技园某个众创空间,希望有 **深圳前端同学** 加入我们。
联系邮箱76632555@qq.com
#### 通过这个项目能学到什么? #### 通过这个项目能学到什么?

View File

@ -11,7 +11,7 @@ class CategoryTreeList extends Builder
public function handle($type) public function handle($type)
{ {
$topCategories = $this->findChildCategories($type, 0); $topCategories = $this->findTopCategories($type);
if ($topCategories->count() == 0) { if ($topCategories->count() == 0) {
return []; return [];
@ -32,7 +32,7 @@ class CategoryTreeList extends Builder
protected function handleChildren(CategoryModel $category) protected function handleChildren(CategoryModel $category)
{ {
$subCategories = $this->findChildCategories($category->type, $category->id); $subCategories = $this->findChildCategories($category->id);
if ($subCategories->count() == 0) { if ($subCategories->count() == 0) {
return []; return [];
@ -51,24 +51,31 @@ class CategoryTreeList extends Builder
} }
/** /**
* @param string $type * @param int $type
* @return ResultsetInterface|Resultset|CategoryModel[]
*/
protected function findTopCategories($type)
{
$query = CategoryModel::query();
$query->where('parent_id = 0');
$query->andWhere('published = 1');
$query->andWhere('type = :type:', ['type' => $type]);
$query->orderBy('priority ASC');
return $query->execute();
}
/**
* @param int $parentId * @param int $parentId
* @return ResultsetInterface|Resultset|CategoryModel[] * @return ResultsetInterface|Resultset|CategoryModel[]
*/ */
protected function findChildCategories($type = 'course', $parentId = 0) protected function findChildCategories($parentId)
{ {
$query = CategoryModel::query(); $query = CategoryModel::query();
$query->where('published = 1'); $query->where('published = 1');
$query->andWhere('parent_id = :parent_id:', ['parent_id' => $parentId]);
if ($type) {
$query->andWhere('type = :type:', ['type' => $type]);
}
if ($parentId) {
$query->andWhere('parent_id = :parent_id:', ['parent_id' => $parentId]);
}
$query->orderBy('priority ASC'); $query->orderBy('priority ASC');
return $query->execute(); return $query->execute();

View File

@ -36,7 +36,7 @@ class ImGroupUserList extends Builder
$userRepo = new UserRepo(); $userRepo = new UserRepo();
$columns = ['id', 'name', 'avatar', 'title', 'about', 'vip']; $columns = ['id', 'name', 'avatar', 'title', 'about', 'vip', 'gender', 'area'];
$users = $userRepo->findByIds($ids, $columns); $users = $userRepo->findByIds($ids, $columns);

90
app/Builders/LiveList.php Normal file
View File

@ -0,0 +1,90 @@
<?php
namespace App\Builders;
use App\Repos\Chapter as ChapterRepo;
use App\Repos\Course as CourseRepo;
use App\Repos\User as UserRepo;
class LiveList extends Builder
{
public function handleCourses(array $lives)
{
$courses = $this->getCourses($lives);
foreach ($lives as $key => $live) {
$lives[$key]['course'] = $courses[$live['course_id']] ?? new \stdClass();
}
return $lives;
}
public function handleChapters(array $lives)
{
$chapters = $this->getChapters($lives);
foreach ($lives as $key => $live) {
$lives[$key]['chapter'] = $chapters[$live['chapter_id']] ?? new \stdClass();
}
return $lives;
}
public function getCourses(array $lives)
{
$courseIds = kg_array_column($lives, 'course_id');
$courseRepo = new CourseRepo();
$courses = $courseRepo->findByIds($courseIds, ['id', 'title', 'cover', 'teacher_id']);
$teacherIds = kg_array_column($courses->toArray(), 'teacher_id');
$userRepo = new UserRepo();
$users = $userRepo->findByIds($teacherIds, ['id', 'name', 'title', 'avatar', 'about']);
$baseUrl = kg_cos_url();
$teachers = [];
foreach ($users->toArray() as $user) {
$user['avatar'] = $baseUrl . $user['avatar'];
$teachers[$user['id']] = $user;
}
$result = [];
foreach ($courses->toArray() as $course) {
$course['cover'] = $baseUrl . $course['cover'];
$course['teacher'] = $teachers[$course['teacher_id']] ?? new \stdClass();
$result[$course['id']] = [
'id' => $course['id'],
'title' => $course['title'],
'cover' => $course['cover'],
'teacher' => $course['teacher'],
];
}
return $result;
}
public function getChapters(array $lives)
{
$ids = kg_array_column($lives, 'chapter_id');
$chapterRepo = new ChapterRepo();
$chapters = $chapterRepo->findByIds($ids, ['id', 'title']);
$result = [];
foreach ($chapters->toArray() as $chapter) {
$result[$chapter['id']] = $chapter;
}
return $result;
}
}

31
app/Caches/App.php Normal file
View File

@ -0,0 +1,31 @@
<?php
namespace App\Caches;
use App\Repos\App as AppRepo;
class App extends Cache
{
protected $lifetime = 365 * 86400;
public function getLifetime()
{
return $this->lifetime;
}
public function getKey($id = null)
{
return "app:{$id}";
}
public function getContent($id = null)
{
$appRepo = new AppRepo();
$result = $appRepo->findByAppKey($id);
return $result ?: null;
}
}

View File

@ -4,6 +4,9 @@ namespace App\Console\Tasks;
use App\Caches\IndexFreeCourseList as IndexFreeCourseListCache; use App\Caches\IndexFreeCourseList as IndexFreeCourseListCache;
use App\Caches\IndexNewCourseList as IndexNewCourseListCache; use App\Caches\IndexNewCourseList as IndexNewCourseListCache;
use App\Caches\IndexSimpleFreeCourseList as IndexSimpleFreeCourseListCache;
use App\Caches\IndexSimpleNewCourseList as IndexSimpleNewCourseListCache;
use App\Caches\IndexSimpleVipCourseList as IndexSimpleVipCourseListCache;
use App\Caches\IndexVipCourseList as IndexVipCourseListCache; use App\Caches\IndexVipCourseList as IndexVipCourseListCache;
use App\Http\Admin\Services\Setting as SettingService; use App\Http\Admin\Services\Setting as SettingService;
use App\Library\Utils\Password as PasswordUtil; use App\Library\Utils\Password as PasswordUtil;
@ -22,20 +25,41 @@ class MaintainTask extends Task
{ {
$section = $params[0] ?? null; $section = $params[0] ?? null;
$site = $this->getSettings('site');
$type = $site['index_tpl_type'] ?: 'full';
if (!$section || $section == 'new_course') { if (!$section || $section == 'new_course') {
$cache = new IndexNewCourseListCache(); if ($type == 'full') {
$cache->rebuild(); $cache = new IndexNewCourseListCache();
$cache->rebuild();
} else {
$cache = new IndexSimpleNewCourseListCache();
$cache->rebuild();
}
} }
if (!$section || $section == 'free_course') { if (!$section || $section == 'free_course') {
$cache = new IndexFreeCourseListCache(); if ($type == 'full') {
$cache->rebuild(); $cache = new IndexFreeCourseListCache();
$cache->rebuild();
} else {
$cache = new IndexSimpleFreeCourseListCache();
$cache->rebuild();
}
} }
if (!$section || $section == 'vip_course') { if (!$section || $section == 'vip_course') {
$cache = new IndexVipCourseListCache(); if ($type == 'full') {
$cache->rebuild(); $cache = new IndexVipCourseListCache();
$cache->rebuild();
} else {
$cache = new IndexSimpleVipCourseListCache();
$cache->rebuild();
}
} }
echo 'rebuild index course cache success' . PHP_EOL;
} }
/** /**

View File

@ -41,7 +41,7 @@ class Task extends \Phalcon\Cli\Task
{ {
$appService = new AppService(); $appService = new AppService();
return $appService->getLogger($section); return $appService->getSettings($section);
} }
} }

View File

@ -43,7 +43,6 @@ class UpgradeTask extends Task
public function resetAnnotationAction() public function resetAnnotationAction()
{ {
$config = $this->getConfig(); $config = $this->getConfig();
$redis = $this->getRedis(); $redis = $this->getRedis();
$dbIndex = $config->path('annotation.db'); $dbIndex = $config->path('annotation.db');
@ -56,9 +55,7 @@ class UpgradeTask extends Task
echo "start reset annotation..." . PHP_EOL; echo "start reset annotation..." . PHP_EOL;
if (count($keys) > 0) { if (count($keys) > 0) {
$keys = $this->handlePhKeys($keys); $keys = $this->handlePhKeys($keys);
$redis->del(...$keys); $redis->del(...$keys);
$redis->del($statsKey); $redis->del($statsKey);
} }
@ -74,7 +71,6 @@ class UpgradeTask extends Task
public function resetMetadataAction() public function resetMetadataAction()
{ {
$config = $this->getConfig(); $config = $this->getConfig();
$redis = $this->getRedis(); $redis = $this->getRedis();
$dbIndex = $config->path('metadata.db'); $dbIndex = $config->path('metadata.db');
@ -87,9 +83,7 @@ class UpgradeTask extends Task
echo "start reset metadata..." . PHP_EOL; echo "start reset metadata..." . PHP_EOL;
if (count($keys) > 0) { if (count($keys) > 0) {
$keys = $this->handlePhKeys($keys); $keys = $this->handlePhKeys($keys);
$redis->del(...$keys); $redis->del(...$keys);
$redis->del($statsKey); $redis->del($statsKey);
} }

View File

@ -19,16 +19,16 @@ class UploadController extends Controller
$file = $service->uploadCoverImage(); $file = $service->uploadCoverImage();
if ($file) { if (!$file) {
return $this->jsonSuccess([
'data' => [
'src' => $service->getImageUrl($file->path),
'title' => $file->name,
]
]);
} else {
return $this->jsonError(['msg' => '上传文件失败']); return $this->jsonError(['msg' => '上传文件失败']);
} }
$data = [
'src' => $service->getImageUrl($file->path),
'title' => $file->name,
];
return $this->jsonSuccess(['data' => $data]);
} }
/** /**
@ -40,16 +40,16 @@ class UploadController extends Controller
$file = $service->uploadAvatarImage(); $file = $service->uploadAvatarImage();
if ($file) { if (!$file) {
return $this->jsonSuccess([
'data' => [
'src' => $service->getImageUrl($file->path),
'title' => $file->name,
]
]);
} else {
return $this->jsonError(['msg' => '上传文件失败']); return $this->jsonError(['msg' => '上传文件失败']);
} }
$data = [
'src' => $service->getImageUrl($file->path),
'title' => $file->name,
];
return $this->jsonSuccess(['data' => $data]);
} }
/** /**
@ -61,16 +61,16 @@ class UploadController extends Controller
$file = $service->uploadContentImage(); $file = $service->uploadContentImage();
if ($file) { if (!$file) {
return $this->jsonSuccess([
'data' => [
'src' => $service->getImageUrl($file->path),
'title' => $file->name,
]
]);
} else {
return $this->jsonError(['msg' => '上传文件失败']); return $this->jsonError(['msg' => '上传文件失败']);
} }
$data = [
'src' => $service->getImageUrl($file->path),
'title' => $file->name,
];
return $this->jsonSuccess(['data' => $data]);
} }
/** /**

View File

@ -77,7 +77,7 @@ class AuthMenu extends Component
foreach ($routeIdMapping as $key => $value) { foreach ($routeIdMapping as $key => $value) {
$ids = explode('-', $value); $ids = explode('-', $value);
if (in_array($key, $this->authInfo['routes'])) { if (is_array($this->authInfo['routes']) && in_array($key, $this->authInfo['routes'])) {
$owned1stLevelIds[] = $ids[0]; $owned1stLevelIds[] = $ids[0];
$owned2ndLevelIds[] = $ids[0] . '-' . $ids[1]; $owned2ndLevelIds[] = $ids[0] . '-' . $ids[1];
$owned3rdLevelIds[] = $value; $owned3rdLevelIds[] = $value;

View File

@ -671,7 +671,7 @@ class AuthNode extends Service
{ {
return [ return [
'id' => '5', 'id' => '5',
'title' => '系统配置', 'title' => '系统管理',
'children' => [ 'children' => [
[ [
'id' => '5-1', 'id' => '5-1',

View File

@ -29,7 +29,6 @@
{% endif %} {% endif %}
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-input-block"> <div class="layui-input-block">
<button id="submit-btn" class="layui-btn layui-btn-fluid {{ disabled_class }}" {{ disabled_submit }} lay-submit="true" lay-filter="go">立即登录</button> <button id="submit-btn" class="layui-btn layui-btn-fluid {{ disabled_class }}" {{ disabled_submit }} lay-submit="true" lay-filter="go">立即登录</button>
<input type="hidden" name="ticket"> <input type="hidden" name="ticket">
<input type="hidden" name="rand"> <input type="hidden" name="rand">

View File

@ -55,6 +55,10 @@
<td>cover_270</td> <td>cover_270</td>
<td>mageMogr2/thumbnail/270x/interlace/0</td> <td>mageMogr2/thumbnail/270x/interlace/0</td>
</tr> </tr>
<tr>
<td>content_800</td>
<td>mageMogr2/thumbnail/800x/interlace/0</td>
</tr>
<tr> <tr>
<td>slide_1100</td> <td>slide_1100</td>
<td>imageMogr2/thumbnail/1100x/interlace/0</td> <td>imageMogr2/thumbnail/1100x/interlace/0</td>

View File

@ -0,0 +1,113 @@
<?php
namespace App\Http\Api\Controllers;
use App\Http\Api\Services\Account as AccountService;
use App\Services\Logic\Account\EmailUpdate as EmailUpdateService;
use App\Services\Logic\Account\PasswordReset as PasswordResetService;
use App\Services\Logic\Account\PasswordUpdate as PasswordUpdateService;
use App\Services\Logic\Account\PhoneUpdate as PhoneUpdateService;
/**
* @RoutePrefix("/api/account")
*/
class AccountController extends Controller
{
/**
* @Post("/register", name="api.account.register")
*/
public function registerAction()
{
$service = new AccountService();
$token = $service->register();
return $this->jsonSuccess(['token' => $token]);
}
/**
* @Post("/password/login", name="api.account.register")
*/
public function loginByPasswordAction()
{
$service = new AccountService();
$token = $service->loginByPassword();
return $this->jsonSuccess(['token' => $token]);
}
/**
* @Post("/verify/login", name="api.account.verify_login")
*/
public function loginByVerifyAction()
{
$service = new AccountService();
$token = $service->loginByVerify();
return $this->jsonSuccess(['token' => $token]);
}
/**
* @Get("/logout", name="api.account.logout")
*/
public function logoutAction()
{
$service = new AccountService();
$service->logout();
return $this->jsonSuccess();
}
/**
* @Post("/password/reset", name="api.account.reset_pwd")
*/
public function resetPasswordAction()
{
$service = new PasswordResetService();
$service->handle();
return $this->jsonSuccess();
}
/**
* @Post("/phone/update", name="api.account.update_phone")
*/
public function updatePhoneAction()
{
$service = new PhoneUpdateService();
$service->handle();
return $this->jsonSuccess();
}
/**
* @Post("/email/update", name="api.account.update_email")
*/
public function updateEmailAction()
{
$service = new EmailUpdateService();
$service->handle();
return $this->jsonSuccess();
}
/**
* @Post("/password/update", name="api.account.update_pwd")
*/
public function updatePasswordAction()
{
$service = new PasswordUpdateService();
$service->handle();
return $this->jsonSuccess();
}
}

View File

@ -0,0 +1,83 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\Chapter\ChapterInfo as ChapterInfoService;
use App\Services\Logic\Chapter\ChapterLike as ChapterLikeService;
use App\Services\Logic\Chapter\ConsultList as ChapterConsultListService;
use App\Services\Logic\Chapter\Learning as ChapterLearningService;
use App\Services\Logic\Chapter\ResourceList as ChapterResourceListService;
/**
* @RoutePrefix("/api/chapter")
*/
class ChapterController extends Controller
{
/**
* @Get("/{id:[0-9]+}/consults", name="api.chapter.consults")
*/
public function consultsAction($id)
{
$service = new ChapterConsultListService();
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/{id:[0-9]+}/resources", name="api.chapter.resourses")
*/
public function resourcesAction($id)
{
$service = new ChapterResourceListService();
$resources = $service->handle($id);
return $this->jsonSuccess(['resources' => $resources]);
}
/**
* @Get("/{id:[0-9]+}/info", name="api.chapter.info")
*/
public function infoAction($id)
{
$service = new ChapterInfoService();
$chapter = $service->handle($id);
$owned = $chapter['me']['owned'] ?? false;
if (!$owned) {
return $this->jsonError(['msg' => '没有访问章节权限']);
}
return $this->jsonSuccess(['chapter' => $chapter]);
}
/**
* @Post("/{id:[0-9]+}/like", name="api.chapter.like")
*/
public function likeAction($id)
{
$service = new ChapterLikeService();
$service->handle($id);
return $this->jsonSuccess();
}
/**
* @Post("/{id:[0-9]+}/learning", name="api.chapter.learning")
*/
public function learningAction($id)
{
$service = new ChapterLearningService();
$service->handle($id);
return $this->jsonSuccess();
}
}

View File

@ -0,0 +1,97 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\Consult\ConsultCreate as ConsultCreateService;
use App\Services\Logic\Consult\ConsultDelete as ConsultDeleteService;
use App\Services\Logic\Consult\ConsultInfo as ConsultInfoService;
use App\Services\Logic\Consult\ConsultLike as ConsultLikeService;
use App\Services\Logic\Consult\ConsultUpdate as ConsultUpdateService;
/**
* @RoutePrefix("/api/consult")
*/
class ConsultController extends Controller
{
/**
* @Get("/{id:[0-9]+}/info", name="api.consult.info")
*/
public function infoAction($id)
{
$service = new ConsultInfoService();
$consult = $service->handle($id);
return $this->jsonSuccess(['consult' => $consult]);
}
/**
* @Post("/create", name="api.consult.create")
*/
public function createAction()
{
$service = new ConsultCreateService();
$consult = $service->handle();
$service = new ConsultInfoService();
$consult = $service->handle($consult->id);
return $this->jsonSuccess(['consult' => $consult]);
}
/**
* @Post("/{id:[0-9]+}/update", name="api.consult.update")
*/
public function updateAction($id)
{
$service = new ConsultUpdateService();
$consult = $service->handle($id);
$service = new ConsultInfoService();
$consult = $service->handle($consult->id);
return $this->jsonSuccess(['consult' => $consult]);
}
/**
* @Post("/{id:[0-9]+}/delete", name="api.consult.delete")
*/
public function deleteAction($id)
{
$service = new ConsultDeleteService();
$service->handle($id);
return $this->jsonSuccess();
}
/**
* @Post("/{id:[0-9]+}/like", name="api.consult.like")
*/
public function likeAction($id)
{
$service = new ConsultLikeService();
$service->handle($id);
return $this->jsonSuccess();
}
/**
* @Post("/{id:[0-9]+}/unlike", name="api.consult.unlike")
*/
public function unlikeAction($id)
{
$service = new ConsultLikeService();
$service->handle($id);
return $this->jsonSuccess();
}
}

View File

@ -2,6 +2,7 @@
namespace App\Http\Api\Controllers; namespace App\Http\Api\Controllers;
use App\Services\Auth\Api as AppAuth;
use App\Traits\Response as ResponseTrait; use App\Traits\Response as ResponseTrait;
use App\Traits\Security as SecurityTrait; use App\Traits\Security as SecurityTrait;
use Phalcon\Mvc\Dispatcher; use Phalcon\Mvc\Dispatcher;
@ -14,7 +15,25 @@ class Controller extends \Phalcon\Mvc\Controller
public function beforeExecuteRoute(Dispatcher $dispatcher) public function beforeExecuteRoute(Dispatcher $dispatcher)
{ {
$this->checkRateLimit(); if ($this->request->getHeader('Origin')) {
$this->setCors();
}
if (!$this->request->isOptions()) {
$this->checkRateLimit();
}
return true;
}
protected function getAuthUser()
{
/**
* @var AppAuth $auth
*/
$auth = $this->getDI()->get('auth');
return $auth->getCurrentUser();
} }
} }

View File

@ -0,0 +1,128 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\Course\CategoryList as CourseCategoryListService;
use App\Services\Logic\Course\ChapterList as CourseChapterListService;
use App\Services\Logic\Course\ConsultList as CourseConsultListService;
use App\Services\Logic\Course\CourseFavorite as CourseFavoriteService;
use App\Services\Logic\Course\CourseInfo as CourseInfoService;
use App\Services\Logic\Course\CourseList as CourseListService;
use App\Services\Logic\Course\PackageList as CoursePackageListService;
use App\Services\Logic\Course\ReviewList as CourseReviewListService;
/**
* @RoutePrefix("/api/course")
*/
class CourseController extends Controller
{
/**
* @Get("/categories", name="api.course.categories")
*/
public function categoriesAction()
{
$service = new CourseCategoryListService();
$categories = $service->handle();
return $this->jsonSuccess(['categories' => $categories]);
}
/**
* @Get("/list", name="api.course.list")
*/
public function listAction()
{
$service = new CourseListService();
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/{id:[0-9]+}/info", name="api.course.info")
*/
public function infoAction($id)
{
$service = new CourseInfoService();
$course = $service->handle($id);
return $this->jsonSuccess(['course' => $course]);
}
/**
* @Get("/{id:[0-9]+}/chapters", name="api.course.chapters")
*/
public function chaptersAction($id)
{
$service = new CourseChapterListService();
$chapters = $service->handle($id);
return $this->jsonSuccess(['chapters' => $chapters]);
}
/**
* @Get("/{id:[0-9]+}/packages", name="api.course.packages")
*/
public function packagesAction($id)
{
$service = new CoursePackageListService();
$packages = $service->handle($id);
return $this->jsonSuccess(['packages' => $packages]);
}
/**
* @Get("/{id:[0-9]+}/consults", name="api.course.consults")
*/
public function consultsAction($id)
{
$service = new CourseConsultListService();
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/{id:[0-9]+}/reviews", name="api.course.reviews")
*/
public function reviewsAction($id)
{
$service = new CourseReviewListService();
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Post("/{id:[0-9]+}/favorite", name="api.course.favorite")
*/
public function favoriteAction($id)
{
$service = new CourseFavoriteService();
$service->handle($id);
return $this->jsonSuccess();
}
/**
* @Post("/{id:[0-9]+}/unfavorite", name="api.course.unfavorite")
*/
public function unfavoriteAction($id)
{
$service = new CourseFavoriteService();
$service->handle($id);
return $this->jsonSuccess();
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\Help\HelpInfo as HelpInfoService;
use App\Services\Logic\Help\HelpList as HelpListService;
/**
* @RoutePrefix("/api/help")
*/
class HelpController extends Controller
{
/**
* @Get("/list", name="api.help.list")
*/
public function listAction()
{
$service = new HelpListService();
$helps = $service->handle();
return $this->jsonSuccess(['helps' => $helps]);
}
/**
* @Get("/{id:[0-9]+}/info", name="api.help.info")
*/
public function infoAction($id)
{
$service = new HelpInfoService();
$help = $service->handle($id);
return $this->jsonSuccess(['help' => $help]);
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\Im\GroupInfo as GroupInfoService;
use App\Services\Logic\Im\GroupList as GroupListService;
use App\Services\Logic\Im\GroupUserList as GroupUserListService;
/**
* @RoutePrefix("/api/im/group")
*/
class ImGroupController extends Controller
{
/**
* @Get("/list", name="api.im_group.list")
*/
public function listAction()
{
$service = new GroupListService();
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/{id:[0-9]+}/info", name="api.im_group.info")
*/
public function infoAction($id)
{
$service = new GroupInfoService();
$group = $service->handle($id);
return $this->jsonSuccess(['group' => $group]);
}
/**
* @Get("/{id:[0-9]+}/users", name="api.im_group.users")
*/
public function usersAction($id)
{
$service = new GroupUserListService();
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
}
}

View File

@ -2,39 +2,63 @@
namespace App\Http\Api\Controllers; namespace App\Http\Api\Controllers;
use App\Caches\IndexSimpleFreeCourseList;
use App\Caches\IndexSimpleNewCourseList;
use App\Caches\IndexSimpleVipCourseList;
use App\Caches\IndexSlideList;
/** /**
* @RoutePrefix("/api") * @RoutePrefix("/api/index")
*/ */
class IndexController extends Controller class IndexController extends Controller
{ {
/** /**
* @Get("/", name="api.index") * @Get("/slides", name="api.index.slides")
*/ */
public function indexAction() public function slidesAction()
{ {
return $this->jsonSuccess(['data' => 'ok']); $cache = new IndexSlideList();
$slides = $cache->get();
return $this->jsonSuccess(['slides' => $slides]);
} }
/** /**
* @Get("/routes", name="api.routes") * @Get("/courses/new", name="api.index.new_courses")
*/ */
public function routesAction() public function newCoursesAction()
{ {
$definitions = []; $cache = new IndexSimpleNewCourseList();
$routes = $this->router->getRoutes(); $courses = $cache->get();
foreach ($routes as $route) { return $this->jsonSuccess(['courses' => $courses]);
if (strpos($route->getPattern(), '/api') !== false) { }
$definitions[] = [
'pattern' => $route->getPattern(),
'methods' => $route->getHttpMethods(),
];
}
}
return $this->jsonSuccess(['routes' => $definitions]); /**
* @Get("/courses/free", name="api.index.free_courses")
*/
public function freeCoursesAction()
{
$cache = new IndexSimpleFreeCourseList();
$courses = $cache->get();
return $this->jsonSuccess(['courses' => $courses]);
}
/**
* @Get("/courses/vip", name="api.index.vip_courses")
*/
public function vipCoursesAction()
{
$cache = new IndexSimpleVipCourseList();
$courses = $cache->get();
return $this->jsonSuccess(['courses' => $courses]);
} }
} }

View File

@ -0,0 +1,86 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\Live\LiveChapter as LiveChapterService;
use App\Services\Logic\Live\LiveList as LiveListService;
/**
* @RoutePrefix("/api/live")
*/
class LiveController extends Controller
{
/**
* @Get("/list", name="api.live.list")
*/
public function listAction()
{
$service = new LiveListService();
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/{id:[0-9]+}/chats", name="api.live.chats")
*/
public function chatsAction($id)
{
$service = new LiveChapterService();
$chats = $service->getRecentChats($id);
return $this->jsonSuccess(['chats' => $chats]);
}
/**
* @Get("/{id:[0-9]+}/stats", name="api.live.stats")
*/
public function statsAction($id)
{
$service = new LiveChapterService();
$stats = $service->getStats($id);
return $this->jsonSuccess(['stats' => $stats]);
}
/**
* @Get("/{id:[0-9]+}/status", name="api.live.status")
*/
public function statusAction($id)
{
$service = new LiveChapterService();
$status = $service->getStatus($id);
return $this->jsonSuccess(['status' => $status]);
}
/**
* @Post("/{id:[0-9]+}/user/bind", name="api.live.bind_user")
*/
public function bindUserAction($id)
{
$service = new LiveChapterService();
$service->bindUser($id);
return $this->jsonSuccess();
}
/**
* @Post("/{id:[0-9]+}/msg/send", name="api.live.send_msg")
*/
public function sendMessageAction($id)
{
$service = new LiveChapterService();
$message = $service->sendMessage($id);
return $this->jsonSuccess(['message' => $message]);
}
}

View File

@ -0,0 +1,76 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\Order\OrderCancel as OrderCancelService;
use App\Services\Logic\Order\OrderConfirm as OrderConfirmService;
use App\Services\Logic\Order\OrderCreate as OrderCreateService;
use App\Services\Logic\Order\OrderInfo as OrderInfoService;
/**
* @RoutePrefix("/api/order")
*/
class OrderController extends Controller
{
/**
* @Get("/info", name="api.order.info")
*/
public function infoAction()
{
$sn = $this->request->getQuery('sn', 'string');
$service = new OrderInfoService();
$order = $service->handle($sn);
return $this->jsonSuccess(['order' => $order]);
}
/**
* @Get("/confirm", name="api.order.confirm")
*/
public function confirmAction()
{
$itemId = $this->request->getQuery('item_id', 'int');
$itemType = $this->request->getQuery('item_type', 'int');
$service = new OrderConfirmService();
$confirm = $service->handle($itemId, $itemType);
return $this->jsonSuccess(['confirm' => $confirm]);
}
/**
* @Post("/create", name="api.order.create")
*/
public function createAction()
{
$service = new OrderCreateService();
$order = $service->handle();
$service = new OrderInfoService();
$order = $service->handle($order->sn);
return $this->jsonSuccess(['order' => $order]);
}
/**
* @Post("/cancel", name="api.order.cancel")
*/
public function cancelAction()
{
$sn = $this->request->getPost('sn', 'string');
$service = new OrderCancelService();
$order = $service->handle($sn);
return $this->jsonSuccess(['order' => $order]);
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\Page\PageInfo as PageInfoService;
/**
* @RoutePrefix("/api/page")
*/
class PageController extends Controller
{
/**
* @Get("/{id:[0-9]+}/info", name="api.page.info")
*/
public function infoAction($id)
{
$service = new PageInfoService();
$page = $service->handle($id);
return $this->jsonSuccess(['page' => $page]);
}
}

View File

@ -2,14 +2,107 @@
namespace App\Http\Api\Controllers; namespace App\Http\Api\Controllers;
use App\Services\Logic\Reward\OptionList as RewardOptionList;
use App\Services\Logic\Vip\OptionList as VipOptionList;
use App\Services\Service as AppService;
use App\Traits\Response as ResponseTrait; use App\Traits\Response as ResponseTrait;
/** /**
* @RoutePrefix("/api") * @RoutePrefix("/api")
*/ */
class PublicController extends \Phalcon\Mvc\Controller class PublicController extends Controller
{ {
use ResponseTrait; use ResponseTrait;
/**
* @Options("/{match:(.*)}", name="api.match_options")
*/
public function corsAction()
{
$this->response->setStatusCode(204);
return $this->response;
}
/**
* @Get("/now", name="api.public.now")
*/
public function nowAction()
{
return $this->jsonSuccess(['now' => time()]);
}
/**
* @Get("/socket/info", name="api.public.socket_info")
*/
public function socketInfoAction()
{
$service = new AppService();
$websocket = $service->getConfig()->get('websocket');
$content = [];
if ($this->request->isSecure()) {
$content['connect_url'] = sprintf('wss://%s/wss', $this->request->getHttpHost());
} else {
$content['connect_url'] = sprintf('ws://%s', $websocket->connect_address);
}
$content['ping_interval'] = $websocket->ping_interval;
return $this->jsonSuccess(['socket' => $content]);
}
/**
* @Get("/site/info", name="api.public.site_info")
*/
public function siteInfoAction()
{
$service = new AppService();
$site = $service->getSettings('site');
return $this->jsonSuccess(['site' => $site]);
}
/**
* @Get("/captcha/info", name="api.public.captcha_info")
*/
public function captchaInfoAction()
{
$service = new AppService();
$captcha = $service->getSettings('captcha');
unset($captcha['secret_key']);
return $this->jsonSuccess(['captcha' => $captcha]);
}
/**
* @Get("/reward/options", name="api.public.reward_options")
*/
public function rewardOptionsAction()
{
$service = new RewardOptionList();
$options = $service->handle();
return $this->jsonSuccess(['options' => $options]);
}
/**
* @Get("/vip/options", name="api.public.vip_options")
*/
public function vipOptionsAction()
{
$service = new VipOptionList();
$options = $service->handle();
return $this->jsonSuccess(['options' => $options]);
}
} }

View File

@ -0,0 +1,78 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\Refund\RefundCancel as RefundCancelService;
use App\Services\Logic\Refund\RefundConfirm as RefundConfirmService;
use App\Services\Logic\Refund\RefundCreate as RefundCreateService;
use App\Services\Logic\Refund\RefundInfo as RefundInfoService;
/**
* @RoutePrefix("/api/refund")
*/
class RefundController extends Controller
{
/**
* @Get("/confirm", name="api.refund.confirm")
*/
public function confirmAction()
{
$sn = $this->request->getQuery('sn', 'string');
$service = new RefundConfirmService();
$confirm = $service->handle($sn);
return $this->jsonSuccess(['confirm' => $confirm]);
}
/**
* @Get("/info", name="api.refund.info")
*/
public function infoAction()
{
$sn = $this->request->getQuery('sn', 'string');
$service = new RefundInfoService();
$refund = $service->handle($sn);
return $this->jsonSuccess(['refund' => $refund]);
}
/**
* @Post("/create", name="api.refund.create")
*/
public function createAction()
{
$service = new RefundCreateService();
$refund = $service->handle();
$service = new RefundInfoService();
$refund = $service->handle($refund->sn);
return $this->jsonSuccess(['refund' => $refund]);
}
/**
* @Post("/cancel", name="api.refund.cancel")
*/
public function cancelAction()
{
$sn = $this->request->getPost('sn', 'string');
$service = new RefundCancelService();
$service->handle($sn);
$service = new RefundInfoService();
$refund = $service->handle($sn);
return $this->jsonSuccess(['refund' => $refund]);
}
}

View File

@ -0,0 +1,97 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\Review\ReviewCreate as ReviewCreateService;
use App\Services\Logic\Review\ReviewDelete as ReviewDeleteService;
use App\Services\Logic\Review\ReviewInfo as ReviewInfoService;
use App\Services\Logic\Review\ReviewLike as ReviewLikeService;
use App\Services\Logic\Review\ReviewUpdate as ReviewUpdateService;
/**
* @RoutePrefix("/api/review")
*/
class ReviewController extends Controller
{
/**
* @Get("/{id:[0-9]+}/info", name="api.review.info")
*/
public function infoAction($id)
{
$service = new ReviewInfoService();
$review = $service->handle($id);
return $this->jsonSuccess(['review' => $review]);
}
/**
* @Post("/create", name="api.order.create")
*/
public function createAction()
{
$service = new ReviewCreateService();
$review = $service->handle();
$service = new ReviewInfoService();
$review = $service->handle($review->id);
return $this->jsonSuccess(['review' => $review]);
}
/**
* @Post("/{id:[0-9]+}/update", name="api.review.update")
*/
public function updateAction($id)
{
$service = new ReviewUpdateService();
$service->handle($id);
$service = new ReviewInfoService();
$review = $service->handle($id);
return $this->jsonSuccess(['review' => $review]);
}
/**
* @Post("/{id:[0-9]+}/delete", name="api.review.delete")
*/
public function deleteAction($id)
{
$service = new ReviewDeleteService();
$service->handle($id);
return $this->jsonSuccess();
}
/**
* @Post("/{id:[0-9]+}/like", name="api.review.like")
*/
public function likeAction($id)
{
$service = new ReviewLikeService();
$service->handle($id);
return $this->jsonSuccess();
}
/**
* @Post("/{id:[0-9]+}/unlike", name="api.review.unlike")
*/
public function unlikeAction($id)
{
$service = new ReviewLikeService();
$service->handle($id);
return $this->jsonSuccess();
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\Search\Course as CourseSearchService;
use App\Services\Logic\Search\Group as GroupSearchService;
use App\Services\Logic\Search\User as UserSearchService;
/**
* @RoutePrefix("/api/search")
*/
class SearchController extends Controller
{
/**
* @Get("/", name="api.search.index")
*/
public function indexAction()
{
$query = $this->request->get('query', ['trim', 'string']);
$type = $this->request->get('type', ['trim', 'string'], 'course');
$pager = [
'total_pages' => 0,
'total_items' => 0,
'items' => [],
];
if (empty($query)) {
return $this->jsonSuccess(['pager' => $pager]);
}
$service = $this->getSearchService($type);
$pager = $service->search();
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @param string $type
* @return CourseSearchService|GroupSearchService|UserSearchService
*/
protected function getSearchService($type)
{
switch ($type) {
case 'group':
$service = new GroupSearchService();
break;
case 'user':
$service = new UserSearchService();
break;
default:
$service = new CourseSearchService();
break;
}
return $service;
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\Teacher\CourseList as CourseListService;
use App\Services\Logic\Teacher\TeacherInfo as TeacherInfoService;
use App\Services\Logic\Teacher\TeacherList as TeacherListService;
/**
* @RoutePrefix("/api/teacher")
*/
class TeacherController extends Controller
{
/**
* @Get("/list", name="api.teacher.list")
*/
public function listAction()
{
$service = new TeacherListService();
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/{id:[0-9]+}/info", name="api.teacher.info")
*/
public function infoAction($id)
{
$service = new TeacherInfoService();
$teacher = $service->handle($id);
return $this->jsonSuccess(['teacher' => $teacher]);
}
/**
* @Get("/{id:[0-9]+}/courses", name="api.teacher.courses")
*/
public function coursesAction($id)
{
$service = new CourseListService();
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
}
}

View File

@ -0,0 +1,88 @@
<?php
namespace App\Http\Api\Controllers;
use App\Http\Api\Services\Trade as TradeService;
use App\Services\Logic\Trade\TradeInfo as TradeInfoService;
/**
* @RoutePrefix("/api/trade")
*/
class TradeController extends Controller
{
/**
* @Get("/info", name="api.trade.info")
*/
public function infoAction()
{
$sn = $this->request->getQuery('sn', 'string');
$service = new TradeInfoService();
$trade = $service->handle($sn);
return $this->jsonSuccess(['trade' => $trade]);
}
/**
* @Get("/h5/pay", name="api.trade.h5_pay")
*/
public function h5PayAction()
{
$sn = $this->request->getQuery('sn', 'string');
$service = new TradeService();
$response = $service->h5Pay($sn);
if (!$response) {
echo "H5支付跳转失败请回退重试";
}
$response->send();
exit();
}
/**
* @Post("/h5/create", name="api.trade.h5_create")
*/
public function createH5TradeAction()
{
$service = new TradeService();
$trade = $service->createH5Trade();
$service = new TradeInfoService();
$trade = $service->handle($trade->sn);
return $this->jsonSuccess(['trade' => $trade]);
}
/**
* @Post("/mp/create", name="api.trade.mp_create")
*/
public function createMpTradeAction()
{
$service = new TradeService();
$content = $service->createMpTrade();
return $this->jsonSuccess($content);
}
/**
* @Post("/app/create", name="api.trade.app_create")
*/
public function createAppTradeAction()
{
$service = new TradeService();
$content = $service->createMpTrade();
return $this->jsonSuccess($content);
}
}

View File

@ -0,0 +1,50 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\MyStorage as StorageService;
/**
* @RoutePrefix("/api/upload")
*/
class UploadController extends Controller
{
/**
* @Post("/avatar/img", name="api.upload.avatar_img")
*/
public function uploadAvatarImageAction()
{
$service = new StorageService();
$file = $service->uploadAvatarImage();
if (!$file) {
return $this->jsonError(['msg' => '上传文件失败']);
}
$data = [
'src' => $service->getImageUrl($file->path),
'title' => $file->name,
];
return $this->jsonSuccess(['data' => $data]);
}
/**
* @Post("/im/img", name="api.upload.im_img")
*/
public function uploadImImageAction()
{
}
/**
* @Post("/im/file", name="api.upload.im_file")
*/
public function uploadImFileAction()
{
}
}

View File

@ -0,0 +1,155 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\User\Console\AccountInfo as AccountInfoService;
use App\Services\Logic\User\Console\ConsultList as ConsultListService;
use App\Services\Logic\User\Console\CourseList as CourseListService;
use App\Services\Logic\User\Console\FavoriteList as FavoriteListService;
use App\Services\Logic\User\Console\FriendList as FriendListService;
use App\Services\Logic\User\Console\GroupList as GroupListService;
use App\Services\Logic\User\Console\OrderList as OrderListService;
use App\Services\Logic\User\Console\ProfileInfo as ProfileInfoService;
use App\Services\Logic\User\Console\ProfileUpdate as ProfileUpdateService;
use App\Services\Logic\User\Console\RefundList as RefundListService;
use App\Services\Logic\User\Console\ReviewList as ReviewListService;
/**
* @RoutePrefix("/api/uc")
*/
class UserConsoleController extends Controller
{
/**
* @Get("/profile", name="api.uc.profile")
*/
public function profileAction()
{
$service = new ProfileInfoService();
$profile = $service->handle();
return $this->jsonSuccess(['profile' => $profile]);
}
/**
* @Get("/account", name="api.uc.account")
*/
public function accountAction()
{
$service = new AccountInfoService();
$account = $service->handle();
return $this->jsonSuccess(['account' => $account]);
}
/**
* @Get("/courses", name="api.uc.courses")
*/
public function coursesAction()
{
$service = new CourseListService();
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/favorites", name="api.uc.favorites")
*/
public function favoritesAction()
{
$service = new FavoriteListService();
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/consults", name="api.uc.consults")
*/
public function consultsAction()
{
$service = new ConsultListService();
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/reviews", name="api.uc.reviews")
*/
public function reviewsAction()
{
$service = new ReviewListService();
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/orders", name="api.uc.orders")
*/
public function ordersAction()
{
$service = new OrderListService();
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/refunds", name="api.uc.refunds")
*/
public function refundsAction()
{
$service = new RefundListService();
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/friends", name="api.uc.friends")
*/
public function friendsAction()
{
$service = new FriendListService();
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/groups", name="api.uc.groups")
*/
public function groupsAction()
{
$service = new GroupListService();
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Post("/profile/update", name="api.uc.update_profile")
*/
public function updateProfileAction()
{
$service = new ProfileUpdateService();
$service->handle();
return $this->jsonSuccess();
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\User\CourseList as UserCourseListService;
use App\Services\Logic\User\FavoriteList as UserFavoriteListService;
use App\Services\Logic\User\FriendList as UserFriendListService;
use App\Services\Logic\User\GroupList as UserGroupListService;
use App\Services\Logic\User\UserInfo as UserInfoService;
/**
* @RoutePrefix("/api/user")
*/
class UserController extends Controller
{
/**
* @Get("/{id:[0-9]+}/info", name="api.user.info")
*/
public function infoAction($id)
{
$service = new UserInfoService();
$user = $service->handle($id);
return $this->jsonSuccess(['user' => $user]);
}
/**
* @Get("/{id:[0-9]+}/courses", name="api.user.courses")
*/
public function coursesAction($id)
{
$service = new UserCourseListService();
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/{id:[0-9]+}/favorites", name="api.user.favorites")
*/
public function favoritesAction($id)
{
$service = new UserFavoriteListService();
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/{id:[0-9]+}/friends", name="api.user.friends")
*/
public function friendsAction($id)
{
$service = new UserFriendListService();
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/{id:[0-9]+}/groups", name="api.user.groups")
*/
public function groupsAction($id)
{
$service = new UserGroupListService();
$pager = $service->handle($id);
return $this->jsonSuccess(['pager' => $pager]);
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\Verify\EmailCode as EmailCodeService;
use App\Services\Logic\Verify\SmsCode as SmsCodeService;
/**
* @RoutePrefix("/api/verify")
*/
class VerifyController extends Controller
{
/**
* @Post("/sms/code", name="api.verify.sms_code")
*/
public function smsCodeAction()
{
$service = new SmsCodeService();
$service->handle();
return $this->jsonSuccess();
}
/**
* @Post("/email/code", name="api.verify.email_code")
*/
public function emailCodeAction()
{
$service = new EmailCodeService();
$service->handle();
return $this->jsonSuccess();
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace App\Http\Api\Controllers;
use App\Services\Logic\Vip\CourseList as VipCourseListService;
use App\Services\Logic\Vip\UserList as VipUserListService;
/**
* @RoutePrefix("/api/vip")
*/
class VipController extends Controller
{
/**
* @Get("/courses", name="api.vip.courses")
*/
public function coursesAction()
{
$type = $this->request->getQuery('type', 'string', 'discount');
$service = new VipCourseListService();
$pager = $service->handle($type);
return $this->jsonSuccess(['pager' => $pager]);
}
/**
* @Get("/users", name="api.vip.users")
*/
public function usersAction()
{
$service = new VipUserListService();
$pager = $service->handle();
return $this->jsonSuccess(['pager' => $pager]);
}
}

View File

@ -2,7 +2,7 @@
namespace App\Http\Api; namespace App\Http\Api;
use App\Services\Auth\Api as ApiAuth; use App\Services\Auth\Api as AppAuth;
use Phalcon\DiInterface; use Phalcon\DiInterface;
use Phalcon\Mvc\ModuleDefinitionInterface; use Phalcon\Mvc\ModuleDefinitionInterface;
use Phalcon\Mvc\View; use Phalcon\Mvc\View;
@ -24,7 +24,7 @@ class Module implements ModuleDefinitionInterface
}); });
$di->setShared('auth', function () { $di->setShared('auth', function () {
return new ApiAuth(); return new AppAuth();
}); });
} }

View File

@ -0,0 +1,81 @@
<?php
namespace App\Http\Api\Services;
use App\Repos\User as UserRepo;
use App\Services\Auth\Api as AuthService;
use App\Services\Logic\Account\Register as RegisterService;
use App\Validators\Account as AccountValidator;
class Account extends Service
{
/**
* @var AuthService
*/
protected $auth;
public function __construct()
{
$this->auth = $this->getDI()->get('auth');
}
public function register()
{
$service = new RegisterService();
$account = $service->handle();
$userRepo = new UserRepo();
$user = $userRepo->findById($account->id);
return $this->auth->saveAuthInfo($user);
}
public function loginByPassword()
{
$post = $this->request->getPost();
/**
* 使用[account|phone|email]做账户名字段兼容
*/
if (isset($post['phone'])) {
$post['account'] = $post['phone'];
} elseif (isset($post['email'])) {
$post['account'] = $post['email'];
}
$validator = new AccountValidator();
$user = $validator->checkUserLogin($post['account'], $post['password']);
return $this->auth->saveAuthInfo($user);
}
public function loginByVerify()
{
$post = $this->request->getPost();
/**
* 使用[account|phone|email]做账户名字段兼容
*/
if (isset($post['phone'])) {
$post['account'] = $post['phone'];
} elseif (isset($post['email'])) {
$post['account'] = $post['email'];
}
$validator = new AccountValidator();
$user = $validator->checkVerifyLogin($post['account'], $post['verify_code']);
return $this->auth->saveAuthInfo($user);
}
public function logout()
{
$this->auth->clearAuthInfo();
}
}

View File

@ -1,33 +0,0 @@
<?php
namespace App\Http\Api\Services;
use App\Services\Auth\Api as ApiAuth;
use App\Validators\Account as AccountValidator;
class Login extends Service
{
public function loginByPassword($name, $password)
{
$validator = new AccountValidator();
$user = $validator->checkUserLogin($name, $password);
$auth = new ApiAuth();
return $auth->saveAuthInfo($user);
}
public function loginByVerify($name, $code)
{
$validator = new AccountValidator();
$user = $validator->checkVerifyLogin($name, $code);
$auth = new ApiAuth();
return $auth->saveAuthInfo($user);
}
}

View File

@ -1,17 +0,0 @@
<?php
namespace App\Http\Api\Services;
use App\Services\Auth\Api as ApiAuth;
class Logout extends Service
{
public function logout()
{
$auth = new ApiAuth();
return $auth->clearAuthInfo();
}
}

View File

@ -0,0 +1,125 @@
<?php
namespace App\Http\Api\Services;
use App\Models\Client as ClientModel;
use App\Models\Trade as TradeModel;
use App\Services\Logic\OrderTrait;
use App\Services\Logic\TradeTrait;
use App\Services\Pay\Alipay;
use App\Services\Pay\Wxpay;
use App\Validators\Client as ClientValidator;
use App\Validators\Trade as TradeValidator;
class Trade extends Service
{
use OrderTrait;
use TradeTrait;
public function h5Pay($sn)
{
$trade = $this->checkTradeBySn($sn);
$response = null;
if ($trade->channel == TradeModel::CHANNEL_ALIPAY) {
$alipay = new Alipay();
$response = $alipay->wap($trade);
} elseif ($trade->channel == TradeModel::CHANNEL_WXPAY) {
$wxpay = new Wxpay();
$response = $wxpay->wap($trade);
}
return $response;
}
public function createH5Trade()
{
$post = $this->request->getPost();
$validator = new ClientValidator();
$platform = $this->getPlatform();
$validator->checkH5Platform($platform);
$order = $this->checkOrderBySn($post['order_sn']);
$user = $this->getLoginUser();
$validator = new TradeValidator();
$channel = $validator->checkChannel($post['channel']);
$trade = new TradeModel();
$trade->subject = $order->subject;
$trade->amount = $order->amount;
$trade->channel = $channel;
$trade->order_id = $order->id;
$trade->owner_id = $user->id;
$trade->create();
return $trade;
}
public function createMpTrade()
{
$post = $this->request->getPost();
$validator = new ClientValidator();
$platform = $this->getPlatform();
$platform = $validator->checkMpPlatform($platform);
$order = $this->checkOrderBySn($post['order_sn']);
$user = $this->getLoginUser();
$channel = TradeModel::CHANNEL_WXPAY;
if ($platform == ClientModel::TYPE_MP_ALIPAY) {
$channel = TradeModel::CHANNEL_ALIPAY;
} elseif ($platform == ClientModel::TYPE_MP_WEIXIN) {
$channel = TradeModel::CHANNEL_WXPAY;
}
$trade = new TradeModel();
$trade->subject = $order->subject;
$trade->amount = $order->amount;
$trade->channel = $channel;
$trade->order_id = $order->id;
$trade->owner_id = $user->id;
$trade->create();
$response = null;
if ($post['channel'] == TradeModel::CHANNEL_ALIPAY) {
$alipay = new Alipay();
$buyerId = '';
$response = $alipay->mini($trade, $buyerId);
} elseif ($post['channel'] == TradeModel::CHANNEL_WXPAY) {
$wxpay = new Wxpay();
$openId = '';
$response = $wxpay->mini($trade, $openId);
}
return $response;
}
public function createAppTrade()
{
}
protected function getPlatform()
{
return $this->request->getHeader('X-Platform');
}
}

View File

@ -81,9 +81,7 @@ class AccountController extends Controller
$location = $returnUrl ?: $this->url->get(['for' => 'home.index']); $location = $returnUrl ?: $this->url->get(['for' => 'home.index']);
$content = ['location' => $location]; return $this->jsonSuccess(['location' => $location]);
return $this->jsonSuccess($content);
} }
/** /**
@ -99,9 +97,7 @@ class AccountController extends Controller
$location = $returnUrl ?: $this->url->get(['for' => 'home.index']); $location = $returnUrl ?: $this->url->get(['for' => 'home.index']);
$content = ['location' => $location]; return $this->jsonSuccess(['location' => $location]);
return $this->jsonSuccess($content);
} }
/** /**

View File

@ -29,6 +29,18 @@ class ChapterController extends Controller
$this->view->setVar('items', $items); $this->view->setVar('items', $items);
} }
/**
* @Get("/{id:[0-9]+}/danmus", name="home.chapter.danmus")
*/
public function danmusAction($id)
{
$service = new ChapterDanmuListService();
$items = $service->handle($id);
return $this->jsonSuccess(['items' => $items]);
}
/** /**
* @Get("/{id:[0-9]+}", name="home.chapter.show") * @Get("/{id:[0-9]+}", name="home.chapter.show")
*/ */
@ -75,18 +87,6 @@ class ChapterController extends Controller
$this->view->setVar('catalog', $catalog); $this->view->setVar('catalog', $catalog);
} }
/**
* @Get("/{id:[0-9]+}/danmu", name="home.chapter.danmu")
*/
public function danmuAction($id)
{
$service = new ChapterDanmuListService();
$items = $service->handle($id);
return $this->jsonSuccess(['items' => $items]);
}
/** /**
* @Post("/{id:[0-9]+}/like", name="home.chapter.like") * @Post("/{id:[0-9]+}/like", name="home.chapter.like")
*/ */
@ -98,9 +98,7 @@ class ChapterController extends Controller
$msg = $like->deleted == 0 ? '点赞成功' : '取消点赞成功'; $msg = $like->deleted == 0 ? '点赞成功' : '取消点赞成功';
$content = ['msg' => $msg]; return $this->jsonSuccess(['msg' => $msg]);
return $this->jsonSuccess($content);
} }
/** /**

View File

@ -58,9 +58,12 @@ class ConsultController extends Controller
$service = new ConsultInfoService(); $service = new ConsultInfoService();
$service->handle($consult->id); $consult = $service->handle($consult->id);
$content = ['msg' => '提交咨询成功']; $content = [
'consult' => $consult,
'msg' => '提交咨询成功',
];
return $this->jsonSuccess($content); return $this->jsonSuccess($content);
} }
@ -72,9 +75,16 @@ class ConsultController extends Controller
{ {
$service = new ConsultUpdateService(); $service = new ConsultUpdateService();
$service->handle($id); $consult = $service->handle($id);
$content = ['msg' => '更新咨询成功']; $service = new ConsultInfoService();
$consult = $service->handle($consult->id);
$content = [
'consult' => $consult,
'msg' => '更新咨询成功',
];
return $this->jsonSuccess($content); return $this->jsonSuccess($content);
} }
@ -88,9 +98,7 @@ class ConsultController extends Controller
$service->handle($id); $service->handle($id);
$content = ['msg' => '删除咨询成功']; return $this->jsonSuccess(['msg' => '删除咨询成功']);
return $this->jsonSuccess($content);
} }
/** /**
@ -102,9 +110,16 @@ class ConsultController extends Controller
$service = new ConsultReplyService(); $service = new ConsultReplyService();
$service->handle($id); $consult = $service->handle($id);
$content = ['msg' => '回复咨询成功']; $service = new ConsultInfoService();
$consult = $service->handle($consult->id);
$content = [
'consult' => $consult,
'msg' => '回复咨询成功',
];
return $this->jsonSuccess($content); return $this->jsonSuccess($content);
@ -129,9 +144,7 @@ class ConsultController extends Controller
$msg = $like->deleted == 0 ? '点赞成功' : '取消点赞成功'; $msg = $like->deleted == 0 ? '点赞成功' : '取消点赞成功';
$content = ['msg' => $msg]; return $this->jsonSuccess(['msg' => $msg]);
return $this->jsonSuccess($content);
} }
} }

View File

@ -58,6 +58,7 @@ class Controller extends \Phalcon\Mvc\Controller
'controller' => 'error', 'controller' => 'error',
'action' => 'maintain', 'action' => 'maintain',
]); ]);
return false;
} }
if ($this->isNotSafeRequest()) { if ($this->isNotSafeRequest()) {

View File

@ -3,7 +3,6 @@
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Http\Home\Services\Im as ImService; use App\Http\Home\Services\Im as ImService;
use App\Traits\Response as ResponseTrait;
use Phalcon\Mvc\View; use Phalcon\Mvc\View;
/** /**
@ -12,8 +11,6 @@ use Phalcon\Mvc\View;
class ImController extends Controller class ImController extends Controller
{ {
use ResponseTrait;
public function initialize() public function initialize()
{ {
parent::initialize(); parent::initialize();
@ -265,9 +262,7 @@ class ImController extends Controller
$service->applyFriend(); $service->applyFriend();
$content = ['msg' => '发送申请成功,请等待对方通过']; return $this->jsonSuccess(['msg' => '发送申请成功']);
return $this->jsonSuccess($content);
} }
/** /**
@ -303,9 +298,7 @@ class ImController extends Controller
$service->applyGroup(); $service->applyGroup();
$content = ['msg' => '发送申请成功,请等待管理员通过']; return $this->jsonSuccess(['msg' => '发送申请成功']);
return $this->jsonSuccess($content);
} }
/** /**
@ -341,9 +334,7 @@ class ImController extends Controller
$service->quitFriend($id); $service->quitFriend($id);
$content = ['msg' => '解除好友成功']; return $this->jsonSuccess(['msg' => '解除好友成功']);
return $this->jsonSuccess($content);
} }
/** /**
@ -355,9 +346,7 @@ class ImController extends Controller
$service->quitGroup($id); $service->quitGroup($id);
$content = ['msg' => '退出群组成功']; return $this->jsonSuccess(['msg' => '退出群组成功']);
return $this->jsonSuccess($content);
} }
} }

View File

@ -48,9 +48,7 @@ class ImGroupManageController extends Controller
$service->updateGroup($id); $service->updateGroup($id);
$content = ['msg' => '更新群组成功']; return $this->jsonSuccess(['msg' => '更新群组成功']);
return $this->jsonSuccess($content);
} }
/** /**
@ -62,8 +60,10 @@ class ImGroupManageController extends Controller
$service->deleteGroupUser($gid, $uid); $service->deleteGroupUser($gid, $uid);
$location = $this->request->getHTTPReferer();
$content = [ $content = [
'location' => $this->request->getHTTPReferer(), 'location' => $location,
'msg' => '移除用户成功', 'msg' => '移除用户成功',
]; ];

View File

@ -3,10 +3,26 @@
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Http\Home\Services\Index as IndexService; use App\Http\Home\Services\Index as IndexService;
use App\Traits\Client as ClientTrait;
use Phalcon\Mvc\Dispatcher;
class IndexController extends Controller class IndexController extends Controller
{ {
use ClientTrait;
public function beforeExecuteRoute(Dispatcher $dispatcher)
{
if ($this->isMobileBrowser()) {
$this->response->redirect('/h5', true);
return false;
}
return parent::beforeExecuteRoute($dispatcher);
}
/** /**
* @Get("/", name="home.index") * @Get("/", name="home.index")
*/ */

View File

@ -2,24 +2,21 @@
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Http\Home\Services\ChapterLive as ChapterLiveService; use App\Services\Logic\Live\LiveChapter as LiveChapterService;
use App\Traits\Response as ResponseTrait;
use Phalcon\Mvc\View; use Phalcon\Mvc\View;
/** /**
* @RoutePrefix("/live") * @RoutePrefix("/live")
*/ */
class ChapterLiveController extends Controller class LiveController extends Controller
{ {
use ResponseTrait;
/** /**
* @Get("/{id:[0-9]+}/chats", name="home.live.chats") * @Get("/{id:[0-9]+}/chats", name="home.live.chats")
*/ */
public function chatsAction($id) public function chatsAction($id)
{ {
$service = new ChapterLiveService(); $service = new LiveChapterService();
$chats = $service->getRecentChats($id); $chats = $service->getRecentChats($id);
@ -33,7 +30,7 @@ class ChapterLiveController extends Controller
*/ */
public function statsAction($id) public function statsAction($id)
{ {
$service = new ChapterLiveService(); $service = new LiveChapterService();
$stats = $service->getStats($id); $stats = $service->getStats($id);
@ -45,7 +42,7 @@ class ChapterLiveController extends Controller
*/ */
public function statusAction($id) public function statusAction($id)
{ {
$service = new ChapterLiveService(); $service = new LiveChapterService();
$status = $service->getStatus($id); $status = $service->getStatus($id);
@ -57,7 +54,7 @@ class ChapterLiveController extends Controller
*/ */
public function bindUserAction($id) public function bindUserAction($id)
{ {
$service = new ChapterLiveService(); $service = new LiveChapterService();
$service->bindUser($id); $service->bindUser($id);
@ -69,7 +66,7 @@ class ChapterLiveController extends Controller
*/ */
public function sendMessageAction($id) public function sendMessageAction($id)
{ {
$service = new ChapterLiveService(); $service = new LiveChapterService();
$response = $service->sendMessage($id); $response = $service->sendMessage($id);

View File

@ -48,8 +48,8 @@ class OrderController extends Controller
*/ */
public function confirmAction() public function confirmAction()
{ {
$itemId = $this->request->getQuery('item_id', 'int'); $itemId = $this->request->getQuery('item_id', 'string');
$itemType = $this->request->getQuery('item_type', 'int'); $itemType = $this->request->getQuery('item_type', 'string');
$service = new OrderConfirmService(); $service = new OrderConfirmService();
@ -87,7 +87,7 @@ class OrderController extends Controller
$order = $service->handle($sn); $order = $service->handle($sn);
if ($order['status'] != OrderModel::STATUS_PENDING) { if ($order['status'] != OrderModel::STATUS_PENDING) {
$this->response->redirect(['for' => 'home.my.orders']); $this->response->redirect(['for' => 'home.uc.orders']);
} }
$this->view->setVar('order', $order); $this->view->setVar('order', $order);

View File

@ -10,7 +10,6 @@ use App\Services\Pay\Wxpay as WxpayService;
use App\Services\Storage as StorageService; use App\Services\Storage as StorageService;
use App\Traits\Response as ResponseTrait; use App\Traits\Response as ResponseTrait;
use App\Traits\Security as SecurityTrait; use App\Traits\Security as SecurityTrait;
use Phalcon\Text;
use PHPQRCode\QRcode; use PHPQRCode\QRcode;
class PublicController extends \Phalcon\Mvc\Controller class PublicController extends \Phalcon\Mvc\Controller
@ -44,31 +43,6 @@ class PublicController extends \Phalcon\Mvc\Controller
} }
} }
/**
* @Get("/img/{id:[0-9]+}", name="home.img")
*/
public function imageAction($id)
{
$repo = new UploadRepo();
$file = $repo->findById($id);
if ($file && Text::startsWith($file->mime, 'image')) {
$service = new StorageService();
$location = $service->getImageUrl($file->path);
$this->response->redirect($location);
} else {
$this->response->setStatusCode(404);
return $this->response;
}
}
/** /**
* @Get("/qrcode", name="home.qrcode") * @Get("/qrcode", name="home.qrcode")
*/ */

View File

@ -44,12 +44,7 @@ class RefundController extends Controller
$service->handle(); $service->handle();
$content = [ return $this->jsonSuccess(['msg' => '申请退款成功']);
'location' => $this->url->get(['for' => 'home.my.refunds']),
'msg' => '申请退款成功',
];
return $this->jsonSuccess($content);
} }
/** /**
@ -78,12 +73,7 @@ class RefundController extends Controller
$service->handle($sn); $service->handle($sn);
$content = [ return $this->jsonSuccess(['msg' => '取消退款成功']);
'location' => $this->url->get(['for' => 'home.my.refunds']),
'msg' => '取消退款成功',
];
return $this->jsonSuccess($content);
} }
} }

View File

@ -99,9 +99,7 @@ class ReviewController extends Controller
$service->handle($id); $service->handle($id);
$content = ['msg' => '删除评价成功']; return $this->jsonSuccess(['msg' => '删除评价成功']);
return $this->jsonSuccess($content);
} }
/** /**
@ -115,9 +113,7 @@ class ReviewController extends Controller
$msg = $like->deleted == 0 ? '点赞成功' : '取消点赞成功'; $msg = $like->deleted == 0 ? '点赞成功' : '取消点赞成功';
$content = ['msg' => $msg]; return $this->jsonSuccess(['msg' => $msg]);
return $this->jsonSuccess($content);
} }
} }

View File

@ -5,7 +5,6 @@ namespace App\Http\Home\Controllers;
use App\Services\Logic\Search\Course as CourseSearchService; use App\Services\Logic\Search\Course as CourseSearchService;
use App\Services\Logic\Search\Group as GroupSearchService; use App\Services\Logic\Search\Group as GroupSearchService;
use App\Services\Logic\Search\User as UserSearchService; use App\Services\Logic\Search\User as UserSearchService;
use App\Traits\Response as ResponseTrait;
/** /**
* @RoutePrefix("/search") * @RoutePrefix("/search")
@ -13,8 +12,6 @@ use App\Traits\Response as ResponseTrait;
class SearchController extends Controller class SearchController extends Controller
{ {
use ResponseTrait;
/** /**
* @Get("/", name="home.search.index") * @Get("/", name="home.search.index")
*/ */
@ -42,14 +39,6 @@ class SearchController extends Controller
$this->view->setVar('pager', $pager); $this->view->setVar('pager', $pager);
} }
/**
* @Get("/form", name="home.search.form")
*/
public function formAction()
{
}
/** /**
* @param string $type * @param string $type
* @return CourseSearchService|GroupSearchService|UserSearchService * @return CourseSearchService|GroupSearchService|UserSearchService
@ -58,7 +47,7 @@ class SearchController extends Controller
{ {
switch ($type) { switch ($type) {
case 'group': case 'group':
$service = new GroupSearchService; $service = new GroupSearchService();
break; break;
case 'user': case 'user':
$service = new UserSearchService(); $service = new UserSearchService();

View File

@ -1,9 +1,9 @@
<?php <?php
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Services\MyStorage as StorageService; use App\Services\MyStorage as StorageService;
use App\Validators\Validator as AppValidator;
/** /**
* @RoutePrefix("/upload") * @RoutePrefix("/upload")
@ -11,6 +11,15 @@ use App\Services\MyStorage as StorageService;
class UploadController extends Controller class UploadController extends Controller
{ {
public function initialize()
{
$authUser = $this->getAuthUser();
$validator = new AppValidator();
$validator->checkAuthUser($authUser->id);
}
/** /**
* @Post("/avatar/img", name="home.upload.avatar_img") * @Post("/avatar/img", name="home.upload.avatar_img")
*/ */
@ -20,16 +29,16 @@ class UploadController extends Controller
$file = $service->uploadAvatarImage(); $file = $service->uploadAvatarImage();
if ($file) { if (!$file) {
return $this->jsonSuccess([
'data' => [
'src' => $service->getImageUrl($file->path),
'title' => $file->name,
]
]);
} else {
return $this->jsonError(['msg' => '上传文件失败']); return $this->jsonError(['msg' => '上传文件失败']);
} }
$data = [
'src' => $service->getImageUrl($file->path),
'title' => $file->name,
];
return $this->jsonSuccess(['data' => $data]);
} }
/** /**

View File

@ -4,7 +4,6 @@ namespace App\Http\Home\Controllers;
use App\Services\Logic\Verify\EmailCode as EmailCodeService; use App\Services\Logic\Verify\EmailCode as EmailCodeService;
use App\Services\Logic\Verify\SmsCode as SmsCodeService; use App\Services\Logic\Verify\SmsCode as SmsCodeService;
use App\Services\Logic\Verify\VerifyCode as VerifyCodeService;
use App\Traits\Response as ResponseTrait; use App\Traits\Response as ResponseTrait;
/** /**
@ -15,18 +14,6 @@ class VerifyController extends \Phalcon\Mvc\Controller
use ResponseTrait; use ResponseTrait;
/**
* @Post("/code", name="verify.code")
*/
public function verifyCodeAction()
{
$service = new VerifyCodeService();
$service->handle();
return $this->jsonSuccess();
}
/** /**
* @Post("/sms/code", name="verify.sms_code") * @Post("/sms/code", name="verify.sms_code")
*/ */

View File

@ -3,7 +3,7 @@
namespace App\Http\Home\Services; namespace App\Http\Home\Services;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use App\Services\Auth as AuthService; use App\Services\Auth\Home as AuthService;
use App\Services\Logic\Account\Register as RegisterService; use App\Services\Logic\Account\Register as RegisterService;
use App\Validators\Account as AccountValidator; use App\Validators\Account as AccountValidator;
use App\Validators\Captcha as CaptchaValidator; use App\Validators\Captcha as CaptchaValidator;
@ -40,13 +40,13 @@ class Account extends Service
{ {
$post = $this->request->getPost(); $post = $this->request->getPost();
$accountValidator = new AccountValidator(); $validator = new AccountValidator();
$user = $accountValidator->checkUserLogin($post['account'], $post['password']); $user = $validator->checkUserLogin($post['account'], $post['password']);
$captchaValidator = new CaptchaValidator(); $validator = new CaptchaValidator();
$captchaValidator->checkCode($post['ticket'], $post['rand']); $validator->checkCode($post['ticket'], $post['rand']);
$this->auth->saveAuthInfo($user); $this->auth->saveAuthInfo($user);
} }
@ -55,9 +55,9 @@ class Account extends Service
{ {
$post = $this->request->getPost(); $post = $this->request->getPost();
$accountValidator = new AccountValidator(); $validator = new AccountValidator();
$user = $accountValidator->checkVerifyLogin($post['account'], $post['verify_code']); $user = $validator->checkVerifyLogin($post['account'], $post['verify_code']);
$this->auth->saveAuthInfo($user); $this->auth->saveAuthInfo($user);
} }

View File

@ -7,11 +7,10 @@
<ul class="sidebar-lesson-list"> <ul class="sidebar-lesson-list">
{% for lesson in item.children %} {% for lesson in item.children %}
{% set url = url({'for':'home.chapter.show','id':lesson.id}) %} {% set url = url({'for':'home.chapter.show','id':lesson.id}) %}
{% set free_flag = lesson.free == 1 ? '<span class="layui-badge">免费</span>' : '' %}
{% set active = (chapter.id == lesson.id) ? 'active' : 'normal' %} {% set active = (chapter.id == lesson.id) ? 'active' : 'normal' %}
<li class="lesson-title layui-elip"> <li class="lesson-title layui-elip">
{% if lesson.me.owned == 1 %} {% if lesson.me.owned == 1 %}
<a class="{{ active }}" href="{{ url }}" title="{{ lesson.title }}">{{ lesson.title }} {{ free_flag }}</a> <a class="{{ active }}" href="{{ url }}" title="{{ lesson.title }}">{{ lesson.title }}</a>
{% else %} {% else %}
<span class="deny" title="{{ lesson.title }}">{{ lesson.title }}</span> <span class="deny" title="{{ lesson.title }}">{{ lesson.title }}</span>
{% endif %} {% endif %}

View File

@ -16,7 +16,6 @@
<div class="breadcrumb"> <div class="breadcrumb">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a href="{{ course_url }}"><i class="layui-icon layui-icon-return"></i> 返回课程</a> <a href="{{ course_url }}"><i class="layui-icon layui-icon-return"></i> 返回课程</a>
<a><cite>{{ chapter.course.title }}</cite></a>
<a><cite>{{ chapter.title }}</cite></a> <a><cite>{{ chapter.title }}</cite></a>
</span> </span>
<span class="share"> <span class="share">

View File

@ -7,7 +7,6 @@
<div class="breadcrumb"> <div class="breadcrumb">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a href="{{ course_url }}"><i class="layui-icon layui-icon-return"></i> 返回课程</a> <a href="{{ course_url }}"><i class="layui-icon layui-icon-return"></i> 返回课程</a>
<a><cite>{{ chapter.course.title }}</cite></a>
<a><cite>{{ chapter.title }}</cite></a> <a><cite>{{ chapter.title }}</cite></a>
</span> </span>
</div> </div>

View File

@ -8,7 +8,6 @@
<div class="breadcrumb"> <div class="breadcrumb">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a href="{{ course_url }}"><i class="layui-icon layui-icon-return"></i> 返回课程</a> <a href="{{ course_url }}"><i class="layui-icon layui-icon-return"></i> 返回课程</a>
<a><cite>{{ chapter.course.title }}</cite></a>
<a><cite>{{ chapter.title }}</cite></a> <a><cite>{{ chapter.title }}</cite></a>
</span> </span>
</div> </div>

View File

@ -13,7 +13,6 @@
<div class="breadcrumb"> <div class="breadcrumb">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a href="{{ course_url }}"><i class="layui-icon layui-icon-return"></i> 返回课程</a> <a href="{{ course_url }}"><i class="layui-icon layui-icon-return"></i> 返回课程</a>
<a><cite>{{ chapter.course.title }}</cite></a>
<a><cite>{{ chapter.title }}</cite></a> <a><cite>{{ chapter.title }}</cite></a>
</span> </span>
<span class="share"> <span class="share">

View File

@ -14,7 +14,6 @@
<div class="breadcrumb"> <div class="breadcrumb">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a href="{{ course_url }}"><i class="layui-icon layui-icon-return"></i> 返回课程</a> <a href="{{ course_url }}"><i class="layui-icon layui-icon-return"></i> 返回课程</a>
<a><cite>{{ chapter.course.title }}</cite></a>
<a><cite>{{ chapter.title }}</cite></a> <a><cite>{{ chapter.title }}</cite></a>
</span> </span>
<span class="share"> <span class="share">

View File

@ -17,7 +17,6 @@
{%- macro live_lesson_info(lesson) %} {%- macro live_lesson_info(lesson) %}
{% set url = lesson.me.owned ? url({'for':'home.chapter.show','id':lesson.id}) : '' %} {% set url = lesson.me.owned ? url({'for':'home.chapter.show','id':lesson.id}) : '' %}
{% set priv = lesson.me.owned ? 'allow' : 'deny' %} {% set priv = lesson.me.owned ? 'allow' : 'deny' %}
{% set over_flag = lesson.attrs.end_time < time() ? '已结束' : '' %}
<a class="{{ priv }} view-lesson" href="javascript:" data-url="{{ url }}"> <a class="{{ priv }} view-lesson" href="javascript:" data-url="{{ url }}">
<i class="layui-icon layui-icon-video"></i> <i class="layui-icon layui-icon-video"></i>
<span class="title">{{ lesson.title }}</span> <span class="title">{{ lesson.title }}</span>
@ -36,7 +35,7 @@
{% set priv = lesson.me.owned ? 'allow' : 'deny' %} {% set priv = lesson.me.owned ? 'allow' : 'deny' %}
<a class="{{ priv }} view-lesson" href="javascript:" data-url="{{ url }}"> <a class="{{ priv }} view-lesson" href="javascript:" data-url="{{ url }}">
<i class="layui-icon layui-icon-read"></i> <i class="layui-icon layui-icon-read"></i>
<span class="title">{{ lesson.title|e }}</span> <span class="title">{{ lesson.title }}</span>
{% if lesson.free == 1 %} {% if lesson.free == 1 %}
<span class="layui-badge free-badge">免费</span> <span class="layui-badge free-badge">免费</span>
{% endif %} {% endif %}

View File

@ -8,7 +8,7 @@
{% set teacher.title = teacher.title ? teacher.title : '小小教书匠' %} {% set teacher.title = teacher.title ? teacher.title : '小小教书匠' %}
<div class="sidebar-teacher-card clearfix"> <div class="sidebar-teacher-card clearfix">
<div class="avatar"> <div class="avatar">
<img src="{{ teacher.avatar }}" alt="{{ teacher.name }}"> <img src="{{ teacher.avatar }}!avatar_160" alt="{{ teacher.name }}">
</div> </div>
<div class="info"> <div class="info">
<div class="name layui-elip"> <div class="name layui-elip">

View File

@ -32,12 +32,12 @@
<div class="course-card"> <div class="course-card">
<div class="cover"> <div class="cover">
<a href="{{ course_url }}"> <a href="{{ course_url }}">
<img src="{{ course.cover }}!cover_270" alt="{{ course.title|e }}" title="{{ course.title|e }}"> <img src="{{ course.cover }}!cover_270" alt="{{ course.title }}" title="{{ course.title }}">
</a> </a>
</div> </div>
<div class="info"> <div class="info">
<div class="title layui-elip"> <div class="title layui-elip">
<a href="{{ course_url }}" title="{{ course.title|e }}">{{ course.title }}</a> <a href="{{ course_url }}" title="{{ course.title }}">{{ course.title }}</a>
</div> </div>
<div class="meta"> <div class="meta">
{% if course.market_price > course.vip_price %} {% if course.market_price > course.vip_price %}
@ -69,11 +69,11 @@
{% set course_url = url({'for':'home.course.show','id':course.id}) %} {% set course_url = url({'for':'home.course.show','id':course.id}) %}
<div class="sidebar-course-card clearfix"> <div class="sidebar-course-card clearfix">
<div class="cover"> <div class="cover">
<img src="{{ course.cover }}!cover_270" alt="{{ course.title|e }}"> <img src="{{ course.cover }}!cover_270" alt="{{ course.title }}">
</div> </div>
<div class="info"> <div class="info">
<div class="title layui-elip"> <div class="title layui-elip">
<a href="{{ course_url }}" title="{{ course.title|e }}">{{ course.title }}</a> <a href="{{ course_url }}" title="{{ course.title }}">{{ course.title }}</a>
</div> </div>
<div class="meta"> <div class="meta">
{% if course.market_price > 0 %} {% if course.market_price > 0 %}
@ -91,7 +91,7 @@
{%- endmacro %} {%- endmacro %}
{%- macro learning_course_card(item) %} {%- macro learning_course_card(item) %}
{% set course_title = item.course.title|e %} {% set course_title = item.course.title %}
{% set course_url = url({'for':'home.course.show','id':item.course.id}) %} {% set course_url = url({'for':'home.course.show','id':item.course.id}) %}
<div class="course-card"> <div class="course-card">
<div class="cover"> <div class="cover">

View File

@ -1,12 +1,12 @@
{%- macro item_info(order) %} {%- macro item_info(order) %}
{% if order.item_type == '1' %} {% if order.item_type == 1 %}
{% set course = order.item_info.course %} {% set course = order.item_info.course %}
<div class="order-item"> <div class="order-item">
<p>课程名称:<span>{{ course.title }}</span></p> <p>课程名称:<span>{{ course.title }}</span></p>
<p>市场价格:<span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span>会员价格:<span class="price">{{ '¥%0.2f'|format(course.vip_price) }}</span></p> <p>市场价格:<span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span>会员价格:<span class="price">{{ '¥%0.2f'|format(course.vip_price) }}</span></p>
<p>学习期限:<span>{{ date('Y-m-d',course.study_expiry_time) }}</span>退款期限:<span>{{ date('Y-m-d',course.refund_expiry_time) }}</span></p> <p>学习期限:<span>{{ date('Y-m-d',course.study_expiry_time) }}</span>退款期限:<span>{{ date('Y-m-d',course.refund_expiry_time) }}</span></p>
</div> </div>
{% elseif order.item_type == '2' %} {% elseif order.item_type == 2 %}
{% set courses = order.item_info.courses %} {% set courses = order.item_info.courses %}
{% for course in courses %} {% for course in courses %}
<div class="order-item"> <div class="order-item">
@ -15,20 +15,20 @@
<p>学习期限:<span>{{ date('Y-m-d',course.study_expiry_time) }}</span>退款期限:<span>{{ date('Y-m-d',course.refund_expiry_time) }}</span></p> <p>学习期限:<span>{{ date('Y-m-d',course.study_expiry_time) }}</span>退款期限:<span>{{ date('Y-m-d',course.refund_expiry_time) }}</span></p>
</div> </div>
{% endfor %} {% endfor %}
{% elseif order.item_type == '3' %} {% elseif order.item_type == 3 %}
{% set course = order.item_info.course %} {% set course = order.item_info.course %}
{% set reward = order.item_info.reward %} {% set reward = order.item_info.reward %}
<div class="order-item"> <div class="order-item">
<p>课程名称:<span>{{ course.title }}</span></p> <p>课程名称:<span>{{ course.title }}</span></p>
<p>赞赏金额:<span class="price">{{ '¥%0.2f'|format(reward.price) }}</span></p> <p>赞赏金额:<span class="price">{{ '¥%0.2f'|format(reward.price) }}</span></p>
</div> </div>
{% elseif order.item_type == '4' %} {% elseif order.item_type == 4 %}
{% set vip = order.item_info.vip %} {% set vip = order.item_info.vip %}
<div class="order-item"> <div class="order-item">
<p>商品名称:<span>{{ order.subject }}</span></p> <p>商品名称:<span>{{ order.subject }}</span></p>
<p>商品价格:<span class="price">{{ '¥%0.2f'|format(order.amount) }}</span></p> <p>商品价格:<span class="price">{{ '¥%0.2f'|format(order.amount) }}</span></p>
</div> </div>
{% elseif order.item_type == '99' %} {% elseif order.item_type == 99 %}
<div class="order-item"> <div class="order-item">
<p>商品名称:<span>{{ order.subject }}</span></p> <p>商品名称:<span>{{ order.subject }}</span></p>
<p>商品价格:<span class="price">{{ '¥%0.2f'|format(order.amount) }}</span></p> <p>商品价格:<span class="price">{{ '¥%0.2f'|format(order.amount) }}</span></p>
@ -38,30 +38,30 @@
{%- macro status_history(items) %} {%- macro status_history(items) %}
{% for item in items %} {% for item in items %}
{% if item.status == '1' %} {% if item.status == 1 %}
<p>创建时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p> <p>创建时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p>
{% elseif item.status == '2' %} {% elseif item.status == 2 %}
<p>支付时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p> <p>支付时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p>
{% elseif item.status == '3' %} {% elseif item.status == 3 %}
<p>完成时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p> <p>完成时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p>
{% elseif item.status == '4' %} {% elseif item.status == 4 %}
<p>关闭时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p> <p>关闭时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p>
{% elseif item.status == '5' %} {% elseif item.status == 5 %}
<p>退款时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p> <p>退款时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{%- endmacro %} {%- endmacro %}
{%- macro order_status(value) %} {%- macro order_status(value) %}
{% if value == '1' %} {% if value == 1 %}
待支付 待支付
{% elseif value == '2' %} {% elseif value == 2 %}
发货中 发货中
{% elseif value == '3' %} {% elseif value == 3 %}
已完成 已完成
{% elseif value == '4' %} {% elseif value == 4 %}
已关闭 已关闭
{% elseif value == '5' %} {% elseif value == 5 %}
已退款 已退款
{% endif %} {% endif %}
{%- endmacro %} {%- endmacro %}

View File

@ -8,7 +8,7 @@
{% set course_url = url({'for':'home.course.show','id':course.id}) %} {% set course_url = url({'for':'home.course.show','id':course.id}) %}
<div class="cart-course-card clearfix"> <div class="cart-course-card clearfix">
<div class="cover"> <div class="cover">
<img src="{{ course.cover }}!cover_270" alt="course.title|e"> <img src="{{ course.cover }}!cover_270" alt="{{ course.title }}">
</div> </div>
<div class="info"> <div class="info">
<p><a href="{{ course_url }}" target="_blank">{{ course.title }}</a></p> <p><a href="{{ course_url }}" target="_blank">{{ course.title }}</a></p>
@ -30,7 +30,7 @@
{% set course_url = url({'for':'home.course.show','id':course.id}) %} {% set course_url = url({'for':'home.course.show','id':course.id}) %}
<div class="cart-course-card clearfix"> <div class="cart-course-card clearfix">
<div class="cover"> <div class="cover">
<img src="{{ course.cover }}!cover_270" alt="course.title|e"> <img src="{{ course.cover }}!cover_270" alt="{{ course.title }}">
</div> </div>
<div class="info"> <div class="info">
<p><a href="{{ course_url }}" target="_blank">{{ course.title }}</a></p> <p><a href="{{ course_url }}" target="_blank">{{ course.title }}</a></p>

View File

@ -3,7 +3,7 @@
{% block content %} {% block content %}
{%- macro item_info(confirm) %} {%- macro item_info(confirm) %}
{% if confirm.item_type == 'course' %} {% if confirm.item_type == 1 %}
{% set course = confirm.item_info.course %} {% set course = confirm.item_info.course %}
{% set expiry_flag = course.refund_expiry_time < time() ? '(已过期)' : '' %} {% set expiry_flag = course.refund_expiry_time < time() ? '(已过期)' : '' %}
<div class="order-item"> <div class="order-item">
@ -11,7 +11,7 @@
<p>退款期限:<span>{{ date('Y-m-d H:i:s',course.refund_expiry_time) }} {{ expiry_flag }}</span></p> <p>退款期限:<span>{{ date('Y-m-d H:i:s',course.refund_expiry_time) }} {{ expiry_flag }}</span></p>
<p>退款金额:<span class="price">{{ '¥%0.2f'|format(course.refund_amount) }}</span>退款比例:<span class="price">{{ 100 * course.refund_percent }}%</span></p> <p>退款金额:<span class="price">{{ '¥%0.2f'|format(course.refund_amount) }}</span>退款比例:<span class="price">{{ 100 * course.refund_percent }}%</span></p>
</div> </div>
{% elseif confirm.item_type == 'package' %} {% elseif confirm.item_type == 2 %}
{% set courses = confirm.item_info.courses %} {% set courses = confirm.item_info.courses %}
{% for course in courses %} {% for course in courses %}
{% set expiry_flag = course.refund_expiry_time < time() ? '(已过期)' : '' %} {% set expiry_flag = course.refund_expiry_time < time() ? '(已过期)' : '' %}
@ -45,7 +45,6 @@
<textarea class="layui-textarea" name="apply_note" lay-verify="required"></textarea> <textarea class="layui-textarea" name="apply_note" lay-verify="required"></textarea>
</div> </div>
</div> </div>
<br>
<div class="layui-form-item center"> <div class="layui-form-item center">
<button class="layui-btn" lay-submit="true" lay-filter="go">申请退款</button> <button class="layui-btn" lay-submit="true" lay-filter="go">申请退款</button>
<input type="hidden" name="order_sn" value="{{ order.sn }}"> <input type="hidden" name="order_sn" value="{{ order.sn }}">
@ -63,6 +62,7 @@
layui.use(['jquery', 'layer'], function () { layui.use(['jquery', 'layer'], function () {
var index = parent.layer.getFrameIndex(window.name); var index = parent.layer.getFrameIndex(window.name);
parent.layer.title('申请退款', index); parent.layer.title('申请退款', index);
parent.layer.iframeAuto(index);
}); });
</script> </script>

View File

@ -21,7 +21,7 @@
</table> </table>
<br> <br>
<div class="center"> <div class="center">
{% if refund.status == 'approved' %} {% if refund.status == 3 %}
<button class="kg-refund layui-btn" data-sn="{{ refund.sn }}" data-url="{{ cancel_url }}">取消退款</button> <button class="kg-refund layui-btn" data-sn="{{ refund.sn }}" data-url="{{ cancel_url }}">取消退款</button>
{% endif %} {% endif %}
</div> </div>
@ -40,15 +40,17 @@
parent.layer.iframeAuto(index); parent.layer.iframeAuto(index);
$('.kg-refund').on('click', function () { $('.kg-refund').on('click', function () {
var url = $(this).data('url');
var data = {sn: $(this).data('sn')};
layer.confirm('确定要取消退款吗?', function () { layer.confirm('确定要取消退款吗?', function () {
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: $(this).data('url'), url: url,
data: {sn: $(this).data('sn')}, data: data,
success: function (res) { success: function (res) {
layer.msg(res.msg, {icon: 1}); layer.msg(res.msg, {icon: 1});
setTimeout(function () { setTimeout(function () {
parent.window.location.href = '/my/refunds'; parent.window.location.href = '/uc/refunds';
}, 1500); }, 1500);
} }
}); });

View File

@ -25,7 +25,7 @@
<div class="user-profile wrap clearfix"> <div class="user-profile wrap clearfix">
{{ vip_info(user.vip) }} {{ vip_info(user.vip) }}
<div class="avatar"> <div class="avatar">
<img src="{{ user.avatar }}" alt="{{ user.name }}"> <img src="{{ user.avatar }}!avatar_160" alt="{{ user.name }}">
</div> </div>
<div class="info"> <div class="info">
<p><span class="name">{{ user.name }}</span><span>{{ gender_icon(user.gender) }}</span></p> <p><span class="name">{{ user.name }}</span><span>{{ gender_icon(user.gender) }}</span></p>

View File

@ -1,20 +0,0 @@
<?php
namespace App\Http\Mobile\Controllers;
use App\Traits\Response as ResponseTrait;
use App\Traits\Security as SecurityTrait;
use Phalcon\Mvc\Dispatcher;
class Controller extends \Phalcon\Mvc\Controller
{
use ResponseTrait;
use SecurityTrait;
public function beforeExecuteRoute(Dispatcher $dispatcher)
{
$this->checkRateLimit();
}
}

View File

@ -1,40 +0,0 @@
<?php
namespace App\Http\Mobile\Controllers;
/**
* @RoutePrefix("/mobile")
*/
class IndexController extends Controller
{
/**
* @Get("/", name="mobile.index")
*/
public function indexAction()
{
}
/**
* @Get("/routes", name="mobile.routes")
*/
public function routesAction()
{
$definitions = [];
$routes = $this->router->getRoutes();
foreach ($routes as $route) {
if (strpos($route->getPattern(), '/api') !== false) {
$definitions[] = [
'pattern' => $route->getPattern(),
'methods' => $route->getHttpMethods(),
];
}
}
return $this->jsonSuccess(['routes' => $definitions]);
}
}

View File

@ -1,14 +0,0 @@
<?php
namespace App\Http\Mobile\Controllers;
use App\Traits\Response as ResponseTrait;
/**
* @RoutePrefix("/mobile")
*/
class PublicController extends \Phalcon\Mvc\Controller
{
use ResponseTrait;
}

View File

@ -1,31 +0,0 @@
<?php
namespace App\Http\Mobile;
use App\Library\Mvc\View as MyView;
use App\Services\Auth\Mobile as MobileAuth;
use Phalcon\DiInterface;
use Phalcon\Mvc\ModuleDefinitionInterface;
class Module implements ModuleDefinitionInterface
{
public function registerAutoLoaders(DiInterface $di = null)
{
}
public function registerServices(DiInterface $di)
{
$di->setShared('view', function () {
$view = new MyView();
$view->disable();
return $view;
});
$di->setShared('auth', function () {
return new MobileAuth();
});
}
}

View File

@ -1,29 +0,0 @@
<?php
namespace App\Http\Mobile\Services;
use App\Validators\Account as AccountValidator;
class Login extends Service
{
public function loginByPassword($account, $password)
{
$validator = new AccountValidator();
$user = $validator->checkUserLogin($account, $password);
}
public function loginByVerify($account, $code)
{
$validator = new AccountValidator();
$user = $validator->checkVerifyLogin($account, $code);
}
protected function grantAuthToken()
{
}
}

View File

@ -1,18 +0,0 @@
<?php
namespace App\Http\Mobile\Services;
class Logout extends Service
{
public function logoutBySession()
{
}
public function logoutByToken()
{
}
}

View File

@ -1,8 +0,0 @@
<?php
namespace App\Http\Mobile\Services;
class Service extends \App\Services\Service
{
}

View File

@ -11,7 +11,7 @@ class AppInfo
protected $link = 'https://gitee.com/koogua'; protected $link = 'https://gitee.com/koogua';
protected $version = '1.1.0'; protected $version = '1.2.0';
public function __get($name) public function __get($name)
{ {

View File

@ -246,6 +246,42 @@ function kg_cos_cover_url($path, $style = null)
return kg_cos_img_url($path, $style); return kg_cos_img_url($path, $style);
} }
/**
* 获取幻灯片URL
*
* @param string $path
* @param string $style
* @return string
*/
function kg_cos_slide_url($path, $style = null)
{
return kg_cos_img_url($path, $style);
}
/**
* 清除存储图片处理样式
*
* @param $path
* @return string
*/
function kg_cos_img_style_trim($path)
{
return preg_replace('/!\w+/', '', $path);
}
/**
* 解析markdown内容
*
* @param $content
* @return string
*/
function kg_parse_markdown($content)
{
return preg_replace_callback('/\/img\/content\/(.*?)\)/', function ($matches) {
return '/img/content/' . trim($matches[1]) . '!content_800';
}, $content);
}
/** /**
* 隐藏部分字符 * 隐藏部分字符
* *

View File

@ -8,18 +8,30 @@ class Client
/** /**
* 类型 * 类型
*/ */
const TYPE_DESKTOP = 1; // desktop const TYPE_PC = 1;
const TYPE_MOBILE = 2; // mobile const TYPE_H5 = 2;
const TYPE_APP = 3; // app const TYPE_APP = 3;
const TYPE_MINI = 4; // 小程序 const TYPE_MP = 4;
const TYPE_MP_WEIXIN = 5;
const TYPE_MP_ALIPAY = 6;
const TYPE_MP_BAIDU = 7;
const TYPE_MP_TOUTIAO = 8;
const TYPE_MP_QQ = 9;
const TYPE_MP_360 = 10;
public static function types() public static function types()
{ {
return [ return [
self::TYPE_DESKTOP => 'desktop', self::TYPE_PC => 'PC',
self::TYPE_MOBILE => 'mobile', self::TYPE_H5 => 'H5',
self::TYPE_APP => 'app', self::TYPE_APP => 'APP',
self::TYPE_MINI => 'mini', self::TYPE_MP => 'MP',
self::TYPE_MP_WEIXIN => 'MP-WEIXIN',
self::TYPE_MP_ALIPAY => 'MP-ALIPAY',
self::TYPE_MP_BAIDU => 'MP-BAIDU',
self::TYPE_MP_TOUTIAO => 'MP-TOUTIAO',
self::TYPE_MP_QQ => 'MP-QQ',
self::TYPE_MP_360 => 'MP-360',
]; ];
} }

View File

@ -143,7 +143,7 @@ class Slide extends Model
public function afterFetch() public function afterFetch()
{ {
if (!Text::startsWith($this->cover, 'http')) { if (!Text::startsWith($this->cover, 'http')) {
$this->cover = kg_cos_cover_url($this->cover); $this->cover = kg_cos_slide_url($this->cover);
} }
} }

57
app/Repos/ChapterLive.php Normal file
View File

@ -0,0 +1,57 @@
<?php
namespace App\Repos;
use App\Library\Paginator\Adapter\QueryBuilder as PagerQueryBuilder;
use App\Models\Chapter as ChapterModel;
use App\Models\ChapterLive as ChapterLiveModel;
class ChapterLive extends Repository
{
public function paginate($where = [], $sort = 'latest', $page = 1, $limit = 15)
{
$builder = $this->modelsManager->createBuilder();
$builder->columns('cl.*');
$builder->addFrom(ChapterLiveModel::class, 'cl');
$builder->join(ChapterModel::class, 'cl.chapter_id = c.id', 'c');
$builder->where('1 = 1');
if (!empty($where['start_time'])) {
$builder->andWhere('cl.start_time > :time:', ['time' => $where['start_time']]);
}
if (!empty($where['end_time'])) {
$builder->andWhere('cl.start_time < :time:', ['time' => $where['end_time']]);
}
if (!empty($where['course_id'])) {
$builder->andWhere('c.course_id = :course_id:', ['course_id' => $where['course_id']]);
}
if (isset($where['published'])) {
$builder->andWhere('c.published = :published:', ['published' => $where['published']]);
}
switch ($sort) {
default:
$orderBy = 'cl.start_time ASC';
break;
}
$builder->orderBy($orderBy);
$pager = new PagerQueryBuilder([
'builder' => $builder,
'page' => $page,
'limit' => $limit,
]);
return $pager->paginate();
}
}

View File

@ -28,10 +28,18 @@ class Consult extends Repository
$builder->andWhere('course_id = :course_id:', ['course_id' => $where['course_id']]); $builder->andWhere('course_id = :course_id:', ['course_id' => $where['course_id']]);
} }
if (!empty($where['chapter_id'])) {
$builder->andWhere('chapter_id = :chapter_id:', ['chapter_id' => $where['chapter_id']]);
}
if (!empty($where['owner_id'])) { if (!empty($where['owner_id'])) {
$builder->andWhere('owner_id = :owner_id:', ['owner_id' => $where['owner_id']]); $builder->andWhere('owner_id = :owner_id:', ['owner_id' => $where['owner_id']]);
} }
if (!empty($where['replied'])) {
$builder->andWhere('reply_time > 0');
}
if (isset($where['private'])) { if (isset($where['private'])) {
$builder->andWhere('private = :private:', ['private' => $where['private']]); $builder->andWhere('private = :private:', ['private' => $where['private']]);
} }
@ -87,15 +95,15 @@ class Consult extends Repository
} }
/** /**
* @param int $chapterId * @param int $courseId
* @param int $userId * @param int $userId
* @return ConsultModel|Model|bool * @return ConsultModel|Model|bool
*/ */
public function findUserLastChapterConsult($chapterId, $userId) public function findUserLastCourseConsult($courseId, $userId)
{ {
return ConsultModel::findFirst([ return ConsultModel::findFirst([
'conditions' => 'chapter_id = ?1 AND owner_id = ?2 AND deleted = 0', 'conditions' => 'course_id = ?1 AND owner_id = ?2 AND deleted = 0',
'bind' => [1 => $chapterId, 2 => $userId], 'bind' => [1 => $courseId, 2 => $userId],
'order' => 'id DESC', 'order' => 'id DESC',
]); ]);
} }

View File

@ -41,7 +41,7 @@ class Api extends AuthService
public function getAuthInfo() public function getAuthInfo()
{ {
$authToken = $this->getAuthToken(); $authToken = $this->request->getHeader('X-Token');
if (!$authToken) return null; if (!$authToken) return null;
@ -69,11 +69,4 @@ class Api extends AuthService
]; ];
} }
protected function getAuthToken()
{
$authorization = $this->request->getHeader('Authorization');
return trim(str_ireplace('Bearer', '', $authorization));
}
} }

View File

@ -72,6 +72,7 @@ class BasicInfo extends Service
'model' => $chapter->model, 'model' => $chapter->model,
'play_urls' => $playUrls, 'play_urls' => $playUrls,
'resource_count' => $chapter->resource_count, 'resource_count' => $chapter->resource_count,
'consult_count' => $chapter->consult_count,
'user_count' => $chapter->user_count, 'user_count' => $chapter->user_count,
'like_count' => $chapter->like_count, 'like_count' => $chapter->like_count,
]; ];
@ -99,6 +100,7 @@ class BasicInfo extends Service
'end_time' => $live->end_time, 'end_time' => $live->end_time,
'status' => $live->status, 'status' => $live->status,
'resource_count' => $chapter->resource_count, 'resource_count' => $chapter->resource_count,
'consult_count' => $chapter->consult_count,
'user_count' => $chapter->user_count, 'user_count' => $chapter->user_count,
'like_count' => $chapter->like_count, 'like_count' => $chapter->like_count,
]; ];
@ -117,6 +119,7 @@ class BasicInfo extends Service
'model' => $chapter->model, 'model' => $chapter->model,
'content' => $read->content, 'content' => $read->content,
'resource_count' => $chapter->resource_count, 'resource_count' => $chapter->resource_count,
'consult_count' => $chapter->consult_count,
'user_count' => $chapter->user_count, 'user_count' => $chapter->user_count,
'like_count' => $chapter->like_count, 'like_count' => $chapter->like_count,
]; ];

View File

@ -0,0 +1,36 @@
<?php
namespace App\Services\Logic\Chapter;
use App\Library\Paginator\Query as PagerQuery;
use App\Services\Logic\ChapterTrait;
use App\Services\Logic\Consult\ConsultList as ConsultListHandler;
use App\Services\Logic\Service;
class ConsultList extends Service
{
use ChapterTrait;
public function handle($id)
{
$chapter = $this->checkChapter($id);
$pagerQuery = new PagerQuery();
$sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage();
$limit = $pagerQuery->getLimit();
$params = [
'chapter_id' => $chapter->id,
'private' => 0,
'published' => 1,
];
$service = new ConsultListHandler();
return $service->paginate($params, $sort, $page, $limit);
}
}

View File

@ -38,13 +38,13 @@ class Learning extends Service
$data['position'] = $validator->checkPosition($post['position']); $data['position'] = $validator->checkPosition($post['position']);
} }
$interval = $validator->checkInterval($post['interval']); $intervalTime = $validator->checkIntervalTime($post['interval_time']);
$learning = new LearningModel($data); $learning = new LearningModel($data);
$sync = new LearningSyncService(); $sync = new LearningSyncService();
$sync->addItem($learning, $interval); $sync->addItem($learning, $intervalTime);
} }
} }

View File

@ -20,29 +20,83 @@ class ConsultCreate extends Service
public function handle() public function handle()
{ {
$post = $this->request->getPost(); $chapterId = $this->request->getPost('chapter_id', 'int', 0);
$courseId = $this->request->getPost('course_id', 'int', 0);
$user = $this->getLoginUser(); $user = $this->getLoginUser();
$chapter = $this->checkChapter($post['chapter_id']);
$course = $this->checkCourse($chapter->course_id);
$validator = new UserLimitValidator(); $validator = new UserLimitValidator();
$validator->checkDailyConsultLimit($user); $validator->checkDailyConsultLimit($user);
$validator = new UserLimitValidator();
$validator->checkDailyConsultLimit($user);
if ($chapterId > 0) {
$chapter = $this->checkChapter($chapterId);
return $this->handleChapterConsult($chapter, $user);
} else {
$course = $this->checkCourse($courseId);
return $this->handleCourseConsult($course, $user);
}
}
protected function handleCourseConsult(CourseModel $course, UserModel $user)
{
$post = $this->request->getPost();
$validator = new ConsultValidator(); $validator = new ConsultValidator();
$question = $validator->checkQuestion($post['question']); $question = $validator->checkQuestion($post['question']);
$private = $validator->checkPrivateStatus($post['private']);
$validator->checkIfDuplicated($question, $chapter->id, $user->id); $validator->checkIfDuplicated($course->id, $user->id, $question);
$priority = $this->getPriority($course, $user); $priority = $this->getPriority($course, $user);
$consult = new ConsultModel(); $consult = new ConsultModel();
$consult->question = $question; $consult->question = $question;
$consult->private = $private;
$consult->priority = $priority;
$consult->course_id = $course->id;
$consult->owner_id = $user->id;
$consult->published = 1;
$consult->create();
$this->incrCourseConsultCount($course);
$this->incrUserDailyConsultCount($user);
return $consult;
}
protected function handleChapterConsult(ChapterModel $chapter, UserModel $user)
{
$course = $this->checkCourse($chapter->course_id);
$post = $this->request->getPost();
$validator = new ConsultValidator();
$question = $validator->checkQuestion($post['question']);
$private = $validator->checkPrivateStatus($post['private']);
$validator->checkIfDuplicated($course->id, $user->id, $question);
$priority = $this->getPriority($course, $user);
$consult = new ConsultModel();
$consult->question = $question;
$consult->private = $private;
$consult->priority = $priority; $consult->priority = $priority;
$consult->course_id = $course->id; $consult->course_id = $course->id;
$consult->chapter_id = $chapter->id; $consult->chapter_id = $chapter->id;
@ -63,6 +117,7 @@ class ConsultCreate extends Service
protected function getPriority(CourseModel $course, UserModel $user) protected function getPriority(CourseModel $course, UserModel $user)
{ {
$charge = $course->market_price > 0; $charge = $course->market_price > 0;
$vip = $user->vip == 1; $vip = $user->vip == 1;
if ($vip && $charge) { if ($vip && $charge) {

View File

@ -21,10 +21,6 @@ class ConsultDelete extends Service
{ {
$consult = $this->checkConsult($id); $consult = $this->checkConsult($id);
$course = $this->checkCourse($consult->course_id);
$chapter = $this->checkChapter($consult->chapter_id);
$user = $this->getLoginUser(); $user = $this->getLoginUser();
$validator = new ConsultValidator(); $validator = new ConsultValidator();
@ -33,9 +29,19 @@ class ConsultDelete extends Service
$consult->update(['deleted' => 1]); $consult->update(['deleted' => 1]);
$this->decrCourseConsultCount($course); if ($consult->course_id > 0) {
$this->decrChapterConsultCount($chapter); $course = $this->checkCourse($consult->course_id);
$this->decrCourseConsultCount($course);
}
if ($consult->chapter_id > 0) {
$chapter = $this->checkChapter($consult->chapter_id);
$this->decrChapterConsultCount($chapter);
}
} }
protected function decrCourseConsultCount(CourseModel $course) protected function decrCourseConsultCount(CourseModel $course)

View File

@ -32,46 +32,57 @@ class ConsultInfo extends Service
'like_count' => $consult->like_count, 'like_count' => $consult->like_count,
'create_time' => $consult->create_time, 'create_time' => $consult->create_time,
'update_time' => $consult->update_time, 'update_time' => $consult->update_time,
'course' => new \stdClass(),
'chapter' => new \stdClass(),
'owner' => new \stdClass(),
]; ];
$courseRepo = new CourseRepo(); $result['course'] = $this->handleCourseInfo($consult);
$result['chapter'] = $this->handleChapterInfo($consult);
$course = $courseRepo->findById($consult->course_id); $result['owner'] = $this->handleOwnerInfo($consult);
if ($course) {
$result['course'] = [
'id' => $course->id,
'title' => $course->title,
];
}
$chapterRepo = new ChapterRepo();
$chapter = $chapterRepo->findById($consult->chapter_id);
if ($chapter) {
$result['chapter'] = [
'id' => $chapter->id,
'title' => $chapter->title,
];
}
$userRepo = new UserRepo();
$owner = $userRepo->findById($consult->owner_id);
if ($owner) {
$result['owner'] = [
'id' => $owner->id,
'name' => $owner->name,
'avatar' => $owner->avatar,
];
}
return $result; return $result;
} }
protected function handleCourseInfo(ConsultModel $consult)
{
$courseRepo = new CourseRepo();
$course = $courseRepo->findById($consult->course_id);
if (!$course) return new \stdClass();
return [
'id' => $course->id,
'title' => $course->title,
'cover' => $course->cover,
];
}
protected function handleChapterInfo(ConsultModel $consult)
{
$chapterRepo = new ChapterRepo();
$chapter = $chapterRepo->findById($consult->chapter_id);
if (!$chapter) return new \stdClass();
return [
'id' => $chapter->id,
'title' => $chapter->title,
];
}
protected function handleOwnerInfo(ConsultModel $consult)
{
$userRepo = new UserRepo();
$owner = $userRepo->findById($consult->owner_id);
if (!$owner) return new \stdClass();
return [
'id' => $owner->id,
'name' => $owner->name,
'avatar' => $owner->avatar,
];
}
} }

View File

@ -0,0 +1,56 @@
<?php
namespace App\Services\Logic\Consult;
use App\Builders\ConsultList as ConsultListBuilder;
use App\Repos\Consult as ConsultRepo;
use App\Services\Logic\Service;
class ConsultList extends Service
{
public function paginate($params, $sort, $page, $limit)
{
$consultRepo = new ConsultRepo();
$pager = $consultRepo->paginate($params, $sort, $page, $limit);
return $this->handleConsults($pager);
}
protected function handleConsults($pager)
{
if ($pager->total_items == 0) {
return $pager;
}
$consults = $pager->items->toArray();
$builder = new ConsultListBuilder();
$users = $builder->getUsers($consults);
$items = [];
foreach ($consults as $consult) {
$owner = $users[$consult['owner_id']] ?? new \stdClass();
$items[] = [
'id' => $consult['id'],
'question' => $consult['question'],
'answer' => $consult['answer'],
'like_count' => $consult['like_count'],
'reply_time' => $consult['reply_time'],
'create_time' => $consult['create_time'],
'update_time' => $consult['update_time'],
'owner' => $owner,
];
}
$pager->items = $items;
return $pager;
}
}

View File

@ -22,6 +22,8 @@ class BasicInfo extends Service
public function handleBasicInfo(CourseModel $course) public function handleBasicInfo(CourseModel $course)
{ {
$course->details = kg_parse_markdown($course->details);
$teachers = $this->handleTeachers($course); $teachers = $this->handleTeachers($course);
$ratings = $this->handleRatings($course); $ratings = $this->handleRatings($course);
@ -43,6 +45,7 @@ class BasicInfo extends Service
'attrs' => $course->attrs, 'attrs' => $course->attrs,
'user_count' => $course->user_count, 'user_count' => $course->user_count,
'lesson_count' => $course->lesson_count, 'lesson_count' => $course->lesson_count,
'resource_count' => $course->resource_count,
'package_count' => $course->package_count, 'package_count' => $course->package_count,
'review_count' => $course->review_count, 'review_count' => $course->review_count,
'consult_count' => $course->consult_count, 'consult_count' => $course->consult_count,

View File

@ -0,0 +1,19 @@
<?php
namespace App\Services\Logic\Course;
use App\Caches\CategoryTreeList as CategoryTreeListCache;
use App\Models\Category as CategoryModel;
use App\Services\Logic\Service;
class CategoryList extends Service
{
public function handle()
{
$cache = new CategoryTreeListCache();
return $cache->get(CategoryModel::TYPE_COURSE);
}
}

View File

@ -6,6 +6,7 @@ use App\Library\Paginator\Query as PagerQuery;
use App\Repos\Course as CourseRepo; use App\Repos\Course as CourseRepo;
use App\Services\Category as CategoryService; use App\Services\Category as CategoryService;
use App\Services\Logic\Service; use App\Services\Logic\Service;
use App\Validators\CourseQuery as CourseQueryValidator;
class CourseList extends Service class CourseList extends Service
{ {
@ -16,6 +17,8 @@ class CourseList extends Service
$params = $pagerQuery->getParams(); $params = $pagerQuery->getParams();
$params = $this->checkQueryParams($params);
/** /**
* tc => top_category * tc => top_category
* sc => sub_category * sc => sub_category
@ -34,7 +37,6 @@ class CourseList extends Service
} }
$params['published'] = 1; $params['published'] = 1;
$params['deleted'] = 0;
$sort = $pagerQuery->getSort(); $sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage(); $page = $pagerQuery->getPage();
@ -84,4 +86,29 @@ class CourseList extends Service
return $pager; return $pager;
} }
protected function checkQueryParams($params)
{
$validator = new CourseQueryValidator();
$query = [];
if (isset($params['tc'])) {
$query['tc'] = $validator->checkTopCategory($params['tc']);
}
if (isset($params['sc'])) {
$query['sc'] = $validator->checkSubCategory($params['sc']);
}
if (isset($params['model'])) {
$query['model'] = $validator->checkModel($params['model']);
}
if (isset($params['level'])) {
$query['level'] = $validator->checkLevel($params['level']);
}
return $query;
}
} }

View File

@ -20,10 +20,14 @@ class HelpInfo extends Service
protected function handleHelp(HelpModel $help) protected function handleHelp(HelpModel $help)
{ {
$help->content = kg_parse_markdown($help->content);
return [ return [
'id' => $help->id, 'id' => $help->id,
'title' => $help->title, 'title' => $help->title,
'content' => $help->content, 'content' => $help->content,
'create_time' => $help->create_time,
'update_time' => $help->update_time,
]; ];
} }

View File

@ -0,0 +1,42 @@
<?php
namespace App\Services\Logic\Im;
use App\Repos\User as UserRepo;
use App\Services\Logic\ImGroupTrait;
use App\Services\Logic\Service;
class GroupInfo extends Service
{
use ImGroupTrait;
public function handle($id)
{
$group = $this->checkGroup($id);
$userRepo = new UserRepo();
$owner = $userRepo->findById($group->owner_id);
return [
'id' => $group->id,
'type' => $group->type,
'name' => $group->name,
'avatar' => $group->avatar,
'about' => $group->about,
'user_count' => $group->user_count,
'msg_count' => $group->msg_count,
'owner' => [
'id' => $owner->id,
'name' => $owner->name,
'avatar' => $owner->avatar,
'title' => $owner->title,
'about' => $owner->about,
'vip' => $owner->vip,
],
];
}
}

View File

@ -0,0 +1,70 @@
<?php
namespace App\Services\Logic\Im;
use App\Builders\ImGroupList as ImGroupListBuilder;
use App\Library\Paginator\Query as PagerQuery;
use App\Repos\ImGroup as ImGroupRepo;
use App\Services\Logic\Service;
class GroupList extends Service
{
public function handle()
{
$pagerQuery = new PagerQuery();
$params = $pagerQuery->getParams();
$params['published'] = 1;
$sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage();
$limit = $pagerQuery->getLimit();
$groupRepo = new ImGroupRepo();
$pager = $groupRepo->paginate($params, $sort, $page, $limit);
return $this->handleGroups($pager);
}
protected function handleGroups($pager)
{
if ($pager->total_items == 0) {
return $pager;
}
$builder = new ImGroupListBuilder();
$groups = $pager->items->toArray();
$users = $builder->getUsers($groups);
$baseUrl = kg_cos_url();
$items = [];
foreach ($groups as $group) {
$group['avatar'] = $baseUrl . $group['avatar'];
$group['owner'] = $users[$group['owner_id']] ?? new \stdClass();
$items[] = [
'id' => $group['id'],
'type' => $group['type'],
'name' => $group['name'],
'avatar' => $group['avatar'],
'about' => $group['about'],
'user_count' => $group['user_count'],
'msg_count' => $group['msg_count'],
'owner' => $group['owner'],
];
}
$pager->items = $items;
return $pager;
}
}

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