index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. <template>
  2. <div class="app-container">
  3. <!-- 搜索区域 -->
  4. <div class="filter-container">
  5. <div class="filter-control">
  6. <span>视频标题:</span>
  7. <el-input v-model="listQuery.videoTitle" placeholder="视频标题" @keyup.enter.native="getList" />
  8. </div>
  9. <div class="filter-control">
  10. <span>审核状态:</span>
  11. <el-select v-model="listQuery.auditStatus" placeholder="审核状态" clearable @change="getList">
  12. <el-option label="全部" value="" />
  13. <el-option label="待审核" :value="2" />
  14. <el-option label="审核通过" :value="1" />
  15. <el-option label="审核未通过" :value="0" />
  16. </el-select>
  17. </div>
  18. <div class="filter-control">
  19. <span>上线状态:</span>
  20. <el-select v-model="listQuery.status" placeholder="上线状态" clearable @change="getList">
  21. <el-option label="全部" value="" />
  22. <el-option label="已上线" :value="1" />
  23. <el-option label="待上线" :value="2" />
  24. <el-option label="未上线" :value="0" />
  25. </el-select>
  26. </div>
  27. <div class="filter-control">
  28. <permission-button type="primary" @click="getList">查询</permission-button>
  29. <permission-button type="primary" @click="handleShowDialog('add')">添加视频</permission-button>
  30. </div>
  31. </div>
  32. <!-- 搜索区域END -->
  33. <!-- 表格区域 -->
  34. <el-table
  35. v-loading="listLoading"
  36. :data="list"
  37. style="width: 100%"
  38. border
  39. fit
  40. highlight-current-row
  41. cell-class-name="table-cell"
  42. header-row-class-name="tableHeader"
  43. >
  44. <el-table-column label="序号" :index="indexMethod" type="index" width="80" align="center" />
  45. <el-table-column label="视频标题" prop="videoTitle" align="center" />
  46. <el-table-column label="审核状态" width="120px" align="center">
  47. <template slot-scope="{ row }">
  48. <el-tag v-if="row.auditStatus === 2" size="small" type="warning">待审核</el-tag>
  49. <el-tag v-if="row.auditStatus === 1" size="small" type="success">审核通过</el-tag>
  50. <!-- 未通过原因展示 -->
  51. <template v-if="row.auditStatus === 0">
  52. <!-- <span class="status danger">审核未通过&nbsp;</span> -->
  53. <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="row.invalidReason">
  54. <el-tag slot="reference" size="small" type="danger" class="reason">
  55. <span>审核未通过</span>
  56. <span class="el-icon-question status danger " />
  57. </el-tag>
  58. </el-popover>
  59. <!-- 未通过原因展示END -->
  60. </template>
  61. </template>
  62. </el-table-column>
  63. <el-table-column label="上线状态" width="160px" align="center">
  64. <template slot-scope="{ row }">
  65. <!-- 只有审核通过了才能操作上下线 auditStatus :审核状态 -->
  66. <template v-if="row.auditStatus === 1">
  67. <template v-if="row.status === 0">
  68. <span style="margin-right:10px;" class="status danger">已下线</span>
  69. <permission-button type="primary" size="mini" @click="handleChangeStatus(row)">上线</permission-button>
  70. </template>
  71. <template v-else>
  72. <span style="margin-right:10px;" class="status success ">已上线</span>
  73. <permission-button type="info" size="mini" plain @click="handleChangeStatus(row)">下线</permission-button>
  74. </template>
  75. </template>
  76. <template v-else>
  77. <!-- <el-tag type="warning">待上线</el-tag> -->
  78. <span style="margin-right:10px;" class="status warning">待上线</span>
  79. </template>
  80. </template>
  81. </el-table-column>
  82. <el-table-column label="创建时间" width="160px" align="center">
  83. <template slot-scope="{ row }">
  84. {{ row.createTime | formatTime }}
  85. </template>
  86. </el-table-column>
  87. <el-table-column label="操作" width="280px" align="center">
  88. <template slot-scope="{ row }">
  89. <permission-button
  90. type="primary"
  91. size="mini"
  92. style="margin-right:5px"
  93. @click="handlePlayer(row)"
  94. >播放</permission-button>
  95. <permission-button
  96. type="primary"
  97. size="mini"
  98. style="margin-right:5px"
  99. @click="handleShowDialog('edit', row)"
  100. >编辑</permission-button>
  101. <permission-button
  102. type="danger"
  103. size="mini"
  104. style="margin-right:5px"
  105. @click="handleRemoveVideo(row)"
  106. >删除</permission-button>
  107. </template>
  108. </el-table-column>
  109. </el-table>
  110. <!-- 表格区域END -->
  111. <pagination
  112. v-show="total > 0"
  113. :total="total"
  114. :page.sync="listQuery.pageNum"
  115. :limit.sync="listQuery.pageSize"
  116. @pagination="getList(listQuery)"
  117. />
  118. <!-- 视频预览对话框 -->
  119. <el-dialog
  120. :title="dialogTitle"
  121. :visible.sync="dialogVisible"
  122. width="40%"
  123. :close-on-click-modal="false"
  124. :close-on-press-escape="false"
  125. @close="beforeDialogClose"
  126. @closed="dialogColosed"
  127. >
  128. <el-form ref="formRef" :model="dialogData" label-width="110px" :rules="dialogFormRules">
  129. <el-form-item label="标题:" prop="videoTitle">
  130. <el-input v-model="dialogData.videoTitle" maxlength="50" show-word-limit />
  131. </el-form-item>
  132. <el-form-item ref="formVideoUrlRef" label="上传视频:" prop="videoPreviewUrl">
  133. <div class="file-upload-box" style="height:40px;">
  134. <!-- 上传文件组件 -->
  135. <el-upload
  136. ref="uploadRef"
  137. accept=".mp4"
  138. :class="{ hidden: hasVideo }"
  139. :auto-upload="false"
  140. :headers="headers"
  141. :action="action"
  142. :on-success="handleUploadSuccess"
  143. :on-change="handleUploadChange"
  144. :on-remove="handleFileRemove"
  145. :before-upload="beforeUpload"
  146. :file-list="fileList"
  147. >
  148. <permission-button size="mini" type="primary" style="width:100%">上传视频</permission-button>
  149. </el-upload>
  150. <el-input v-model="dialogData.videoPreviewUrl" type="hidden" class="hiddenInput" />
  151. </div>
  152. <span style="color:#999;font-size:12px">视频大小不能超过<i style="color:red">*500MB*</i></span>
  153. </el-form-item>
  154. </el-form>
  155. <div slot="footer" class="dialog-footer">
  156. <permission-button @click="dialogVisible = false">取 消</permission-button>
  157. <permission-button type="primary" :loading="submitLoading" @click="handleSubmit">提 交</permission-button>
  158. </div>
  159. </el-dialog>
  160. <!-- 视频预览对话框END -->
  161. <!-- 视频预览对话框 -->
  162. <el-dialog title="视频预览" :visible.sync="dialogPreviewVisible" width="60%" @closed="dialogPreviewColosed">
  163. <video :src="videoPreviewUrl" controls="controls" width="100%">
  164. 您的浏览器不支持播放该视频
  165. </video>
  166. <div slot="footer" class="dialog-footer">
  167. <permission-button type="primary" @click="dialogPreviewVisible = false">关闭</permission-button>
  168. </div>
  169. </el-dialog>
  170. <!-- 视频预览对话框END -->
  171. </div>
  172. </template>
  173. <script>
  174. import PermissionButton from '@/views/components/PermissionButton'
  175. import Pagination from '@/components/Pagination' // secondary package based on el-pagination
  176. import { mapGetters } from 'vuex'
  177. import { getToken } from '@/utils/auth'
  178. import { changeVideoStatus, getVideoList, removeVideo, saveVideo } from '@/api/doc'
  179. export default {
  180. components: { Pagination, PermissionButton },
  181. data() {
  182. return {
  183. dialogPreviewVisible: false,
  184. listLoading: false, // 列表加载
  185. submitLoading: false, // 按钮加载
  186. dialogVisible: false, // 是否显示dialog
  187. dialogTitle: '添加视频', // dialog标题
  188. total: 0, // 数据条数
  189. hasVideo: false, // 是否上传了视频
  190. chooseNewVideo: false, // 是否重新选择了视频
  191. fileList: [], // 上传的视频列表
  192. previewUrl: '', // 上传视频成功的url
  193. downloadUrl: '',
  194. listQuery: {
  195. authUserId: '', // 供应商用户id
  196. listType: 1, // 列表类型:1视频列表,2视频审核列表
  197. videoTitle: '', // 供应商类型
  198. auditStatus: '', // 审核状态:0审核未通过,1审核通过,2待审核
  199. status: '', // 视频状态:0已下线,1已上线,2待上线
  200. pageNum: 1, // 页码
  201. pageSize: 10 // 分页大小
  202. },
  203. // dialog中表单的数据
  204. dialogData: {
  205. videoId: '',
  206. authUserId: '',
  207. videoName: '',
  208. videoTitle: '',
  209. // videoUrl: '',
  210. videoPreviewUrl: '',
  211. videoDownloadUrl: ''
  212. },
  213. // dialog中表单字段校验规则
  214. dialogFormRules: {
  215. videoTitle: [{ required: true, message: '标题不能为空', trigger: 'blur' }],
  216. videoPreviewUrl: [{ required: true, message: '链接不能为空', trigger: ['change', 'blur'] }]
  217. },
  218. list: [],
  219. videoPreviewUrl: ''
  220. }
  221. },
  222. computed: {
  223. ...mapGetters(['authUserId', 'userIdentity']),
  224. headers() {
  225. return {
  226. 'X-Token': getToken()
  227. }
  228. },
  229. action() {
  230. return `${process.env.VUE_APP_UPLOAD_API}/upload/file`
  231. }
  232. },
  233. created() {
  234. this.getList()
  235. },
  236. methods: {
  237. // 播放视频
  238. handlePlayer(row) {
  239. this.currentVideoUrl = row.videoPreviewUrl
  240. this.dialogPreviewVisible = true
  241. },
  242. dialogPreviewColosed() {
  243. this.currentVideoUrl = ''
  244. },
  245. // 获取列表数据
  246. getList() {
  247. this.listLoading = true
  248. this.listQuery.authUserId = this.authUserId
  249. getVideoList(this.listQuery)
  250. .then(res => {
  251. if (res.code !== 0) return
  252. this.list = res.data.list
  253. this.total = res.data.total
  254. console.log(res)
  255. })
  256. .finally(() => {
  257. this.listLoading = false
  258. })
  259. },
  260. // 提交
  261. handleSubmit() {
  262. if (!this.dialogData.videoPreviewUrl) {
  263. this.$refs.formRef.validateField('videoTitle')
  264. this.$refs.formRef.validateField('videoPreviewUrl')
  265. return
  266. }
  267. // 对标题字段进行规则校验
  268. this.$refs.formRef.validateField('videoTitle', error => {
  269. if (!error) {
  270. /**
  271. * 新增视频和修改视频
  272. * 表单有两种提交方式
  273. * 1、直接提交保存,不上传视频
  274. * 2、上传视频成功后再保存
  275. * 要针对这两种上传方式做响应的判断
  276. * 组合:1.新增时,填写视频地址,不上传视频 --直接提交
  277. * 2.新增时,填写视频地址,再选择上传视频 --上传的视频优先级高
  278. * 3.新增时,不填写视频地址,选择上传视频 --上传视频后再提交
  279. * 4.修改时,只修改视频标题,已经有了视频地址 --直接提交
  280. * 5.修改时,重新选择了视频 --上传视频后再提交
  281. */
  282. this.submitLoading = true
  283. this.dialogData.videoPreviewUrl && (!this.hasVideo || (this.hasVideo && !this.chooseNewVideo))
  284. ? this.save()
  285. : this.$refs.uploadRef.submit()
  286. }
  287. })
  288. },
  289. // 保存视频
  290. save() {
  291. this.$refs.formRef.validate(valide => {
  292. if (!valide) return
  293. this.dialogData.authUserId = this.authUserId
  294. // uploadVideoUrl不为空,就代表重新上传了视频,需要为表单中的videoUrl重新赋值,新增时该值也不为空
  295. if (this.previewUrl && this.downloadUrl) {
  296. this.dialogData.videoPreviewUrl = this.previewUrl
  297. this.dialogData.videoDownloadUrl = this.downloadUrl
  298. }
  299. saveVideo(this.dialogData)
  300. .then(res => {
  301. console.log(res)
  302. if (res.code !== 0) return
  303. this.dialogVisible = false
  304. this.getList()
  305. this.$message({
  306. type: 'success',
  307. message: res.data,
  308. duration: 500
  309. })
  310. })
  311. .finally(() => {
  312. this.submitLoading = false
  313. })
  314. })
  315. },
  316. // 设置表单初始值
  317. setDialogData(row) {
  318. if (!row) return
  319. console.log(row)
  320. for (const key in this.dialogData) {
  321. if (Object.hasOwnProperty.call(this.dialogData, key)) {
  322. this.dialogData[key] = row[key]
  323. }
  324. }
  325. if (this.dialogData.videoPreviewUrl) {
  326. this.fileList.push({ name: row.videoName, url: row.videoPreviewUrl })
  327. this.hasVideo = true
  328. }
  329. },
  330. // 删除视频
  331. async handleRemoveVideo(row) {
  332. const text = await this.$confirm('视频删除后不可恢复,确认删除该视频吗?', '提示', {
  333. confirmButtonText: '确定',
  334. cancelButtonText: '取消',
  335. type: 'warning'
  336. }).catch(() => {
  337. this.$message.info('已取消操作')
  338. })
  339. if (text !== 'confirm') return
  340. removeVideo({ videoId: row.videoId }).then(res => {
  341. if (res.code !== 0) return
  342. this.$message.success(res.data)
  343. this.getList()
  344. })
  345. },
  346. // 显示对话框
  347. handleShowDialog(type, row) {
  348. this.dialogTitle = type === 'add' ? '添加视频' : '修改视频'
  349. this.setDialogData(row)
  350. this.dialogVisible = true
  351. },
  352. // 对话框关闭的回调
  353. dialogColosed() {
  354. this.fileList = []
  355. this.hasVideo = false
  356. this.dialogData.videoId = ''
  357. this.dialogData.authUserId = ''
  358. this.dialogData.videoTitle = ''
  359. this.dialogData.videoPreviewUrl = ''
  360. this.dialogData.videoDownloadUrl = ''
  361. this.chooseNewVideo = false
  362. this.downloadUrl = ''
  363. this.previewUrl = ''
  364. this.submitLoading = false
  365. },
  366. // 对话框关闭前的回调
  367. beforeDialogClose() {
  368. this.$refs.formRef.resetFields()
  369. // 停止上传文件
  370. this.$refs.uploadRef.abort()
  371. },
  372. // 视频上传成功
  373. handleUploadSuccess(response, file, fileList) {
  374. console.log(response)
  375. // this.dialogData.videoUrl = response.fileUrl
  376. this.previewUrl = response.previewUrl
  377. this.downloadUrl = response.downloadUrl
  378. this.dialogData.videoName = response.fileName
  379. this.save()
  380. },
  381. // 选添加文件、上传成功和上传失败时都会被调用
  382. handleUploadChange(file, fileList) {
  383. console.log(file)
  384. this.chooseNewVideo = true
  385. this.hasVideo = fileList.length > 0
  386. this.dialogData.videoPreviewUrl = '-'
  387. this.dialogData.videoDownloadUrl = '-'
  388. },
  389. // 移除视频
  390. handleFileRemove(file, fileList) {
  391. this.hasVideo = fileList.length > 0
  392. this.dialogData.videoPreviewUrl = ''
  393. this.dialogData.videoDownloadUrl = ''
  394. this.submitLoading = false
  395. },
  396. // 上传视频前判断文件大小
  397. beforeUpload(file, fileList) {
  398. const flag = file.size <= 500 * 1024 * 1204
  399. if (!flag) {
  400. this.$message({
  401. message: '文件大小超过100MB,请重新选择!',
  402. duration: 1000,
  403. type: 'warning'
  404. })
  405. this.fileList = []
  406. }
  407. return flag
  408. },
  409. // 状态改变
  410. handleChangeStatus(item) {
  411. this.listLoading = true
  412. console.log(item)
  413. const params = {
  414. videoId: item.videoId,
  415. status: item.status === 1 ? 0 : 1
  416. }
  417. changeVideoStatus(params)
  418. .then(res => {
  419. // this.$message.success(res.data)
  420. this.$message({
  421. message: res.data,
  422. duration: 500,
  423. type: 'success'
  424. })
  425. this.getList()
  426. })
  427. .catch(err => {
  428. console.log(err)
  429. })
  430. .finally(() => {
  431. this.listLoading = false
  432. })
  433. },
  434. indexMethod(index) {
  435. return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
  436. }
  437. }
  438. }
  439. </script>
  440. <style lang="scss" scoped>
  441. .el-table .cell {
  442. overflow: visible;
  443. }
  444. .el-badge {
  445. margin: 0 6px;
  446. }
  447. .hasBottom {
  448. padding-bottom: 40px;
  449. }
  450. </style>