多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# 课程编辑器: 录播课增加上传重点片段视频 http://tower.wm3dao.com:8880/browse/XUETANG-21 (1)上传视频:支持编辑视频标题,上传视频文件。(都是必填) (2)修改视频:支持删除当前视频重新上传,支持修改标题。 ## 编辑课程页面 http://tcourse.wmxuetang.com/index.php?r=courseCenter/course/EidtContent&courseID=6 *D:\wamp\www\xue.test\xuetang\protected\modules\courseCenter\views\course\_edit_content.php* ``` on("click", ".js_addReview", function() { // 打开上传课程视频弹框 $(this).addClass("js_uploadOn"); tb_show(null, "<?php echo $this->createUrl('course/ReviewUploadBox');?>&width=602&height=286", null, null); } ``` *D:\wamp\www\xue.test\xuetang\protected\modules\courseCenter\controllers\CourseController.php* ``` UPDATE `wkxuetang`.`tbCourseReview` SET `id`='34', `fdCourseID`='6', `fdCourseCatalogID`='84', `fdName`='1.mp4', `fdUrl`='http://qn.cnweike.cn/content/coursecenter/0/0/0/6/84/8503418145313132544.mp4', `fdDuration`='49', `fdThumb`=NULL, `fdPersistentId`='zhongzhi6-z0.5cf4eb9238b9f31ea67eea7f', `fdCreate`='2019-06-03 17:09:31' WHERE (`id`='34'); ``` ## 接口 http://tcourse.wmxuetang.com/index.php?r=courseCenter/course/getResource&type=26&from=2&tagID=17&tagType=1&start=0&len=8 ``` { "data": { "list": [{ "type": 26, "id": "3585186", "title": "1", "schoolName": "太阳岛未名未来教室", "author": "庄不懂", "thumb": "http:\/\/tcourse.wmxuetang.com\/public\/ketang\/images\/weixin.png", "date": 1559555858000, "duration": 0, "score": 0, "appraisenum": 0, "playnum": 0, "downloadsNum": 0, "tag": { "assists": [{ "schoolTypeID": 2, "schoolType": "初中", "subjectID": 2, "subject": "数学", "versionID": 120, "version": "其他", "textbookID": 16, "textbook": "数学中考总复习", "tags": [{ "id": "16", "level": "1", "title": "数学中考总复习" }, { "id": "17", "level": "2", "title": "一、数与式" }] }], "knows": null, "editions": null }, "diff": "1", "weikeType": "讲授", "isFlash": 0 }, { "type": 26, "id": "3585185", "title": "1", "schoolName": "太阳岛未名未来教室", "author": "庄不懂", "thumb": "http:\/\/qn.cnweike.cn\/content\/0\/54\/180\/3585185\/542651.m.jpg", "date": 1559555719000, "duration": "49", "score": 0, "appraisenum": 0, "playnum": 0, "downloadsNum": 0, "tag": { "assists": [{ "schoolTypeID": 2, "schoolType": "初中", "subjectID": 2, "subject": "数学", "versionID": 120, "version": "其他", "textbookID": 16, "textbook": "数学中考总复习", "tags": [{ "id": "16", "level": "1", "title": "数学中考总复习" }, { "id": "17", "level": "2", "title": "一、数与式" }] }], "knows": null, "editions": null }, "diff": "1", "weikeType": "讲授", "isFlash": 0 }], "total": "2" }, "status": 0, "msg": "success", "ssk": null } ``` ### 上传任务视频: http://tcourse.wmxuetang.com/index.php?r=courseCenter/course/FileResourceSave ```json { "data": { "id": "3585186" }, "status": 0, "msg": "success", "ssk": null } ``` ```sql INSERT INTO `wkxuetang`.`tbCourseTaskRecord` (`id`, `fdCourseID`, `fdCourseCatalogID`, `fdCourseTaskID`, `fdType`, `fdValue`, `fdOrder`, `fdUserID`, `fdCreate`, `fdStatus`) VALUES ('84', '6', '84', '19', '26', '3585185', '1', '451299', '2019-06-03 17:55:22', '0'); ``` ## 上传课程视频弹框 course/ReviewUploadBox ```php public function actionReviewUploadBox() { $this->renderPartial("_review_upload_box"); } ``` *D:\wamp\www\xue.test\xuetang\protected\modules\courseCenter\views\course\_review_upload_box.php* ```php+HTML <div class="w hidden pt20 pb20"> <div class="w mt20 clr"> <div class="fl w105 pr5 tr fb mt5"><span class="red vm mr3">*</span>视频标题:</div> <div class="fl"> <input type="text" class="w400 inputText" id="weike-name"> </div> <div id="name-tip" class="fl ml10 f12 red mt5 none">名字不能为空</div> </div> <div class="w mt20 clr"> <div class="fl w105 pr5 tr fb mt4"><span class="red vm mr3">*</span>视频文件:</div> <div class="fl h100"> <?php echo $this->renderPartial('upload/upload_video_unit', array('idName' => "weike-name", 'maxSize' => 1024))?> </div> </div> <div class="w tc"><a href="javaScript:void(0)" class="button_3 w100" id="upsubmit">确 定</a></div> </div> ``` *点击确定按钮:* ```javascript .on("click", "#review-upload-box #upsubmit", function() { // 课程视频弹框确定 if ($(this).hasClass("button_off")) return false; $(this).addClass("button_off").text("正在上传"); var $groups = $("#review-upload-box .js_resHiddenGroup"); if ($('#review-upload-box #weike-name').val().length == 0) { $.showBoxs("请输入视频名称!"); $(this).removeClass("button_off").text("确定"); return false; } if ($("#review-upload-box .upload-complete").length <= 0) { $.showBoxs("请添加视频文件!"); $(this).removeClass("button_off").text("确定"); return false; } if ($("#review-upload-box .res-uploading").length > 0) { $.showBoxs("您还有未上传完的文件!"); $(this).removeClass("button_off").text("确定"); return false; } var $first = $($groups[0]), $ps = $(".js_uploadOn").parent(); var data = { courseID: $ps.data("cid"), courseCatalogID: $ps.data("catalog"), path: $first.find(".coverTempName").val(), name: $first.find(".coverOriginName").val(), } var $self = $(this); var iurl = "<?php echo $this->createUrl('course/reviewUpload');?>"; $.ajax({ url: iurl, type: "POST", data: {data: data}, success: function(result) { $self.removeClass("button_off"); if (result.status == 0) { $.showBox2("提交成功!"); var id = (result.data || {}).id || "", url = (result.data || {}).url || ""; $(".js_uploadOn").replaceWith('<div class="courseCenter-resourceView" style="margin-bottom:15px;">' + '<a href="javaScript:" class="delete js_reviewDel" title="删除" data-id="' + id + '"></a>' + '<a href="javaScript:" class="js_reviewPlay" data-url="' + url + '" title="' + data.name + '">' + '<div><img src="<?php echo Yii::app()->request->baseUrl; ?>/public/ketang/images/weixin.png" class="loading-img" width="154" height="114" data-src="<?php echo Yii::app()->request->baseUrl; ?>/public/ketang/images/weixin.png"></div>' + '<div class="txt">' + data.name + '</div>' + '</a>' + '</div>'); outlineObj[$(".js_scItem.on").data("id")] = outlineObj[$(".js_scItem.on").data("id")] || {}; outlineObj[$(".js_scItem.on").data("id")].courseReview = { duration: 0, id: id, name: data.name, thumb: "<?php echo Yii::app()->request->baseUrl; ?>/public/ketang/images/weixin.png", url: url, }; tb_remove(); } else { $.showBox2(result.msg); } }, error: function(error) { $self.removeClass("button_off"); $.showBox2("服务器出错,错误码为" + error.status); } }) }); ``` *D:\wamp\www\xue.test\xuetang\protected\modules\courseCenter\views\course\upload\upload_video_unit.php* ```php+HTML <div class="w460 fl"> <div class="w clr"> <a id="weike-upload-btn" href="javascript:" > <i class="glyphicon glyphicon-plus"></i> <span class="button_1">选择文件</span> </a> <span class="mt4 gray f13">(格式:mp4,flv,avi,rmvb,3gp,mpeg,swf 限制大小为:<?php echo ($maxSize ?: WK::WEIKE_MAXFILESIZE);?>MB)</span> </div> <div class="w" id="weike-upload-container"> <div class="w" id="res-container"></div> </div> <script type="text/javascript"> var idName = "<?php echo $idName?>"; function createProgressTep(file) { var fname = (file.name || ""); fname = fname.slice(0, fname.lastIndexOf(".")); return '<div id="' + file.id + '" class="w450 box-sizing p10 clr mt15 bg4 lh14 template-upload res-uploading">' + '<div class="fl mr20 word-ellipsis f14 js_resTitle" title="' + fname + '" style="max-width:230px;">' + fname + '</div>' + '<a href="javaScript:" class="fr gray ml30 js_resCancel" title="删除">删除</a>' + '<div class="fr w120 h14 box-sizing border1 br6 bgcolor-white hidden js_resProgress">' + '<div class="h bg5 js_resProgressBar" style="width:0%;"></div>' + '</div>' + '<div class="js_resHiddenGroup hidden fl">' + '<input type="hidden" class="coverOriginName" value=""/>' + '<input type="hidden" class="coverTempName" value=""/>' + '</div>' + '</div>'; } // 上传视频 var uploader = Qiniu.uploader({ runtimes: 'html5,flash,html4', //上传模式,依次退化 browse_button: 'weike-upload-btn', //上传选择的点选按钮,**必需** uptoken_url: '', //Ajax请求upToken的Url,**必需**(服务端提供) uptoken: '<?php echo $upToken; ?>', domain: 'http://wmzz.qiniudn.com/', //bucket 域名,下载资源时用到,**必需** container: 'weike-upload-container', //上传区域DOM ID,默认是browser_button的父元素, max_file_size: '<?php echo ($maxSize ?: WK::WEIKE_MAXFILESIZE);?>mb', //最大文件体积限制 flash_swf_url: '/public/qiniu/js/plupload/Moxie.swf', //引入flash,相对路径 max_retries: 3, //上传失败最大重试次数 dragdrop: false, //开启可拖曳上传 drop_element: 'weike-upload-container', //拖曳上传区域元素的ID,拖曳文件或文件夹后可触发上传 chunk_size: '4mb', //分块上传时,每片的体积 auto_start: true, //选择文件后自动上传,若关闭需要自己绑定事件触发上传 mime_types: 'mp4,flv,avi,rmvb,3gp,mpeg,swf', unique_names: true, filters : [{ title : "视频文件(.wmv.mp4.flv.avi.rmvb.3gp.mpeg.swf)", extensions : "wmv,mp4,flv,avi,rmvb,3gp,mpeg,swf" }], multi_selection: false, init: { 'FilesAdded': function(up, files) { plupload.each(files, function(file) { var progress = new FileProgress(file, 'res-container', createProgressTep, 1); progress.bindUploadCancel(up); if ($(".template-upload").length > 1) { progress.fileProgressWrapper.find(".js_resCancel").click(); $.showBox("最多只能上传1个文件"); } else if (idName) { ($('#' + idName).val().length == 0 || <?php echo $nameFlag;?> == 1) && $('#' + idName).val(file.name.substr(0, file.name.lastIndexOf('.'))); } }); }, 'BeforeUpload': function(up, file) { var progress = new FileProgress(file, 'res-container', createProgressTep, 1); var chunk_size = plupload.parseSize(this.getOption('chunk_size')); if (up.runtime === 'html5' && chunk_size) { progress.setChunkProgess(chunk_size); } }, 'UploadProgress': function(up, file) { var progress = new FileProgress(file, 'res-container', createProgressTep, 1); var chunk_size = plupload.parseSize(this.getOption('chunk_size')); progress.setProgress(file.percent + "%", up.total.bytesPerSec, chunk_size); }, 'UploadComplete': function() { }, 'FileUploaded': function(up, file, info) { var progress = new FileProgress(file, 'res-container', createProgressTep, 1); progress.setComplete(up, info); }, 'Error': function(up, err, errTip) { var progress = new FileProgress(err.file, 'res-container', createProgressTep, 1); progress.setError(); // err.errType = progress.fileProgressWrapper.data("type"); // errList.push(err); } } }); uploader.bind('FileUploaded', function(up, files) { window.console && console.log('hello man,a file is uploaded'); }); </script> </div> ``` *上传完成后的表单内容:* ```html <div class="w" id="weike-upload-container" style="position: relative;"> <div class="w" id="res-container"> <div id="o_1dclq20k13vbtbto2sirrcfv9" class="w450 box-sizing p10 clr mt15 bg4 lh14 template-upload upload-complete" style="opacity: 1;"> <div class="fl mr20 word-ellipsis f14 js_resTitle" title="1" style="max-width:230px;">1</div> <a href="javaScript:" class="fr gray ml30 js_resCancel" title="删除">删除</a> <div class="fr w120 js_resProgress green tc">7.30MB</div> <div class="js_resHiddenGroup hidden fl"> <input type="hidden" class="coverOriginName" value="1.mp4"> <input type="hidden" class="coverTempName" value="o_1dclq20k13vbtbto2sirrcfv9.mp4"> </div> </div> </div> <div id="html5_1dclphonj1ji66mk1ri0lihb63_container" class="moxie-shim moxie-shim-html5" style="position: absolute; top: 168px; left: 602px; width: 74px; height: 19px; overflow: hidden; z-index: 0;"><input id="html5_1dclphonj1ji66mk1ri0lihb63" type="file" style="font-size: 999px; opacity: 0; position: absolute; top: 0px; left: 0px; width: 100%; height: 100%;" accept="video/x-ms-wmv,video/mp4,video/x-flv,video/avi,.rmvb,video/3gpp,video/mpeg,application/x-shockwave-flash"></div> </div> ``` ## 点击确认>添加课程视频: http://tcourse.wmxuetang.com/index.php?r=courseCenter/course/reviewUpload ``` D:\wamp\www\xue.test\xuetang\protected\modules\courseCenter\controllers\CourseController.php:2264: POST提交参数: array (size=4) 'courseID' => string '53' (length=2) 'courseCatalogID' => string '246' (length=3) 'path' => string 'o_1dclr0h5k1cfg1eu019a4k4q11d89.mp4' (length=35) 'name' => string '2.mp4' (length=5) ``` ``` { "data": { "id": "34", "url": "http:\/\/qn.cnweike.cn\/content\/coursecenter\/0\/0\/0\/6\/84\/8657731716053471232.mp4", "name": "1.mp4" }, "status": 0, "msg": "success", "ssk": null } ``` ``` /** * 上传保存直播视频回顾 * @author tangjf 2018-12-29 */ public function actionReviewUpload() { $params = Yii::app()->request->getParam( "data" ); if ( !$params || !$params[ "courseID" ] || !$params[ "courseCatalogID" ] || !$params[ "path" ] || !$params[ "name" ] ) ResponseUtils::json( null, 21, ResponseUtils::$rmsg[ 21 ] ); $this->_isCourse( $params[ "courseID" ] ); $this->_isCourseTeacher( $params[ "courseID" ] ); $args = array( "courseID" => $params[ "courseID" ], "courseCatalogID" => $params[ "courseCatalogID" ], "name" => $params[ "name" ], "path" => $params[ "path" ], ); if ( $reviewID = CourseCenterService::factory()->saveCourseReview( $args ) ) { $review = xtCourseReview::model()->findByPk( $reviewID ); ResponseUtils::json( array( "data" => array( "id" => $reviewID, "url" => $review->fdUrl,"name"=>$review->fdName ) ) ); } else ResponseUtils::json( null, 1, ResponseUtils::$rmsg[ 21 ] ); } ``` D:\wamp\www\xue.test\xuetang\protected\modules\courseCenter\views\course\_edit_content.php ``` .on("click", ".js_addReview", function() { // 打开上传课程视频弹框 $(this).addClass("js_uploadOn"); tb_show(null, "<?php echo $this->createUrl('course/ReviewUploadBox');?>&width=602&height=286", null, null); }) ... var $self = $(this); var iurl = "<?php echo $this->createUrl('course/reviewUpload');?>"; $.ajax({ url: iurl, type: "POST", data: {data: data}, success: function(result) { $self.removeClass("button_off"); if (result.status == 0) { $.showBox2("提交成功!"); var id = (result.data || {}).id || "", url = (result.data || {}).url || ""; $(".js_uploadOn").replaceWith('<div class="courseCenter-resourceView" style="margin-bottom:15px;">' + '<a href="javaScript:" class="delete js_reviewDel" title="删除" data-id="' + id + '"></a>' + '<a href="javaScript:" class="js_reviewPlay" data-url="' + url + '" title="' + data.name + '">' + '<div><img src="<?php echo Yii::app()->request->baseUrl; ?>/public/ketang/images/weixin.png" class="loading-img" width="154" height="114" data-src="<?php echo Yii::app()->request->baseUrl; ?>/public/ketang/images/weixin.png"></div>' + '<div class="txt">' + data.name + '</div>' + '</a>' + '</div>'); outlineObj[$(".js_scItem.on").data("id")] = outlineObj[$(".js_scItem.on").data("id")] || {}; outlineObj[$(".js_scItem.on").data("id")].courseReview = { duration: 0, id: id, name: data.name, thumb: "<?php echo Yii::app()->request->baseUrl; ?>/public/ketang/images/weixin.png", url: url, }; tb_remove(); } else { $.showBox2(result.msg); } }, error: function(error) { $self.removeClass("button_off"); $.showBox2("服务器出错,错误码为" + error.status); } }) // 保存课程 $("#course-save").click(function() { var $this = $(this); if ($this.hasClass("button_off")) { return false; } var $confirm = $("#task-confirm"), beforeID = $(".js_scItem.on").data("id"); if ($confirm .length == 1 && !$confirm .hasClass("button_off")) { $this.addClass("button_off"); packingTaskData($confirm , function($el, rd) { $this.removeClass("button_off") isClosed = true; window.location.href = "<?php echo $this->createUrl('course/mycourse')?>"; }); } else { isClosed = true; window.location.href = "<?php echo $this->createUrl('course/mycourse')?>"; } }) ... function packingTaskData($el, callback) { var $item = $(".js_taskEditItem"), taskID = $item.data("id"); var data = { courseID: courseID, catalogID: $(".js_scItem.on").data("id"), taskID: taskID, name: $item.find(".js_taskTitle").val() || "", intro: editors[$item.find(".js_teditor").attr("id")].getValue(), order: $item.data("order") || 1, resourses: [] } $("#taskItemList .courseCenter-resourceView").each(function(i) { var type = $(this).data("type"), id = $(this).data("cid"); data.resourses.push({ resourseType: type, resourseID: id, order: i, recordID: $(this).data('record') }); }); if (data.name == "") { $el.removeClass("button_off"); $.showBox2("请输入任务名称"); return false; } if (data.resourses.length == 0) { $el.removeClass("button_off"); $.showBox2("请添加任务内容"); return false; } for (var i = 0, len = taskResourceDel.length; i < len; i++) { data.resourses.push({ recordID: taskResourceDel[i] }); } globals.saveTask = $.Deferred(); ajaxDeal({ url: "<?php echo $this->createUrl('course/SaveTask');?>", type: "POST", data: {data: data}, }, function(result) { if (callback) { callback($el, result.data); } globals.saveTask.resolve(true); }, function(error) { globals.saveTask.resolve(false); }) } ``` ## 删除视频 http://xue.test/index.php?r=courseCenter/course/delReviewVideo&courseID=53&courseCatalogID=246&reviewID=9 ``` 参数: r: courseCenter/course/delReviewVideo courseID: 53 courseCatalogID: 246 reviewID: 9 返回信息: {"status":0,"msg":"success","ssk":null} ``` ## 设置 章节/知识点信息 http://xue.test/index.php?r=courseCenter/course/saveCatalogInfo ``` data[courseID]: 53 data[catalogID]: 246 data[tagTypeID]: 1 data[tagID]: 45607 ``` http://xue.test/index.php?r=courseCenter/course/reviewUpload ``` data[courseID]: 53 data[courseCatalogID]: 246 data[path]: o_1dcg823qh8lk10m9om61aid1nkt9.mp4 data[name]: 1.mp4 { "data": { "id": "9", "url": "http:\/\/qn.cnweike.cn\/content\/coursecenter\/0\/0\/0\/53\/246\/282741952.mp4", "name": "1.mp4" }, "status": 0, "msg": "success", "ssk": null } public function actionReviewUpload() { $params = Yii::app()->request->getParam( "data" ); if ( !$params || !$params[ "courseID" ] || !$params[ "courseCatalogID" ] || !$params[ "path" ] || !$params[ "name" ] ) ResponseUtils::json( null, 21, ResponseUtils::$rmsg[ 21 ] ); $this->_isCourse( $params[ "courseID" ] ); $this->_isCourseTeacher( $params[ "courseID" ] ); $args = array( "courseID" => $params[ "courseID" ], "courseCatalogID" => $params[ "courseCatalogID" ], "name" => $params[ "name" ], "path" => $params[ "path" ], ); if ( $reviewID = CourseCenterService::factory()->saveCourseReview( $args ) ) { $review = xtCourseReview::model()->findByPk( $reviewID ); ResponseUtils::json( array( "data" => array( "id" => $reviewID, "url" => $review->fdUrl,"name"=>$review->fdName ) ) ); } else ResponseUtils::json( null, 1, ResponseUtils::$rmsg[ 21 ] ); } D:\wamp\www\xue.test\xuetang\protected\service\CourseCenterService.php public function saveCourseReview( $args ) { if ( !$args[ "courseID" ] || !$args[ "courseCatalogID" ] ) return false; $attributes = array(); $attributes[ "courseID" ] = $args[ "courseID" ]; $attributes[ "courseCatalogID" ] = $args[ "courseCatalogID" ]; $attributes[ "name" ] = $args[ "name" ]; $courseCenterHybrid = new CourseCenterHybrid(); if ( $reviewID = $courseCenterHybrid->saveCourseReview( $attributes ) ) { if ( $args[ "courseCatalogID" ] && $args[ "path" ]) { $this->_saveQinniu( $args[ "path" ], $args[ "courseID" ], $args[ "courseCatalogID" ] ); } } return $reviewID; } public function _saveQinniu( $fileName, $courseID, $courseCatalogID = null) { if ( !IS_QINIU_UPLOAD ) return false; $newDir = "content/coursecenter/" . ( ( $courseID >> 24 ) & 0xff ) . "/" . ( ( $courseID >> 16 ) & 0xff ) . "/" . ( ( $courseID >> 8 ) & 0xff ) . "/" . $courseID; if($courseCatalogID) $newDir.="/".$courseCatalogID; $newDir.="/" . abs( Uniq::id( 1, 1 ) ); // content/coursecenter/0/0/0/53/246/117539872 $fileExt = FileUtils::getExtension( $fileName ); // .mp4 $uniquePath = $newDir . '.' . $fileExt; // content/coursecenter/0/0/0/53/246/117539872.mp4 $qiniu = new QINIU(); $bucket = WK::QINIU_BUCKET; $bucket_tmp = WK::QINIU_TMP_BUCKET; Qiniu_setKeys( WK::QINIU_ACCESSKEY, WK::QINIU_SECRETKEY ); $client = new Qiniu_MacHttpClient( null ); $err = Qiniu_RS_Copy( $client, $bucket_tmp, $fileName, $bucket, $uniquePath ); if ( $err !== null ) { return false; } else { if($courseCatalogID){ if($xtCourseReview = xtCourseReview::model()->findByAttributes(array("fdCourseID"=>$courseID,"fdCourseCatalogID"=>$courseCatalogID))){ $xtCourseReview->fdUrl = WK::QINIU_HOST . $uniquePath; // http://qn.cnweike.cn/content/coursecenter/0/0/0/53/246/166370560.mp4 $avInfo = QiniuService::factory()->getAvInfo(WK::QINIU_HOST.$uniquePath); if($avInfo) $xtCourseReview->fdDuration = floor($avInfo->format->duration); $xtCourseReview->save(); } }else xtCourse::model()->updateByPk( $courseID, array( "fdVideo" => WK::QINIU_HOST . $uniquePath) ); if ( $fileExt != 'swf' ) $res = $this->_qiniuPfop( $uniquePath, $courseID,$courseCatalogID ); return $res ? true : false; } } ``` ## 重点片段实现过程 1、弹出窗口,上传视频到七牛云; 2、点击确认上传按钮,在页面上生成一条添加记录,写入`tbCourseReview`表; ```sql CREATE TABLE `tbCourseReview` ( `id` int(11) NOT NULL AUTO_INCREMENT, `fdCourseID` int(11) DEFAULT NULL COMMENT '课程ID', `fdCourseCatalogID` int(11) DEFAULT NULL COMMENT '课程章节id', `fdName` varchar(255) DEFAULT NULL COMMENT '视频名称', `fdUrl` varchar(255) DEFAULT NULL COMMENT '回放视频地址', `fdDuration` int(11) DEFAULT NULL COMMENT '回放视频时长,单位是秒', `fdThumb` varchar(255) DEFAULT NULL COMMENT '回放视频封面截图', `fdPersistentId` varchar(255) DEFAULT NULL COMMENT '七牛转码队列ID', `fdCreate` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `fdCourseID` (`fdCourseID`), KEY `fdCourseCatalogID` (`fdCourseCatalogID`) ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COMMENT='直播视频回放'; ``` 参考方法 \courseCenter\controllers\CourseController->actionReviewUpload 每次上传都新增1条记录,排序值取最大的排序值+1 3、新增删除重点片段的接口 4、新增排序接口 ​ 参数: ​ 方向:1往下 0 往上 ​ 当前重点片段视频 ID ​ 被调整的片段视频 ID ​