wesmiler 6 months ago
parent
commit
7659d81bd4

+ 0 - 83
.env

@@ -1,83 +0,0 @@
-APP_NAME=shuati
-APP_ENV=local
-LOCAL_LANG=zh-cn
-APP_KEY=base64:5c43a8wcR8LOQtT3fxxtJ/Y4Hf4y4KdLsGF5Gi6v7SY=
-APP_DEBUG=true
-API_KEY=
-APP_SIGN_KEY=stapp&688
-APP_URL=https://shuati.derkj.com/
-WEB_URL=https://shuati.derkj.com/
-LOG_CHANNEL=stack
-ORDER_REPORT_STATUS=1
-
-# 短信调试
-SMS_DEBUG=true
-SMS_CODE=1221
-
-DB_CONNECTION=mysql
-DB_PREFIX=lev_
-#DB_DATABASE=NN2025062001
-#DB_HOST=127.0.0.1
-#DB_PORT=3306
-#DB_USERNAME=root
-#DB_PASSWORD=Login*123
-
-DB_HOST=47.112.222.163
-DB_PORT=63306
-DB_USERNAME=nn2025081602
-DB_DATABASE=nn2025081602
-DB_PASSWORD=5BdDShTMeKPbcxMw
-
-
-FILESYSTEM_DRIVER=public # 文件系统
-
-BROADCAST_DRIVER=log
-QUEUE_DRIVER=redis
-QUEUE_CONNECTION=redis
-SESSION_DRIVER=file
-SESSION_LIFETIME=120
-
-REDIS_PREFIX=null
-REDIS_HOST=127.0.0.1
-REDIS_PASSWORD=derkj&6688
-REDIS_PORT=16379
-REDIS_DB=1
-
-CACHE_DRIVER=redis
-#REDIS_PREFIX=null
-#REDIS_HOST=47.112.222.163
-#REDIS_PASSWORD=derkj&6688
-#REDIS_PORT=16379
-#REDIS_DB=2
-
-#socket
-SOCKET_PORT=8660
-
-# 微信
-WEIXIN_APP_ID=
-WEIXIN_SECRET=
-WEIXIN_REDIRECT_URL
-
-MAIL_DRIVER=smtp
-MAIL_HOST=smtp.163.com
-MAIL_PORT=25
-MAIL_USERNAME=
-MAIL_FROM_ADDRESS=
-MAIL_PASSWORD=
-MAIL_ENCRYPTION=tls
-
-PUSHER_APP_ID=
-PUSHER_APP_KEY=
-PUSHER_APP_SECRET=
-PUSHER_APP_CLUSTER=mt1
-
-MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
-MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
-
-SITE_NAME = UTC
-NICK_NAME = UTC
-VERSION = v1.2.0
-
-# 预览压缩尺寸和域名
-PREVIEW_IMG_COMPRESS = '@640w_640H'
-IMG_URL = https://shuati.derkj.com/uploads

+ 19 - 0
app/Helpers/common.php

@@ -2337,6 +2337,25 @@ if (!function_exists('api_decrypt')) {
     }
 }
 
+if (!function_exists('crypt_answer')) {
+    /**
+     * 编码答案
+     * @param $id
+     * @param $answer
+     * @param string $key
+     * @return false|string
+     */
+    function crypt_answer($id, $answer, $key = '')
+    {
+        if (empty($id) || empty($answer)) {
+            return false;
+        }
+
+        $key = $key ? $key : env('APP_SIGN_KEY', '');
+        return md5($id.'-'. $answer.'-'.$key);
+    }
+}
+
 if (!function_exists('format_message')) {
     /**
      * 格式化消息内容

+ 73 - 0
app/Http/Controllers/Api/v1/CourseController.php

@@ -0,0 +1,73 @@
+<?php
+
+namespace App\Http\Controllers\Api\v1;
+
+use App\Http\Controllers\Api\webApp;
+use App\Services\Api\CourseService;
+use App\Services\Api\PaperService;
+
+/**
+ * 视频课管理
+ * @package App\Http\Controllers\Api
+ */
+class CourseController extends webApp
+{
+
+    /**
+     * 主页列表
+     * @return array
+     */
+    public function index()
+    {
+        try {
+            $params = request()->all();
+            $datas = CourseService::make()->getListByCate($params);
+            return message(1010, true, $datas);
+        } catch (\Exception $exception) {
+            return message(1009, false, $exception->getMessage());
+        }
+    }
+
+    /**
+     * 列表
+     * @return array
+     */
+    public function list()
+    {
+        try {
+            $params = request()->all();
+            $groupId = isset($params['gid']) ? $params['gid'] : 0;
+            if (empty($groupId)) {
+                return message(1036, false);
+            }
+            $pageSize = isset($params['pageSize']) ? $params['pageSize'] : 10;
+            $datas = CourseService::make()->getListByGroup($groupId, $params, $pageSize);
+            return message(1010, true, $datas);
+        } catch (\Exception $exception) {
+            return message(1009, false, $exception->getMessage());
+        }
+    }
+
+    /**
+     * 详情
+     */
+    public function info()
+    {
+        try {
+            $params = request()->all();
+            $id = isset($params['id']) ? intval($params['id']) : 0;
+            if (empty($id)) {
+                return message(1036, false);
+            }
+
+            if ($info = CourseService::make()->getInfo($this->userId, $id)) {
+                return message(1010, true, $info);
+            } else {
+                return message(1009, false);
+            }
+        } catch (\Exception $exception) {
+            return message(1009, false, $exception->getMessage());
+        }
+    }
+
+}

+ 19 - 18
app/Http/Controllers/Api/v1/ExamController.php

@@ -19,7 +19,7 @@ class ExamController extends webApp
      */
     public function index()
     {
-        $params =request()->post();
+        $params = request()->post();
         $pageSize = request()->post('pageSize', 15);
         $datas = ExamService::make()->getDataList($params, $pageSize);
         return message(1010, true, $datas);
@@ -31,10 +31,14 @@ class ExamController extends webApp
      */
     public function history()
     {
-        $params =request()->post();
-        $pageSize = request()->post('pageSize', 15);
-        $datas = ExamService::make()->getHistoryList($params, $pageSize);
-        return message(1010, true, $datas);
+        try {
+            $params = request()->post();
+            $pageSize = request()->post('pageSize', 15);
+            $datas = ExamService::make()->getHistoryList($params, $pageSize);
+            return message(1010, true, $datas);
+        } catch (\Exception $exception) {
+            return message(1009, false);
+        }
     }
 
     /**
@@ -43,34 +47,31 @@ class ExamController extends webApp
     public function info()
     {
         $params = request()->all();
-        $id = isset($params['id'])? intval($params['id']) : 0;
-        if(empty($id)){
+        $id = isset($params['id']) ? intval($params['id']) : 0;
+        if (empty($id)) {
             return message(1036, false);
         }
 
-        if($info = ArticleService::make()->getInfo($id)){
+        if ($info = ArticleService::make()->getInfo($id)) {
             return message(1010, true, $info);
-        }else{
+        } else {
             return message(1009, false);
         }
     }
 
 
     /**
-     * 单页数据
+     * 排行榜
      */
-    public function page()
+    public function ranks()
     {
         $params = request()->all();
-        $type = isset($params['type'])? intval($params['type']) : 0;
-        if(empty($type)){
+        $type = isset($params['type']) ? intval($params['type']) : 0;
+        if (empty($type)) {
             return message(1031, false);
         }
 
-        if($info = ArticleService::make()->getInfoByType($type)){
-            return message(1010, true, $info);
-        }else{
-            return message(1009, false);
-        }
+        $datas = ExamService::make()->getRankByType($type);
+        return message(1010, true, $datas);
     }
 }

+ 4 - 7
app/Http/Controllers/Api/v1/IndexController.php

@@ -3,13 +3,9 @@
 namespace App\Http\Controllers\Api\v1;
 
 use App\Http\Controllers\Api\webApp;
-use App\Services\Api\AccountService;
-use App\Services\Api\MemberService;
-use App\Services\Api\OrderService;
+use App\Services\Api\CourseService;
 use App\Services\Common\NoticeService;
-use App\Services\Common\VideoService;
 use App\Services\ConfigService;
-use App\Services\MpService;
 use App\Services\RedisService;
 
 /**
@@ -37,6 +33,7 @@ class IndexController extends webApp
                     'app_version' => ConfigService::make()->getConfigByCode('app_version'),
                     'wxpay_open' => ConfigService::make()->getConfigByCode('wxpay_open', 1),
                     'vip_buy_desc' => format_content(ConfigService::make()->getConfigByCode('vip_buy_desc', '')),
+                    'video_vip_tips' => format_content(ConfigService::make()->getConfigByCode('video_vip_tips', '')),
                     'kfUrl' => ConfigService::make()->getConfigByCode('wechat_kf_url', ''),
                 ];
                 RedisService::set($cacheKey, $config, 3600);
@@ -62,8 +59,8 @@ class IndexController extends webApp
             'notices' => NoticeService::make()->getRecommandList(),
             // 线上课程
             'courses' => [
-                VideoService::make()->getListByType(1),
-                VideoService::make()->getListByType(2),
+                CourseService::make()->getListByType(1),
+                CourseService::make()->getListByType(2),
             ],
         ];
         return showJson(1010, true, $data);

+ 18 - 30
app/Http/Controllers/Api/v1/PaperController.php

@@ -3,7 +3,7 @@
 namespace App\Http\Controllers\Api\v1;
 
 use App\Http\Controllers\Api\webApp;
-use App\Services\Api\ArticleService;
+use App\Services\Api\PaperService;
 
 /**
  * 试卷管理
@@ -20,7 +20,7 @@ class PaperController extends webApp
     {
         $params =request()->post();
         $pageSize = request()->post('pageSize', 15);
-        $datas = Exa::make()->getDataList($params, $pageSize);
+        $datas = PaperService::make()->getDataList($params, $pageSize);
         return message(1010, true, $datas);
     }
 
@@ -29,35 +29,23 @@ class PaperController extends webApp
      */
     public function info()
     {
-        $params = request()->all();
-        $id = isset($params['id'])? intval($params['id']) : 0;
-        if(empty($id)){
-            return message(1036, false);
-        }
-
-        if($info = ArticleService::make()->getInfo($id)){
-            return message(1010, true, $info);
-        }else{
-            return message(1009, false);
+        try {
+            $params = request()->all();
+            $id = isset($params['id'])? intval($params['id']) : 0;
+            $tid = isset($params['tid'])? intval($params['tid']) : 0;
+            $rid = isset($params['rid'])? intval($params['rid']) : 0;
+            if(empty($id)){
+                return message(1036, false);
+            }
+
+            if($info = PaperService::make()->getInfo($this->userId, $id, $tid, $rid)){
+                return message(1010, true, $info);
+            }else{
+                return message(1009, false);
+            }
+        }catch (\Exception $exception){
+            return message(1009, false, $exception->getMessage());
         }
     }
 
-
-    /**
-     * 单页数据
-     */
-    public function page()
-    {
-        $params = request()->all();
-        $type = isset($params['type'])? intval($params['type']) : 0;
-        if(empty($type)){
-            return message(1031, false);
-        }
-
-        if($info = ArticleService::make()->getInfoByType($type)){
-            return message(1010, true, $info);
-        }else{
-            return message(1009, false);
-        }
-    }
 }

+ 44 - 0
app/Models/ExamAccessLogModel.php

@@ -6,7 +6,51 @@
  * @package App\Models
  */
 namespace App\Models;
+use App\Services\RedisService;
+use Illuminate\Support\Facades\DB;
+
 class ExamAccessLogModel extends BaseModel
 {
     protected $table = 'exam_access_logs';
+
+    /**
+     * 模块访问日志
+     * @param $date 日期
+     * @param int $type 模块
+     * @param int $scene 场景
+     */
+    public static function saveLog($date, $type=1, $scene=1, $userId=0)
+    {
+        if($type <= 0){
+            return false;
+        }
+
+        $cacheKey = "caches:access:{$date}:{$type}_{$scene}";
+        if(RedisService::get($cacheKey."_lock:{$userId}")){
+            return false;
+        }
+
+        RedisService::set($cacheKey."_lock:{$userId}", date('Y-m-d H:i:s'), rand(2, 3));
+        $checkId = RedisService::get($cacheKey);
+        if(!$checkId){
+            $checkId = self::where(['date'=> $date,'type'=>$type,'mark'=>1])
+                ->value('id');
+        }
+
+        if($checkId){
+            self::where(['id'=> $checkId])->update(["scene_count{$scene}"=>DB::raw("scene_count{$scene} + 1"),'update_time'=>time()]);
+        }else{
+            $id = self::insertGetId([
+                'date'=> $date,
+                'type'=> $type,
+                "scene_count{$scene}"=> 1,
+                'create_time'=>time(),
+                'update_time'=>time(),
+                'status'=>1,
+            ]);
+            if($id){
+                RedisService::set($cacheKey, $id, rand(300, 600));
+            }
+        }
+    }
 }

+ 3 - 14
app/Models/DepositModel.php

@@ -12,24 +12,13 @@
 namespace App\Models;
 
 /**
- * 保证金-模型
+ * 会员答题排名-模型
  * @author laravel开发员
  * @since 2020/11/11
- * Class CityModel
  * @package App\Models
  */
-class DepositModel extends BaseModel
+class MemberAnswerRankModel extends BaseModel
 {
     // 设置数据表
-    protected $table = 'deposit_orders';
-
-    /**
-     * 用户
-     * @return \Illuminate\Database\Eloquent\Relations\HasOne
-     */
-    public function user()
-    {
-        return $this->hasOne(MemberModel::class, 'id','user_id')
-            ->select(['id','mobile','nickname','status']);
-    }
+    protected $table = 'member_answer_ranks';
 }

+ 19 - 0
app/Models/VideoCategoryModel.php

@@ -22,4 +22,23 @@ class VideoCategoryModel extends BaseModel
     // 设置数据表
     protected $table = 'videos_categorys';
 
+    public function getIconAttribute($value)
+    {
+        return $value? get_image_url($value) : '';
+    }
+
+    public function setIconAttribute($value)
+    {
+        return $value? get_image_path($value) : '';
+    }
+
+    /**
+     * 课程列表
+     * @return \Illuminate\Database\Eloquent\Relations\HasMany
+     */
+    public function courses(){
+        return $this->hasMany(VideoModel::class, 'category_id','id')
+            ->where(['status'=>1,'mark'=>1])->orderBy('sort','desc');
+    }
+
 }

+ 59 - 0
app/Models/VideoCoursesModel.php

@@ -22,4 +22,63 @@ class VideoCoursesModel extends BaseModel
     // 设置数据表
     protected $table = 'videos_courses';
 
+    public function getPosterAttribute($value)
+    {
+        return $value? get_image_url($value) : '';
+    }
+
+    public function setPosterAttribute($value)
+    {
+        return $value? get_image_path($value) : '';
+    }
+
+    public function getFeeAttribute($value)
+    {
+        return $value? floatval($value) : 0.00;
+    }
+
+    /**
+     * 课程集
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function collection()
+    {
+        return $this->hasOne(VideoModel::class, 'id', 'video_id')
+            ->with(['category'])
+            ->where(['status'=>1,'mark'=>1])
+            ->select(['id', 'video_name', 'category_id','type','poster','description', 'status']);
+    }
+
+    /**
+     * 是否有效购买单集VIP
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function vip()
+    {
+        return $this->hasOne(VideoOrderModel::class, 'goods_id', 'id')
+            ->where('expired_at','>', date('Y-m-d H:i:s'))
+            ->where(['status'=>2,'mark'=>1])
+            ->select(['id', 'order_no', 'goods_id','total','expired_at', 'status']);
+    }
+
+    /**
+     * 所有课程
+     * @return \Illuminate\Database\Eloquent\Relations\HasMany
+     */
+    public function courses()
+    {
+        return $this->hasMany(VideoCoursesModel::class, 'video_id', 'video_id')
+            ->where(['status'=>1,'mark'=>1]);
+    }
+
+    /**
+     * 学习记录
+     * @return \Illuminate\Database\Eloquent\Relations\HasMany
+     */
+    public function learns()
+    {
+        return $this->hasMany(VideoLearnLogModel::class, 'video_id', 'video_id')
+            ->where(['status'=>1,'mark'=>1]);
+    }
+
 }

+ 24 - 0
app/Models/VideoLearnLogModel.php

@@ -0,0 +1,24 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 视频课学习记录-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Models
+ */
+class VideoLearnLogModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'videos_learn_logs';
+}

+ 19 - 0
app/Models/VideoModel.php

@@ -22,4 +22,23 @@ class VideoModel extends BaseModel
     // 设置数据表
     protected $table = 'videos';
 
+    public function getPosterAttribute($value)
+    {
+        return $value? get_image_url($value) : '';
+    }
+
+    public function setPosterAttribute($value)
+    {
+        return $value? get_image_path($value) : '';
+    }
+
+    /**
+     * 课程分类
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function category()
+    {
+        return $this->hasOne(VideoCategoryModel::class, 'id', 'category_id')
+            ->select(['id', 'name', 'pid','icon']);
+    }
 }

+ 10 - 0
app/Models/VipModel.php

@@ -22,6 +22,16 @@ class VipModel extends BaseModel
     // 设置数据表
     protected $table = 'member_vips';
 
+    public function getOriginalPriceAttribute($value)
+    {
+        return $value? floatval($value) : 0;
+    }
+
+    public function getPriceAttribute($value)
+    {
+        return $value? floatval($value) : 0;
+    }
+
     /**
      * 用户
      * @return \Illuminate\Database\Eloquent\Relations\HasOne

+ 2 - 6
app/Services/Api/AccountService.php

@@ -65,15 +65,11 @@ class AccountService extends BaseService
             $accountTypes = config('payment.accountTypes');
             foreach($list['data'] as &$item){
                 $item['create_time'] = $item['create_time']? datetime($item['create_time'],'Y-m-d H:i:s') : '';
-                $item['time_text'] = $item['create_time']? datetime($item['create_time'],'Y年m月d日') : '';
+                $item['time_text'] = $item['create_time']? datetime($item['create_time'],'Y-m-d H:i') : '';
                 $type = isset($item['type'])? intval($item['type']) : 0;
                 $item['type_text'] = isset($item['remark'])? trim($item['remark']) : '';
                 if(empty($item['type_text'])){
-                    $item['type_text'] = isset($accountTypes[$type])? $accountTypes[$type] : '收支明细';
-                }
-                $item['change_type'] = 1;
-                if(in_array($type,[3,4])){
-                    $item['change_type'] = 2;
+                    $item['type_text'] = isset($accountTypes[$type])? $accountTypes[$type] : '支付订单';
                 }
             }
         }

+ 240 - 0
app/Services/Api/CourseService.php

@@ -0,0 +1,240 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Services\Api;
+
+use App\Models\ExamAccessLogModel;
+use App\Models\VideoCategoryModel;
+use App\Models\VideoCoursesModel;
+use App\Models\VideoModel;
+use App\Services\BaseService;
+use App\Services\ConfigService;
+use App\Services\RedisService;
+
+/**
+ * 视频课服务-服务类
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Services\Api
+ */
+class CourseService extends BaseService
+{
+    // 静态对象
+    protected static $instance = null;
+
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     */
+    public function __construct()
+    {
+        $this->model = new VideoCoursesModel();
+    }
+
+    /**
+     * 静态入口
+     */
+    public static function make()
+    {
+        if (!self::$instance) {
+            self::$instance = new static();
+        }
+        return self::$instance;
+    }
+
+    /**
+     * 获取
+     * @param $type
+     * @param int $num
+     * @return array|mixed
+     */
+    public function getListByType($type, $num = 0)
+    {
+        $num = $num? $num : \App\Services\ConfigService::make()->getConfigByCode('show_course_num', 4);
+        $cacheKey = "caches:videos:type_list_{$type}_{$num}";
+        $datas = RedisService::get($cacheKey);
+        if($datas){
+            return $datas;
+        }
+
+        $datas = VideoModel::where(['type'=>$type,'status'=>1,'mark'=>1])
+            ->select(['id','video_name','poster','type','description','is_recommend','status'])
+            ->orderBy('is_recommend','asc')
+            ->orderBy('create_time','desc')
+            ->limit($num)
+            ->get();
+        $datas = $datas? $datas->toArray() : [];
+        if($datas){
+            foreach ($datas as &$item){
+                $item['poster'] = $item['poster'] ? get_image_url($item['poster']) : '';
+            }
+
+            RedisService::set($cacheKey, $datas, rand(3600, 7200));
+        }
+
+        return $datas;
+    }
+
+    /**
+     * 获取分类下视频课
+     * @param int
+     * @return array|mixed
+     */
+    public function getListByCate($params)
+    {
+        $type = isset($params['type'])? $params['type'] : 0;
+        $sc = isset($params['sc'])? $params['sc'] : 0;
+        $cacheKey = "caches:videos:list_by_cate:{$type}_".md5(json_encode($params));
+        $datas = RedisService::get($cacheKey);
+
+        // 视频课访问次数统计
+        if(empty($sc)){
+            ExamAccessLogModel::saveLog(date('Y-m-d'), $type, 20);
+        }
+        if($datas){
+            return $datas;
+        }
+
+        //
+        $datas = VideoCategoryModel::with(['courses'=>function($query) use($params){
+                $kw = isset($params['keyword'])? trim($params['keyword']) : '';
+                if($kw){
+                    $query->where(function($query) use($kw){
+                        $query->where('video_name',"like","%{$kw}%")
+                            ->orwhere('description',"like","%{$kw}%");
+                    });
+                }
+
+                $type = isset($params['type'])? intval($params['type']) : 0;
+                if($type>0){
+                    $query->where('type',$type);
+                }
+            }])->distinct()
+            ->from('videos_categorys as a')
+            ->where(['a.status'=>1,'a.mark'=>1])
+            ->select(['a.id','a.name','a.sort','a.icon'])
+            ->orderBy('a.sort','desc')
+            ->get();
+        $datas = $datas? $datas->toArray() : [];
+        if($datas){
+            foreach ($datas as &$item){
+                $item['icon'] = $item['icon']? get_image_url($item['icon']) : '';
+            }
+            RedisService::set($cacheKey, $datas, rand(300,600));
+        }
+
+        return $datas;
+    }
+
+    /**
+     * 获取视频集下课程列表
+     * @param int
+     * @return array|mixed
+     */
+    public function getListByGroup($groupId,$params,$pageSize)
+    {
+        $page = isset($params['page'])? $params['page'] : 1;
+        $type = isset($params['type'])? $params['type'] : 0;
+        $cid = isset($params['cid'])? $params['cid'] : 0;
+        $sc = isset($params['sc'])? $params['sc'] : 0;
+        $cacheKey = "caches:videos:list_by_group:{$groupId}_{$page}_{$pageSize}_{$type}".md5(json_encode($params));
+        $datas = RedisService::get($cacheKey);
+        // 视频课访问次数统计
+        if(empty($sc)){
+            ExamAccessLogModel::saveLog(date('Y-m-d'), $type, 20);
+        }
+
+        if($datas){
+            return $datas;
+        }
+
+        $list = $this->model->leftJoin('videos as b','b.id','=','videos_courses.video_id')
+            ->with(['vip'])
+            ->where(['videos_courses.video_id'=> $groupId,'videos_courses.status'=>1,'videos_courses.mark'=>1,'b.status'=>1,'b.mark'=>1])
+            ->where(function($query) use($params){
+                $kw = isset($params['keyword'])? trim($params['keyword']) : '';
+                if($kw){
+                    $query->where('videos_courses.course_name',"like","%{$kw}%")
+                        ->orwhere('videos_courses.description',"like","%{$kw}%");
+                }
+            })
+            ->where(function($query) use($cid){
+                if($cid){
+                    $query->whereNotIn('videos_courses.id', [$cid]);
+                }
+            })
+            ->select(['videos_courses.id','videos_courses.video_id','videos_courses.course_name','videos_courses.course_url','videos_courses.fee','videos_courses.poster','videos_courses.description','videos_courses.sort'])
+            ->withCount(['courses','learns'])
+            ->orderBy('videos_courses.sort','desc')
+            ->orderBy('videos_courses.id','asc')
+            ->paginate($pageSize > 0 ? $pageSize : 9999999);
+        $list = $list? $list->toArray() :[];
+        if($list){
+            foreach ($list['data'] as &$item){
+
+            }
+        }
+        $rows = isset($list['data'])? $list['data'] : [];
+        $datas = [
+            'pageSize'=> $pageSize,
+            'total'=> isset($list['total'])? $list['total'] : 0,
+            'list'=> $rows
+        ];
+        if($rows){
+            RedisService::set($cacheKey, $datas, rand(300,600));
+        }
+
+        return $datas;
+    }
+
+    /**
+     * 视频课详情
+     * @param $userId 用户
+     * @param $id 课程ID
+     * @return array|mixed
+     */
+    public function getInfo($userId, $id)
+    {
+        $cacheKey = "caches:videos:info_{$userId}_{$id}";
+        $data = RedisService::get($cacheKey, $cacheKey);
+        if($data){
+            return $data;
+        }
+
+        $data = $this->model->from('videos_courses as videos_courses')
+            ->leftJoin('videos as b','b.id','=','videos_courses.video_id')
+            /*->leftJoin('videos_learn_logs as c',function($join) use($userId){
+                $join->on('c.course_id','=','videos_courses.id')
+                    ->where(['c.user_id'=>$userId,'c.status'=>1,'c.mark'=>1]);
+            })*/
+            ->with(['vip'])
+            ->withCount(['courses','learns'])
+            ->where(['videos_courses.id'=>$id,'videos_courses.status'=>1,'videos_courses.mark'=>1])
+            ->select(['videos_courses.id','videos_courses.video_id','videos_courses.course_name','videos_courses.course_url','videos_courses.fee','videos_courses.poster','videos_courses.description','videos_courses.sort','b.type'])
+            ->first();
+        $data = $data? $data->toArray() : [];
+        if($data){
+            // 验证付费视频是否有播放权限
+            $fee = isset($data['fee'])? $data['fee'] : 0;
+            $buyVipData = isset($data['vip'])? $data['vip'] : [];
+            $data['buy_vip'] = $buyVipData? 1 : 0;
+            $data['can_play'] = $buyVipData || $fee<=0? 1 : 0;
+            $data['preview_time'] = ConfigService::make()->getConfigByCode('course_play_preview_time', 3);
+
+            // 播放
+            RedisService::set($cacheKey, $data, rand(5, 10));
+        }
+
+        $this->model->where(['id'=> $id])->increment('views', 1);
+        return $data;
+    }
+}

+ 33 - 73
app/Services/Api/ExamService.php

@@ -12,9 +12,11 @@
 namespace App\Services\Api;
 
 use App\Models\ExamAnswerModel;
+use App\Models\MemberAnswerRankModel;
 use App\Services\BaseService;
 use App\Services\ConfigService;
 use App\Services\RedisService;
+use Illuminate\Support\Facades\DB;
 
 /**
  * 答题服务-服务类
@@ -157,99 +159,57 @@ class ExamService extends BaseService
             'list'=> $rows
         ];
         if($rows){
-            RedisService::set($cacheKey, $datas, rand(300, 600));
+            RedisService::set($cacheKey, $datas, rand(10, 20));
         }
 
         return $datas;
     }
 
     /**
-     * 获取文章详情
-     * @param $id
+     * 答题排行榜
+     * @param $type 1-日,2-周(7天),3-月
+     * @param int $num
      * @return array|mixed
      */
-    public function getInfo($id)
+    public function getRankByType($type, $num = 0)
     {
-        $cacheKey = "caches:articles:info_{$id}";
-        $info = RedisService::get($cacheKey);
-        if($info){
-            return $info;
-        }
-
-        $info = $this->model->where(['id'=> $id,'status'=>1,'mark'=>1])
-            ->select(['id','title','type','cover','view_num','author','description','create_time','type','content'])
-            ->first();
-        $info = $info? $info->toArray() : [];
-        if($info){
-            $info['create_time'] = $info['create_time']? datetime($info['create_time'],'Y-m-d') : '';
-            $info['cover'] = get_image_url($info['cover']);
-            $info['content'] = get_format_content($info['content']);
-            $this->model->where(['id'=> $id])->increment('view_num',1);
-            $info['view_num'] += intval($info['view_num']);
-            RedisService::set($cacheKey, $info, rand(5,10));
-        }
-
-        return $info;
-    }
-
-    /**
-     * 获取分类文章推荐
-     * @param int $cateId 推荐分类ID
-     * @param int $type 类别:3-普通文章,4-客服回复
-     * @return array|mixed
-     */
-    public function getCustomRecommend($cateId=0, $type=4)
-    {
-        $cacheKey = "caches:articles:list_{$cateId}";
+        $num = $num? $num : ConfigService::make()->getConfigByCode('rank_num', 10);
+        $cacheKey = "caches:exams:ranks:{$type}_{$num}";
         $datas = RedisService::get($cacheKey);
         if($datas){
             return $datas;
         }
 
-        $limitNum = ConfigService::make()->getConfigByCode('custom_recommend_num', 6);
-        $limitNum = $limitNum? $limitNum : 6;
-        $datas = ArticleCateModel::where(function($query) use($cateId){
-                if($cateId){
-                    $query->where('cate_id', $cateId);
+        $prefix = env('DB_PREFIX','lev_');
+        $datas = MemberAnswerRankModel::from('member_answer_ranks as a')
+            ->leftJoin('member as b','b.id','=','a.user_id')
+            ->where(['a.status'=>1,'a.mark'=>1])
+            ->where(function($query) use($type){
+                if($type==1){
+                    // 日
+                    $query->where('a.date', date('Y-m-d'));
+                }else if($type == 2){
+                    // 周
+                    $query->where('a.date','>=', date('Y-m-d', time() - 7 * 86400));
+                }else if($type == 3){
+                    // 月
+                    $query->where('a.date','>=', date('Y-m-01'));
                 }
-            })->where(['type'=>$type,'status'=>1,'mark'=>1])
-            ->select(['id','cate_id','title','description','sort','type','status'])
-            ->limit($limitNum)
-            ->orderBy('sort','desc')
-            ->orderBy('create_time','desc')
+            })
+            ->select(['a.id','a.user_id','b.avatar','b.nickname','a.answer_time','a.answer_count',DB::raw("ROUND(sum({$prefix}a.answer_time)/3600,0) as answer_hour"),DB::raw("sum({$prefix}a.answer_count) as count")])
+            ->groupBy('a.user_id')
+            ->orderByRaw("sum({$prefix}a.answer_time)/3600 desc")
+            ->take($num)
             ->get();
         $datas = $datas? $datas->toArray() : [];
         if($datas){
-            RedisService::set($cacheKey, $datas, rand(300,600));
-        }
-
-        return $datas;
-    }
-
-    /**
-     * 获取文章推荐分类
-     * @param int $type 1-普通文章分类
-     * @return array|mixed
-     */
-    public function getCateList($type=2)
-    {
-        $cacheKey = "caches:articles:cateList_{$type}";
-        $datas = RedisService::get($cacheKey);
-        if($datas){
-            return $datas;
-        }
+            foreach ($datas as &$item){
+                $item['avatar'] = $item['avatar']? get_image_url($item['avatar']) : '';
+            }
 
-        $limitNum = ConfigService::make()->getConfigByCode('custom_cate_num', 6);
-        $limitNum = $limitNum? $limitNum : 6;
-        $datas = ArticleCateModel::where(['type'=> $type,'status'=>1,'mark'=>1])
-            ->select(['cate_id','name','sort','type'])
-            ->limit($limitNum)
-            ->get();
-        $datas = $datas? $datas->toArray() : [];
-        if($datas){
-            RedisService::set($cacheKey, $datas, rand(300,600));
+            RedisService::set($cacheKey, $datas, rand(20, 30));
         }
-
         return $datas;
     }
+
 }

+ 11 - 2
app/Services/Api/MemberService.php

@@ -353,13 +353,22 @@ class MemberService extends BaseService
                 $isZsbVip = 0;
             }
 
+            $isVideoVip = isset($info['is_video_vip']) ? $info['is_video_vip'] : 0;
+            $videoVipExpired = isset($info['video_vip_expired']) && !empty($info['video_vip_expired']) ? $info['video_vip_expired'] : '';
+            if ($isVideoVip==1 && $videoVipExpired && $videoVipExpired > date('Y-m-d H:i:s')) {
+                $isVideoVip = 1;
+            } else {
+                $isVideoVip = 0;
+            }
+
             $info['is_vip'] = $isVip;
             $info['is_zg_vip'] = $isZgVip;
             $info['is_zsb_vip'] = $isZsbVip;
             $info['vip_expired'] = $vipExpired;
             $info['zg_vip_expired'] = $zgVipExpired;
             $info['zsb_vip_expired'] = $zsbVipExpired;
-            $info['video_vip_expired'] = isset($info['video_vip_expired']) && !empty($info['video_vip_expired']) ? $info['video_vip_expired'] : '';
+            $info['is_video_vip'] = $isVideoVip;
+            $info['video_vip_expired'] = $videoVipExpired;
             RedisService::set($cacheKey, $info, rand(5, 10));
         }
 
@@ -549,7 +558,7 @@ class MemberService extends BaseService
         }
 
         $datas = VipModel::where(['type' => $type, 'status' => 1, 'mark' => 1])
-            ->select(['id', 'name', 'type', 'price', 'day', 'remark', 'status'])
+            ->select(['id', 'name', 'type', 'price','original_price', 'day', 'remark', 'status'])
             ->orderBy('id', 'asc')
             ->get();
         $datas = $datas ? $datas->toArray() : [];

+ 0 - 191
app/Services/Api/MessageService.php

@@ -1,191 +0,0 @@
-<?php
-// +----------------------------------------------------------------------
-// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
-// +----------------------------------------------------------------------
-// | 版权所有 2017~2021 LARAVEL研发中心
-// +----------------------------------------------------------------------
-// | 官方网站: http://www.laravel.cn
-// +----------------------------------------------------------------------
-// | Author: laravel开发员 <laravel.qq.com>
-// +----------------------------------------------------------------------
-
-namespace App\Services\Api;
-
-use App\Models\MessageModel;
-use App\Services\BaseService;
-use App\Services\RedisService;
-
-/**
- * 消息服务-服务类
- * @author laravel开发员
- * @since 2020/11/11
- * @package App\Services\Api
- */
-class MessageService extends BaseService
-{
-    // 静态对象
-    protected static $instance = null;
-
-    /**
-     * 构造函数
-     * @author laravel开发员
-     * @since 2020/11/11
-     * NoticeService constructor.
-     */
-    public function __construct()
-    {
-        $this->model = new MessageModel();
-    }
-
-    /**
-     * 静态入口
-     */
-    public static function make()
-    {
-        if (!self::$instance) {
-            self::$instance = new static();
-        }
-        return self::$instance;
-    }
-
-    /**
-     * @param $params
-     * @param int $pageSize
-     * @return array
-     */
-    public function getDataList($params, $pageSize = 20)
-    {
-        $query = $this->getQuery($params);
-        $list = $query->select(['a.*'])
-            ->orderBy('a.create_time','desc')
-            ->paginate($pageSize > 0 ? $pageSize : 9999999);
-        $list = $list? $list->toArray() :[];
-        if($list){
-            foreach($list['data'] as &$item){
-                $item['create_time'] = $item['create_time']? datetime($item['create_time'],'Y-m-d H.i.s') : '';
-                $item['time_text'] = $item['create_time']? dateFormat($item['create_time']) : '';
-                $msgType = $item['msg_type']? $item['msg_type'] : 1;
-                if($msgType == 1 || $msgType == 3){
-                    $item['content'] = format_message($item['content']);
-                }else if($msgType==2){
-                    $item['content'] = $item['content']? get_image_url($item['content']) : '';
-                }else if($msgType == 4){
-                    $item['content'] = $item['content']? json_decode($item['content'], true) : [];
-                }
-
-                if(isset($item['from_user']) && $item['from_user']){
-                    $item['from_user_name'] = $item['from_user']['nickname']? $item['from_user']['nickname'] : '用户'.$item['from_uid'];
-                    $item['from_user_avatar'] = $item['from_user']['avatar']? get_image_url($item['from_user']['avatar']) : get_image_url('/images/member/logo.png');
-                }else if($item['from_uid'] <=1){
-                    $item['from_user_name'] = '客服';
-                    $item['from_user_avatar'] = get_image_url('/images/member/custom.png');
-                }
-
-                if(isset($item['to_user']) && $item['to_user']){
-                    $item['to_user_name'] = $item['to_user']['nickname']? $item['to_user']['nickname'] : '用户'.$item['to_uid'];
-                    $item['to_user_avatar'] = $item['to_user']['avatar']? get_image_url($item['to_user']['avatar']) : get_image_url('/images/member/logo.png');
-                }else if($item['to_uid'] <=1){
-                    $item['to_user_name'] = '客服';
-                    $item['to_user_avatar'] = get_image_url('/images/member/custom.png');
-                }
-            }
-
-            if(count($list['data'])) {
-                $this->model->where(['chat_key' => $list['data'][0]['chat_key'], 'is_read' => 2, 'mark' => 1])->where('id', '<=', $list['data'][0]['id'])->update(['is_read' => 1, 'update_time' => time()]);
-                RedisService::keyDel("caches:messages:unread_count*");
-            }
-        }
-
-        return [
-            'pageSize'=> $pageSize,
-            'total'=>isset($list['total'])? $list['total'] : 0,
-            'list'=> isset($list['data'])? array_reverse($list['data']) : []
-        ];
-    }
-
-    /**
-     * 查询
-     * @param $params
-     * @return mixed
-     */
-    public function getQuery($params)
-    {
-        $where = ['a.mark' => 1];
-        $status = isset($params['status'])? $params['status'] : 0;
-        $type = isset($params['type'])? $params['type'] : 0;
-        if($status>0){
-            $where['a.status'] = $status;
-        }
-        if($type>0){
-            $where['a.type'] = $type;
-        }
-
-        return $this->model->with(['fromUser','toUser'])->from('message as a')
-            ->where($where)
-            ->where(function ($query) use($params){
-                $keyword = isset($params['keyword'])? $params['keyword'] : '';
-                if($keyword){
-                    $query->where('a.title','like',"%{$keyword}%");
-                }
-
-
-                $fromUserId= isset($params['from_uid'])? intval($params['from_uid']) : 0;
-                if($fromUserId>0){
-                    $query->where('a.from_uid', $fromUserId);
-                }
-
-                $toUserId= isset($params['to_uid'])? intval($params['to_uid']) : 0;
-                if($fromUserId>0){
-                    $query->where('a.to_uid', $toUserId);
-                }
-
-                $isRead= isset($params['is_read'])? intval($params['is_read']) : 0;
-                if($isRead>0){
-                    $query->where('a.is_read', $isRead);
-                }
-
-            }) ->where(function ($query) use($params){
-                $userId = isset($params['user_id'])? intval($params['user_id']) : 0;
-                if($userId>0){
-                    $query->where('a.from_uid',$userId)->orWhere('a.to_uid', $userId);
-                }
-            });
-    }
-
-    /**
-     * 消息推送处理
-     * @param $userId 用户
-     * @param $msgData 消息数据
-     * @return bool
-     */
-    public function pushMessage($userId, $msgData)
-    {
-        return true;
-    }
-
-    /**
-     * 未读通知消息
-     * @param $type
-     * @return array|mixed
-     */
-    public function getUnreadCount($userId)
-    {
-        $cacheKey = "caches:messages:unread_count_{$userId}";
-        $count = RedisService::get($cacheKey);
-        if($count){
-            return $count;
-        }
-
-        $count = $this->model->where(function($query) use($userId){
-            if($userId){
-                $query->where('to_uid',$userId);
-            }
-        })->where(['is_read'=>2,'type'=>1,'status'=>1,'mark'=>1])
-        ->count('id');
-
-        if($count){
-            RedisService::set($cacheKey, $count, rand(300,600));
-        }
-        return $count;
-    }
-}

+ 268 - 0
app/Services/Api/PaperService.php

@@ -0,0 +1,268 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Services\Api;
+
+use App\Models\ExamAnswerModel;
+use App\Models\ExamPaperModel;
+use App\Models\ExamTopicModel;
+use App\Services\BaseService;
+use App\Services\ConfigService;
+use App\Services\RedisService;
+
+/**
+ * 试卷服务-服务类
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Services\Api
+ */
+class PaperService extends BaseService
+{
+    // 静态对象
+    protected static $instance = null;
+
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     */
+    public function __construct()
+    {
+        $this->model = new ExamPaperModel();
+    }
+
+    /**
+     * 静态入口
+     */
+    public static function make()
+    {
+        if (!self::$instance) {
+            self::$instance = new static();
+        }
+        return self::$instance;
+    }
+
+    /**
+     * @param $params
+     * @param int $pageSize
+     * @return array
+     */
+    public function getDataList($params, $pageSize = 15)
+    {
+        $page = isset($params['page'])? $params['page'] : 1;
+        $cacheKey = "caches:paper:list_{$page}_{$pageSize}:".md5(json_encode($params));
+        $datas = RedisService::get($cacheKey);
+        if($datas){
+            return $datas;
+        }
+
+        $query = $this->getQuery($params);
+        $list = $query->select(['a.id','a.user_id','a.paper_id','a.score','a.accurate_count','b.name','b.type','b.topic_count','b.score_total','b.is_charge','a.create_time','a.answer_times','a.status'])
+            ->orderBy('a.create_time','desc')
+            ->paginate($pageSize > 0 ? $pageSize : 9999999);
+        $list = $list? $list->toArray() :[];
+        if($list){
+            foreach($list['data'] as &$item){
+                $item['create_time'] = $item['create_time']? datetime($item['create_time'],'Y-m-d H.i.s') : '';
+            }
+        }
+
+        $rows = isset($list['data'])? $list['data'] : [];
+        $datas = [
+            'pageSize'=> $pageSize,
+            'total'=> isset($list['total'])? $list['total'] : 0,
+            'list'=> $rows
+        ];
+        if($rows){
+            RedisService::set($cacheKey, $datas, rand(300, 600));
+        }
+
+        return $datas;
+    }
+
+    /**
+     * 查询
+     * @param $params
+     * @return mixed
+     */
+    public function getQuery($params)
+    {
+        $where = ['b.status'=>1,'b.mark'=>1,'a.mark' => 1];
+        $status = isset($params['status'])? $params['status'] : 0;
+        $type = isset($params['type'])? $params['type'] : 0;
+        $sceneType = isset($params['scene_type'])? $params['scene_type'] : 0;
+        $subjectId = isset($params['subject_id'])? $params['subject_id'] : 0;
+        if($status>0){
+            $where['a.status'] = $status;
+        }
+        if($type>0){
+            $where['b.type'] = $type;
+        }
+
+        if($sceneType>0){
+            $where['b.scene_type'] = $sceneType;
+        }
+
+        if($subjectId>0){
+            $where['b.subject_id'] = $subjectId;
+        }
+
+        return $this->model->from('exam_answers as a')
+            ->leftJoin('exam_papers as b','b.id','=','a.paper_id')
+            ->where($where)
+            ->where(function ($query) use($params){
+                $keyword = isset($params['keyword'])? $params['keyword'] : '';
+                if($keyword){
+                    $query->where('b.name','like',"%{$keyword}%");
+                }
+            });
+    }
+
+    /**
+     * 最近是否答过该题
+     * @param $userId 用户ID
+     * @param $paperId 试卷ID
+     * @param int $submit 是否已交卷,1-是,0-否
+     * @return array|mixed
+     */
+    public function getLastAnswer($userId, $paperId, $submit=0)
+    {
+        $cacheKey = "caches:paper:answer_last_{$userId}:{$paperId}_{$submit}";
+        $data = RedisService::get($cacheKey);
+        if($data){
+            return $data;
+        }
+
+        $lastTime = ConfigService::make()->getConfigByCode('submit_paper_time', 30);
+        $lastTime = $lastTime>=1 && $lastTime <= 150? $lastTime : 30;
+        $data = ExamAnswerModel::where(['user_id'=>$userId,'is_submit'=> $submit,'paper_id'=> $paperId,'status'=>1,'mark'=>1])
+            ->where(function($query) use($lastTime, $submit){
+                if($submit<=0){
+                    // 未交卷
+                    $query->where('is_submit', 0)->orWhere('answer_last_at','>=', time() - $lastTime * 60);
+                }else{
+                    $query->where('is_submit', $submit)->orWhere('answer_last_at','<', time() - $lastTime * 60);
+                }
+            })
+            ->select(['id','paper_id','score','answer_last_at'])
+            ->first();
+        $data = $data? $data->toArray() : [];
+        if($data){
+            RedisService::set($cacheKey, $data, rand(5, 10));
+        }
+        return $data;
+    }
+
+    /**
+     * 获取详情
+     * @param $id
+     * @return array|mixed
+     */
+    public function getInfo($userId, $paperId, $tid=0, $rid=0)
+    {
+        $cacheKey = "caches:paper:info_{$userId}:p{$paperId}_t{$tid}_r{$rid}";
+        $info = RedisService::get($cacheKey);
+        if($info){
+            return $info;
+        }
+
+        // 若进行答题
+        if($rid<=0){
+            // 判断N分钟内是否有未交卷的答题
+            $lastAnswerInfo = $this->getLastAnswer($userId, $paperId, 0);
+            $rid = isset($lastAnswerInfo['id'])? $lastAnswerInfo['id'] : 0;
+        }
+
+        $where = ['a.id'=> $paperId,'a.status'=>1,'a.mark'=>1];
+        $info = $this->model->from('exam_papers as a')
+            ->leftJoin('exam_answers as b','b.paper_id','=','a.id')
+            ->where($where)
+            ->where(function($query) use($rid){
+                if($rid>0){
+                    $query->where(['b.id'=>$rid]);
+                }
+            })
+            ->select(['a.id as paper_id','b.id as rid','b.score','b.accurate_count','b.answer_times','a.name','a.type','a.scene_type','a.subject_id','a.score_total','a.topic_count','a.is_charge','a.create_time','a.status'])
+            ->first();
+        $info = $info? $info->toArray() : [];
+        if($info){
+            $info['create_time'] = $info['create_time']? datetime($info['create_time'],'Y-m-d') : '';
+
+            // 当前题目
+            //$prefix = env('DB_PREFIX','_lev');
+            $info['topic'] = ExamTopicModel::from('exam_topics as a')
+                ->leftJoin('exam_answers_topics as b', function($join) use($rid){
+                    // 是否有最近答题记录
+                    $join->on('b.topic_id','=',"a.id")->where("b.answer_log_id",'=', $rid);
+                })
+                ->where(['a.paper_id'=> $paperId,'a.status'=>1,'a.mark'=>1])
+                ->where(function($query) use($tid){
+                    // 答题卡选择的题目,否则默认按题目排序返回第一题
+                    if($tid>0){
+                      $query->where('a.id', $tid);
+                    }
+                })
+                ->select(['a.*','b.id as answer_topic_id','b.answer_log_id','b.answer as submit_answer','b.answer_type as submit_answer_type','b.score as submit_score','b.accurate'])
+                ->orderBy('a.sort','desc')
+                ->orderBy('a.id','asc')
+                ->first();
+            if($info['topic']) {
+                if($info['topic']['show_type'] == 1){
+                    $info['topic']['topic_name'] = format_content($info['topic']['topic_name']);
+                    if($rid<=0){
+                        $info['topic']['correct_answer'] = crypt_answer($info['topic']['id'], $info['topic']['correct_answer']);
+                        $info['topic']['topic_analysis'] = '';
+                    }
+                }else if($info['topic']['show_type'] == 2){
+                    $info['topic']['topic_name'] = get_image_url($info['topic']['topic_name']);
+
+                    // 已经答题,返回答案
+                    if($rid>0){
+                        $info['topic']['topic_analysis'] = get_image_url($info['topic']['topic_analysis']);
+                        if(preg_match("/images/", $info['topic']['correct_answer'])){
+                            $info['topic']['correct_answer'] = get_image_url($info['topic']['correct_answer']);
+                        }
+
+                        if(preg_match("/images/", $info['topic']['answer_A'])){
+                            $info['topic']['answer_A'] = get_image_url($info['topic']['answer_A']);
+                        }
+
+                        if(preg_match("/images/", $info['topic']['answer_B'])){
+                            $info['topic']['answer_B'] = get_image_url($info['topic']['answer_B']);
+                        }
+
+                        if(preg_match("/images/", $info['topic']['answer_C'])){
+                            $info['topic']['answer_C'] = get_image_url($info['topic']['answer_C']);
+                        }
+
+                        if(preg_match("/images/", $info['topic']['answer_D'])){
+                            $info['topic']['answer_D'] = get_image_url($info['topic']['answer_D']);
+                        }
+
+                        if(preg_match("/images/", $info['topic']['answer_E'])){
+                            $info['topic']['answer_E'] = get_image_url($info['topic']['answer_E']);
+                        }
+
+                        if(preg_match("/images/", $info['topic']['answer_F'])){
+                            $info['topic']['answer_F'] = get_image_url($info['topic']['answer_F']);
+                        }
+                    }
+                }
+
+            }
+
+            RedisService::set($cacheKey, $info, rand(10, 20));
+        }
+
+        return $info;
+    }
+
+}

+ 0 - 33
app/Services/Common/VideoService.php

@@ -151,37 +151,4 @@ class VideoService extends BaseService
 
         return $datas ? $datas->toArray() : [];
     }
-
-    /**
-     * 获取
-     * @param $type
-     * @param int $num
-     * @return array|mixed
-     */
-    public function getListByType($type, $num = 0)
-    {
-        $num = $num? $num : \App\Services\ConfigService::make()->getConfigByCode('show_course_num', 4);
-        $cacheKey = "caches:videos:type_list_{$type}_{$num}";
-        $datas = RedisService::get($cacheKey);
-        if($datas){
-            return $datas;
-        }
-
-        $datas = $this->model->where(['type'=>$type,'status'=>1,'mark'=>1])
-                ->select(['id','video_name','poster','type','description','is_recommend','status'])
-                ->orderBy('is_recommend','asc')
-                ->orderBy('create_time','desc')
-                ->limit($num)
-                ->get();
-        $datas = $datas? $datas->toArray() : [];
-        if($datas){
-            foreach ($datas as &$item){
-                $item['poster'] = $item['poster'] ? get_image_url($item['poster']) : '';
-            }
-
-            RedisService::set($cacheKey, $datas, rand(3600, 7200));
-        }
-
-        return $datas;
-    }
 }

+ 0 - 1
app/Services/MpService.php

@@ -313,7 +313,6 @@ class MpService extends BaseService
 
             $url = sprintf($this->apiUrls['getServiceToken'], $this->mpAppid, $this->mpAppSecret);
             $result = httpRequest($url,'', 'get','',5);
-            var_dump($result);
             $this->saveLog($cacheKey.'kfTokens:request', ['url'=>$url,'result'=>$result,'date'=>date('Y-m-d H:i:s')]);
             $token = isset($result['access_token'])? $result['access_token'] : '';
             if(empty($result) || empty($token)){

+ 10 - 2
routes/api.php

@@ -71,10 +71,18 @@ Route::prefix('v1')->middleware('web.login')->group(function() {
     // 答题
     Route::post('/exam/index', [\App\Http\Controllers\Api\v1\ExamController::class, 'index']);
     Route::post('/exam/history', [\App\Http\Controllers\Api\v1\ExamController::class, 'history']);
+    Route::post('/exam/ranks', [\App\Http\Controllers\Api\v1\ExamController::class, 'ranks']);
 
     // 试卷
-    Route::post('/paper/index', [\App\Http\Controllers\Api\v1\MessageController::class, 'index']);
-    Route::post('/paper/subject', [\App\Http\Controllers\Api\v1\MessageController::class, 'subject']);
+    Route::post('/paper/index', [\App\Http\Controllers\Api\v1\PaperController::class, 'index']);
+    Route::post('/paper/info', [\App\Http\Controllers\Api\v1\PaperController::class, 'info']);
+    Route::post('/paper/subject', [\App\Http\Controllers\Api\v1\PaperController::class, 'subject']);
+
+    // 视频课
+    Route::post('/course/index', [\App\Http\Controllers\Api\v1\CourseController::class, 'index']);
+    Route::post('/course/list', [\App\Http\Controllers\Api\v1\CourseController::class, 'list']);
+    Route::post('/course/info', [\App\Http\Controllers\Api\v1\CourseController::class, 'info']);
+
 
 });