فهرست منبع

Merge branch 'master' into HK

lsc 2 سال پیش
والد
کامیت
126a955ff4
36فایلهای تغییر یافته به همراه543 افزوده شده و 25 حذف شده
  1. 3 1
      dist/index.html
  2. 6 0
      dist/report.html
  3. 8 0
      dist/static/css/app.745921f5.css
  4. 0 0
      dist/static/css/chunk-29b1de2d.07cd7845.css
  5. 1 0
      dist/static/css/chunk-2bcf596a.a0bfd533.css
  6. 0 0
      dist/static/css/chunk-6637cd0c.a8cc665a.css
  7. 1 0
      dist/static/css/chunk-7d027967.7f5e6538.css
  8. 0 0
      dist/static/css/chunk-c8697d60.8bb9d470.css
  9. 0 0
      dist/static/css/chunk-libs.33961e53.css
  10. 0 0
      dist/static/css/chunk-vantUI.6c0b0952.css
  11. BIN
      dist/static/fonts/VideoJS.46ac6629.eot
  12. BIN
      dist/static/img/answerBgNew.8088cd05.png
  13. BIN
      dist/static/img/isVideo.1182258a.png
  14. 0 0
      dist/static/js/app.0dfcd25e.js
  15. 0 0
      dist/static/js/chunk-01979dd3.30fb23f3.js
  16. 0 0
      dist/static/js/chunk-29b1de2d.dc4f471c.js
  17. 1 0
      dist/static/js/chunk-2bcf596a.3b82301e.js
  18. 0 0
      dist/static/js/chunk-6637cd0c.d2f1b83f.js
  19. 1 0
      dist/static/js/chunk-7d027967.789f01af.js
  20. 0 0
      dist/static/js/chunk-c8697d60.633e0995.js
  21. 0 0
      dist/static/js/chunk-libs.12cf6b23.js
  22. 0 0
      dist/static/js/chunk-vantUI.e6f750cb.js
  23. 1 0
      package.json
  24. 10 0
      src/api/course.js
  25. 52 0
      src/assets/css/player.css
  26. BIN
      src/assets/images/works/answerBgNew.png
  27. BIN
      src/assets/images/works/cancel.png
  28. BIN
      src/assets/images/works/isVideo.png
  29. 5 0
      src/main.js
  30. 3 1
      src/plugins/vant.js
  31. 220 0
      src/views/course/components/answerPanel.vue
  32. 14 9
      src/views/course/components/commentBox.vue
  33. 3 3
      src/views/course/components/commentPanel.vue
  34. 57 7
      src/views/course/components/stepsBox.vue
  35. 152 1
      src/views/course/components/works.vue
  36. 5 3
      src/views/course/index.vue

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 3 - 1
dist/index.html


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 6 - 0
dist/report.html


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 8 - 0
dist/static/css/app.745921f5.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/static/css/chunk-29b1de2d.07cd7845.css


+ 1 - 0
dist/static/css/chunk-2bcf596a.a0bfd533.css

@@ -0,0 +1 @@
+h3[data-v-70f5745f]{margin:1.06667rem 0 0}ul[data-v-70f5745f]{list-style-type:none;padding:0}li[data-v-70f5745f]{display:inline-block;margin:0 .26667rem}a[data-v-70f5745f]{color:#42b983}.app-container[data-v-232f728e]{height:100vh}.app-container .layout-content[data-v-232f728e]{height:100%}.app-container .layout-footer[data-v-232f728e]{display:block;height:1.33333rem}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/static/css/chunk-6637cd0c.a8cc665a.css


+ 1 - 0
dist/static/css/chunk-7d027967.7f5e6538.css

@@ -0,0 +1 @@
+.loginBox[data-v-4dc8186e]{position:relative;width:100vw;height:100vh;overflow:hidden}.loginBox>iframe[data-v-4dc8186e]{width:100%;height:100%;border:0}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/static/css/chunk-c8697d60.8bb9d470.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/static/css/chunk-libs.33961e53.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/static/css/chunk-vantUI.6c0b0952.css


BIN
dist/static/fonts/VideoJS.46ac6629.eot


BIN
dist/static/img/answerBgNew.8088cd05.png


BIN
dist/static/img/isVideo.1182258a.png


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/static/js/app.0dfcd25e.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/static/js/chunk-01979dd3.30fb23f3.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/static/js/chunk-29b1de2d.dc4f471c.js


+ 1 - 0
dist/static/js/chunk-2bcf596a.3b82301e.js

@@ -0,0 +1 @@
+(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2bcf596a"],{"03af":function(e,t,a){},"2dee":function(e,t,a){},"64fe":function(e,t,a){"use strict";var n=a("2dee"),c=a.n(n);c.a},7431:function(e,t,a){"use strict";a.r(t);var n=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"app-container"},[a("div",{staticClass:"layout-content"},[e.$route.meta.keepAlive?a("keep-alive",[a("router-view")],1):a("router-view")],1),e._e()])},c=[],i=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",[a("van-tabbar",{attrs:{fixed:"",route:""},on:{change:e.handleChange},model:{value:e.active,callback:function(t){e.active=t},expression:"active"}},e._l(e.data,(function(t,n){return a("van-tabbar-item",{key:n,attrs:{to:t.to,icon:t.icon}},[e._v(" "+e._s(t.title)+" ")])})),1)],1)},o=[],r=(a("a9e3"),{name:"TabBar",props:{defaultActive:{type:Number,default:0},data:{type:Array,default:function(){return[]}}},data:function(){return{active:this.defaultActive}},methods:{handleChange:function(e){this.$emit("change",e)}}}),u=r,l=(a("cb41"),a("2877")),s=Object(l["a"])(u,i,o,!1,null,"70f5745f",null),f=s.exports,d={name:"AppLayout",data:function(){return{tabbars:[{title:"学习中心",to:{path:"/home"},icon:"home-o"}]}},components:{TabBar:f},methods:{handleChange:function(e){console.log("tab value:",e)}}},v=d,p=(a("64fe"),Object(l["a"])(v,n,c,!1,null,"232f728e",null));t["default"]=p.exports},cb41:function(e,t,a){"use strict";var n=a("03af"),c=a.n(n);c.a}}]);

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/static/js/chunk-6637cd0c.d2f1b83f.js


+ 1 - 0
dist/static/js/chunk-7d027967.789f01af.js

@@ -0,0 +1 @@
+(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-7d027967"],{"6605e":function(e,t,r){},"9ed6":function(e,t,r){"use strict";r.r(t);var n=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},i=[function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",{staticClass:"loginBox"},[r("iframe",{attrs:{src:"//edu.cocorobo.cn/course/login?type=2",frameborder:"0"}})])}],c=(r("96cf"),r("1da1")),o=r("5530"),u=r("2f62"),a={data:function(){return{redirect:void 0,timer:null}},watch:{$route:{handler:function(e){this.redirect=e.query&&e.query.redirect},immediate:!0}},methods:Object(o["a"])(Object(o["a"])({},Object(u["b"])({login:"user/login"})),{},{handleLogin:function(){this.$router.push({path:this.redirect||"/"})},getLogin:function(){var e=this;return Object(c["a"])(regeneratorRuntime.mark((function t(){var r;return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:return t.next=2,e.login();case 2:r=t.sent,r&&e.$router.push({path:e.redirect||"/"});case 4:case"end":return t.stop()}}),t)})))()}}),beforeDestroy:function(){clearInterval(this.timer),this.timer=null},mounted:function(){var e=this;this.getLogin(),this.timer=setInterval((function(){e.getLogin()}),2e3)}},s=a,l=(r("b792"),r("2877")),d=Object(l["a"])(s,n,i,!1,null,"4dc8186e",null);t["default"]=d.exports},b792:function(e,t,r){"use strict";var n=r("6605e"),i=r.n(n);i.a}}]);

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/static/js/chunk-c8697d60.633e0995.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/static/js/chunk-libs.12cf6b23.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/static/js/chunk-vantUI.e6f750cb.js


+ 1 - 0
package.json

@@ -33,6 +33,7 @@
     "vue-calendar-component": "^2.8.2",
     "vue-mobile-calendar": "^3.3.0",
     "vue-router": "^3.1.5",
+    "vue-video-player": "^5.0.2",
     "vue-wechat-title": "^2.0.7",
     "vuex": "^3.1.2",
     "weixin-js-sdk": "^1.6.0"

+ 10 - 0
src/api/course.js

@@ -98,3 +98,13 @@ export function addCourseWorksPl(data) {
     hideloading: false
   })
 }
+
+// 添加问答作业
+export function addCourseWorks(data) {
+  return request({
+    url: '/addCourseWorks',
+    method: 'post',
+    data,
+    hideloading: false
+  })
+}

+ 52 - 0
src/assets/css/player.css

@@ -0,0 +1,52 @@
+/*播放按钮设置成宽高一致,圆形,居中*/
+.vjs-custom-skin>.video-js .vjs-big-play-button {
+  background-color: rgba(0, 0, 0, 0.45);
+  font-size: 3.5em;
+  border-radius: 50%;
+  height: 2em !important;
+  line-height: 2em !important;
+  margin-top: -1em !important;
+  margin-left: -1em !important;
+  width: 2em !important;
+  outline: none;
+}
+
+.video-js .vjs-big-play-button .vjs-icon-placeholder:before {
+  position: absolute;
+  left: 0;
+  width: 100%;
+  height: 100%;
+}
+
+/*control-bar布局时flex,通过order调整剩余时间的位置到进度条右边*/
+.vjs-custom-skin>.video-js .vjs-control-bar .vjs-remaining-time {
+  order: 3 !important;
+}
+
+/*进度条背景轨道*/
+.video-js .vjs-slider {
+  border-radius: 1em;
+}
+
+/*进度条进度*/
+.vjs-custom-skin>.video-js .vjs-play-progress,
+.vjs-custom-skin>.video-js .vjs-volume-level {
+  border-radius: 1em;
+}
+
+/*鼠标进入播放器后,播放按钮颜色会变*/
+.video-js:hover .vjs-big-play-button,
+.vjs-custom-skin>.video-js .vjs-big-play-button:active,
+.vjs-custom-skin>.video-js .vjs-big-play-button:focus {
+  background-color: rgba(0, 0, 0, 0.4) !important;
+}
+
+/*control bar*/
+.video-js .vjs-control-bar {
+  background-color: rgba(0, 0, 0, 0.2) !important;
+}
+
+/*点击按钮时不显示蓝色边框*/
+.video-js .vjs-control-bar button {
+  outline: none;
+}

BIN
src/assets/images/works/answerBgNew.png


BIN
src/assets/images/works/cancel.png


BIN
src/assets/images/works/isVideo.png


+ 5 - 0
src/main.js

@@ -25,7 +25,12 @@ import 'lib-flexible/flexible.js'
 import './filters'
 // 全局注册微信js-sdk
 import WechatPlugin from '@/utils/wechatPlugin'
+import '@/assets/css/player.css'
+import VideoPlayer from 'vue-video-player'
+import 'video.js/dist/video-js.css' // videoJs的样式
+import 'vue-video-player/src/custom-theme.css' // vue-video-player的样式
 Vue.use(WechatPlugin)
+Vue.use(VideoPlayer)
 // 引入本地存储
 import { storage, sessionStorage } from '@/utils/storage'
 import hevueImgPreview from '@/components/hevue-img-preview'

+ 3 - 1
src/plugins/vant.js

@@ -12,7 +12,8 @@ import {
   Toast,
   Dialog,
   PullRefresh,
-  Empty
+  Empty,
+  Overlay
 } from 'vant'
 Vue.use(Button)
   .use(Cell)
@@ -26,3 +27,4 @@ Vue.use(Button)
   .use(Dialog)
   .use(PullRefresh)
   .use(Empty)
+  .use(Overlay)

+ 220 - 0
src/views/course/components/answerPanel.vue

@@ -0,0 +1,220 @@
+<template>
+  <div class="cp-container" v-if="panelVisible">
+    <div class="cp-title">
+      <span class="back" @click="back"></span>
+      <span class="title" v-if="isTeacher">问答作业</span>
+      <span class="title" v-else>问答作业-{{ sStudent.student }}</span>
+      <span class="btn" v-if="type == 1" @click="addPz(type)">提交</span>
+    </div>
+    <div class="cp-box">
+      <div class="cp-quest">提问:{{ answerQ }}</div>
+      <div class="cp-conent" v-if="type == 1">
+        <van-field v-model="message" rows="20" autosize type="textarea" placeholder="请输入..." />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { addCourseWorks, addCourseWorksTeacher } from '@/api/course'
+import { mapGetters } from 'vuex'
+
+export default {
+  props: {
+    panelVisible: {
+      type: Boolean
+    },
+    courseid: {
+      type: String,
+      default: ''
+    },
+    courseType: {
+      type: Number,
+      default: 0
+    },
+    taskCount: {
+      type: Number,
+      default: 0
+    },
+    toolindex: {
+      type: Number
+    },
+    isTeacher: {
+      type: Boolean
+    },
+    answerQ: {
+      type: String
+    },
+    sStudent: {
+      type: Object
+    }
+  },
+  components: {},
+  data() {
+    return {
+      type: 1,
+      message: '',
+      imgList: []
+    }
+  },
+  computed: {
+    ...mapGetters(['userinfo'])
+  },
+  methods: {
+    back() {
+      this.$emit('setPanelVisible', false)
+    },
+    setType(type) {
+      this.type = type
+    },
+    getImage(imgList) {
+      this.imgList = imgList
+      this.$forceUpdate()
+    },
+    addPz() {
+      const fun = [addCourseWorks, addCourseWorksTeacher]
+      const answerList = [
+        {
+          answerTitle: this.answerQ.replaceAll(/%/g, '%25'),
+          answer: this.message.replaceAll(/%/g, '%25')
+        }
+      ]
+      let params = []
+      if (this.isTeacher) {
+        params = [
+          {
+            uid: this.userinfo.userid,
+            cid: this.courseid,
+            stage: this.courseType,
+            task: this.taskCount,
+            tool: this.toolindex,
+            content: JSON.stringify(answerList),
+            type: 3
+          }
+        ]
+      } else {
+        params = [
+          {
+            uid: this.sStudent.userid,
+            cid: this.courseid,
+            stage: this.courseType,
+            task: this.taskCount,
+            tool: this.toolindex,
+            content: JSON.stringify(answerList),
+            type: 3,
+            ateacher: this.userinfo.userid
+          }
+        ]
+      }
+      fun[this.isTeacher ? 0 : 1](params)
+        .then(res => {
+          this.$toast({
+            message: '上传成功',
+            type: 'success'
+          })
+          this.$emit('setPanelVisible', false)
+        })
+        .catch(err => {
+          console.error(err)
+        })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.cp-container {
+  width: 100vw;
+  height: 100vh;
+  position: fixed;
+  top: 0;
+  left: 0;
+  background: #fff;
+  z-index: 2;
+  .cp-title {
+    height: 1.5rem;
+    width: 100%;
+    border-bottom: 1px solid #cecece;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    box-sizing: border-box;
+    position: relative;
+    .back {
+      width: 0.3rem;
+      height: 0.3rem;
+      border-top: 2px solid #000000;
+      border-left: 2px solid #000000;
+      position: absolute;
+      transform: rotate(-45deg) translateY(-50%);
+      top: 47%;
+      left: 0.8rem;
+      cursor: pointer;
+    }
+    .title {
+      font-size: 16px;
+    }
+    .btn {
+      font-size: 14px;
+      transform: translateY(-50%);
+      top: 50%;
+      right: 0.8rem;
+      position: absolute;
+      color: #2274ff;
+      cursor: pointer;
+    }
+  }
+  .cp-box {
+    width: 100%;
+    height: calc(100% - 1.5rem);
+    overflow: auto;
+    .type-nav {
+      height: 60px;
+      width: 100%;
+      display: flex;
+      align-items: center;
+      padding: 10px 0.3rem;
+      box-sizing: border-box;
+
+      .type-nav-box {
+        height: 100%;
+        opacity: 0.5;
+        transition: all 0.5s;
+
+        + .type-nav-box {
+          margin-left: 0.3rem;
+        }
+
+        &.active {
+          opacity: 1;
+        }
+        > img {
+          height: 100%;
+        }
+      }
+    }
+    .cp-quest {
+      width: 100%;
+      padding: 10px 15px;
+      font-size: 18px;
+      word-break: break-all;
+      box-sizing: border-box;
+    }
+    .cp-conent {
+      // margin-top: 10px;
+      height: auto;
+      overflow: auto;
+      font-size: 14px;
+      width: 100%;
+      /deep/ .van-field__control {
+        // height: auto !important;
+      }
+    }
+    .cp-audio {
+      height: calc(100% - 60px);
+      position: relative;
+      width: 100%;
+    }
+  }
+}
+</style>

+ 14 - 9
src/views/course/components/commentBox.vue

@@ -11,7 +11,12 @@
           <!--  -->
           <div class="pzDelete" @click="deletePz(pz.id)" v-if="pz.userid == userinfo.userid">删除</div>
         </div>
-        <div @click="checkImg(getImgList(pz.content))" class="pzContent cont navAndImg" v-html="pz.content" v-if="pz.type == '1'"></div>
+        <div
+          @click="checkImg(getImgList(pz.content))"
+          class="pzContent cont navAndImg"
+          v-html="pz.content"
+          v-if="pz.type == '1'"
+        ></div>
         <div class="pzContent" v-if="pz.type == '2'">
           <audio :src="pz.content" controls="controls" ref="audio">
             Your browser does not support the audio element.
@@ -56,8 +61,8 @@ export default {
       type: String,
       default: ''
     },
-    panelVisible:{
-      type:Boolean
+    panelVisible: {
+      type: Boolean
     },
     courseType: {
       type: Number,
@@ -73,16 +78,16 @@ export default {
   },
   data() {
     return {
-      pzList: [],
+      pzList: []
     }
   },
   computed: {
     ...mapGetters(['userinfo']),
     getImgList() {
-      return function (val) {
-        let srcList = [] // 定义一个数组用来接收后面的img地址
+      return function(val) {
+        const srcList = [] // 定义一个数组用来接收后面的img地址
 
-        val.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/g, function (match, capture) {
+        val.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/g, function(match, capture) {
           // 查找匹配的元素   match为整个img标签  capture为src中的内容
           srcList.push(capture)
         })
@@ -102,7 +107,7 @@ export default {
     }
   },
   methods: {
-    setPanelVisible(bool){
+    setPanelVisible(bool) {
       this.$emit('update:panelVisible', bool)
     },
     previewImg(url) {
@@ -265,7 +270,7 @@ export default {
     }
   }
 
-  /deep/.navAndImg img{
+  /deep/.navAndImg img {
     width: 100%;
   }
 

+ 3 - 3
src/views/course/components/commentPanel.vue

@@ -73,8 +73,8 @@ export default {
       this.type = type
     },
     getImage(imgList) {
-      this.imgList = imgList;
-      this.$forceUpdate();
+      this.imgList = imgList
+      this.$forceUpdate()
     },
     addPz(type, content) {
       var a = ''
@@ -82,7 +82,7 @@ export default {
         this.$toast({ message: '批注不能为空!', type: 'fail' })
         return
       }
-      if (type === 1 && this.message != '') {
+      if (type === 1 && this.message !== '') {
         var img = ''
         for (var i = 0; i < this.imgList.length; i++) {
           img += "<img src='" + this.imgList[i] + "' />"

+ 57 - 7
src/views/course/components/stepsBox.vue

@@ -19,7 +19,7 @@
         <div class="tool-name">{{ tools[step.tool[0]].name }}</div>
         <input
           type="file"
-          accept="image/*"
+          accept="video/mp4, video/quicktime, video/x-msvideo,image/*"
           style="display: none"
           multiple
           @change="beforeUpload($event, step.tool[0], stepI)"
@@ -27,12 +27,20 @@
         />
         <input
           type="file"
-          accept="image/*"
+          accept="video/mp4, video/quicktime, video/x-msvideo,image/*"
           style="display: none"
           @change="beforeUpload($event, step.tool[0], stepI)"
           v-else
         />
       </div>
+      <div
+        class="tool-box"
+        v-else-if="tools[step.tool[0]] && canWork2.indexOf(step.tool[0]) !== -1"
+        @click="addWork(step.tool[0], stepI, step)"
+      >
+        <div class="tool-img"><img :src="tools[step.tool[0]].img" /></div>
+        <div class="tool-name">{{ tools[step.tool[0]].name }}</div>
+      </div>
       <div class="tool-box" v-else-if="tools[step.tool[0]]">
         <div class="tool-img"><img :src="tools[step.tool[0]].img" /></div>
         <div class="tool-name">{{ tools[step.tool[0]].name }}</div>
@@ -64,13 +72,13 @@
             v-for="(student, noI) in noWorksS[stepI]"
             :key="stepI + '-' + noI"
             class="student"
-            @click="teacherSubmit(step.tool[0], student, $event)"
+            @click="teacherSubmit(step.tool[0], student, $event, step)"
           >
             {{ student.student }}
             <input
               v-if="canWork.indexOf(step.tool[0]) !== -1"
               type="file"
-              accept="image/*"
+              accept="video/mp4, video/quicktime, video/x-msvideo,image/*"
               style="display: none"
               @change="beforeUpload2($event, stepI)"
             />
@@ -96,6 +104,18 @@
         ></el-progress>
       </div>
     </div>
+    <answerPanel
+      v-if="answerPanelVisible"
+      @setPanelVisible="setPanelVisible"
+      :panelVisible="answerPanelVisible"
+      :courseid="courseid"
+      :courseType="courseType"
+      :taskCount="taskCount"
+      :toolindex="toolindex"
+      :isTeacher="isTeacher"
+      :answerQ="answerQ"
+      :sStudent="sStudent"
+    ></answerPanel>
   </div>
 </template>
 
@@ -113,6 +133,7 @@ import {
 import { tools } from '@/const/index'
 import Works from './works.vue'
 import { mapGetters } from 'vuex'
+import answerPanel from './answerPanel.vue'
 
 export default {
   props: {
@@ -146,10 +167,14 @@ export default {
     },
     isLoading: {
       type: Boolean
+    },
+    answerPanelVisible: {
+      type: Boolean
     }
   },
   components: {
-    Works
+    Works,
+    answerPanel
   },
   data() {
     return {
@@ -159,6 +184,7 @@ export default {
       noWorksS: [],
       isWorkTool: [16, 32, 57, 4, 45, 15, 1, 3, 6, 7, 26, 41, 47, 48, 52, 50, 40, 63], //, 49
       canWork: [16, 50], //, 49
+      canWork2: [15],
       fileType: 0,
       tools: tools,
       proVisible: false,
@@ -167,7 +193,10 @@ export default {
       isFinishSize: 0,
       isAllSize: 0,
       sTool: 0,
-      sStudent: {}
+      sStudent: {},
+      isTeacher: false,
+      toolindex: 0,
+      answerQ: ''
     }
   },
   watch: {
@@ -184,6 +213,11 @@ export default {
       if (newValue) {
         this.getWorks()
       }
+    },
+    answerPanelVisible(newValue) {
+      if (!newValue) {
+        this.getWorks()
+      }
     }
   },
   computed: {
@@ -199,6 +233,9 @@ export default {
     }
   },
   methods: {
+    setPanelVisible(bool) {
+      this.$emit('update:answerPanelVisible', bool)
+    },
     arrayToArray(arrayo, arrayt) {
       const array1 = arrayo
       const array2 = arrayt
@@ -1216,7 +1253,7 @@ export default {
           console.error(err)
         })
     },
-    teacherSubmit(tool, studnet, e) {
+    teacherSubmit(tool, studnet, e, content) {
       this.sStudent = studnet
       this.sTool = tool
       if (this.userinfo.type === 1) {
@@ -1224,8 +1261,21 @@ export default {
           var el = e.currentTarget
           el.getElementsByTagName('input')[0].click()
           e.target.value = ''
+        } else if (tool === 15) {
+          this.isTeacher = false
+          this.answerQ = content.answerQ
+          this.setPanelVisible(true)
         }
       }
+    },
+    addWork(tool, toolindex, content) {
+      this.sStudent = {}
+      this.toolindex = toolindex
+      if (tool === 15) {
+        this.isTeacher = true
+        this.answerQ = content.answerQ
+        this.setPanelVisible(true)
+      }
     }
   },
   mounted() {

+ 152 - 1
src/views/course/components/works.vue

@@ -3,11 +3,42 @@
     <!-- v-if="work.type == " -->
     <div class="w-work">
       <div class="work" v-if="work.type == 0" @click="imageView(work.works)"><img :src="work.works" alt="" /></div>
+      <div class="work" v-else-if="work.type == 3" @click="mediaPreview(work.works)">
+        <img src="@/assets/images/works/isVideo.png" alt="" />
+      </div>
+      <div class="work" v-else-if="work.type == 2" @click="checkAnswer(work.works)">
+        <img src="@/assets/images/works/answerBgNew.png" alt="" />
+        <div class="anwerBox">{{ JSON.parse(work.works)[0].answer }}</div>
+      </div>
       <div class="work" v-else><img src="@/assets/images/works/noImg.png" alt="" /></div>
     </div>
     <div class="s-name">
       <span>{{ work.sName }}</span>
     </div>
+    <van-overlay :show="show" @click="overlayShow" style="display: flex; align-items: center">
+      <div class="wrapper" @click.stop>
+        <video-player
+          class="video-player vjs-custom-skin"
+          ref="videoPlayer"
+          :playsinline="playsinline"
+          @canplay="onPlayerCanplay($event)"
+          :options="playerO"
+          @play="onPlayerPlay($event)"
+          style="width: 100%; height: 100%"
+        ></video-player>
+      </div>
+    </van-overlay>
+    <van-overlay :show="answerShow" @click="overlayAnswerShow" style="display: flex; align-items: center">
+      <div class="wrapper" @click.stop>
+        <div class="answerBox">
+          <div class="cancel" @click="overlayAnswerShow"></div>
+          <div class="box">
+            <div class="answerTitle">提问: {{ answerJson.answerTitle }}</div>
+            <div class="answerContent">{{ answerJson.answer }}</div>
+          </div>
+        </div>
+      </div>
+    </van-overlay>
   </div>
 </template>
 
@@ -20,12 +51,73 @@ export default {
     }
   },
   data() {
-    return {}
+    return {
+      playerOptions: {
+        playbackRates: [0.7, 1.0, 1.5, 2.0], // 播放速度
+        autoplay: false, // 如果true,浏览器准备好时开始回放。
+        muted: false, // 默认情况下将会消除任何音频。
+        loop: false, // 导致视频一结束就重新开始。
+        preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
+        language: 'zh-CN',
+        aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
+        fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
+        sources: [
+          {
+            type: 'video/mp4', // 这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目   || "video/ogg"|| "video/webm"
+            src: '' // url地址require("../../assets/media/aaa.mp4")
+          }
+        ],
+        // poster: require("../../assets/tu31.png"), //你的封面地址
+        // poster: dataRes.imgUrl, //你的封面地址
+        notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
+        controlBar: {
+          timeDivider: true, // 当前时间和持续时间的分隔符
+          durationDisplay: true, // 显示持续时间
+          remainingTimeDisplay: false, // 是否显示剩余时间功能
+          fullscreenToggle: true // 全屏按钮
+        }
+      },
+      show: false,
+      playerO: {},
+      answerShow: false,
+      answerJson: {}
+    }
+  },
+  computed: {
+    playsinline() {
+      const ua = navigator.userAgent.toLocaleLowerCase()
+      // x5内核
+      if (ua.match(/tencenttraveler/) != null || ua.match(/qqbrowse/) != null) {
+        return false
+      } else {
+        // ios端
+        return true
+      }
+    }
   },
   methods: {
     imageView(src) {
       // ImagePreview([src]);
       this.$hevueImgPreview({ url: src, clickMaskCLose: true })
+    },
+    mediaPreview(file) {
+      console.log(file)
+      this.show = true
+      this.playerOptions.sources[0].src = file
+      this.playerO = JSON.parse(JSON.stringify(this.playerOptions))
+    },
+    overlayShow() {
+      this.show = false
+      this.$refs.videoPlayer.player.pause()
+    },
+    overlayAnswerShow() {
+      this.answerShow = false
+    },
+    onPlayerCanplay() {},
+    onPlayerPlay() {},
+    checkAnswer(work) {
+      this.answerJson = JSON.parse(work)[0]
+      this.answerShow = true
     }
   }
 }
@@ -47,10 +139,27 @@ export default {
     .work {
       width: 100%;
       height: 100%;
+      position: relative;
+      display: flex;
+      align-items: center;
+      justify-content: center;
       > img {
         width: 100%;
         height: 100%;
         object-fit: cover;
+        position: absolute;
+      }
+      > .anwerBox {
+        text-align: center;
+        max-height: 95%;
+        width: 100%;
+        position: absolute;
+        color: #fff;
+        font-size: 14px;
+        word-break: break-all;
+        padding: 0px 13px;
+        box-sizing: border-box;
+        @include textoverflow(4);
       }
     }
   }
@@ -67,5 +176,47 @@ export default {
       @include textoverflow();
     }
   }
+
+  .wrapper {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 100%;
+    .answerBox {
+      background: #fff;
+      width: 95%;
+      margin: 0 auto;
+      border-radius: 5px;
+      height: 500px;
+      padding: 30px 15px;
+      box-sizing: border-box;
+      position: relative;
+      .cancel {
+        width: 20px;
+        height: 20px;
+        background-image: url(../../../assets/images/works/cancel.png);
+        background-size: 100% 100%;
+        position: absolute;
+        right: 15px;
+        top: 15px;
+      }
+      > .box {
+        margin-top: 10px;
+        height: calc(100% - 15px);
+        overflow: auto;
+        .answerTitle {
+          font-size: 23px;
+          font-weight: 700;
+          width: 100%;
+          word-break: break-all;
+        }
+        .answerContent {
+          word-break: break-all;
+          font-size: 18px;
+          margin-top: 15px;
+        }
+      }
+    }
+  }
 }
 </style>

+ 5 - 3
src/views/course/index.vue

@@ -12,7 +12,7 @@
       </template>
     </head-bar>
     <div class="course-box" ref="cBox">
-      <van-pull-refresh v-model="isLoading" @refresh="onRefresh" :disabled="panelVisible">
+      <van-pull-refresh v-model="isLoading" @refresh="onRefresh" :disabled="panelVisible || answerPanelVisible">
         <course-title :chapInfo="chapInfo" :courseType="courseType" :taskCount="taskCount"></course-title>
         <course-content-list v-if="false"></course-content-list>
         <div class="course-type-box">
@@ -30,6 +30,7 @@
           </div>
           <steps-box
             v-show="type == 1"
+            :answerPanelVisible.sync="answerPanelVisible"
             :courseDetail="courseDetail"
             :chapInfo="chapInfo"
             :courseType="courseType"
@@ -113,7 +114,8 @@ export default {
       tcid2: this.$route.query.tcid,
       navVisible: false,
       isLoading: false,
-      panelVisible: false
+      panelVisible: false,
+      answerPanelVisible: false
     }
   },
   methods: {
@@ -171,7 +173,7 @@ export default {
     },
     back() {
       // eslint-disable-next-line prettier/prettier
-      this.$router.push({ path: '/courseDetail', query: { courseid: this.courseid } })
+      this.$router.push({ path: '/courseDetail', query: { courseid: this.courseid }})
     },
     onRefresh() {
       this.getCourse()

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است