Commit 396049ae authored by lipengcheng 's avatar lipengcheng

conf

parents 9474cfc4 e6c32c9a
...@@ -43,6 +43,7 @@ module.exports = { ...@@ -43,6 +43,7 @@ module.exports = {
], ],
'comma-dangle': ['error', 'never'], 'comma-dangle': ['error', 'never'],
quotes: ['error', 'single'], quotes: ['error', 'single'],
semi: ['error', 'always'],
'vue/html-indent': [ 'vue/html-indent': [
'error', 'error',
2, 2,
......
...@@ -7,46 +7,47 @@ ...@@ -7,46 +7,47 @@
<right-panel></right-panel> <right-panel></right-panel>
</body> </body>
<modal-layer></modal-layer> <modal-layer></modal-layer>
<uploader></uploader>
</div> </div>
</template> </template>
<script> <script>
import CommonHeader from '@/components/header/index.vue' import CommonHeader from '@/components/header/index.vue';
import ModalLayer from '@/components/modal/modalLayer.vue'
export default { export default {
components: { components: {
CommonHeader, CommonHeader,
ModalLayer,
SideNav: () => import('@/components/sideNav/index.vue'), SideNav: () => import('@/components/sideNav/index.vue'),
RightPanel: () => import('@/components/rightPanel/index.vue') RightPanel: () => import('@/components/rightPanel/index.vue'),
ModalLayer: () => import('@/components/modal/modalLayer.vue'),
Uploader: () => import('@/components/misc/uploader.vue')
}, },
data() { data() {
return {} return {};
}, },
async created() { async created() {
let result = await this.$http.get('/webapi/home/banner?type=1&category=18') let result = await this.$http.get('/webapi/home/banner?type=1&category=18');
console.log('result:', result) console.log('result:', result);
} }
} };
</script> </script>
<style lang="scss"> <style lang="scss">
#app { #app {
font-family: Avenir, Helvetica, Arial, sans-serif; font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
text-align: center; text-align: center;
color: #2c3e50; color: #2c3e50;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100vh; height: 100vh;
position: relative; position: relative;
} }
.body-container { .body-container {
flex: 1; flex: 1;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
overflow: hidden; overflow: hidden;
} }
</style> </style>
...@@ -20,26 +20,26 @@ export default { ...@@ -20,26 +20,26 @@ export default {
tipPanel: () => import('@/components/header/tipPanel.vue') tipPanel: () => import('@/components/header/tipPanel.vue')
}, },
data() { data() {
return {} return {};
}, },
created() {}, created() {},
mounted() {}, mounted() {},
methods: { methods: {
showModal() { showModal() {
this.$modal.show('selectModal') this.$modal.show('selectModal');
} }
} }
} };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
/* @import url(); 引入css类 */ /* @import url(); 引入css类 */
.comp-commonheader { .comp-commonheader {
width: 100%; width: 100%;
height: 100px; height: 100px;
border: 1px solid pink; border: 1px solid pink;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
} }
</style> </style>
...@@ -7,11 +7,11 @@ ...@@ -7,11 +7,11 @@
<script> <script>
export default { export default {
data() { data() {
return {} return {};
}, },
created() {}, created() {},
mounted() {} mounted() {}
} };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
......
...@@ -5,10 +5,10 @@ ...@@ -5,10 +5,10 @@
<script> <script>
export default { export default {
data() { data() {
return {} return {};
}, },
methods: {} methods: {}
} };
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>
<template>
<div>
<input
id="video-input"
ref="videoInput"
type="file"
accept="video/mp4, video/NMP4"
@change="onVideoInputChange"
@click="onInputClick"
>
</div>
</template>
<script>
import { mapActions } from 'vuex';
export default {
data() {
return {
videoInput: {}
};
},
mounted() {
this.videoInput = this.$refs.videoInput;
},
methods: {
...mapActions({
upload: 'uploader/upload'
}),
onVideoInputChange() {
let file = this.videoInput.files[0];
console.log('turbo: onVideoInputChange -> file', file);
},
onInputClick() {
const vm = this;
window.addEventListener('focus', function h() {
vm.clearInputValue(vm.videoInput);
console.log('turbo: h -> this.videoInput', vm.videoInput);
window.removeEventListener('focus', h);
});
},
clearInputValue(el) {
if (el) {
el.value = '';
}
}
}
};
</script>
<style lang="scss" scoped></style>
...@@ -7,10 +7,10 @@ ...@@ -7,10 +7,10 @@
<script> <script>
export default { export default {
data() { data() {
return {} return {};
}, },
methods: {} methods: {}
} };
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>
...@@ -8,16 +8,16 @@ ...@@ -8,16 +8,16 @@
</template> </template>
<script> <script>
import CompleteContent from './completeContent' import CompleteContent from './completeContent';
export default { export default {
components: { components: {
CompleteContent CompleteContent
}, },
data() { data() {
return {} return {};
}, },
methods: {} methods: {}
} };
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>
...@@ -6,26 +6,26 @@ ...@@ -6,26 +6,26 @@
</template> </template>
<script> <script>
import CompleteModal from '@/components/modal/completeModal' import CompleteModal from '@/components/modal/completeModal';
import SelectModal from '@/components/modal/selectModal' import SelectModal from '@/components/modal/selectModal';
export default { export default {
components: { components: {
CompleteModal, CompleteModal,
SelectModal SelectModal
}, },
data() { data() {
return {} return {};
}, },
methods: {} methods: {}
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.modal-layer { .modal-layer {
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
width: 0; width: 0;
height: 0; height: 0;
} }
</style> </style>
...@@ -6,21 +6,42 @@ ...@@ -6,21 +6,42 @@
> >
close close
</div> </div>
选择视频 <div>选择视频</div>
<ul>
<li
v-for="(item, i) in items"
:key="i"
class="item"
@click="itemClick({ item, index: i })"
>
{{ item.text }}
</li>
</ul>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return {} return {
items: [{ text: '本地上传', type: 'upload' }, { text: '视频库' }, { text: '我的作品' }]
};
}, },
methods: { methods: {
close() { close() {
this.$modal.hide('selectModal') this.$modal.hide('selectModal');
},
triggerUpload() {
const el = document.getElementById('video-input');
el && el.click();
},
itemClick({ item = {} } = {}) {
if (item.type === 'upload') {
this.triggerUpload();
}
} }
} }
} };
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>
...@@ -8,16 +8,16 @@ ...@@ -8,16 +8,16 @@
</template> </template>
<script> <script>
import SelectContent from './selectContent' import SelectContent from './selectContent';
export default { export default {
components: { components: {
SelectContent SelectContent
}, },
data() { data() {
return {} return {};
}, },
methods: {} methods: {}
} };
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>
...@@ -7,18 +7,18 @@ ...@@ -7,18 +7,18 @@
<script> <script>
export default { export default {
data() { data() {
return {} return {};
}, },
created() {}, created() {},
mounted() {} mounted() {}
} };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
/* @import url(); 引入css类 */ /* @import url(); 引入css类 */
.comp-rightpanel { .comp-rightpanel {
width: 150px; width: 150px;
height: 100%; height: 100%;
border: 1px solid skyblue; border: 1px solid skyblue;
} }
</style> </style>
...@@ -7,11 +7,11 @@ ...@@ -7,11 +7,11 @@
<script> <script>
export default { export default {
data() { data() {
return {} return {};
}, },
created() {}, created() {},
mounted() {} mounted() {}
} };
</script> </script>
<style></style> <style></style>
...@@ -21,32 +21,32 @@ ...@@ -21,32 +21,32 @@
<script> <script>
export default { export default {
data() { data() {
return {} return {};
}, },
created() {}, created() {},
mounted() {} mounted() {}
} };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
/* @import url(); 引入css类 */ /* @import url(); 引入css类 */
.comp-sidenav { .comp-sidenav {
padding: 30px; padding: 30px;
// width: 100px; // width: 100px;
border: 1px solid skyblue; border: 1px solid skyblue;
height: 100%; height: 100%;
// display: flex; // display: flex;
a { a {
font-weight: bold; font-weight: bold;
color: #2c3e50; color: #2c3e50;
display: inline-block; display: inline-block;
width: 100%; width: 100%;
padding: 10px 0; padding: 10px 0;
&.router-link-exact-active { &.router-link-exact-active {
color: #42b983; color: #42b983;
}
} }
}
} }
</style> </style>
<template>
<div class="taskComplete"></div>
</template>
<script>
export default {
name: 'TaskComplete',
components: {},
props: {},
data() {
return {};
},
computed: {},
watch: {},
methods: {}
};
</script>
<style scoped lang="scss">
.taskComplete {
width: 100%;
height: 100%;
background-color: #fff;
border: 0px solid black;
margin: 0px;
}
</style>
<template>
<div class="taskEdit">
<ul>
<li
v-for="(item, index) in taskList"
:key="index"
>
<div class="info">
<div class="cove">
视频封面
</div>
<div>
<div>{{ item.name }}.mp4</div>
<div>时长:{{ item.duration }}</div>
</div>
</div>
<div class="operationPanel">
<div
v-show="item.state == 0"
class="wait"
>
<div>输出格式</div>
<div class="selectionFormat">
mp4
</div>
<div
class="delete"
@click="clearTask(item)"
>
删除
</div>
</div>
<div
v-show="item.state == 1"
class="active"
>
<div class="progress">
<div>转换中{{ item.progress }}%</div>
<div class="slide">
<div></div>
</div>
</div>
<div
class="stop"
@click="stopTask(item)"
>
取消
</div>
</div>
</div>
</li>
</ul>
<div class="editBar">
<div
class="addVideo"
@click="addVideo"
>
添加视频
</div>
<div
class="clearList"
@click="clearAllTasks"
>
清空列表
</div>
<div class="clearWatermark">
去除水印
</div>
</div>
<div
class="startAll"
@click="startAllTasks"
>
开始转换
</div>
</div>
</template>
<script>
import { start, stop, clear, checkStatus } from './webApi';
export default {
name: 'TaskEdit',
components: {},
props: {},
data() {
return {
taskList: []
};
},
computed: {},
watch: {},
created() {
for (let i = 1; i < 10; i++) {
this.taskList.push({
cover: '',
name: '视频片段' + i,
duration: '10:00',
state: 0,
progress: 60,
outputFormat: 'mp4'
});
}
},
methods: {
async startTask(item) {
let result = await start();
if (result) {
item.state = 1;
} else {
item.state = 2;
}
},
async stopTask(item) {
let result = await stop();
if (result) {
item.state = 0;
}
},
async clearTask(item) {
let result = await clear();
if (result) {
let index = this.taskList.indexOf(item);
if (index > -1) {
this.taskList.splice(index, 1);
}
}
},
async checkTaskStatus() {
await checkStatus();
},
addVideo() {
this.taskList.push({
cover: '',
name: '视频片段' + (this.taskList.length + 1),
duration: '10:00',
state: 0,
progress: 60,
outputFormat: 'mp4'
});
},
clearAllTasks() {
this.taskList = [];
},
startAllTasks() {
this.taskList.forEach((task) => {
task.state = 1;
});
}
}
};
</script>
<style scoped lang="scss">
.taskEdit {
width: 100%;
height: 100%;
background-color: #fff;
border: 0px solid black;
margin: 0px;
padding: 0 20px;
display: flex;
flex-direction: column;
align-items: center;
cursor: default;
overflow: hidden;
> ul {
width: 100%;
height: 100%;
border: 1px solid black;
flex-grow: 1;
overflow-y: auto;
> li {
padding: 5px 0;
height: 60px;
display: flex;
justify-content: space-between;
align-items: center;
}
> li:nth-of-type(odd) {
background-color: gainsboro;
}
.info {
display: flex;
align-items: center;
.cove {
width: 100px;
height: 40px;
background-color: #ccc;
line-height: 40px;
margin-right: 10px;
}
}
.operationPanel {
width: 300px;
height: 100%;
.wait {
height: 100%;
display: flex;
align-items: center;
.selectionFormat {
height: 30px;
width: 100px;
line-height: 30px;
border: 1px solid black;
margin-left: 20px;
}
.delete {
width: 60px;
height: 30px;
line-height: 30px;
background-color: black;
color: #fff;
margin-left: 20px;
}
}
.active {
height: 100%;
width: 300px;
display: flex;
align-items: center;
.progress {
}
.slide {
width: 200px;
height: 5px;
background: gray;
> div {
width: 120px;
height: 100%;
background-color: black;
}
}
.stop {
width: 60px;
height: 30px;
line-height: 30px;
background-color: black;
color: #fff;
margin-left: 20px;
}
}
}
}
.editBar {
position: relative;
height: 30px;
width: 100%;
margin: 20px 0;
.addVideo {
position: absolute;
left: 0;
height: 30px;
line-height: 30px;
border: 1px solid black;
}
.clearList {
position: absolute;
left: 100px;
height: 30px;
line-height: 30px;
border: 1px solid black;
}
.clearWatermark {
position: absolute;
right: 0;
height: 30px;
line-height: 30px;
border: 1px solid black;
}
}
.startAll {
height: 30px;
width: 100px;
background-color: black;
color: #fff;
line-height: 30px;
}
}
</style>
async function start() {
let result = await new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, 1000);
});
return result;
}
async function stop() {
let result = await new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, 500);
});
return result;
}
async function clear() {
let result = await new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, 500);
});
return result;
}
async function checkStatus(fakeValue) {
let result = await new Promise((resolve) => {
setTimeout(() => {
resolve(fakeValue++);
}, 500);
});
return result;
}
export { start, stop, clear, checkStatus };
...@@ -10,10 +10,10 @@ ...@@ -10,10 +10,10 @@
export default { export default {
methods: { methods: {
changeVideo() { changeVideo() {
this.$emit('changeVideo') this.$emit('changeVideo');
} }
} }
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.video-change { .video-change {
......
...@@ -21,27 +21,27 @@ ...@@ -21,27 +21,27 @@
export default { export default {
filters: { filters: {
formatTime(duration) { formatTime(duration) {
if (duration <= 0) return '00:00' if (duration <= 0) return '00:00';
if (!duration) return '--:--' if (!duration) return '--:--';
let min = ~~(duration / 60) let min = ~~(duration / 60);
min = (min + '').length === 1 ? '0' + min : min min = (min + '').length === 1 ? '0' + min : min;
let sec = Math.floor(duration % 60) let sec = Math.floor(duration % 60);
sec = (sec + '').length === 1 ? '0' + sec : sec sec = (sec + '').length === 1 ? '0' + sec : sec;
min = min || '00' min = min || '00';
sec = sec || '00' sec = sec || '00';
return min + ':' + sec return min + ':' + sec;
} }
}, },
props: ['duration', 'nowTime'], // eslint-disable-line props: ['duration', 'nowTime'], // eslint-disable-line
data() { data() {
return {} return {};
}, },
methods: { methods: {
play() { play() {
this.$emit('play') this.$emit('play');
} }
} }
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.video-control { .video-control {
......
...@@ -13,54 +13,54 @@ export default { ...@@ -13,54 +13,54 @@ export default {
state: 'pluse', state: 'pluse',
times: 0, times: 0,
canPlay: false canPlay: false
} };
}, },
mounted() { mounted() {
this.$bus.on('videoPlayer.play', (data) => { this.$bus.on('videoPlayer.play', (data) => {
if (data.time !== undefined) { if (data.time !== undefined) {
this.currentTime(data.time) this.currentTime(data.time);
} }
if (data.play) { if (data.play) {
this.play() this.play();
} else { } else {
this.pause() this.pause();
} }
}) });
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.videoDom.addEventListener('canplay', this.canPlayFunc) this.$refs.videoDom.addEventListener('canplay', this.canPlayFunc);
this.$refs.videoDom.addEventListener('ended', () => { this.$refs.videoDom.addEventListener('ended', () => {
this.$emit('ended') this.$emit('ended');
}) });
this.$refs.videoDom.addEventListener('timeupdate', () => { this.$refs.videoDom.addEventListener('timeupdate', () => {
this.$emit('timeupdate', this.$refs.videoDom.currentTime) this.$emit('timeupdate', this.$refs.videoDom.currentTime);
}) });
}) });
}, },
beforeDestroy() { beforeDestroy() {
this.$refs.videoDom.removeEventListener('canplay') this.$refs.videoDom.removeEventListener('canplay');
this.$refs.videoDom.removeEventListener('ended') this.$refs.videoDom.removeEventListener('ended');
this.$refs.videoDom.removeEventListener('timeupdate') this.$refs.videoDom.removeEventListener('timeupdate');
}, },
methods: { methods: {
canPlayFunc() { canPlayFunc() {
this.canPlay = true this.canPlay = true;
let from = this.$parent.$options.name || 'videoPlayer' let from = this.$parent.$options.name || 'videoPlayer';
this.$bus.emit(`${from}.canPlay`, this.$refs.videoDom.duration) this.$bus.emit(`${from}.canPlay`, this.$refs.videoDom.duration);
}, },
play() { play() {
if (!this.canPlay) return if (!this.canPlay) return;
this.$refs.videoDom.play() this.$refs.videoDom.play();
}, },
pause() { pause() {
if (!this.canPlay) return if (!this.canPlay) return;
this.$refs.videoDom.pause() this.$refs.videoDom.pause();
}, },
currentTime(time) { currentTime(time) {
if (!this.canPlay) return if (!this.canPlay) return;
this.$refs.videoDom.currentTime = time this.$refs.videoDom.currentTime = time;
} }
} }
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.video-player { .video-player {
......
<template>
<div class="video-timeline">
<div
ref="sliderWidth"
v-drag
class="time-slider"
>
<div class="time-slider-rail"></div>
<div
class="time-slider-track"
:style="{ width: ((info.val - info.min) / info.max) * 100 + '%' }"
></div>
<div
data-action="handle"
class="time-slider-handle"
:style="{ left: ((info.val - info.min) / info.max) * 100 + '%' }"
></div>
</div>
</div>
</template>
<script>
export default {
name: 'VideoTimeline',
directives: {
drag(el, binding, vnode) {
let _this = vnode.context,
mousemove = null,
mouseup = null,
dataAction = '';
mousemove = (e) => {
_this.dragMove && _this.dragMove(e.pageX, dataAction, e);
};
mouseup = (e) => {
document.removeEventListener('mousemove', mousemove);
document.removeEventListener('mouseup', mouseup);
_this.dragUp && _this.dragUp(e.pageX, dataAction, e);
};
el.onmousedown = (e) => {
dataAction = e.target.dataset.action;
if (e.which === 3 || e.which === 2) {
e.stopPropagation();
return;
}
document.addEventListener('mousemove', mousemove);
document.addEventListener('mouseup', mouseup);
_this.dragDown && _this.dragDown(e.pageX, dataAction, e);
};
}
},
props: {
info: {
type: Object,
required: true,
default: function() {
return { step: 0.1, min: 0, max: 10, val: 0, cut: [0, 10] };
}
}
},
data() {
return {
width: 100
};
},
methods: {
dragDown(dis, action) {
if (!action) return;
this.width = this.$refs.sliderWidth.clientWidth;
this.action = action;
this.dragHand = true;
this.mpos = {
x: dis,
v: this.info.val
};
this.$emit('changeData', { val: this.mpos.v, action: action, type: 'start' });
},
dragMove(pos) {
if (!this.action) return;
let val = 0;
console.log(pos, '<_-------------');
// let pre = Math.round(((pos.x - this.mpos.x) / 120 * this.item.len + this.mpos.v) / this.item.step) / (1 / this.item.step);
// this.item.val = pre > this.item.max ? this.item.max : pre < this.item.min ? this.item.min : pre;
this.$emit('changeData', { val: val, action: this.action, type: 'change' });
},
dragUp() {
if (!this.action) return;
let val = 0;
this.mpos = null;
this.dragHand = false;
this.action = '';
this.$emit('changeData', { val: val, action: this.action, type: 'end' });
}
}
};
</script>
<style lang="scss" scoped>
.video-timeline {
width: 100%;
height: 50px;
background-color: beige;
}
.time-slider {
position: relative;
height: 15px;
padding: 5px 0;
width: 100%;
margin-right: 1px;
-ms-touch-action: none;
touch-action: none;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
.time-slider-rail {
position: absolute;
width: 100%;
background-color: #d9ddea;
height: 4px;
border-radius: 3px;
}
.time-slider-track {
position: absolute;
background-color: #737596;
border-radius: 3px;
height: 4px;
left: 0%;
width: 69.1515%;
}
.time-slider-handle {
position: absolute;
margin-left: -6px;
margin-top: -4px;
left: 69.1515%;
width: 12px;
height: 12px;
background-color: #737596;
cursor: -webkit-grab;
cursor: grab;
border-radius: 50%;
-ms-touch-action: pan-x;
touch-action: pan-x;
}
}
</style>
import Vue from 'vue' import Vue from 'vue';
import App from './App.vue' import App from './App.vue';
import router from './router' import router from './router';
import store from './store' import store from './store';
import './registerServiceWorker' import './registerServiceWorker';
import './assets/style/index.scss' import './assets/style/index.scss';
import axios from 'axios' import axios from 'axios';
import VueBus from 'vue-bus' import VueBus from 'vue-bus';
import VModal from 'vue-js-modal' import VModal from 'vue-js-modal';
Vue.use(VueBus) Vue.use(VueBus);
Vue.use(VModal) Vue.use(VModal);
import baseURL from '../config/baseUrl.js' import baseURL from '../config/baseUrl.js';
console.log('baseURL:', baseURL) console.log('baseURL:', baseURL);
Vue.config.productionTip = false Vue.config.productionTip = false;
Vue.prototype.$http = axios Vue.prototype.$http = axios;
new Vue({ new Vue({
router, router,
store, store,
render: (h) => h(App) render: (h) => h(App)
}).$mount('#app') }).$mount('#app');
/* eslint-disable no-console */ /* eslint-disable no-console */
import { register } from 'register-service-worker' import { register } from 'register-service-worker';
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, { register(`${process.env.BASE_URL}service-worker.js`, {
ready() { ready() {
console.log('App is being served from cache by a service worker.\n' + 'For more details, visit https://goo.gl/AFskqB') console.log('App is being served from cache by a service worker.\n' + 'For more details, visit https://goo.gl/AFskqB');
}, },
registered() { registered() {
console.log('Service worker has been registered.') console.log('Service worker has been registered.');
}, },
cached() { cached() {
console.log('Content has been cached for offline use.') console.log('Content has been cached for offline use.');
}, },
updatefound() { updatefound() {
console.log('New content is downloading.') console.log('New content is downloading.');
}, },
updated() { updated() {
console.log('New content is available; please refresh.') console.log('New content is available; please refresh.');
}, },
offline() { offline() {
console.log('No internet connection found. App is running in offline mode.') console.log('No internet connection found. App is running in offline mode.');
}, },
error(error) { error(error) {
console.error('Error during service worker registration:', error) console.error('Error during service worker registration:', error);
} }
}) });
} }
import Vue from 'vue' import Vue from 'vue';
import VueRouter from 'vue-router' import VueRouter from 'vue-router';
import Bao3 from '../views/bao3.vue' import Bao3 from '../views/bao3.vue';
import Screenshot from '../views/screenshot.vue' import Screenshot from '../views/screenshot.vue';
import screenshotPanel from '../components/rightPanel/screenshotPanel.vue' import screenshotPanel from '../components/rightPanel/screenshotPanel.vue';
Vue.use(VueRouter) Vue.use(VueRouter);
const routes = [ const routes = [
{ {
...@@ -37,12 +37,12 @@ const routes = [ ...@@ -37,12 +37,12 @@ const routes = [
panel: screenshotPanel panel: screenshotPanel
} }
} }
] ];
const router = new VueRouter({ const router = new VueRouter({
mode: 'history', mode: 'history',
base: process.env.BASE_URL, base: process.env.BASE_URL,
routes routes
}) });
export default router export default router;
...@@ -3,19 +3,19 @@ ...@@ -3,19 +3,19 @@
const state = { const state = {
_test: 1 _test: 1
} };
const getters = { const getters = {
test: (state) => state._test test: (state) => state._test
} };
const mutations = {} const mutations = {};
const actions = {} const actions = {};
export default { export default {
state, state,
getters, getters,
mutations, mutations,
actions actions
} };
import Vue from 'vue' import Vue from 'vue';
import Vuex from 'vuex' import Vuex from 'vuex';
import global from './global' import global from './global';
import moduleA from './modules/moduleA' import moduleA from './modules/moduleA';
import uploader from './modules/uploader';
Vue.use(Vuex) Vue.use(Vuex);
export default new Vuex.Store({ export default new Vuex.Store({
...global, ...global,
modules: { modules: {
moduleA moduleA,
uploader
} }
}) });
...@@ -3,15 +3,15 @@ ...@@ -3,15 +3,15 @@
const state = { const state = {
_moduleState: 'moduleState' _moduleState: 'moduleState'
} };
const getters = { const getters = {
moduleState: (state) => state._moduleState moduleState: (state) => state._moduleState
} };
const mutations = {} const mutations = {};
const actions = {} const actions = {};
export default { export default {
namespaced: true, namespaced: true,
...@@ -19,4 +19,4 @@ export default { ...@@ -19,4 +19,4 @@ export default {
getters, getters,
mutations, mutations,
actions actions
} };
// 模块化vuex数据
// getter调用示例:this.$store.getters['moduleA/moduleState']
const state = {
video: {}
};
const getters = {
video: (state) => state.video
};
const mutations = {};
const actions = {
async upload(store, payload) {
console.log('turbo: upload -> store, payload', store, payload);
},
async storeMaterial() {}
};
export default {
namespaced: true,
state,
getters,
mutations,
actions
};
...@@ -7,11 +7,11 @@ ...@@ -7,11 +7,11 @@
<script> <script>
export default { export default {
data() { data() {
return {} return {};
}, },
created() {}, created() {},
mounted() {} mounted() {}
} };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
......
...@@ -8,11 +8,11 @@ ...@@ -8,11 +8,11 @@
<script> <script>
export default { export default {
data() { data() {
return {} return {};
}, },
created() {}, created() {},
mounted() {} mounted() {}
} };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
......
...@@ -10,13 +10,23 @@ ...@@ -10,13 +10,23 @@
></video> ></video>
</div> </div>
<div class="operate-area"> <div class="operate-area">
<input <div class="play-area">
id="screenshot-input" <input
type="file" id="screenshot-input"
style="display:none;" type="file"
@change="changeFile" style="display:none;"
> @change="changeFile"
<label id="select-btn">选择文件</label> >
<label id="select-btn">
<span>选择文件</span>
</label>
</div>
<div class="time-area">
<div id="ss-time-line">
<div class="track"></div>
</div>
</div>
<div class="clip-area"></div>
</div> </div>
</div> </div>
</template> </template>
...@@ -26,70 +36,67 @@ export default { ...@@ -26,70 +36,67 @@ export default {
name: 'Screenshot', name: 'Screenshot',
data() { data() {
return { return {
srcUrl: null srcUrl: null,
} videoEle: null,
current: 0,
duration: 10
};
}, },
created() {}, created() {},
mounted() { mounted() {
let input = document.getElementById('screenshot-input') let input = document.getElementById('screenshot-input');
let fileBtn = document.getElementById('select-btn') let fileBtn = document.getElementById('select-btn');
fileBtn.addEventListener('click', function () { fileBtn.addEventListener('click', function() {
input.click() input.click();
}) });
let video = document.getElementById('screenshot-video') let video = document.getElementById('screenshot-video');
video.onerror = function (e) { video.onerror = function(e) {
console.log('onerror', e) console.log('onerror', e);
} };
video.addEventListener('loadedmetadata', function (e) { video.addEventListener('loadedmetadata', function(e) {
console.log('loadedmetadata', e) console.log('loadedmetadata', e);
//webkitVideoDecodedByteCount //webkitVideoDecodedByteCount
if (e.target.webkitVideoDecodedByteCount < 1) { if (e.target.webkitVideoDecodedByteCount < 1) {
console.error('格式不支持') console.error('格式不支持');
} }
}) });
//loadedmetadata //loadedmetadata
}, },
methods: { methods: {
selectClick() {},
changeFile(e) { changeFile(e) {
//console.log('changeFile', e) //console.log('changeFile', e)
if (e.target.files[0]) { if (e.target.files[0]) {
this.srcUrl = URL.createObjectURL(e.target.files[0]) this.srcUrl = URL.createObjectURL(e.target.files[0]);
// let _this = this
// let reader = new FileReader()
// reader.addEventListener(
// 'load',
// () => {
// console.log('_this.srcUrl', this)
// _this.srcUrl = reader.result
// },
// false
// )
// reader.readAsDataURL(e.target.files[0])
} }
//e.target
} }
} }
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.screenshot { .screenshot {
position: relative;
width: 100%; width: 100%;
height: 100%; height: 100%;
margin: 30px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.content { .content {
height: 90%; height: 100%;
margin: 20px 30px; margin: 20px 30px;
background-color: lightcyan; background-color: lightcyan;
} }
.operate-area { .operate-area {
background-color: aqua;
height: 200px;
display: flex;
flex-shrink: 0;
#select-btn { #select-btn {
width: 200px; background-color: bisque;
height: 100px; width: 100px;
height: 30px;
line-height: 30px;
} }
} }
} }
......
<template> <template>
<div class="videoConverter"> <div class="videoConverter">
<ul> <taskEdit></taskEdit>
<li
v-for="(item, index) in taskList"
:key="index"
>
<div class="info">
<div class="cove">
视频封面
</div>
<div>
<div>{{ item.name }}.mp4</div>
<div>时长:{{ item.duration }}</div>
</div>
</div>
<div class="operationPanel">
<div
v-show="item.state == 0"
class="wait"
>
<div>输出格式</div>
<div class="selectionFormat">
mp4
</div>
<div
class="delete"
@click="clearTask(item)"
>
删除
</div>
</div>
<div
v-show="item.state == 1"
class="active"
>
<div class="progress">
<div>转换中{{ item.progress }}%</div>
<div class="slide">
<div></div>
</div>
</div>
<div
class="stop"
@click="stopTask(item)"
>
取消
</div>
</div>
</div>
</li>
</ul>
<div class="editBar">
<div
class="addVideo"
@click="addVideo"
>
添加视频
</div>
<div
class="clearList"
@click="clearAllTasks"
>
清空列表
</div>
<div class="clearWatermark">
去除水印
</div>
</div>
<div
class="startAll"
@click="startAllTasks"
>
开始转换
</div>
</div> </div>
</template> </template>
<script> <script>
import taskEdit from '@/components/videoConverter/taskEdit';
export default { export default {
name: 'VideoConverter', name: 'VideoConverter',
components: {}, components: { taskEdit },
props: {}, props: {},
data() { data() {
return { return {};
taskList: []
}
}, },
computed: {}, computed: {},
watch: {}, watch: {},
created() { created() {},
for (let i = 1; i < 10; i++) { methods: {}
this.taskList.push({ };
cover: '',
name: '视频片段' + i,
duration: '10:00',
state: 0,
progress: 60,
outputFormat: 'mp4'
})
}
},
methods: {
addVideo() {
this.taskList.push({
cover: '',
name: '视频片段' + (this.taskList.length + 1),
duration: '10:00',
state: 0,
progress: 60,
outputFormat: 'mp4'
})
},
stopTask(item) {
item.state = 0
},
clearTask(item) {
let index = this.taskList.indexOf(item)
if (index > -1) {
this.taskList.splice(index, 1)
}
},
clearAllTasks() {
this.taskList = []
},
startAllTasks() {
this.taskList.forEach((task) => {
task.state = 1
})
}
}
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
...@@ -142,129 +27,5 @@ export default { ...@@ -142,129 +27,5 @@ export default {
background-color: #fff; background-color: #fff;
border: 0px solid black; border: 0px solid black;
margin: 0px; margin: 0px;
padding: 0 20px;
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
overflow: hidden;
> ul {
width: 100%;
height: 100%;
border: 1px solid black;
flex-grow: 1;
overflow-y: auto;
> li {
padding: 5px 0;
height: 60px;
display: flex;
justify-content: space-between;
align-items: center;
}
> li:nth-of-type(odd) {
background-color: gainsboro;
}
.info {
display: flex;
align-items: center;
.cove {
width: 100px;
height: 40px;
background-color: #ccc;
line-height: 40px;
margin-right: 10px;
}
}
.operationPanel {
width: 300px;
height: 100%;
.wait {
height: 100%;
display: flex;
align-items: center;
.selectionFormat {
height: 30px;
width: 100px;
line-height: 30px;
border: 1px solid black;
margin-left: 20px;
}
.delete {
width: 60px;
height: 30px;
line-height: 30px;
background-color: black;
color: #fff;
margin-left: 20px;
}
}
.active {
height: 100%;
width: 300px;
display: flex;
align-items: center;
.progress {
}
.slide {
width: 200px;
height: 5px;
background: gray;
> div {
width: 120px;
height: 100%;
background-color: black;
}
}
.stop {
width: 60px;
height: 30px;
line-height: 30px;
background-color: black;
color: #fff;
margin-left: 20px;
}
}
}
}
.editBar {
position: relative;
height: 30px;
width: 100%;
margin: 20px 0;
.addVideo {
position: absolute;
left: 0;
height: 30px;
line-height: 30px;
border: 1px solid black;
}
.clearList {
position: absolute;
left: 100px;
height: 30px;
line-height: 30px;
border: 1px solid black;
}
.clearWatermark {
position: absolute;
right: 0;
height: 30px;
line-height: 30px;
border: 1px solid black;
}
}
.startAll {
height: 30px;
width: 100px;
background-color: black;
color: #fff;
line-height: 30px;
}
} }
</style> </style>
<template> <template>
<div class="video-cutter"> <div class="video-cutter">
<div class="video-content"> <div class="video-content">
<VideoPlayer <videoPlayer
@currentTime="changeTime" @currentTime="changeTime"
@end="playEnd" @end="playEnd"
@timeupdate="timeupdate" @timeupdate="timeupdate"
></VideoPlayer> ></videoPlayer>
</div> </div>
<div class="video-btn"> <div class="video-btn">
<videoChange @changeVideo="changeVideo"></videoChange> <videoChange @changeVideo="changeVideo"></videoChange>
...@@ -14,9 +14,18 @@ ...@@ -14,9 +14,18 @@
:now-time="nowTime" :now-time="nowTime"
@play="videoPlay" @play="videoPlay"
></videoControl> ></videoControl>
<div></div> <div class="video-water">
<input
id="cutterRemoveWater"
v-model="noWater"
type="checkbox"
>
<label for="cutterRemoveWater">去除水印</label>
</div>
</div>
<div class="timeline-content">
<videoTimeline :info="timelineObj"></videoTimeline>
</div> </div>
<div></div>
<div></div> <div></div>
</div> </div>
</template> </template>
...@@ -27,7 +36,8 @@ export default { ...@@ -27,7 +36,8 @@ export default {
components: { components: {
VideoPlayer: () => import('@/components/videoCutter/videoPlayer.vue'), VideoPlayer: () => import('@/components/videoCutter/videoPlayer.vue'),
VideoChange: () => import('@/components/videoCutter/videoChange.vue'), VideoChange: () => import('@/components/videoCutter/videoChange.vue'),
VideoControl: () => import('@/components/videoCutter/videoControl.vue') VideoControl: () => import('@/components/videoCutter/videoControl.vue'),
VideoTimeline: () => import('@/components/videoCutter/videoTimeline.vue')
}, },
data() { data() {
return { return {
...@@ -35,47 +45,53 @@ export default { ...@@ -35,47 +45,53 @@ export default {
nowTime: 0, nowTime: 0,
duration: 0, duration: 0,
playing: false, playing: false,
canPlay: false canPlay: false,
} noWater: true,
timelineObj: { step: 0.1, min: 0, max: 10, val: 0 }
};
}, },
created() {}, created() {},
mounted() { mounted() {
this.$bus.on('VideoCutter.canPlay', this.canPlayFunc) this.$bus.on('VideoCutter.canPlay', this.canPlayFunc);
}, },
methods: { methods: {
changeVideo() { changeVideo() {
console.log('todo change video, <-----lilei') console.log('todo change video, <-----lilei');
}, },
canPlayFunc(data) { canPlayFunc(data) {
this.duration = data this.duration = data;
this.canPlay = true this.timelineObj.max = this.duration;
this.canPlay = true;
}, },
videoPlay() { videoPlay() {
if (!this.canPlay) return if (!this.canPlay) return;
let ob = {} let ob = {};
if (this.playing) { if (this.playing) {
ob.play = false ob.play = false;
} else { } else {
ob.play = true ob.play = true;
if (this.nowTime >= this.duration) { if (this.nowTime >= this.duration) {
ob.time = 0 ob.time = 0;
this.timelineObj.val = 0;
} }
} }
this.playing = !this.playing this.playing = !this.playing;
this.$bus.emit('videoPlayer.play', ob) this.$bus.emit('videoPlayer.play', ob);
}, },
changeTime(data) { changeTime(data) {
console.log(data) console.log(data);
}, },
playEnd() { playEnd() {
this.playing = false this.playing = false;
this.nowTime = this.duration this.nowTime = this.duration;
this.timelineObj.val = this.nowTime;
}, },
timeupdate(time) { timeupdate(time) {
this.nowTime = time this.nowTime = time;
this.timelineObj.val = this.nowTime;
} }
} }
} };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
...@@ -92,4 +108,21 @@ export default { ...@@ -92,4 +108,21 @@ export default {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
.video-water {
display: flex;
align-items: center;
input {
margin-right: 4px;
}
* {
cursor: pointer;
}
}
.timeline-content {
width: 100%;
margin: 10px 0;
padding: 0 20px;
}
</style> </style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment