完成视频点播功能

This commit is contained in:
gooking 2018-05-23 21:05:17 +08:00
parent d5d64ed5e1
commit 46ef4de89b
11 changed files with 400 additions and 8 deletions

View File

@ -4,6 +4,9 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>api工厂独立后台</title>
<script src="./static/aliyun-upload-sdk-1.3.1/es6-promise.min.js"></script>
<script src="./static/aliyun-upload-sdk-1.3.1/aliyun-oss-sdk4.13.2.min.js"></script>
<script src="./static/aliyun-upload-sdk-1.3.1/aliyun-upload-sdk1.3.1.min.js"></script>
</head>
<body>
<div id="app"></div>

View File

@ -14,6 +14,7 @@
},
"dependencies": {
"axios": "0.17.1",
"clipboard": "2.0.1",
"element-ui": "2.3.9",
"js-cookie": "2.2.0",
"normalize.css": "8.0.0",

29
src/api/apiExtVod.js Normal file
View File

@ -0,0 +1,29 @@
import request from '@/utils/request'
export function fetchDataList(page, pageSize, data) {
return request({
url: '/user/apiExtVod/list',
method: 'post',
data: {
page,
pageSize,
...data
}
})
}
export function authAndAddress(fileName) {
return request({
url: '/user/apiExtVod/authAndAddress',
method: 'post',
data: { fileName }
})
}
export function delData(id) {
return request({
url: '/user/apiExtVod/del',
method: 'post',
data: { id }
})
}

1
src/icons/svg/video.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1527062330285" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1982" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M937.711762 274.326226a43.422282 43.422282 0 0 0-38.747704-6.29298l-209.452903 66.845749v-25.547618a43.350032 43.350032 0 0 0-43.350032-43.350032H108.656855a43.350032 43.350032 0 0 0-43.350032 43.350032v413.465377a43.350032 43.350032 0 0 0 43.350032 43.350032h537.504268a43.350032 43.350032 0 0 0 43.350032-43.350032v-25.540393l209.452903 66.838524a43.328357 43.328357 0 0 0 56.528442-41.298131V309.331377a43.350032 43.350032 0 0 0-17.780738-35.005151z" fill="" p-id="1983"></path></svg>

After

Width:  |  Height:  |  Size: 873 B

View File

@ -114,14 +114,15 @@ export const constantRouterMap = [
},
{
path: '/form',
name: '视频点播',
path: '/user/apiExtVod',
component: Layout,
children: [
{
path: 'index',
name: 'Form',
component: () => import('@/views/form/index'),
meta: { title: 'Form', icon: 'form' }
path: 'list',
name: '视频点播',
component: () => import('@/views/apiExtVod/list'),
meta: { title: '视频点播', icon: 'video' }
}
]
},

36
src/utils/clipboard.js Normal file
View File

@ -0,0 +1,36 @@
import Vue from 'vue'
import Clipboard from 'clipboard'
function clipboardSuccess() {
Vue.prototype.$message({
message: '复制成功',
type: 'success',
duration: 1500
})
}
function clipboardError() {
Vue.prototype.$message({
message: '复制失败',
type: 'error'
})
}
export default function handleClipboard(text, event) {
const clipboard = new Clipboard(event.target, {
text: () => text
})
clipboard.on('success', () => {
clipboardSuccess()
clipboard.off('error')
clipboard.off('success')
clipboard.destroy()
})
clipboard.on('error', () => {
clipboardError()
clipboard.off('error')
clipboard.off('success')
clipboard.destroy()
})
clipboard.onClick(event)
}

View File

@ -0,0 +1,299 @@
<template>
<div class="app-container">
<div class="filter-container">
<el-input clearable @keyup.enter.native="fetchData" style="width: 200px;" class="filter-item" placeholder="名称" v-model="searchData.titleLike">
</el-input>
<el-input clearable @keyup.enter.native="fetchData" style="width: 200px;" class="filter-item" placeholder="视频ID" v-model="searchData.videoId">
</el-input>
<el-date-picker type="date" placeholder="添加时间起" v-model="searchData.dateAddBegin" style="width: 200px;" class="filter-item"></el-date-picker>
<el-date-picker type="date" placeholder="添加时间止" v-model="searchData.dateAddEnd" style="width: 200px;" class="filter-item"></el-date-picker>
<el-date-picker type="date" placeholder="更新时间起" v-model="searchData.dateUploadBegin" style="width: 200px;" class="filter-item"></el-date-picker>
<el-date-picker type="date" placeholder="更新时间止" v-model="searchData.dateUploadEnd" style="width: 200px;" class="filter-item"></el-date-picker>
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="fetchData">搜索</el-button>
<el-button class="filter-item" style="margin-left: 10px;" @click="handleCreate" type="success" icon="el-icon-edit">上传视频</el-button>
</div>
<el-table :data="list" v-loading.body="listLoading" element-loading-text="Loading" border fit highlight-current-row empty-text="暂无数据" @selection-change="handleSelectionChange">
<el-table-column type="selection" align="center" width="55" row-key="id"></el-table-column>
<el-table-column prop="videoId" label="视频ID"></el-table-column>
<el-table-column prop="title" label="名称"></el-table-column>
<el-table-column prop="statusStr" label="状态"></el-table-column>
<el-table-column align="center" label="封面">
<template slot-scope="scope">
<el-tooltip placement="right">
<div v-if="scope.row.coverUrl" slot="content"><img :src="scope.row.coverUrl" style="max-width:600px;"></div>
<div v-else slot="content">-</div>
<i class="el-icon-picture"></i>
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="视频地址">
<template slot-scope="scope">
<div><el-button type="text" @click='handleCopy(scope.row.fdMp4,$event)'>复制流畅Mp4地址</el-button></div>
<div><el-button type="text" @click='handleCopy(scope.row.fdM3u8,$event)'>复制流畅M3u8</el-button></div>
<div><el-button type="text" @click='handleCopy(scope.row.ldMp4,$event)'>复制标清Mp4</el-button></div>
<div><el-button type="text" @click='handleCopy(scope.row.ldM3u8,$event)'>复制标清M3u8</el-button></div>
</template>
</el-table-column>
<el-table-column prop="dateAdd" label="上传时间"></el-table-column>
<el-table-column prop="dateUpload" label="更新时间"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="text" @click="delData(scope.row.id)" style="color:red">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-button style='margin-top:20px' type="danger" @click="delDataMore">批量删除</el-button>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="page"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="totalRow" style="margin-top:20px;">
</el-pagination>
<el-dialog :title="pushData.dialogTitle" :visible.sync="pushData.dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false" :before-close="reloadPage">
<el-form ref="addEditPopForm" label-position="left" label-width="100px">
<el-form-item label="选择视频">
<input type="file" name="file" id="files"/>
</el-form-item>
<el-form-item label="视频格式">
<div>支持 .3gp, .asf, .avi, .dat, .dv, .flv, .f4v, .gif, .m2t, .m3u8, .m4v, .mj2, .mjpeg, .mkv, .mov, .mp4, .mpe, .mpg, .mpeg, .mts, .ogg, .qt, .rm, .rmvb, .swf, .ts, .vob, .wmv, .webm.aac, .ac3, .acm, .amr, .ape, .caf, .flac, .m4a, .mp3, .ra, .wav, .wma</div>
</el-form-item>
<el-form-item label="上传进度">
<select multiple="multiple" id="textarea" style="position:relative; width:100%; height:250px; vertical-align:top; border:1px solid #cccccc;"></select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="reloadPage">取消</el-button>
<el-button type="primary" @click="handleCreateSave">开始上传</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { fetchDataList, delData, authAndAddress } from '@/api/apiExtVod'
import { Message, MessageBox } from 'element-ui'
import { mapGetters } from 'vuex'
import clip from '@/utils/clipboard'
var uploader,vm
export default {
computed: {
...mapGetters([
'centerUserBase'
])
},
data() {
return {
page:1,
pageSize:10,
totalRow:0,
searchData:{
titleLike:undefined,
videoId:undefined,
dateAddBegin:undefined,
dateAddEnd:undefined,
dateUploadBegin:undefined,
dateUploadEnd:undefined,
},
pushData: {
dialogTitle : undefined,
dialogFormVisible:false,
id:undefined,
goodsId:undefined,
number:undefined,
originalPrice:undefined,
minPrice:undefined,
helpPriceMin:undefined,
helpPriceMax:undefined,
status:undefined,
dateAddStr:undefined,
dateEndStr:undefined
},
multipleSelection: [],
list: null,
listLoading: true,
statisticsData:{}
}
},
created() {
this.pushDataTmp = Object.assign({}, this.pushData)
this.fetchData()
},
mounted() {
vm = this
},
methods: {
reloadPage(){
location.reload();
},
handleCopy(text, event) {
clip(text, event)
},
handleSizeChange(val) {
this.pageSize = val;
this.fetchData();
},
handleCurrentChange(val) {
this.page = val
this.fetchData()
},
handleSelectionChange(val) {
this.multipleSelection = val
},
fetchData() {
this.list = null
this.listLoading = true
fetchDataList(this.page, this.pageSize, this.searchData).then(response => {
if (response.code == 0) {
this.list = response.data.result
this.totalRow = response.data.totalRow
}
this.listLoading = false
})
},
handleCreate(){
this.pushData.dialogTitle = '上传视频文件'
this.pushData.dialogFormVisible = true
this.$nextTick(() => {
//this.$refs['addEditPopForm'].clearValidate()
uploader = new AliyunUpload.Vod({
//
'onUploadFailed': function (uploadInfo, code, message) {
vm.log("onUploadFailed: file:" + uploadInfo.file.name + ",code:" + code + ", message:" + message);
},
//
'onUploadSucceed': function (uploadInfo) {
vm.log("onUploadSucceed: " + uploadInfo.file.name + ", endpoint:" + uploadInfo.endpoint + ", bucket:" + uploadInfo.bucket + ", object:" + uploadInfo.object);
},
//
'onUploadProgress': function (uploadInfo, totalSize, loadedPercent) {
vm.log("onUploadProgress:file:" + uploadInfo.file.name + ", fileSize:" + totalSize + ", percent:" + (loadedPercent * 100.00).toFixed(2) + "%");
},
// STS
'onUploadTokenExpired': function (uploadInfo) {
vm.log("onUploadTokenExpired");
},
onUploadCanceled:function(uploadInfo)
{
vm.log("onUploadCanceled:file:" + uploadInfo.file.name);
},
//
'onUploadstarted': function (uploadInfo) {
authAndAddress(uploadInfo.file.name).then(res=>{
if (res.code != 0) {
Message({
message: res.msg,
type: 'error',
duration: 3 * 1000,
onClose: () => {
location.reload()
}
})
return;
}
uploader.setUploadAuthAndAddress(uploadInfo, res.data.uploadAuth, res.data.uploadAddress);
vm.log("onUploadStarted:" + uploadInfo.file.name + ", endpoint:" + uploadInfo.endpoint + ", bucket:" + uploadInfo.bucket + ", object:" + uploadInfo.object);
})
}
,
'onUploadEnd':function(uploadInfo){
vm.log("onUploadEnd: uploaded all the files");
}
});
document.getElementById("files")
.addEventListener('change', function (event) {
let userData = '{"Vod":{"UserData":{"IsShowWaterMark":"false","Priority":"7"}}}'
for(var i=0; i<event.target.files.length; i++) {
vm.log("add file: " + event.target.files[i].name);
uploader.addFile(event.target.files[i], null, null, null, userData);
}
});
})
},
log(value){
let textarea=document.getElementById("textarea");
if (!value) {
return;
}
let len = textarea.options.length;
if (len > 0 && textarea.options[len-1].value.substring(0, 40) == value.substring(0, 40)) {
//textarea.remove(len-1);
} else if (len > 25) {
textarea.remove(0);
}
let option=document.createElement("option");
option.value=value,option.innerHTML=value;
textarea.appendChild(option);
},
handleCreateSave(){
uploader.startUpload();
},
delData(id){
this.$confirm('删除无法恢复, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delData(id).then(res => {
Message({
message: '删除成功',
type: 'success',
duration: 1 * 1000,
onClose: () => {
this.fetchData()
}
})
})
}).catch(() => {});
},
delDataMore(){
if (!this.multipleSelection.length) {
Message({
message: '请先选择需要删除的数据',
type: 'error',
duration: 1 * 1000
})
return
}
this.$confirm('删除无法恢复, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.multipleSelection.forEach(obj => {
delData(obj.id).then(res => {
this.fetchData()
})
})
}).catch(() => {});
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss">
.filter-container {
padding-bottom: 10px;
.filter-item {
display: inline-block;
vertical-align: middle;
margin-bottom: 10px;
}
}
</style>

View File

@ -71,9 +71,9 @@ export default {
imgcode:''
},
loginRules: {
username: [{ required: true, trigger: 'blur' }],
password: [{ required: true, trigger: 'blur' }],
imgcode: [{ required: true, trigger: 'blur', validator:validateImgCode }],
username: [{ required: true, trigger: 'blur', message:'不能为空' }],
password: [{ required: true, trigger: 'blur', message:'不能为空' }],
imgcode: [{ required: true, trigger: 'blur', validator:validateImgCode, message:'不能为空' }],
},
loading: false,
pwdType: 'password'

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long