Browse Source

【Mod】课程分支

liuxiangxin 3 tháng trước cách đây
mục cha
commit
eaa5281064
36 tập tin đã thay đổi với 2666 bổ sung13 xóa
  1. 27 0
      app/Facades/Servers/Aliyun/Oss.php
  2. 0 7
      app/Http/Controllers/Admin/Product.php
  3. 154 0
      app/Http/Controllers/Admin/VideoAnswer.php
  4. 164 0
      app/Http/Controllers/Admin/VideoCourse.php
  5. 172 0
      app/Http/Controllers/Admin/VideoCourseQuestion.php
  6. 185 0
      app/Http/Controllers/Admin/VideoPlayQuestion.php
  7. 131 0
      app/Http/Controllers/Admin/VideoQuestion.php
  8. 49 0
      app/Http/Requests/Admin/Video/Answer.php
  9. 56 0
      app/Http/Requests/Admin/Video/Course.php
  10. 55 0
      app/Http/Requests/Admin/Video/CourseQuestion.php
  11. 55 0
      app/Http/Requests/Admin/Video/PlayQuestion.php
  12. 50 0
      app/Http/Requests/Admin/Video/Question.php
  13. 125 0
      app/Models/Video/Answer.php
  14. 100 0
      app/Models/Video/Course.php
  15. 84 0
      app/Models/Video/CourseQuestion.php
  16. 84 0
      app/Models/Video/PlayQuestion.php
  17. 103 0
      app/Models/Video/Question.php
  18. 55 0
      app/Servers/Aliyun/Oss.php
  19. 1 0
      composer.json
  20. 55 4
      composer.lock
  21. 24 0
      resources/views/admin/video_answer/add.blade.php
  22. 25 0
      resources/views/admin/video_answer/edit.blade.php
  23. 84 0
      resources/views/admin/video_answer/index.blade.php
  24. 119 0
      resources/views/admin/video_course/add.blade.php
  25. 120 0
      resources/views/admin/video_course/edit.blade.php
  26. 98 0
      resources/views/admin/video_course/index.blade.php
  27. 28 0
      resources/views/admin/video_course_question/add.blade.php
  28. 29 0
      resources/views/admin/video_course_question/edit.blade.php
  29. 89 0
      resources/views/admin/video_course_question/index.blade.php
  30. 39 0
      resources/views/admin/video_play_question/add.blade.php
  31. 40 0
      resources/views/admin/video_play_question/edit.blade.php
  32. 91 0
      resources/views/admin/video_play_question/index.blade.php
  33. 20 0
      resources/views/admin/video_question/add.blade.php
  34. 21 0
      resources/views/admin/video_question/edit.blade.php
  35. 79 0
      resources/views/admin/video_question/index.blade.php
  36. 55 2
      routes/web.php

+ 27 - 0
app/Facades/Servers/Aliyun/Oss.php

@@ -0,0 +1,27 @@
+<?php namespace App\Facades\Servers\Aliyun;
+
+use Illuminate\Support\Facades\Facade;
+
+/**
+ * 对象存储
+ * 
+ * @method static string|array signUrl($bucket, $object, $options=['Content-Type'=>'multipart/form-data'] ) 获取签名路径
+ * 
+ * @see \App\Servers\Aliyun\Oss
+ * 
+ * 
+ */
+class Oss extends Facade
+{
+    /**
+     * Get the registered name of the component.
+     *
+     * @return string
+     */
+    protected static function getFacadeAccessor()
+    {
+        return '\App\Servers\Aliyun\Oss';
+    }
+}
+
+?>

+ 0 - 7
app/Http/Controllers/Admin/Product.php

@@ -77,13 +77,6 @@ class Product extends Auth{
 		$salesList				= $OrdersProduct->query()->where([['status','<>',4]])->whereIn('product_id',array_column($list->items(),'id'))->groupBy('product_id')->select([DB::raw('sum(`buy_num`) as sales_total'),'product_id'])->pluck('sales_total','product_id')->toArray();
 		// 循环处理数据
 		foreach ($list as $key => $value) {
-			// 判断总库存
-			if( !$value['stock_total'] )	{
-				// 以首次添加时的为准
-				$value['stock_total']= (int) $AdminHistory->query()->where([['table_name','=','product'],['primary_id','=',$value['id']],['notes_type','=',1],['column_name','=','stock']])->orderBy('update_time')->value('after_value');
-				// 修改库存
-				$Model->edit($value['id'],['stock_total'=>$value['stock_total']]);
-			}
 			// id转编号
 			$value['product_code']	= $Model->idToCode($value['id']);
             $value['business_name']= Business::query()->where('id',$value['business_id'])->value('name');

+ 154 - 0
app/Http/Controllers/Admin/VideoAnswer.php

@@ -0,0 +1,154 @@
+<?php namespace App\Http\Controllers\Admin;
+
+use App\Http\Requests\Admin\Video\Answer as Request;
+use App\Models\Video\Answer as Model;
+use App\Models\Video\Question as Question;
+/**
+ * 灯谜答案
+ *
+ * @author    刘相欣
+ *
+ */
+class VideoAnswer extends Auth{
+	
+	protected function _initialize(){
+		parent::_initialize();
+		$this->assign('breadcrumb1','课程习题');
+		$this->assign('breadcrumb2','习题答案');
+	}
+
+	/**
+	 * 列表页
+	 * 
+	 * */
+    public function index(Model $Model,Question $Question){
+		// 接收参数
+		$questionId				= request('question_id','');
+		// 查询条件
+		$map 					= [];
+		// 组合条件
+		if( $questionId )		$map[] = ['question_id','=',$questionId];
+		// 查询数据
+		$list					= $Model->query()->where($map)->orderByDesc('id')->paginate(config('page_num',10));
+		// 循环处理数据
+		foreach ($list as $key => $value) {
+			// 重组
+			$list[$key]			= $value;
+		}
+		// 问题列表
+		$questionList			= $Question->query()->get(['id','title'])->toArray();
+		// 分配数据
+		$this->assign('empty', '<tr><td colspan="20">~~暂无数据</td></tr>');
+		$this->assign('questionList',$questionList);
+		$this->assign('list',$list);
+		// 加载模板
+		return 					$this->fetch();
+    }
+
+
+	/**
+	 * 添加
+	 * 
+	 * */
+	public function add(Request $request,Model $Model,Question $Question){
+		if( request()->isMethod('post') ){
+			// 验证参数
+			$request->scene('add')->validate();
+			// 接收数据
+			$data['question_id']	= request('question_id',0);
+			$data['value']			= request('value','');
+			// 通过查询
+			$count					= count($Model->getListByQuestion($data['question_id']));
+			// 最多添加4个选项
+			if( $count >= 4 )		return json_send(['code'=>'error','msg'=>'最多添加4个选项']);
+			// 写入数据表
+			$id						= $Model->add($data);
+			// 如果操作失败
+			if( !$id ) 				return json_send(['code'=>'error','msg'=>'新增失败']);
+			// 记录行为
+			$this->addAdminHistory(admin('uid'),$Model->getTable(),$id,1,[],$data);
+			// 告知结果
+			return					json_send(['code'=>'success','msg'=>'新增成功','action'=>'add']);
+		}
+		// 问题列表
+		$questionList				= $Question->query()->get(['id','title'])->toArray();
+		// 分配数据
+		$this->assign('questionList',$questionList);
+		$this->assign('crumbs','新增');
+		// 加载模板
+		return						$this->fetch(); 
+	}
+
+	/**
+	 * 修改
+	 * 
+	 * */
+	public function edit(Request $request,Model $Model,Question $Question){
+		// 接收参数
+		$id							= request('id',0);
+		// 查询用户
+		$oldData					= $Model->where(['id'=>$id])->first();
+		// 修改
+		if(request()->isMethod('post')){
+			// 验证参数
+			$request->scene('edit')->validate();
+			// 接收数据
+			$data['question_id']	= request('question_id',0);
+			$data['value']			= request('value','');
+			// 获取当前问题
+			$oldQuestion			= $Model->getOne($data['question_id'],$id,'question_id');
+			// 如果当前选项值,不是当前的问题ID
+			if( $oldQuestion != $data['question_id'] ){
+				// 通过查询
+				$count					= count($Model->getListByQuestion($data['question_id']));
+				// 最多添加4个选项
+				if( $count >= 4 )		return json_send(['code'=>'error','msg'=>'最多添加4个选项']);
+			}
+			// 写入数据表
+			$result					= $Model->edit($id,$data);
+			// 如果操作失败
+			if( !$result ) 			return json_send(['code'=>'error','msg'=>'修改失败']);
+			// 记录行为
+			$this->addAdminHistory(admin('uid'),$Model->getTable(),$id,2,$oldData,$data);
+			// 告知结果
+			return					json_send(['code'=>'success','msg'=>'修改成功','action'=>'edit']);
+		}
+		// 错误告知
+		if( !$oldData )				return $this->error('查无数据');
+		// 问题列表
+		$questionList				= $Question->query()->get(['id','title'])->toArray();
+		// 分配数据
+		$this->assign('questionList',$questionList);
+		$this->assign('oldData',$oldData);
+		$this->assign('crumbs','修改');
+		// 加载模板
+		return						$this->fetch();
+	}
+
+	/**
+	 * 修改状态
+	 * 
+	 * */
+	public function set_answer(Request $request,Model $Model){
+		// 验证参数
+		$request->scene('set_answer')->validate();
+		// 设置状态
+		$id				= request('id',0);
+		$status			= request('is_answer',0);
+		// 查询用户
+		$oldData		= $Model->where(['id'=>$id])->first();
+		// 如果用户不存在
+		if( !$oldData )	return json_send(['code'=>'error','msg'=>'数据不存在']);
+		// 执行修改
+		$result			= $Model->query()->where([['question_id','=',$oldData['question_id']]])->update(['is_answer'=>0]);
+		// 执行修改
+		$result			= $Model->edit($id,['is_answer'=>$status]);
+		// 提示新增失败
+		if( !$result )	return json_send(['code'=>'error','msg'=>'设置失败']);
+		// 记录行为
+		$this->addAdminHistory(admin('uid'),$Model->getTable(),$id,2,$oldData,['status'=>$status]);
+		// 告知结果
+		return 			json_send(['code'=>'success','msg'=>'设置成功','path'=>'']);
+	}
+
+}

+ 164 - 0
app/Http/Controllers/Admin/VideoCourse.php

@@ -0,0 +1,164 @@
+<?php namespace App\Http\Controllers\Admin;
+
+use App\Facades\Servers\Aliyun\Oss;
+use App\Http\Requests\Admin\Video\Course as Request;
+use App\Models\Video\Course as Model;
+
+/**
+ * 课程管理
+ *
+ * @author    huanglei
+ *
+ */
+class VideoCourse extends Auth{
+	
+	protected function _initialize(){
+		parent::_initialize();
+		$this->assign('breadcrumb1','课程管理');
+		$this->assign('breadcrumb2','课程列表');
+	}
+
+	/**
+	 * 首页列表
+	 * 
+	 * */
+    public function index(Model $Model){
+		
+		// 接受参数
+		$name					= request('name','');
+		$status					= request('status');
+		$startTime				= request('start_time','');
+		$endTime				= request('end_time','');
+		// 查询条件
+		$map 					= [];
+		// 编码ID
+		if( $name )				$map[] = ['name','LIKE','%'.$name.'%'];
+		if( $startTime )		$map[] = ['insert_time','>=',strtotime($startTime)];
+		if( $endTime )			$map[] = ['insert_time','<=',strtotime($endTime)];
+		if( !is_null($status) )	$map[] = ['status','=',$status];
+		// 查询数据
+		$list					= $Model->query()->where($map)->orderByDesc('id')->paginate(request('limit',config('page_num',10)))->appends(request()->all());
+		// 循环处理数据
+		foreach ($list as $key => $value) {
+			// 重组
+			$list[$key]				= $value;
+		}
+		// 分配数据
+		$this->assign('empty', '<tr><td colspan="20">~~暂无数据</td></tr>');
+		$this->assign('list', $list);
+		// 加载模板
+		return					$this->fetch();
+    }
+
+	/**
+	 * 添加
+	 * 
+	 * */
+	public function add( Request $request, Model $Model){
+		if( request()->isMethod('post') ){
+			// 验证参数
+			$request->scene('add')->validate();
+			// 组合数据
+			$data['thumb']			= request('thumb','');
+			$data['video_src']		= request('video_src','');
+			$data['name']			= request('name','');
+			$data['content']		= request('content','');
+			$data['start_time']		= request('start_time','');
+			$data['end_time']		= request('end_time','');
+			$data['start_time']		= $data['start_time'] ? strtotime($data['start_time']) : 0;
+			$data['end_time']		= $data['end_time'] ? strtotime($data['end_time']) : 0;
+			$data['status']			= 1;
+			// 写入
+			$id						= $Model->add($data);
+			// 提示新增失败
+			if( !$id )				return json_send(['code'=>'error','msg'=>'新增失败']);
+			// 记录行为
+			$this->addAdminHistory(admin('uid'),$Model->getTable(),$id,1,[],$data);
+			// 告知结果
+			return					json_send(['code'=>'success','msg'=>'新增成功','action'=>'add']);
+		}
+		// 分配数据
+		$this->assign('crumbs','新增');
+		// 加载模板
+		return 						$this->fetch();
+	}
+	
+	/**
+	 * 编辑
+	 * 
+	 * */
+	public function edit( Request $request, Model $Model){
+		// 接收参数
+		$id							= request('id',0);
+		// 查询数据
+		$oldData					= $Model->where(['id'=>$id])->first();
+		$oldData					= $oldData ? $oldData->toArray() : [];
+		// 修改
+		if(request()->isMethod('post')){
+			// 验证参数
+			$request->scene('edit')->validate();
+			// 组合数据
+			$data['thumb']			= request('thumb','');
+			$data['video_src']		= request('video_src','');
+			$data['name']			= request('name','');
+			$data['content']		= request('content','');
+			$data['start_time']		= request('start_time','');
+			$data['end_time']		= request('end_time','');
+			$data['start_time']		= $data['start_time'] ? strtotime($data['start_time']) : 0;
+			$data['end_time']		= $data['end_time'] ? strtotime($data['end_time']) : 0;
+			$data['status']			= 1;
+			// 写入
+			$result					= $Model->edit($id,$data);
+			// 提示新增失败
+			if( !$result )			return json_send(['code'=>'error','msg'=>'修改失败']);
+			// 删除结果
+			unset($oldData['content']);
+			// 记录行为
+			$this->addAdminHistory(admin('uid'),$Model->getTable(),$id,2,$oldData,$data);
+			// 告知结果
+			return					json_send(['code'=>'success','msg'=>'修改成功','action'=>'edit']);
+		}
+		// 如果是没有数据
+		if( !$oldData ) 			return $this->error('查无数据');
+		// 分配数据
+		$this->assign('oldData',$oldData);
+		$this->assign('crumbs','修改');
+		// 加载模板
+		return 						$this->fetch();
+	}
+
+	/**
+	 * 状态
+	 * 
+	 * */
+	public function set_status( Request $request, Model $Model){
+		// 验证参数
+		
+		$request->scene('set_status')->validate();
+		// 接收参数
+		$id				= request('id',0);
+		$status			= request('status',0);
+		// 查询数据
+		$result			= $Model->edit($id,['status'=>$status]);
+		// 提示新增失败
+		if( !$result )	return json_send(['code'=>'error','msg'=>'设置失败']);
+		// 告知结果
+		return			json_send(['code'=>'success','msg'=>'设置成功','path'=>'']);
+	}
+	
+	/**
+	 * 获取上传视频签名URL
+	 * 
+	 * */
+	public function get_sign_url()		{
+		// 获取签名URL
+        $signUrl        				= Oss::signUrl('kailin-mp', 'uploads/video/'.admin('uid').'/'.date('Ymd').'/'.uniqid().'.mp4',['Content-Type'=>'']);
+		// 如果签名失败
+		if( !$signUrl )					return json_send(['code'=>'error','msg'=>'生成签名失败']);
+		// 签名异常
+		if( isset($signUrl['error']) )	return json_send(['code'=>'error','msg'=>$signUrl['error']]);
+		// 下发
+		return							json_send(['code'=>'success','msg'=>'获取成功','data'=>['sign_url'=>$signUrl,'video_src'=>str_ireplace('?'.parse_url($signUrl,PHP_URL_QUERY),'',$signUrl)]]);
+	}
+
+}

+ 172 - 0
app/Http/Controllers/Admin/VideoCourseQuestion.php

@@ -0,0 +1,172 @@
+<?php namespace App\Http\Controllers\Admin;
+
+use App\Http\Requests\Admin\Video\CourseQuestion as Request;
+use App\Models\Video\CourseQuestion as Model;
+use App\Models\Video\Course as VideoCourse;
+use App\Models\Video\Question as VideoQuestion;
+
+
+/**
+ * 课程习题
+ *
+ * @author    刘相欣
+ *
+ */
+class VideoCourseQuestion extends Auth{
+	
+	protected function _initialize(){
+		parent::_initialize();
+		$this->assign('breadcrumb1','课程习题');
+		$this->assign('breadcrumb2','课后习题');
+	}
+
+	/**
+	 * 列表页
+	 * 
+	 * */
+    public function index(Model $Model,VideoCourse $VideoCourse,VideoQuestion $VideoQuestion){
+		// 接收参数
+		$courseId				= request('course_id',0);
+		$questionId				= request('question_id',0);
+		// 查询条件
+		$map 					= [];
+		// 组合条件
+		if( $courseId )			$map[] = ['video_course.id','=',$courseId];
+		if( $questionId )		$map[] = ['video_question.id','=',$questionId];
+		// 查询数据
+		$list					= $Model->query()
+									->join('video_course','video_course.id','=','video_course_question.course_id')
+									->join('video_question','video_question.id','=','video_course_question.question_id')
+									->where($map)->select(['video_course_question.*','video_course.name as course_name','video_question.title as question_title'])
+									->orderBy('video_course_question.id')->paginate(config('page_num',10));
+		// 循环处理数据
+		foreach ($list as $key => $value) {
+			// 重组
+			$list[$key]			= $value;
+		}
+		// 查询数据
+		$courseList 			= $VideoCourse->query()->orderByDesc('id')->get(['id','name']);
+		$questionList 			= $VideoQuestion->query()->orderByDesc('id')->get(['id','title']);
+		// 分配数据
+		$this->assign('list',$list);
+		$this->assign('courseList',$courseList);
+		$this->assign('questionList',$questionList);
+		$this->assign('empty', '<tr><td colspan="20">~~暂无数据</td></tr>');
+		// 加载模板
+		return 					$this->fetch();
+    }
+
+
+	/**
+	 * 添加
+	 * 
+	 * */
+	public function add(Request $request,Model $Model,VideoCourse $VideoCourse,VideoQuestion $VideoQuestion){
+		if( request()->isMethod('post') ){
+			// 验证参数
+			$request->scene('add')->validate();
+			// 接收数据
+			$data['course_id']		= request('course_id',0);
+			$data['question_id']	= request('question_id',0);
+			$data['status']			= 1;
+			// 查询
+			$unique					= $Model->where(['course_id'=>$data['course_id'],'question_id'=>$data['question_id']])->first();
+			// 如果存在
+			if( $unique )			return json_send(['code'=>'error','msg'=>'习题已存在']);
+			// 查询
+			$unique					= $Model->where(['course_id'=>$data['course_id'],['play_time','=',$data['play_time']]])->first();
+			// 如果存在
+			if( $unique )			return json_send(['code'=>'error','msg'=>'该时间已设置问题']);
+			// 写入数据表
+			$id						= $Model->add($data);
+			// 如果操作失败
+			if( !$id ) 				return json_send(['code'=>'error','msg'=>'新增失败']);
+			// 记录行为
+			$this->addAdminHistory(admin('uid'),$Model->getTable(),$id,1,[],$data);
+			// 告知结果
+			return					json_send(['code'=>'success','msg'=>'新增成功','action'=>'add']);
+		}
+		// 查询数据
+		$courseList 			= $VideoCourse->query()->orderByDesc('id')->get(['id','name']);
+		$questionList 			= $VideoQuestion->query()->orderByDesc('id')->get(['id','title']);
+		// 分配数据
+		$this->assign('courseList',$courseList);
+		$this->assign('questionList',$questionList);
+		// 分配数据
+		$this->assign('crumbs','新增');
+		// 加载模板
+		return						$this->fetch(); 
+	}
+
+	/**
+	 * 修改
+	 * 
+	 * */
+	public function edit(Request $request,Model $Model,VideoCourse $VideoCourse,VideoQuestion $VideoQuestion){
+		// 接收参数
+		$id							= request('id',0);
+		// 查询用户
+		$oldData					= $Model->where(['id'=>$id])->first();
+		// 修改
+		if(request()->isMethod('post')){
+			// 验证参数
+			$request->scene('edit')->validate();
+			// 接收数据
+			$data['course_id']		= request('course_id',0);
+			$data['question_id']	= request('question_id',0);
+			// 查询
+			$unique					= $Model->where([['course_id','=',$data['course_id']],['question_id','=',$data['question_id']],['id','<>',$id]])->first();
+			// 如果存在
+			if( $unique )			return json_send(['code'=>'error','msg'=>'习题已存在']);
+			// 查询
+			$unique					= $Model->where(['course_id'=>$data['course_id'],['play_time','=',$data['play_time']],['id','<>',$id]])->first();
+			// 如果存在
+			if( $unique )			return json_send(['code'=>'error','msg'=>'该时间已设置问题']);
+			// 写入数据表
+			$result					= $Model->edit($id,$data);
+			// 如果操作失败
+			if( !$result ) 			return json_send(['code'=>'error','msg'=>'修改失败']);
+			// 记录行为
+			$this->addAdminHistory(admin('uid'),$Model->getTable(),$id,2,$oldData,$data);
+			// 告知结果
+			return					json_send(['code'=>'success','msg'=>'修改成功','action'=>'edit']);
+		}
+		// 错误告知
+		if( !$oldData )				return $this->error('查无数据');
+		// 查询数据
+		$courseList 				= $VideoCourse->query()->orderByDesc('id')->get(['id','name']);
+		$questionList 				= $VideoQuestion->query()->orderByDesc('id')->get(['id','title']);
+		// 分配数据
+		$this->assign('oldData',$oldData);
+		$this->assign('courseList',$courseList);
+		$this->assign('questionList',$questionList);
+		$this->assign('crumbs','修改');
+		// 加载模板
+		return						$this->fetch();
+	}
+
+	/**
+	 * 修改状态
+	 * 
+	 * */
+	public function set_status(Request $request,Model $Model){
+		// 验证参数
+		$request->scene('set_status')->validate();
+		// 设置状态
+		$id				= request('id',0);
+		$status			= request('status',0);
+		// 查询用户
+		$oldData		= $Model->where(['id'=>$id])->first();
+		// 如果用户不存在
+		if( !$oldData )	return json_send(['code'=>'error','msg'=>'数据不存在']);
+		// 执行修改
+		$result			= $Model->edit($id,['status'=>$status]);
+		// 提示新增失败
+		if( !$result )	return json_send(['code'=>'error','msg'=>'设置失败']);
+		// 记录行为
+		$this->addAdminHistory(admin('uid'),$Model->getTable(),$id,2,$oldData,['status'=>$status]);
+		// 告知结果
+		return 			json_send(['code'=>'success','msg'=>'设置成功','path'=>'']);
+	}
+
+}

+ 185 - 0
app/Http/Controllers/Admin/VideoPlayQuestion.php

@@ -0,0 +1,185 @@
+<?php namespace App\Http\Controllers\Admin;
+
+use App\Http\Requests\Admin\Video\PlayQuestion as Request;
+use App\Models\Video\PlayQuestion as Model;
+use App\Models\Video\Course as VideoCourse;
+use App\Models\Video\Question as VideoQuestion;
+
+
+/**
+ * 课程习题
+ *
+ * @author    刘相欣
+ *
+ */
+class VideoPlayQuestion extends Auth{
+	
+	protected function _initialize(){
+		parent::_initialize();
+		$this->assign('breadcrumb1','课程习题');
+		$this->assign('breadcrumb2','课中习题');
+	}
+
+	/**
+	 * 列表页
+	 * 
+	 * */
+    public function index(Model $Model,VideoCourse $VideoCourse,VideoQuestion $VideoQuestion){
+		// 接收参数
+		$courseId				= request('course_id',0);
+		$questionId				= request('question_id',0);
+		// 查询条件
+		$map 					= [];
+		// 组合条件
+		if( $courseId )			$map[] = ['video_course.id','=',$courseId];
+		if( $questionId )		$map[] = ['video_question.id','=',$questionId];
+		// 查询数据
+		$list					= $Model->query()
+									->join('video_course','video_course.id','=','video_play_question.course_id')
+									->join('video_question','video_question.id','=','video_play_question.question_id')
+									->where($map)->select(['video_play_question.*','video_course.name as course_name','video_question.title as question_title'])
+									->orderBy('video_play_question.play_time')->paginate(config('page_num',10));
+		// 循环处理数据
+		foreach ($list as $key => $value) {
+			// 出题时间
+			$value['play_time'] = str_pad((floor($value['play_time'] / 60)),2, '0', STR_PAD_LEFT) .':'. str_pad(($value['play_time'] % 60),2, '0', STR_PAD_LEFT);
+			// 重组
+			$list[$key]			= $value;
+		}
+		// 查询数据
+		$courseList 			= $VideoCourse->query()->orderByDesc('id')->get(['id','name']);
+		$questionList 			= $VideoQuestion->query()->orderByDesc('id')->get(['id','title']);
+		// 分配数据
+		$this->assign('list',$list);
+		$this->assign('courseList',$courseList);
+		$this->assign('questionList',$questionList);
+		$this->assign('empty', '<tr><td colspan="20">~~暂无数据</td></tr>');
+		// 加载模板
+		return 					$this->fetch();
+    }
+
+
+	/**
+	 * 添加
+	 * 
+	 * */
+	public function add(Request $request,Model $Model,VideoCourse $VideoCourse,VideoQuestion $VideoQuestion){
+		if( request()->isMethod('post') ){
+			// 验证参数
+			$request->scene('add')->validate();
+			// 接收数据
+			$data['course_id']		= request('course_id',0);
+			$data['question_id']	= request('question_id',0);
+			$minute					= request('minute',0);
+			$second					= request('second',0);
+			$data['play_time']		= ($minute * 60 ) + $second;
+			$data['status']			= 1;
+			// 查询
+			$unique					= $Model->where(['course_id'=>$data['course_id'],'question_id'=>$data['question_id']])->first();
+			// 如果存在
+			if( $unique )			return json_send(['code'=>'error','msg'=>'习题已存在']);
+			// 查询
+			$unique					= $Model->where(['course_id'=>$data['course_id'],['play_time','=',$data['play_time']]])->first();
+			// 如果存在
+			if( $unique )			return json_send(['code'=>'error','msg'=>'该时间已设置问题']);
+			// 写入数据表
+			$id						= $Model->add($data);
+			// 如果操作失败
+			if( !$id ) 				return json_send(['code'=>'error','msg'=>'新增失败']);
+			// 记录行为
+			$this->addAdminHistory(admin('uid'),$Model->getTable(),$id,1,[],$data);
+			// 告知结果
+			return					json_send(['code'=>'success','msg'=>'新增成功','action'=>'add']);
+		}
+		// 查询数据
+		$courseList 			= $VideoCourse->query()->orderByDesc('id')->get(['id','name']);
+		$questionList 			= $VideoQuestion->query()->orderByDesc('id')->get(['id','title']);
+		// 分配数据
+		$this->assign('courseList',$courseList);
+		$this->assign('questionList',$questionList);
+		// 分配数据
+		$this->assign('crumbs','新增');
+		// 加载模板
+		return						$this->fetch(); 
+	}
+
+	/**
+	 * 修改
+	 * 
+	 * */
+	public function edit(Request $request,Model $Model,VideoCourse $VideoCourse,VideoQuestion $VideoQuestion){
+		// 接收参数
+		$id							= request('id',0);
+		// 查询用户
+		$oldData					= $Model->where(['id'=>$id])->first();
+		// 修改
+		if(request()->isMethod('post')){
+			// 验证参数
+			$request->scene('edit')->validate();
+			// 接收数据
+			$data['course_id']		= request('course_id',0);
+			$data['question_id']	= request('question_id',0);
+			$minute					= request('minute',0);
+			$second					= request('second',0);
+			$data['play_time']		= ($minute * 60 ) + $second;
+			// 查询
+			$unique					= $Model->where([['course_id','=',$data['course_id']],['question_id','=',$data['question_id']],['id','<>',$id]])->first();
+			// 如果存在
+			if( $unique )			return json_send(['code'=>'error','msg'=>'习题已存在']);
+			// 查询
+			$unique					= $Model->where(['course_id'=>$data['course_id'],['play_time','=',$data['play_time']],['id','<>',$id]])->first();
+			// 如果存在
+			if( $unique )			return json_send(['code'=>'error','msg'=>'该时间已设置问题']);
+			// 写入数据表
+			$result					= $Model->edit($id,$data);
+			// 如果操作失败
+			if( !$result ) 			return json_send(['code'=>'error','msg'=>'修改失败']);
+			// 记录行为
+			$this->addAdminHistory(admin('uid'),$Model->getTable(),$id,2,$oldData,$data);
+			// 告知结果
+			return					json_send(['code'=>'success','msg'=>'修改成功','action'=>'edit']);
+		}
+		// 错误告知
+		if( !$oldData )				return $this->error('查无数据');
+		// 数据处理
+		$minute						= request('minute',0);
+		$second						= request('second',0);
+		$oldData['minute']			= str_pad(floor($oldData['play_time'] / 60),2, '0', STR_PAD_LEFT);
+		$oldData['second']			= str_pad(($oldData['play_time'] % 60),2, '0', STR_PAD_LEFT);
+		// 查询数据
+		$courseList 				= $VideoCourse->query()->orderByDesc('id')->get(['id','name']);
+		$questionList 				= $VideoQuestion->query()->orderByDesc('id')->get(['id','title']);
+		// 分配数据
+		$this->assign('oldData',$oldData);
+		$this->assign('courseList',$courseList);
+		$this->assign('questionList',$questionList);
+		$this->assign('crumbs','修改');
+		// 加载模板
+		return						$this->fetch();
+	}
+
+	/**
+	 * 修改状态
+	 * 
+	 * */
+	public function set_status(Request $request,Model $Model){
+		// 验证参数
+		$request->scene('set_status')->validate();
+		// 设置状态
+		$id				= request('id',0);
+		$status			= request('status',0);
+		// 查询用户
+		$oldData		= $Model->where(['id'=>$id])->first();
+		// 如果用户不存在
+		if( !$oldData )	return json_send(['code'=>'error','msg'=>'数据不存在']);
+		// 执行修改
+		$result			= $Model->edit($id,['status'=>$status]);
+		// 提示新增失败
+		if( !$result )	return json_send(['code'=>'error','msg'=>'设置失败']);
+		// 记录行为
+		$this->addAdminHistory(admin('uid'),$Model->getTable(),$id,2,$oldData,['status'=>$status]);
+		// 告知结果
+		return 			json_send(['code'=>'success','msg'=>'设置成功','path'=>'']);
+	}
+
+}

+ 131 - 0
app/Http/Controllers/Admin/VideoQuestion.php

@@ -0,0 +1,131 @@
+<?php namespace App\Http\Controllers\Admin;
+
+use App\Http\Requests\Admin\Video\Question as Request;
+use App\Models\Video\Question as Model;
+
+/**
+ * 课程习题
+ *
+ * @author    刘相欣
+ *
+ */
+class VideoQuestion extends Auth{
+	
+	protected function _initialize(){
+		parent::_initialize();
+		$this->assign('breadcrumb1','课程习题');
+		$this->assign('breadcrumb2','习题题目');
+	}
+
+	/**
+	 * 列表页
+	 * 
+	 * */
+    public function index(Model $Model){
+		// 接收参数
+		$name					= request('title','');
+		// 查询条件
+		$map 					= [];
+		// 组合条件
+		if( $name )				$map[] = ['title','=',$name];
+		// 查询数据
+		$list					= $Model->query()->where($map)->orderByDesc('id')->paginate(config('page_num',10));
+		// 循环处理数据
+		foreach ($list as $key => $value) {
+			// 重组
+			$list[$key]			= $value;
+		}
+		// 分配数据
+		$this->assign('empty', '<tr><td colspan="20">~~暂无数据</td></tr>');
+		$this->assign('list',$list);
+		// 加载模板
+		return 					$this->fetch();
+    }
+
+
+	/**
+	 * 添加
+	 * 
+	 * */
+	public function add(Request $request,Model $Model){
+		if( request()->isMethod('post') ){
+			// 验证参数
+			$request->scene('add')->validate();
+			// 接收数据
+			$data['title']			= request('title','');
+			$data['score']			= request('score',0);
+			$data['status']			= 1;
+			// 写入数据表
+			$id						= $Model->add($data);
+			// 如果操作失败
+			if( !$id ) 				return json_send(['code'=>'error','msg'=>'新增失败']);
+			// 记录行为
+			$this->addAdminHistory(admin('uid'),$Model->getTable(),$id,1,[],$data);
+			// 告知结果
+			return					json_send(['code'=>'success','msg'=>'新增成功','action'=>'add']);
+		}
+		// 分配数据
+		$this->assign('crumbs','新增');
+		// 加载模板
+		return						$this->fetch(); 
+	}
+
+	/**
+	 * 修改
+	 * 
+	 * */
+	public function edit(Request $request,Model $Model){
+		// 接收参数
+		$id							= request('id',0);
+		// 查询用户
+		$oldData					= $Model->where(['id'=>$id])->first();
+		// 修改
+		if(request()->isMethod('post')){
+			// 验证参数
+			$request->scene('edit')->validate();
+			// 接收数据
+			$data['title']			= request('title','');
+			$data['score']			= request('score',0);
+			// 写入数据表
+			$result					= $Model->edit($id,$data);
+			// 如果操作失败
+			if( !$result ) 			return json_send(['code'=>'error','msg'=>'修改失败']);
+			// 记录行为
+			$this->addAdminHistory(admin('uid'),$Model->getTable(),$id,2,$oldData,$data);
+			// 告知结果
+			return					json_send(['code'=>'success','msg'=>'修改成功','action'=>'edit']);
+		}
+		// 错误告知
+		if( !$oldData )				return $this->error('查无数据');
+		// 分配数据
+		$this->assign('oldData',$oldData);
+		$this->assign('crumbs','修改');
+		// 加载模板
+		return						$this->fetch();
+	}
+
+	/**
+	 * 修改状态
+	 * 
+	 * */
+	public function set_status(Request $request,Model $Model){
+		// 验证参数
+		$request->scene('set_status')->validate();
+		// 设置状态
+		$id				= request('id',0);
+		$status			= request('status',0);
+		// 查询用户
+		$oldData		= $Model->where(['id'=>$id])->first();
+		// 如果用户不存在
+		if( !$oldData )	return json_send(['code'=>'error','msg'=>'数据不存在']);
+		// 执行修改
+		$result			= $Model->edit($id,['status'=>$status]);
+		// 提示新增失败
+		if( !$result )	return json_send(['code'=>'error','msg'=>'设置失败']);
+		// 记录行为
+		$this->addAdminHistory(admin('uid'),$Model->getTable(),$id,2,$oldData,['status'=>$status]);
+		// 告知结果
+		return 			json_send(['code'=>'success','msg'=>'设置成功','path'=>'']);
+	}
+
+}

+ 49 - 0
app/Http/Requests/Admin/Video/Answer.php

@@ -0,0 +1,49 @@
+<?php namespace App\Http\Requests\Admin\Video;
+
+use App\Http\Requests\BaseRequest;
+
+/**
+ * 选项验证器
+ * 
+ */
+class Answer extends BaseRequest
+{
+    /**
+     * 获取应用于请求的规则
+     *
+     * @return array
+     */
+    public function rules()
+    {
+        // 返回结果
+        return      [
+            // 有时候我们希望某个字段在第一次验证失败后就停止运行验证规则,只需要将 bail 添加到规则中:
+            // 验证字段,验证规则,提示信息
+            'question_id' 		=> 'required|integer|gt:0',
+	        'value' 			=> 'required',
+	        'id'                => 'required|integer|gt:0',
+        ];
+    }
+
+    // 场景列表
+    protected   $scenes         = [
+		'add'  		            => ['value','question_id'],
+        'edit'  		        => ['id','value','question_id'],
+        'set_answer'  		    => ['id'],
+	];
+
+    /**
+     * 获取已定义验证规则的错误消息
+     *
+     * @return array
+     */
+    public function messages()
+    {
+        return [
+            'id.required'       => 'ID未知',
+            'id.integer'        => 'ID格式错误',
+            'id.gt'   		    => 'ID格式错误',
+        ];
+    }
+    
+}

+ 56 - 0
app/Http/Requests/Admin/Video/Course.php

@@ -0,0 +1,56 @@
+<?php namespace App\Http\Requests\Admin\Video;
+
+use App\Http\Requests\BaseRequest;
+/**
+ * 验证器
+ * 
+ */
+class Course extends BaseRequest
+{
+    /**
+     * 获取应用于请求的规则
+     *
+     * @return array
+     */
+    public function rules()
+    {
+        // 编辑时排除ID
+        // 返回结果
+        return      [
+            // 有时候我们希望某个字段在第一次验证失败后就停止运行验证规则,只需要将 bail 添加到规则中:
+            // 验证字段,验证规则,提示信息
+            'id'            => 'required|integer|gt:0',
+            'name'          => 'required|unique:video_course,name,'.request('id',0),
+            'status'        => 'required|integer|gte:0',
+            'video_src'     => 'required',
+        ];
+    }
+
+    // 场景列表
+    protected   $scenes         = [
+        'add'                   => ['name','video_src'],
+        'edit'                  => ['id','name','video_src'],
+        'set_status'            => ['id','status'],
+	];
+
+    /**
+     * 获取已定义验证规则的错误消息
+     *
+     * @return array
+     */
+    public function messages()
+    {
+        return [
+            'id.required'   		    => 'ID未知',
+            'id.integer'   		        => 'ID格式错误',
+            'id.gt'   		            => 'ID格式错误',
+            'name.required'   		    => '请输入课程名称',
+            'name.unique'   		    => '课程名称已存在',
+            'name.required'   		    => '请输入课程名称',
+            'video_src.required'   		=> '请上传视频',
+            'status.integer'   		    => '状态格式错误',
+            'status.gte'   		        => '状态格式错误',
+        ];
+    }
+
+}

+ 55 - 0
app/Http/Requests/Admin/Video/CourseQuestion.php

@@ -0,0 +1,55 @@
+<?php namespace App\Http\Requests\Admin\Video;
+
+use App\Http\Requests\BaseRequest;
+
+/**
+ * 验证器
+ * 
+ */
+class CourseQuestion extends BaseRequest
+{
+    /**
+     * 获取应用于请求的规则
+     *
+     * @return array
+     */
+    public function rules()
+    {
+        // 返回结果
+        return      [
+            // 有时候我们希望某个字段在第一次验证失败后就停止运行验证规则,只需要将 bail 添加到规则中:
+            // 验证字段,验证规则,提示信息
+	        'question_id' 		=> 'required|integer|gt:0',
+            'course_id' 		=> 'required|integer|gt:0',
+	        'id'                => 'required|integer|gt:0',
+        ];
+    }
+
+    // 场景列表
+    protected   $scenes         = [
+		'add'  		            => ['question_id','course_id'],
+        'edit'  		        => ['id','question_id','course_id'],
+        'set_status'  		    => ['id'],
+	];
+
+    /**
+     * 获取已定义验证规则的错误消息
+     *
+     * @return array
+     */
+    public function messages()
+    {
+        return [
+            'id.required'               => 'ID未知',
+            'id.integer'                => 'ID格式错误',
+            'id.gt'   		            => 'ID格式错误',
+            'question_id.required'      => '请选择问题',
+            'question_id.integer'       => '问题ID格式错误',
+            'question_id.gt'   		    => '问题ID格式错误',
+            'course_id.required'        => '请选择课程',
+            'course_id.integer'         => '课程ID格式错误',
+            'course_id.gt'   		    => '课程ID格式错误',
+        ];
+    }
+    
+}

+ 55 - 0
app/Http/Requests/Admin/Video/PlayQuestion.php

@@ -0,0 +1,55 @@
+<?php namespace App\Http\Requests\Admin\Video;
+
+use App\Http\Requests\BaseRequest;
+
+/**
+ * 验证器
+ * 
+ */
+class PlayQuestion extends BaseRequest
+{
+    /**
+     * 获取应用于请求的规则
+     *
+     * @return array
+     */
+    public function rules()
+    {
+        // 返回结果
+        return      [
+            // 有时候我们希望某个字段在第一次验证失败后就停止运行验证规则,只需要将 bail 添加到规则中:
+            // 验证字段,验证规则,提示信息
+	        'question_id' 		=> 'required|integer|gt:0',
+            'course_id' 		=> 'required|integer|gt:0',
+	        'id'                => 'required|integer|gt:0',
+        ];
+    }
+
+    // 场景列表
+    protected   $scenes         = [
+		'add'  		            => ['question_id','course_id'],
+        'edit'  		        => ['id','question_id','course_id'],
+        'set_status'  		    => ['id'],
+	];
+
+    /**
+     * 获取已定义验证规则的错误消息
+     *
+     * @return array
+     */
+    public function messages()
+    {
+        return [
+            'id.required'               => 'ID未知',
+            'id.integer'                => 'ID格式错误',
+            'id.gt'   		            => 'ID格式错误',
+            'question_id.required'      => '请选择问题',
+            'question_id.integer'       => '问题ID格式错误',
+            'question_id.gt'   		    => '问题ID格式错误',
+            'course_id.required'        => '请选择课程',
+            'course_id.integer'         => '课程ID格式错误',
+            'course_id.gt'   		    => '课程ID格式错误',
+        ];
+    }
+    
+}

+ 50 - 0
app/Http/Requests/Admin/Video/Question.php

@@ -0,0 +1,50 @@
+<?php namespace App\Http\Requests\Admin\Video;
+
+use App\Http\Requests\BaseRequest;
+
+/**
+ * 验证器
+ * 
+ */
+class Question extends BaseRequest
+{
+    /**
+     * 获取应用于请求的规则
+     *
+     * @return array
+     */
+    public function rules()
+    {
+        // 返回结果
+        return      [
+            // 有时候我们希望某个字段在第一次验证失败后就停止运行验证规则,只需要将 bail 添加到规则中:
+            // 验证字段,验证规则,提示信息
+	        'title' 			=> 'required|unique:video_question,title,'.request('id',0),
+	        'id'                => 'required|integer|gt:0',
+        ];
+    }
+
+    // 场景列表
+    protected   $scenes         = [
+		'add'  		            => ['title'],
+        'edit'  		        => ['id','title'],
+        'set_status'  		    => ['id'],
+	];
+
+    /**
+     * 获取已定义验证规则的错误消息
+     *
+     * @return array
+     */
+    public function messages()
+    {
+        return [
+            'title.required'    => '题目必填',
+            'title.required'    => '题目已存在',
+            'id.required'       => 'ID未知',
+            'id.integer'        => 'ID格式错误',
+            'id.gt'   		    => 'ID格式错误',
+        ];
+    }
+    
+}

+ 125 - 0
app/Models/Video/Answer.php

@@ -0,0 +1,125 @@
+<?php namespace App\Models\Video;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 灯谜活动模型
+ * 
+ */
+class Answer extends Model
+{
+    use HasFactory;
+
+    // 与模型关联的表名
+    protected $table = 'video_answer';
+    // 是否主动维护时间戳
+    public $timestamps = false;
+    // 定义时间戳字段名
+    // const CREATED_AT = 'insert_time';
+    // const UPDATED_AT = 'update_time';
+
+    /**
+     * 添加数据
+     * 
+     */
+    public function add($data)
+    {
+        // 时间
+        $data['insert_time']				= time();
+        $data['update_time']				= time();
+        // 写入数据表
+        $id						            = $this->query()->insertGetId($data);
+        // 如果操作失败
+        if( !$id )                          return $id;
+        // 更新缓存
+        $this->getList(true);
+        // 返回结果
+        return                              $id;
+    }
+
+    /**
+     * 添加数据
+     * 
+     */
+    public function edit($id,$data)
+    {
+        // 更新时间
+        $data['update_time']                = time();
+        // 写入数据表
+        $result						        = $this->query()->where(['id'=>$id])->update($data);
+        // 如果操作失败
+        if( !$result )                      return $result;
+        // 更新缓存
+        $this->getList(true);
+        // 返回结果
+        return                              $result;
+    }
+
+    /**
+     * 获取列表
+     * @param   bool    $force  是否强制更新
+     * 
+     */
+    public function getList($force = false)
+    {
+        // 结果数据
+        $list                  = $force ? [] : cache('admin:video:answer:list');
+        // 不存在数据
+        if ( !$list ) {
+            // 从数据库获取数据
+            $data              = $this->query()->get(['id','question_id','value','is_answer'])->toArray();
+            // 循环处理数据
+            $list              = [];
+            // 进行更新
+            foreach ($data as $value) {
+                // 重组数据
+                $list[$value['question_id']][$value['id']] = $value;
+            }
+            // 存起来
+            cache(['admin:video:answer:list'=>$list]);
+        }
+        // 返回结果
+        return                  $list;
+    }
+
+
+    /**
+     * 获取配置平台对应的应用数据
+     * 
+     * @param   int     $questionId   问题ID
+     * @param   int     $id           ID
+     * @param   string  $field       字段名
+     * 
+     */
+    public function getListByQuestion($questionId)
+    {
+        // 获取列表数据
+        $list                   = $this->getList();
+        // 获取问题的列表
+        $list                   = isset($list[$questionId]) ? $list[$questionId] : [];
+        // 返回值
+        return                  $list;
+    }
+
+    /**
+     * 获取配置平台对应的应用数据
+     * 
+     * @param   int     $questionId   问题ID
+     * @param   int     $id           ID
+     * @param   string  $field       字段名
+     * 
+     */
+    public function getOne($questionId,$id,$field='')
+    {
+        // 获取列表数据
+        $list                   = $this->getList();
+        // 获取问题的列表
+        $list                   = isset($list[$questionId]) ? $list[$questionId] : [];
+        // 获取数据
+        $one                    = isset($list[$id]) ? $list[$id] : [];
+        // 返回值
+        return                  empty($field) ? $one : ( isset($one[$field]) ? $one[$field] : null);
+    }
+
+}

+ 100 - 0
app/Models/Video/Course.php

@@ -0,0 +1,100 @@
+<?php namespace App\Models\Video;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 模型
+ * 
+ */
+class Course extends Model
+{
+    use HasFactory;
+
+    // 与模型关联的表名
+    protected $table = 'video_course';
+    // 是否主动维护时间戳
+    public $timestamps = false;
+    // 定义时间戳字段名
+    // const CREATED_AT = 'insert_time';
+    // const UPDATED_AT = 'update_time';
+
+    /**
+     * 添加数据
+     * 
+     */
+    public function add($data)
+    {
+        // 时间
+        $data['insert_time']				= time();
+        $data['update_time']				= time();
+        // 写入数据表
+        $id						            = $this->query()->insertGetId($data);
+        // 更新缓存
+        $this->getList(true);
+        // 返回结果
+        return                              $id;
+    }
+
+    /**
+     * 添加数据
+     * 
+     */
+    public function edit($id,$data)
+    {
+        // 更新时间
+        $data['update_time']                = time();
+        // 写入数据表
+        $result						        = $this->query()->where(['id'=>$id])->update($data);
+        // 更新缓存
+        $this->getList(true);
+        // 返回结果
+        return                              $result;
+    }
+
+    /**
+     * 获取列表
+     * @param   Bool    $force  是否强制更新
+     * 
+     */
+    public function getList($force = false)
+    {
+        // 结果数据
+        $list                  = $force ? [] : cache('admin:video:course:list');
+        // 不存在数据
+        if ( !$list ) {
+            // 从数据库获取数据
+            $data              = $this->query()->where([['status','=',0]])->get(['id','name','thumb','video_src','start_time','end_time'])->toArray();
+            // 循环处理数据
+            $list              = [];
+            // 进行更新
+            foreach ($data as $value) {
+                // 重组数据
+                $list[$value['id']] = $value;
+            }
+            // 存起来
+            cache(['admin:video:course:list'=>$list]);
+        }
+        // 返回结果
+        return                  $list;
+    }
+
+    /**
+     * 获取配置平台对应的应用数据
+     * 
+     * @param   Array      用户ID
+     * @param   String     指定字段
+     * 
+     */
+    public function getOne($id,$field='')
+    {
+        // 获取列表数据
+        $list                   = $this->getList();
+        dd($list);
+        // 获取数据
+        $one                    = isset($list[$id]) ? $list[$id] : [];
+        // 返回值
+        return                  empty($field) ? $one : ( isset($one[$field]) ? $one[$field] : null);
+    }
+
+}

+ 84 - 0
app/Models/Video/CourseQuestion.php

@@ -0,0 +1,84 @@
+<?php namespace App\Models\Video;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 模型
+ * 
+ */
+class CourseQuestion extends Model
+{
+    use HasFactory;
+
+    // 与模型关联的表名
+    protected $table = 'video_course_question';
+    // 是否主动维护时间戳
+    public $timestamps = false;
+    // 定义时间戳字段名
+    // const CREATED_AT = 'insert_time';
+    // const UPDATED_AT = 'update_time';
+
+    /**
+     * 添加数据
+     * 
+     */
+    public function add($data)
+    {
+        // 时间
+        $data['insert_time']				= time();
+        $data['update_time']				= time();
+        // 写入数据表
+        $id						            = $this->query()->insertGetId($data);
+        // 如果操作失败
+        if( !$id )                          return $id;
+        // 更新缓存
+        if( isset($data['course_id']) )     $this->getList($data['course_id'],true);
+        // 返回结果
+        return                              $id;
+    }
+
+    /**
+     * 添加数据
+     * 
+     */
+    public function edit($id,$data)
+    {
+        // 更新时间
+        $data['update_time']                = time();
+        // 写入数据表
+        $result						        = $this->query()->where(['id'=>$id])->update($data);
+        // 如果操作失败
+        if( !$result )                      return $result;
+        // 返回结果
+        return                              $result;
+    }
+
+    /**
+     * 获取列表
+     * @param   Bool    $force  是否强制更新
+     * 
+     */
+    public function getList($courseId,$force = false)
+    {
+        // 结果数据
+        $list                  = $force ? [] : cache('admin:video:play:question:list:'.$courseId);
+        // 不存在数据
+        if ( !$list )          {
+            // 从数据库获取数据
+            $data              = $this->query()->where([['status','=',0]])->get(['id','course_id','question_id'])->toArray();
+            // 循环处理数据
+            $list              = [];
+            // 进行更新
+            foreach ($data as $value) {
+                // 重组数据
+                $list[$value['course_id']][$value['question_id']] = $value;
+            }
+            // 存起来
+            cache(['admin:video:play:question:list:'.$courseId=>$list]);
+        }
+        // 返回结果
+        return                  $list;
+    }
+
+}

+ 84 - 0
app/Models/Video/PlayQuestion.php

@@ -0,0 +1,84 @@
+<?php namespace App\Models\Video;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 模型
+ * 
+ */
+class PlayQuestion extends Model
+{
+    use HasFactory;
+
+    // 与模型关联的表名
+    protected $table = 'video_play_question';
+    // 是否主动维护时间戳
+    public $timestamps = false;
+    // 定义时间戳字段名
+    // const CREATED_AT = 'insert_time';
+    // const UPDATED_AT = 'update_time';
+
+    /**
+     * 添加数据
+     * 
+     */
+    public function add($data)
+    {
+        // 时间
+        $data['insert_time']				= time();
+        $data['update_time']				= time();
+        // 写入数据表
+        $id						            = $this->query()->insertGetId($data);
+        // 如果操作失败
+        if( !$id )                          return $id;
+        // 更新缓存
+        if( isset($data['course_id']) )     $this->getList($data['course_id'],true);
+        // 返回结果
+        return                              $id;
+    }
+
+    /**
+     * 添加数据
+     * 
+     */
+    public function edit($id,$data)
+    {
+        // 更新时间
+        $data['update_time']                = time();
+        // 写入数据表
+        $result						        = $this->query()->where(['id'=>$id])->update($data);
+        // 如果操作失败
+        if( !$result )                      return $result;
+        // 返回结果
+        return                              $result;
+    }
+
+    /**
+     * 获取列表
+     * @param   Bool    $force  是否强制更新
+     * 
+     */
+    public function getList($courseId,$force = false)
+    {
+        // 结果数据
+        $list                  = $force ? [] : cache('admin:video:play:question:list:'.$courseId);
+        // 不存在数据
+        if ( !$list )          {
+            // 从数据库获取数据
+            $data              = $this->query()->where([['status','=',0]])->get(['id','course_id','question_id','play_time'])->toArray();
+            // 循环处理数据
+            $list              = [];
+            // 进行更新
+            foreach ($data as $value) {
+                // 重组数据
+                $list[$value['course_id']][$value['question_id']] = $value;
+            }
+            // 存起来
+            cache(['admin:video:play:question:list:'.$courseId=>$list]);
+        }
+        // 返回结果
+        return                  $list;
+    }
+
+}

+ 103 - 0
app/Models/Video/Question.php

@@ -0,0 +1,103 @@
+<?php namespace App\Models\Video;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 模型
+ * 
+ */
+class Question extends Model
+{
+    use HasFactory;
+
+    // 与模型关联的表名
+    protected $table = 'video_question';
+    // 是否主动维护时间戳
+    public $timestamps = false;
+    // 定义时间戳字段名
+    // const CREATED_AT = 'insert_time';
+    // const UPDATED_AT = 'update_time';
+
+    /**
+     * 添加数据
+     * 
+     */
+    public function add($data)
+    {
+        // 时间
+        $data['insert_time']				= time();
+        $data['update_time']				= time();
+        // 写入数据表
+        $id						            = $this->query()->insertGetId($data);
+        // 如果操作失败
+        if( !$id )                          return $id;
+        // 更新缓存
+        $this->getList(true);
+        // 返回结果
+        return                              $id;
+    }
+
+    /**
+     * 添加数据
+     * 
+     */
+    public function edit($id,$data)
+    {
+        // 更新时间
+        $data['update_time']                = time();
+        // 写入数据表
+        $result						        = $this->query()->where(['id'=>$id])->update($data);
+        // 如果操作失败
+        if( !$result )                      return $result;
+        // 更新缓存
+        $this->getList(true);
+        // 返回结果
+        return                              $result;
+    }
+
+    /**
+     * 获取列表
+     * @param   Bool    $force  是否强制更新
+     * 
+     */
+    public function getList($force = false)
+    {
+        // 结果数据
+        $list                  = $force ? [] : cache('admin:video:question:list');
+        // 不存在数据
+        if ( !$list ) {
+            // 从数据库获取数据
+            $data              = $this->query()->where([['status','=',0]])->get(['id','title'])->toArray();
+            // 循环处理数据
+            $list              = [];
+            // 进行更新
+            foreach ($data as $value) {
+                // 重组数据
+                $list[$value['id']] = $value;
+            }
+            // 存起来
+            cache(['admin:video:question:list'=>$list]);
+        }
+        // 返回结果
+        return                  $list;
+    }
+
+    /**
+     * 获取配置平台对应的应用数据
+     * 
+     * @param   Array      用户ID
+     * @param   String     指定字段
+     * 
+     */
+    public function getOne($id,$field='')
+    {
+        // 获取列表数据
+        $list                   = $this->getList();
+        // 获取数据
+        $one                    = isset($list[$id]) ? $list[$id] : [];
+        // 返回值
+        return                  empty($field) ? $one : ( isset($one[$field]) ? $one[$field] : null);
+    }
+
+}

+ 55 - 0
app/Servers/Aliyun/Oss.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace App\Servers\Aliyun;
+
+use OSS\OssClient;
+use OSS\Core\OssException;
+use App\Facades\Servers\Logs\Log;
+use OSS\Credentials\StaticCredentialsProvider;
+
+/**
+ * 阿里oss
+ *
+ * @author    jun
+ */
+
+class Oss {
+
+    private \OSS\OssClient $ossClient;
+
+    function __construct()
+    {
+        $accessKeyId        =   config('aliyun.accessKeyId','');
+        $accessKeySecret    =   config('aliyun.accessKeySecret','');
+        $provider           =   new StaticCredentialsProvider($accessKeyId,$accessKeySecret);
+        $endpoint           =   "https://oss-cn-shenzhen.aliyuncs.com";
+        $config = array(
+            "provider" => $provider,
+            "endpoint" => $endpoint,
+            "signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
+            "region"=> "cn-shenzhen"
+        );
+        $this->ossClient    = new OssClient($config);
+    }
+    /**
+     *  使用签名URL上传
+     * @param string 	bucket	存储空间名称
+     * @param string 	object	不包含Bucket名称在内的Object完整路径
+     *
+     * */
+    function signUrl($bucket, $object, $options=['Content-Type'=>'multipart/form-data'] )
+    {
+        // 指定签名URL的过期时间为600s(最长可达32400s)。
+        $timeout = 600;
+        try {
+            // 生成签名URL。
+            $signedUrl = $this->ossClient->signUrl($bucket, $object, $timeout, "PUT",$options);
+            // 返回结果
+            return $signedUrl;
+        } catch (OssException $e) {
+            Log::error('oss/signUrl','获取签名URL上传失败,错误:'.json_encode($e->getMessage()));
+            return ['error'=>$e->getMessage()];
+        }
+    }
+    
+}

+ 1 - 0
composer.json

@@ -7,6 +7,7 @@
     "require": {
         "php": "^7.3|^8.0",
         "alibabacloud/dysmsapi-20170525": "3.1.1",
+        "aliyuncs/oss-sdk-php": "^2.7",
         "fideloper/proxy": "^4.4",
         "firebase/php-jwt": "^6.10",
         "fruitcake/laravel-cors": "^2.0",

+ 55 - 4
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "5b9b61d91311f39b4ffa1e237fa52a1e",
+    "content-hash": "0dd729ca9353270648f6cb5292e5d3b2",
     "packages": [
         {
             "name": "adbario/php-dot-notation",
@@ -504,6 +504,57 @@
             },
             "time": "2022-08-02T04:12:58+00:00"
         },
+        {
+            "name": "aliyuncs/oss-sdk-php",
+            "version": "v2.7.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/aliyun/aliyun-oss-php-sdk.git",
+                "reference": "483dd0b8bff5d47f0e4ffc99f6077a295c5ccbb5"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/aliyun/aliyun-oss-php-sdk/zipball/483dd0b8bff5d47f0e4ffc99f6077a295c5ccbb5",
+                "reference": "483dd0b8bff5d47f0e4ffc99f6077a295c5ccbb5",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=5.3"
+            },
+            "require-dev": {
+                "php-coveralls/php-coveralls": "*",
+                "phpunit/phpunit": "*"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "OSS\\": "src/OSS"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Aliyuncs",
+                    "homepage": "http://www.aliyun.com"
+                }
+            ],
+            "description": "Aliyun OSS SDK for PHP",
+            "homepage": "http://www.aliyun.com/product/oss/",
+            "support": {
+                "issues": "https://github.com/aliyun/aliyun-oss-php-sdk/issues",
+                "source": "https://github.com/aliyun/aliyun-oss-php-sdk/tree/v2.7.2"
+            },
+            "time": "2024-10-28T10:41:12+00:00"
+        },
         {
             "name": "asm89/stack-cors",
             "version": "v2.1.1",
@@ -11035,12 +11086,12 @@
     ],
     "aliases": [],
     "minimum-stability": "dev",
-    "stability-flags": [],
+    "stability-flags": {},
     "prefer-stable": true,
     "prefer-lowest": false,
     "platform": {
         "php": "^7.3|^8.0"
     },
-    "platform-dev": [],
-    "plugin-api-version": "2.3.0"
+    "platform-dev": {},
+    "plugin-api-version": "2.6.0"
 }

+ 24 - 0
resources/views/admin/video_answer/add.blade.php

@@ -0,0 +1,24 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+<form class="post-form" action="" method="post">
+	<div class="form-group col-sm-12">
+		<label class="control-label">题目标题</label>
+		<select class="form-control selectpicker" name="question_id"  data-live-search="true" data-live-search-placeholder="搜索题目" data-none-results-text="未搜索到 {0}" title="选择题目">
+			@foreach ($questionList as $value)
+				<option value="{{$value['id']}}" @if( $value['id'] == request('question_id',0) ) selected="" @endif >{{$value['title']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col-sm-12">
+		<label class="control-label">题目选项</label>
+		<input class="form-control" required="required" type="text" placeholder="题目选项" name="value" maxlength="255" value="" />
+	</div>
+	<div class="form-group col-sm-12">
+		@csrf
+		<input id="send" type="submit" value="提交" class="btn btn-primary btn-block" />
+	</div>
+</form>
+@endsection

+ 25 - 0
resources/views/admin/video_answer/edit.blade.php

@@ -0,0 +1,25 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+<form class="post-form" action="" method="post">
+	<div class="form-group col-sm-12">
+		<label class="control-label">题目标题</label>
+		<select class="form-control selectpicker" name="question_id"  data-live-search="true" data-live-search-placeholder="搜索题目" data-none-results-text="未搜索到 {0}" title="选择题目">
+			@foreach ($questionList as $value)
+				<option value="{{$value['id']}}" @if( $value['id'] == $oldData['question_id'] ) selected="" @endif >{{$value['title']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col-sm-12">
+		<label class="control-label">题目选项</label>
+		<input class="form-control" required="required" type="text" placeholder="题目选项" name="value" maxlength="255" value="{{$oldData['value']}}" />
+	</div>
+	<div class="form-group col-sm-12">
+		@csrf
+		<input type="hidden" name="id" id="id" value="{{$oldData['id']}}" />
+		<input id="send" type="submit" value="提交" class="btn btn-primary btn-block" />
+	</div>
+</form>
+@endsection

+ 84 - 0
resources/views/admin/video_answer/index.blade.php

@@ -0,0 +1,84 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+
+@if(check_auth('admin/video_answer/add'))
+	<div class="page-header">
+		<a href="{{url('admin/video_answer/add?'.http_build_query(['question_id'=>request('question_id',0)]))}}" class="btn btn-primary">新增</a>
+	</div>
+@endif
+
+<form action="" method="get" class="form-horizontal form-line">
+	<div class="form-group col col-lg-8 col-md-12 col-sm-12 col-xs-12" style="margin-right: 2px;">
+		<select name="question_id" class="form-control selectpicker" data-live-search="true" data-live-search-placeholder="搜索题目" data-none-results-text="未搜索到 {0}" title="选择题目">
+			@foreach ($questionList as $value)
+				<option value="{{$value['id']}}"  @if( $value['id'] == request('question_id',0) ) selected="" @endif >{{$value['title']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<input type="submit" class="btn btn-sm btn-primary" value="查询"/>
+	<a href="{{url('admin/video_answer/index')}}" class="btn btn-sm btn-default" >重置</a>
+</form>
+
+<div class="row">
+	<div class="col-xs-12">	
+		<div class="table-responsive">
+			<table class="table table-striped table-bordered table-hover">
+				<thead>
+					<tr>
+						<th>ID</th>
+						<th>题目</th>
+						<th>题目选项</th>
+						<th>是否答案</th>
+						<th>修改时间</th>
+						<th>操作</th>									
+					</tr>
+				</thead>
+				
+				<tbody>
+						@foreach ($list as $a)
+						<tr>
+							<th>{{$a['id']}}</th>
+							<td>
+							@foreach ($questionList as $value)
+								@if( $value['id'] == $a['question_id'] )
+								{{$value['title']}}								
+								@endif
+							@endforeach
+							</td>
+							<td>{{$a['value']}}</td>
+							<td>
+								@if( $a['is_answer'] )
+								是
+								@else
+								否
+								@endif
+							</td>
+							<td> {{date('Y/m/d H:i:s',$a['update_time'])}}</td>
+							<td>
+								@if(check_auth('admin/video_answer/edit'))
+								<a href="{{url('admin/video_answer/edit?'.http_build_query(['id'=>$a['id']]))}}" class="btn btn-sm btn-warning" >编辑</a>
+								@endif
+								@if(check_auth('admin/video_answer/set_answer'))
+									@if( !$a['is_answer'] )
+									<a data-url="{{url('admin/video_answer/set_answer?'.http_build_query(['id'=>$a['id'],'is_answer'=>1]))}}" class="set_status btn btn-sm btn-danger" >设为答案</a>
+									@endif
+								@endif
+							</td>							
+						</tr>  
+						@endforeach
+						<tr>
+							<td colspan="20" class="page">{{$list->render()}}</td>
+						</tr>
+						<tr>
+							<td colspan="20">总计 {{$list->total()}} 个题目</td>
+						</tr>
+				</tbody>
+				
+			</table>
+		</div>
+	</div>
+</div>
+@endsection

+ 119 - 0
resources/views/admin/video_course/add.blade.php

@@ -0,0 +1,119 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+<form class="post-form" action="" method="post">
+	<div class="form-group col-sm-2">
+		<label class="control-label">课程配图</label>
+		<div id="thumb">
+			<a id="thumb-image" href="#" data-toggle="image" class="img-thumb">
+				<img src="{{path_compat('')}}" height="100" />
+			</a>
+			<input type="hidden" name="thumb" value="" id="input-image" />
+		</div>
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">课程视频</label>
+		<div id="video_src">
+			<a id="video_upload" href="javascript:;" class="img-thumb" >
+				<video src="{{path_compat('')}}" poster="{{path_compat('')}}" height="100" width="100" ></video>
+			</a>
+			<input type="hidden" name="video_src" value=""  />
+		</div>
+	</div>
+	<div class="form-group col-sm-4">
+		<label class="control-label">课程名称</label>
+		<input class="form-control" required="required" type="text" placeholder="课程名称" maxlength="40" name="name" value="" />
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">开始时间</label>
+		<input class="form-control" required="required" type="datetime-local" placeholder="开始时间"  name="start_time" value="" />
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">结束时间</label>
+		<input class="form-control" required="required" type="datetime-local" placeholder="结束时间" name="end_time" value="" />
+	</div>
+	<div class="form-group col-sm-12">
+		<label class="control-label">课程介绍</label>
+		<textarea required="required" id="container" name="content" placeholder="课程介绍" ></textarea>
+	</div>
+	<div class="form-group col-sm-12">
+		@csrf
+		<input id="send" type="submit" value="提交" class="btn btn-primary btn-block" />
+	</div>
+</form>
+@endsection
+@section('javascript')
+<script src="/static/ueditor/ueditor.config.js"></script>  
+<script src="/static/ueditor/ueditor.all.js"></script>
+<script type="text/javascript">
+	var editor = new UE.ui.Editor();
+	editor.render("container");
+</script>
+<script type="text/javascript">
+	$('#video_upload').on('click', function() {
+		// 定义预签名URL
+		var signedUrl	= '';
+		var videoSrc	= '';
+		// 请求接口获取签名URL
+		$.ajax({
+			url: "{{url('admin/video_course/get_sign_url')}}",
+			type: 'get',
+			dataType: 'json',
+			success: function(data) {
+				// 判断返回值
+				if(data.code != 'success'){
+					art.dialog({content: data.msg,lock: true,ok: function() {}});
+					return ;
+				}
+				// 获取签名URL
+				signedUrl = data.data.sign_url;
+				videoSrc  = data.data.video_src;
+				// 没有获取到结果的话,结束
+				if( !signedUrl ) {
+					return;
+				}
+				// 移除之前上传的表单
+				$('#form-upload').remove();
+				// 生成一个表单,并且使用CSRF
+				$('body').prepend('<form enctype="multipart/form-data" id="form-upload" style="display: none;"><input osctype="btn_upload_file" id="form-upload-file" type="file" name="file" /> @csrf </form>');
+				$('#form-upload input[name=\'file\']').trigger('click');
+			},
+			error: function(xhr, status, error) {
+				console.error('Error:', error);
+			}
+		});
+		
+		$(document).on('change','#form-upload-file',function(){
+			// 获取文件
+			const fileInput = document.getElementById('form-upload-file');
+			const file = fileInput.files[0];
+			// 如果没有上传文件
+			if ( !file ) {
+				art.dialog({content: '请上传文件',lock: true,ok: function() {}});
+				return ;
+			}
+			// 调用上传
+			upload(file, signedUrl);
+		})
+
+		const upload = async (file, presignedUrl) => {
+			// 提示上传中
+			art.dialog({id:'loading',lock: true,title:'视频上传中'});
+			// 上传文件
+			const response = await fetch(presignedUrl, {method: 'PUT',body: file.slice(0, file.size)});
+			// 移除loading
+			art.dialog.list['loading'].close();
+			// 结果
+			if (!response.ok) {
+				art.dialog({content: '上传失败',lock: true,ok: function() {}});
+				return ;
+			}
+			// 显示上传成功的图片
+			$('#video_upload').html('<video src="'+videoSrc+'" height="100" width="100" ></video>');
+			$('#video_src input').val(videoSrc);
+		};
+	});
+</script>
+@endsection

+ 120 - 0
resources/views/admin/video_course/edit.blade.php

@@ -0,0 +1,120 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+<form class="post-form" action="" method="post">
+	<div class="form-group col-sm-2">
+		<label class="control-label">课程配图</label>
+		<div id="thumb">
+			<a id="thumb-image" href="#" data-toggle="image" class="img-thumb">
+				<img src="{{path_compat($oldData['thumb'])}}" height="100" />
+			</a>
+			<input type="hidden" name="thumb" value="{{$oldData['thumb']}}" id="input-image" />
+		</div>
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">课程视频</label>
+		<div id="video_src">
+			<a id="video_upload" href="javascript:;" class="img-thumb" >
+				<video src="{{$oldData['video_src']}}" height="100" width="100" ></video>
+			</a>
+			<input type="hidden" name="video_src" value="{{$oldData['video_src']}}"  />
+		</div>
+	</div>
+	<div class="form-group col-sm-4">
+		<label class="control-label">课程名称</label>
+		<input class="form-control" required="required" type="text" placeholder="课程名称" maxlength="40" name="name" value="{{$oldData['name']}}" />
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">开始时间</label>
+		<input class="form-control" required="required" type="datetime-local" placeholder="开始时间"  name="start_time" value="{{date('Y-m-d H:i',$oldData['start_time'])}}" />
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">结束时间</label>
+		<input class="form-control" required="required" type="datetime-local" placeholder="结束时间" name="end_time" value="{{date('Y-m-d H:i',$oldData['end_time'])}}" />
+	</div>
+	<div class="form-group col-sm-12">
+		<label class="control-label">课程内容</label>
+		<textarea required="required" id="container" name="content" placeholder="课程内容" >{{$oldData['content']}}</textarea>
+	</div>
+	<div class="form-group col-sm-12">
+		@csrf
+		<input type="hidden" name="id" value="{{$oldData['id']}}" />
+		<input id="send" type="submit" value="提交" class="btn btn-primary btn-block" />
+	</div>
+</form>
+@endsection
+@section('javascript')
+<script src="/static/ueditor/ueditor.config.js"></script>  
+<script src="/static/ueditor/ueditor.all.js"></script>
+<script type="text/javascript">
+	var editor = new UE.ui.Editor();
+	editor.render("container");
+</script>
+<script type="text/javascript">
+	$('#video_upload').on('click', function() {
+		// 定义预签名URL
+		var signedUrl	= '';
+		var videoSrc	= '';
+		// 请求接口获取签名URL
+		$.ajax({
+			url: "{{url('admin/video_course/get_sign_url')}}",
+			type: 'get',
+			dataType: 'json',
+			success: function(data) {
+				// 判断返回值
+				if(data.code != 'success'){
+					art.dialog({content: data.msg,lock: true,ok: function() {}});
+					return ;
+				}
+				// 获取签名URL
+				signedUrl = data.data.sign_url;
+				videoSrc  = data.data.video_src;
+				// 没有获取到结果的话,结束
+				if( !signedUrl ) {
+					return;
+				}
+				// 移除之前上传的表单
+				$('#form-upload').remove();
+				// 生成一个表单,并且使用CSRF
+				$('body').prepend('<form enctype="multipart/form-data" id="form-upload" style="display: none;"><input osctype="btn_upload_file" id="form-upload-file" type="file" name="file" /> @csrf </form>');
+				$('#form-upload input[name=\'file\']').trigger('click');
+			},
+			error: function(xhr, status, error) {
+				console.error('Error:', error);
+			}
+		});
+		
+		$(document).on('change','#form-upload-file',function(){
+			// 获取文件
+			const fileInput = document.getElementById('form-upload-file');
+			const file = fileInput.files[0];
+			// 如果没有上传文件
+			if ( !file ) {
+				art.dialog({content: '请上传文件',lock: true,ok: function() {}});
+				return ;
+			}
+			// 调用上传
+			upload(file, signedUrl);
+		})
+
+		const upload = async (file, presignedUrl) => {
+			// 提示上传中
+			art.dialog({id:'loading',lock: true,title:'视频上传中'});
+			// 上传文件
+			const response = await fetch(presignedUrl, {method: 'PUT',body: file.slice(0, file.size)});
+			// 移除loading
+			art.dialog.list['loading'].close();
+			// 结果
+			if (!response.ok) {
+				art.dialog({content: '上传失败',lock: true,ok: function() {}});
+				return ;
+			}
+			// 显示上传成功的图片
+			$('#video_upload').html('<video src="'+videoSrc+'" height="100" width="100" ></video>');
+			$('#video_src input').val(videoSrc);
+		};
+	});
+</script>
+@endsection

+ 98 - 0
resources/views/admin/video_course/index.blade.php

@@ -0,0 +1,98 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+<div class="page-header">
+	@if( check_auth('admin/video_course/add') )
+	<a href="{{url('admin/video_course/add')}}" class="btn btn-primary">新增</a>
+	@endif
+</div>
+<form action="" method="get" class="form-horizontal form-line">
+	<div class="form-group col col-lg-2 col-md-2 col-sm-2 col-xs-12" style="margin-right: 2px;">
+		<input type="text" class="form-control" name="title" value="{{request('title','')}}" placeholder="请输入课程标题查询" />
+	</div>
+	<div class="form-group col col-lg-2 col-md-2 col-sm-2 col-xs-12" style="margin-right: 2px;">
+		<input type="text" class="form-control" name="start_time" value="{{request('start_time','')}}" placeholder="请输入开始时间查询" />
+	</div>
+	<div class="form-group col col-lg-2 col-md-2 col-sm-2 col-xs-12" style="margin-right: 2px;">
+		<input type="text" class="form-control" name="end_time" value="{{request('end_time','')}}" placeholder="请输入结束时间查询" />
+	</div>
+	<input type="submit" class="btn btn-sm btn-primary" value="查询"/>
+	<a href="{{url('admin/video_course/index')}}" class="btn btn-sm btn-default" >重置</a>
+	@csrf
+</form>
+<div class="row">
+	<div class="col-xs-12">
+		<div class="table-responsive">
+			<table class="table table-striped table-bordered table-hover">
+				<thead>
+					<tr>
+						<th>ID</th>
+						<th>课程名称</th>
+						<th>课中习题</th>
+						<th>课后习题</th>
+						<th>课程有效期</th>
+						<th>课程状态</th>
+						<th>修改时间</th>
+						<th>操作</th>
+					</tr>
+				</thead>
+				<tbody>
+					@foreach ($list as $a)
+					<tr>
+						<td> {{$a['id']}}</td>
+						<td> {{$a['name']}}</td>
+						<td> 
+							@if( check_auth('admin/video_play_question/index') )
+							<a href="{{url('admin/video_play_question/index?'.http_build_query(['course_id'=>$a['id']]))}}" title="课中习题">
+								课中习题
+							</a>
+							@endif
+						</td>
+						<td> 
+							@if( check_auth('admin/video_course_question/index') )
+							<a href="{{url('admin/video_course_question/index?'.http_build_query(['course_id'=>$a['id']]))}}" title="课后习题">
+								课后习题
+							</a>
+							@endif
+						</td>
+						<td> 
+							<p>开始:{{date('Y/m/d H:i',$a['start_time'])}} </p>
+							<p>结束: {{date('Y/m/d H:i',$a['end_time'])}} </p>
+						</td>
+						<td> @if ($a['status'] == 0) 启用 @endif @if ($a['status'] == 1) 停用 @endif</td>
+						<td> {{date('Y/m/d H:i',$a['update_time'])}}</td>
+						<td>
+							@if( check_auth('admin/video_course/edit') )
+							<a class="btn btn-sm btn-warning" href="{{url('admin/video_course/edit?'.http_build_query(['id'=>$a['id']]))}}" title="查看">
+								修改
+							</a>
+							@endif
+							@if( check_auth('admin/video_course/set_status') )
+								@if ( $a['status'] )
+									<a class="delete btn btn-sm btn-success" data-url="{{url('admin/video_course/set_status?'.http_build_query(['id'=>$a['id'],'status'=>'0']))}}">
+										启用
+									</a>
+								@else
+									<a class="delete btn btn-sm btn-danger" data-url="{{url('admin/video_course/set_status?'.http_build_query(['id'=>$a['id'],'status'=>'1']))}}">
+										停用
+									</a>
+								@endif
+							@endif
+						</td>
+					</tr>
+					@endforeach
+					<tr>
+						<td colspan="20" class="page">{{$list->render()}}</td>
+					</tr>
+					<tr>
+						<td colspan="20">总计 {{$list->total()}} 个课程</td>
+					</tr>
+				</tbody>
+
+			</table>
+		</div>
+	</div>
+</div>
+@endsection

+ 28 - 0
resources/views/admin/video_course_question/add.blade.php

@@ -0,0 +1,28 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+<form class="post-form" action="" method="post">
+	<div class="form-group col-sm-4" >
+		<label class="control-label">课程名称</label>
+		<select name="course_id" class="form-control selectpicker" data-live-search="true" data-live-search-placeholder="搜索课程名称" data-none-results-text="未搜索到 {0}" title="选择课程名称">
+			@foreach ($courseList as $value)
+				<option value="{{$value['id']}}" @if( $value['id'] == request('course_id',0) ) selected @endif>{{$value['name']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col-sm-4" >
+		<label class="control-label">选择习题</label>
+		<select name="question_id" class="form-control selectpicker" data-live-search="true" data-live-search-placeholder="搜索习题题目" data-none-results-text="未搜索到 {0}" title="选择习题题目">
+			@foreach ($questionList as $value)
+				<option value="{{$value['id']}}" @if( $value['id'] == request('question_id',0) ) selected @endif>{{$value['title']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col-sm-12">
+		@csrf
+		<input id="send" type="submit" value="提交" class="btn btn-primary btn-block" />
+	</div>
+</form>
+@endsection

+ 29 - 0
resources/views/admin/video_course_question/edit.blade.php

@@ -0,0 +1,29 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+<form class="post-form" action="" method="post">
+	<div class="form-group col-sm-4" >
+		<label class="control-label">课程名称</label>
+		<select name="course_id" class="form-control selectpicker" data-live-search="true" data-live-search-placeholder="搜索课程名称" data-none-results-text="未搜索到 {0}" title="选择课程名称">
+			@foreach ($courseList as $value)
+				<option value="{{$value['id']}}" @if( $value['id'] == $oldData['course_id'] ) selected @endif>{{$value['name']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col-sm-4" >
+		<label class="control-label">选择习题</label>
+		<select name="question_id" class="form-control selectpicker" data-live-search="true" data-live-search-placeholder="搜索习题题目" data-none-results-text="未搜索到 {0}" title="选择习题题目">
+			@foreach ($questionList as $value)
+				<option value="{{$value['id']}}" @if( $value['id'] == $oldData['question_id'] ) selected @endif>{{$value['title']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col-sm-12">
+		@csrf
+		<input type="hidden" name="id" id="id" value="{{$oldData['id']}}" />
+		<input id="send" type="submit" value="提交" class="btn btn-primary btn-block" />
+	</div>
+</form>
+@endsection

+ 89 - 0
resources/views/admin/video_course_question/index.blade.php

@@ -0,0 +1,89 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+
+@if(check_auth('admin/video_course_question/add'))
+	<div class="page-header">
+		<a href="{{url('admin/video_course_question/add?'.http_build_query(['course_id'=>request('course_id',0)]))}}" class="btn btn-primary">新增</a>
+	</div>
+@endif
+
+<form action="" method="get" class="form-horizontal form-line">
+	<div class="form-group col col-lg-2 col-md-4 col-sm-6 col-xs-12" style="margin-right: 2px;">
+		<select name="course_id" class="form-control selectpicker" data-live-search="true" data-live-search-placeholder="搜索课程名称" data-none-results-text="未搜索到 {0}" title="选择课程名称">
+			<option value="0" @if( 0 == request('course_id',0) ) selected @endif>不限课程</option>
+			@foreach ($courseList as $value)
+				<option value="{{$value['id']}}" @if( $value['id'] == request('course_id',0) ) selected @endif>{{$value['name']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col col-lg-2 col-md-4 col-sm-6 col-xs-12" style="margin-right: 2px;">
+		<select name="question_id" class="form-control selectpicker" data-live-search="true" data-live-search-placeholder="搜索习题题目" data-none-results-text="未搜索到 {0}" title="选择习题题目">
+			<option value="0" @if( 0 == request('question_id',0) ) selected @endif>不限习题</option>
+			@foreach ($questionList as $value)
+				<option value="{{$value['id']}}" @if( $value['id'] == request('question_id',0) ) selected @endif>{{$value['title']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<input type="submit" class="btn btn-sm btn-primary" value="查询"/>
+	<a href="{{url('admin/video_course_question/index')}}" class="btn btn-sm btn-default" >重置</a>
+</form>
+
+<div class="row">
+	<div class="col-xs-12">	
+		<div class="table-responsive">
+			<table class="table table-striped table-bordered table-hover">
+				<thead>
+					<tr>
+						<th>ID</th>
+						<th>课程名称</th>
+						<th>习题题目</th>
+						<th>状态</th>
+						<th>修改时间</th>
+						<th>操作</th>									
+					</tr>
+				</thead>
+				
+				<tbody>
+						@foreach ($list as $a)
+						<tr>
+							<th>{{$a['id']}}</th>
+							<td>{{$a['course_name']}}</td>
+							<td>{{$a['question_title']}}</td>
+							<td>
+								@if( $a['status'] )
+								停用
+								@else
+								启用
+								@endif
+							</td>
+							<td> {{date('Y/m/d H:i:s',$a['update_time'])}}</td>
+							<td>
+								@if(check_auth('admin/video_course_question/edit'))
+								<a href="{{url('admin/video_course_question/edit?'.http_build_query(['id'=>$a['id']]))}}" class="btn btn-sm btn-warning" >编辑</a>
+								@endif
+								@if(check_auth('admin/video_course_question/set_status'))
+									@if($a['status'])
+									<a data-url="{{url('admin/video_course_question/set_status?'.http_build_query(['id'=>$a['id'],'status'=>0]))}}" class="set_status btn btn-sm btn-success" >启用</a>
+									@else
+									<a data-url="{{url('admin/video_course_question/set_status?'.http_build_query(['id'=>$a['id'],'status'=>1]))}}" class="set_status btn btn-sm btn-danger" >停用</a>
+									@endif
+								@endif
+							</td>							
+						</tr>  
+						@endforeach
+						<tr>
+							<td colspan="20" class="page">{{$list->render()}}</td>
+						</tr>
+						<tr>
+							<td colspan="20">总计 {{$list->total()}} 个题目</td>
+						</tr>
+				</tbody>
+				
+			</table>
+		</div>
+	</div>
+</div>
+@endsection

+ 39 - 0
resources/views/admin/video_play_question/add.blade.php

@@ -0,0 +1,39 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+<form class="post-form" action="" method="post">
+	<div class="form-group col-sm-4" >
+		<label class="control-label">课程名称</label>
+		<select name="course_id" class="form-control selectpicker" data-live-search="true" data-live-search-placeholder="搜索课程名称" data-none-results-text="未搜索到 {0}" title="选择课程名称">
+			@foreach ($courseList as $value)
+				<option value="{{$value['id']}}" @if( $value['id'] == request('course_id',0) ) selected @endif>{{$value['name']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col-sm-4" >
+		<label class="control-label">选择习题</label>
+		<select name="question_id" class="form-control selectpicker" data-live-search="true" data-live-search-placeholder="搜索习题题目" data-none-results-text="未搜索到 {0}" title="选择习题题目">
+			@foreach ($questionList as $value)
+				<option value="{{$value['id']}}" @if( $value['id'] == request('question_id',0) ) selected @endif>{{$value['title']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col-sm-4">
+		<label class="control-label">出题时间(00:00)</label>
+		<div class="form-group col-sm-12">
+			<div class="form-group col-sm-6">
+				<input class="form-control" required="required" type="number" placeholder="分" name="minute" min="1" max="255" value="00" />
+			</div>
+			<div class="form-group col-sm-6">
+				<input class="form-control" required="required" type="number" placeholder="秒" name="second" min="0" max="60" value="00" />
+			</div>
+		</div>
+	</div>
+	<div class="form-group col-sm-12">
+		@csrf
+		<input id="send" type="submit" value="提交" class="btn btn-primary btn-block" />
+	</div>
+</form>
+@endsection

+ 40 - 0
resources/views/admin/video_play_question/edit.blade.php

@@ -0,0 +1,40 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+<form class="post-form" action="" method="post">
+	<div class="form-group col-sm-4" >
+		<label class="control-label">课程名称</label>
+		<select name="course_id" class="form-control selectpicker" data-live-search="true" data-live-search-placeholder="搜索课程名称" data-none-results-text="未搜索到 {0}" title="选择课程名称">
+			@foreach ($courseList as $value)
+				<option value="{{$value['id']}}" @if( $value['id'] == $oldData['course_id'] ) selected @endif>{{$value['name']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col-sm-4" >
+		<label class="control-label">选择习题</label>
+		<select name="question_id" class="form-control selectpicker" data-live-search="true" data-live-search-placeholder="搜索习题题目" data-none-results-text="未搜索到 {0}" title="选择习题题目">
+			@foreach ($questionList as $value)
+				<option value="{{$value['id']}}" @if( $value['id'] == $oldData['question_id'] ) selected @endif>{{$value['title']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col-sm-4">
+		<label class="control-label">出题时间(00:00)</label>
+		<div class="form-group col-sm-12">
+			<div class="form-group col-sm-6">
+				<input class="form-control" required="required" type="number" placeholder="分" name="minute" min="1" max="255" value="{{$oldData['minute']}}" />
+			</div>
+			<div class="form-group col-sm-6">
+				<input class="form-control" required="required" type="number" placeholder="秒" name="second" min="0" max="60" value="{{$oldData['second']}}" />
+			</div>
+		</div>
+	</div>
+	<div class="form-group col-sm-12">
+		@csrf
+		<input type="hidden" name="id" id="id" value="{{$oldData['id']}}" />
+		<input id="send" type="submit" value="提交" class="btn btn-primary btn-block" />
+	</div>
+</form>
+@endsection

+ 91 - 0
resources/views/admin/video_play_question/index.blade.php

@@ -0,0 +1,91 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+
+@if(check_auth('admin/video_play_question/add'))
+	<div class="page-header">
+		<a href="{{url('admin/video_play_question/add?'.http_build_query(['course_id'=>request('course_id',0)]))}}" class="btn btn-primary">新增</a>
+	</div>
+@endif
+
+<form action="" method="get" class="form-horizontal form-line">
+	<div class="form-group col col-lg-2 col-md-4 col-sm-6 col-xs-12" style="margin-right: 2px;">
+		<select name="course_id" class="form-control selectpicker" data-live-search="true" data-live-search-placeholder="搜索课程名称" data-none-results-text="未搜索到 {0}" title="选择课程名称">
+			<option value="0" @if( 0 == request('course_id',0) ) selected @endif>不限课程</option>
+			@foreach ($courseList as $value)
+				<option value="{{$value['id']}}" @if( $value['id'] == request('course_id',0) ) selected @endif>{{$value['name']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col col-lg-2 col-md-4 col-sm-6 col-xs-12" style="margin-right: 2px;">
+		<select name="question_id" class="form-control selectpicker" data-live-search="true" data-live-search-placeholder="搜索习题题目" data-none-results-text="未搜索到 {0}" title="选择习题题目">
+			<option value="0" @if( 0 == request('question_id',0) ) selected @endif>不限习题</option>
+			@foreach ($questionList as $value)
+				<option value="{{$value['id']}}" @if( $value['id'] == request('question_id',0) ) selected @endif>{{$value['title']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<input type="submit" class="btn btn-sm btn-primary" value="查询"/>
+	<a href="{{url('admin/video_play_question/index')}}" class="btn btn-sm btn-default" >重置</a>
+</form>
+
+<div class="row">
+	<div class="col-xs-12">	
+		<div class="table-responsive">
+			<table class="table table-striped table-bordered table-hover">
+				<thead>
+					<tr>
+						<th>ID</th>
+						<th>课程名称</th>
+						<th>出题时间</th>
+						<th>习题题目</th>
+						<th>状态</th>
+						<th>修改时间</th>
+						<th>操作</th>									
+					</tr>
+				</thead>
+				
+				<tbody>
+						@foreach ($list as $a)
+						<tr>
+							<th>{{$a['id']}}</th>
+							<td>{{$a['course_name']}}</td>
+							<td>{{$a['play_time']}}</td>
+							<td>{{$a['question_title']}}</td>
+							<td>
+								@if( $a['status'] )
+								停用
+								@else
+								启用
+								@endif
+							</td>
+							<td> {{date('Y/m/d H:i:s',$a['update_time'])}}</td>
+							<td>
+								@if(check_auth('admin/video_play_question/edit'))
+								<a href="{{url('admin/video_play_question/edit?'.http_build_query(['id'=>$a['id']]))}}" class="btn btn-sm btn-warning" >编辑</a>
+								@endif
+								@if(check_auth('admin/video_play_question/set_status'))
+									@if($a['status'])
+									<a data-url="{{url('admin/video_play_question/set_status?'.http_build_query(['id'=>$a['id'],'status'=>0]))}}" class="set_status btn btn-sm btn-success" >启用</a>
+									@else
+									<a data-url="{{url('admin/video_play_question/set_status?'.http_build_query(['id'=>$a['id'],'status'=>1]))}}" class="set_status btn btn-sm btn-danger" >停用</a>
+									@endif
+								@endif
+							</td>							
+						</tr>  
+						@endforeach
+						<tr>
+							<td colspan="20" class="page">{{$list->render()}}</td>
+						</tr>
+						<tr>
+							<td colspan="20">总计 {{$list->total()}} 个题目</td>
+						</tr>
+				</tbody>
+				
+			</table>
+		</div>
+	</div>
+</div>
+@endsection

+ 20 - 0
resources/views/admin/video_question/add.blade.php

@@ -0,0 +1,20 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+<form class="post-form" action="" method="post">
+	<div class="form-group col-sm-12">
+		<label class="control-label">题目</label>
+		<input class="form-control" required="required" type="text" placeholder="题目标题" name="title" maxlength="255" value="" />
+	</div>
+	<div class="form-group col-sm-12">
+		<label class="control-label">积分</label>
+		<input class="form-control" required="required" type="number" placeholder="答题积分" name="score"  value="0" />
+	</div>
+	<div class="form-group col-sm-12">
+		@csrf
+		<input id="send" type="submit" value="提交" class="btn btn-primary btn-block" />
+	</div>
+</form>
+@endsection

+ 21 - 0
resources/views/admin/video_question/edit.blade.php

@@ -0,0 +1,21 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+<form class="post-form" action="" method="post">
+	<div class="form-group col-sm-12">
+		<label class="control-label">题目标题</label>
+		<input class="form-control" required="required" type="text" placeholder="题目标题" name="title" maxlength="255" value="{{$oldData['title']}}" />
+	</div>
+	<div class="form-group col-sm-12">
+		<label class="control-label">积分</label>
+		<input class="form-control" required="required" type="number" placeholder="答题积分" name="score"  value="{{$oldData['score']}}" />
+	</div>
+	<div class="form-group col-sm-12">
+		@csrf
+		<input type="hidden" name="id" id="id" value="{{$oldData['id']}}" />
+		<input id="send" type="submit" value="提交" class="btn btn-primary btn-block" />
+	</div>
+</form>
+@endsection

+ 79 - 0
resources/views/admin/video_question/index.blade.php

@@ -0,0 +1,79 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+
+@if(check_auth('admin/video_question/add'))
+	<div class="page-header">
+		<a href="{{url('admin/video_question/add')}}" class="btn btn-primary">新增</a>
+	</div>
+@endif
+
+<form action="" method="get" class="form-horizontal form-line">
+	<div class="form-group col col-lg-2 col-md-4 col-sm-6 col-xs-12" style="margin-right: 2px;">
+		<input type="text" class="form-control" name="title" value="{{request('title','')}}" placeholder="请输入题目查询" />
+	</div>
+	<input type="submit" class="btn btn-sm btn-primary" value="查询"/>
+	<a href="{{url('admin/video_question/index')}}" class="btn btn-sm btn-default" >重置</a>
+</form>
+
+<div class="row">
+	<div class="col-xs-12">	
+		<div class="table-responsive">
+			<table class="table table-striped table-bordered table-hover">
+				<thead>
+					<tr>
+						<th>ID</th>
+						<th>题目</th>
+						<th>积分</th>
+						<th>状态</th>
+						<th>修改时间</th>
+						<th>操作</th>									
+					</tr>
+				</thead>
+				
+				<tbody>
+						@foreach ($list as $a)
+						<tr>
+							<th>{{$a['id']}}</th>
+							<td>{{$a['title']}}</td>
+							<td>{{$a['score']}}</td>
+							<td>
+								@if( $a['status'] )
+								停用
+								@else
+								启用
+								@endif
+							</td>
+							<td> {{date('Y/m/d H:i:s',$a['update_time'])}}</td>
+							<td>
+								@if(check_auth('admin/video_answer/index'))
+								<a href="{{url('admin/video_answer/index?'.http_build_query(['question_id'=>$a['id']]))}}" class="btn btn-sm btn-primary" >选项</a>
+								@endif
+								@if(check_auth('admin/video_question/edit'))
+								<a href="{{url('admin/video_question/edit?'.http_build_query(['id'=>$a['id']]))}}" class="btn btn-sm btn-warning" >编辑</a>
+								@endif
+								@if(check_auth('admin/video_question/set_status'))
+									@if($a['status'])
+									<a data-url="{{url('admin/video_question/set_status?'.http_build_query(['id'=>$a['id'],'status'=>0]))}}" class="set_status btn btn-sm btn-success" >启用</a>
+									@else
+									<a data-url="{{url('admin/video_question/set_status?'.http_build_query(['id'=>$a['id'],'status'=>1]))}}" class="set_status btn btn-sm btn-danger" >停用</a>
+									@endif
+								@endif
+							</td>							
+						</tr>  
+						@endforeach
+						<tr>
+							<td colspan="20" class="page">{{$list->render()}}</td>
+						</tr>
+						<tr>
+							<td colspan="20">总计 {{$list->total()}} 个题目</td>
+						</tr>
+				</tbody>
+				
+			</table>
+		</div>
+	</div>
+</div>
+@endsection

+ 55 - 2
routes/web.php

@@ -543,8 +543,8 @@ Route::middleware('admin')->prefix('admin')->group(function(){
     // 拉新活动数据列表
     Route::any('recruitment_record/index',[App\Http\Controllers\Admin\RecruitmentRecord::class,'index']);
     
-    /* 营销管理 */
-    //分享设置列表Promo
+    /* 文章管理 */
+    // 文章
     Route::any('article/index',[App\Http\Controllers\Admin\Article::class,'index']);
     // 新增
     Route::any('article/add',[App\Http\Controllers\Admin\Article::class,'add']);
@@ -659,4 +659,57 @@ Route::middleware('admin')->prefix('admin')->group(function(){
     // 状态
     Route::any('riddle_answer/set_answer',[App\Http\Controllers\Admin\RiddleAnswer::class,'set_answer']);
 
+
+    /* 视频课程管理 */
+    // 文章
+    Route::any('video_course/index',[App\Http\Controllers\Admin\VideoCourse::class,'index']);
+    // 新增
+    Route::any('video_course/add',[App\Http\Controllers\Admin\VideoCourse::class,'add']);
+    // 编辑
+    Route::any('video_course/edit',[App\Http\Controllers\Admin\VideoCourse::class,'edit']);
+    // 状态
+    Route::any('video_course/set_status',[App\Http\Controllers\Admin\VideoCourse::class,'set_status']);
+    // 状态
+    Route::any('video_course/get_sign_url',[App\Http\Controllers\Admin\VideoCourse::class,'get_sign_url']);
+
+    /* 课程习题 */
+    // 习题列表
+    Route::any('video_question/index',[App\Http\Controllers\Admin\VideoQuestion::class,'index']);
+    // 详情
+    Route::any('video_question/add',[App\Http\Controllers\Admin\VideoQuestion::class,'add']);
+    // 详情
+    Route::any('video_question/edit',[App\Http\Controllers\Admin\VideoQuestion::class,'edit']);
+    // 状态
+    Route::any('video_question/set_status',[App\Http\Controllers\Admin\VideoQuestion::class,'set_status']);
+
+
+    /* 课程习题 */
+    // 列表
+    Route::any('video_answer/index',[App\Http\Controllers\Admin\VideoAnswer::class,'index']);
+    // 详情
+    Route::any('video_answer/add',[App\Http\Controllers\Admin\VideoAnswer::class,'add']);
+    // 详情
+    Route::any('video_answer/edit',[App\Http\Controllers\Admin\VideoAnswer::class,'edit']);
+    // 状态
+    Route::any('video_answer/set_answer',[App\Http\Controllers\Admin\VideoAnswer::class,'set_answer']);
+
+    /* 课中习题 */
+    // 列表
+    Route::any('video_play_question/index',[App\Http\Controllers\Admin\VideoPlayQuestion::class,'index']);
+    // 详情
+    Route::any('video_play_question/add',[App\Http\Controllers\Admin\VideoPlayQuestion::class,'add']);
+    // 详情
+    Route::any('video_play_question/edit',[App\Http\Controllers\Admin\VideoPlayQuestion::class,'edit']);
+    // 状态
+    Route::any('video_play_question/set_answer',[App\Http\Controllers\Admin\VideoPlayQuestion::class,'set_answer']);
+
+    /* 课后习题 */
+    // 列表
+    Route::any('video_course_question/index',[App\Http\Controllers\Admin\VideoCourseQuestion::class,'index']);
+    // 详情
+    Route::any('video_course_question/add',[App\Http\Controllers\Admin\VideoCourseQuestion::class,'add']);
+    // 详情
+    Route::any('video_course_question/edit',[App\Http\Controllers\Admin\VideoCourseQuestion::class,'edit']);
+    // 状态
+    Route::any('video_course_question/set_answer',[App\Http\Controllers\Admin\VideoCourseQuestion::class,'set_answer']);
 });