addVideo.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <template>
  2. <div class="video-list-container">
  3. <draggable v-model="videoListComputed" handle=".drag-handle" @end="onDragEnd">
  4. <div
  5. v-for="(item, index) in videoListComputed"
  6. :key="index"
  7. :class="['video-item', item.videoError ? 'error-video' : '']"
  8. v-loading="item.videoLoading"
  9. element-loading-text="上传中,请稍后..."
  10. element-loading-spinner="el-icon-loading"
  11. element-loading-background="rgba(0, 0, 0, 0.8)"
  12. element-loading-customClass="loadingTextClolr"
  13. >
  14. <el-row :gutter="20">
  15. <el-col :span="1">
  16. <i class="el-icon-rank drag-handle" style="cursor: move; line-height: 32px;"></i>
  17. </el-col>
  18. <el-col :span="6">
  19. <el-input v-model="item.videoName" size="small" placeholder="请输入视频名称"></el-input>
  20. </el-col>
  21. <el-col :span="4">
  22. <el-select v-model="item.videoLecturerId" placeholder="请选择教师" size="small" style="width: 100%">
  23. <el-option
  24. v-for="type in videoTypes"
  25. :key="type.id"
  26. :label="type.teacherName"
  27. :value="type.id"
  28. ></el-option>
  29. </el-select>
  30. </el-col>
  31. <el-col :span="8" style="display: flex; align-items: center;">
  32. <div>试看时间(分钟)</div>
  33. <el-input-number
  34. size="small"
  35. v-model="item.videoPreviewTime"
  36. :min="0"
  37. :max="600"
  38. placeholder="试看时间(秒)"
  39. :disabled="item.coursePreviousUrl"
  40. ></el-input-number>
  41. </el-col>
  42. <el-col :span="5">
  43. <el-button size="small" type="primary" @click="previewingVideoSrc(item)">预览视频</el-button>
  44. <el-button size="small" type="danger" @click="removeRow(index)">删除</el-button>
  45. </el-col>
  46. </el-row>
  47. </div>
  48. </draggable>
  49. <!-- 预览视频 -->
  50. <el-dialog title="预览视频" append-to-body :visible.sync="previewingVideoVisable" width="900px" top="6.5vh" :before-close="handleClose">
  51. <div class="previewingVideo">
  52. <!-- <video :src="previewVideoSrc" :poster="require('../../assets/image/yunketang.png')" controls></video> -->
  53. <video :src="previewVideoSrc" controls></video>
  54. </div>
  55. </el-dialog>
  56. </div>
  57. </template>
  58. <script>
  59. import draggable from 'vuedraggable'
  60. export default {
  61. name: 'VideoListEditor',
  62. components: {
  63. draggable
  64. },
  65. props: {
  66. value: {
  67. type: Array,
  68. required: true
  69. }
  70. },
  71. computed: {
  72. videoListComputed: {
  73. get() {
  74. return this.value
  75. },
  76. set(val) {
  77. this.$emit('input', val)
  78. }
  79. }
  80. },
  81. data() {
  82. return {
  83. videoTypes: [],
  84. previewVideoSrc: '',
  85. previewingVideoVisable: false
  86. }
  87. },
  88. methods: {
  89. previewingVideoSrc(row) {
  90. console.log(row)
  91. this.previewVideoSrc = row.videoUrl
  92. this.previewingVideoVisable = true
  93. },
  94. getAllTeachers() {
  95. this.http.post(`/course-teacher/list`, {}, res => {
  96. this.videoTypes = res.data || []
  97. })
  98. },
  99. removeRow(index) {
  100. const list = [...this.videoListComputed]
  101. const row = list[index]
  102. this.$confirm(`此操作将删除【${row.videoName}】视频, 是否继续?`, '删除视频', {
  103. confirmButtonText: '确定',
  104. cancelButtonText: '取消',
  105. type: 'warning'
  106. }).then(() => {
  107. const { id, videoUrl, coursePreviousUrl } = row
  108. this.http.post(`/course-sub-info/remove`, {
  109. id,
  110. courseUrl: videoUrl,
  111. coursePreviousUrl: coursePreviousUrl
  112. }, res => {
  113. if(res.code === 'ok') {
  114. this.$message({
  115. type: 'success',
  116. message: '删除成功!'
  117. });
  118. list.splice(index, 1)
  119. this.videoListComputed = list
  120. }
  121. })
  122. })
  123. },
  124. onDragEnd() {
  125. console.log('排序完成', this.videoListComputed)
  126. },
  127. handleClose(done) {
  128. // 清除 video 的 src,释放资源
  129. const videoEl = this.$refs.previewVideo
  130. if (videoEl) {
  131. videoEl.pause()
  132. videoEl.removeAttribute('src')
  133. videoEl.load()
  134. }
  135. this.previewingVideoVisable = false
  136. this.previewVideoSrc = ''
  137. done()
  138. }
  139. },
  140. mounted() {
  141. this.getAllTeachers()
  142. }
  143. }
  144. </script>
  145. <style scoped>
  146. .video-list-container {
  147. padding: 20px;
  148. }
  149. .video-item {
  150. margin-bottom: 15px;
  151. padding: 10px;
  152. background: #f5f7fa;
  153. border-radius: 4px;
  154. position: relative;
  155. }
  156. .error-video {
  157. background: #e6a23c;
  158. }
  159. </style>
  160. <style lang="scss">
  161. .video-list-container {
  162. .el-loading-spinner i {
  163. color: #fff !important;
  164. }
  165. .el-loading-text {
  166. color: #fff !important;
  167. }
  168. }
  169. .previewingVideo {
  170. display: flex;
  171. align-items: center;
  172. justify-content: center;
  173. width: 100%;
  174. height: 68vh;
  175. }
  176. .previewingVideo video {
  177. width: 100%;
  178. height: 100%;
  179. }
  180. </style>