congzc преди 2 години
родител
ревизия
85eea1fcd6
променени са 13 файла, в които са добавени 41544 реда и са изтрити 9089 реда
  1. +31398
    -0
      package-lock.json
  2. +11
    -1
      src/api/chooseModel.js
  3. Двоични данни
      src/assets/icon/icon-download.png
  4. +280
    -0
      src/components/CutImg copy 2.vue
  5. +272
    -0
      src/components/CutImg copy.vue
  6. +70
    -57
      src/components/CutImg.vue
  7. +6
    -0
      src/router/index.js
  8. +1
    -1
      src/views/login/login.vue
  9. +12
    -26
      src/views/model/chooseModel.vue
  10. +3
    -4
      src/views/model/editPosition.vue
  11. +30
    -21
      src/views/myPage/myPage.vue
  12. +243
    -0
      src/views/videoDownload/videoDownload.vue
  13. +9218
    -8979
      yarn.lock

+ 31398
- 0
package-lock.json
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 11
- 1
src/api/chooseModel.js Целия файл

@@ -11,7 +11,17 @@ export function getModeList(sex) {
method: 'get'
})
}

/**
* @description 获取模板列表(新)
* @param {number} sex
* @returns data
*/
export function getModeList1(sex) {
return request({
url: `/api/personPatch/list?sex=${sex}&pageNum=1&pageSize=10`,
method: 'get'
})
}
/**
* @description:根据id获取模板详情
* @param {number} id


Двоични данни
src/assets/icon/icon-download.png Целия файл

Преди След
Ширина: 48  |  Височина: 48  |  Големина: 720 B

+ 280
- 0
src/components/CutImg copy 2.vue Целия файл

@@ -0,0 +1,280 @@
<template>
<div class="uploder">
<div class="change-photo-setter">
<van-uploader class="sett-item" :before-read="beforeRead">
<div style="height: 100%"><img :src="ImgUrl" alt="" /></div>
<img src="https://img01.yzcdn.cn/vant/leaf.jpg" alt="" />
</van-uploader>
</div>
<div class="uploadava">
<van-popup
duration="0"
v-model="showCropper"
position="top"
:style="{ height: '100%' }"
>
<div class="cropper-container">
<van-loading
v-show="loadingShow"
size="50"
color="#fff"
vertical
text-color="#fff"
>上传中...</van-loading
>
<vueCropper
ref="cropper"
:img="option.img"
:outputSize="option.outputSize"
:outputType="option.outputType"
:info="option.info"
:full="option.full"
:autoCropWidth="option.autoCropWidth"
:autoCropHeight="option.autoCropHeight"
:canMove="option.canMove"
:canMoveBox="option.canMoveBox"
:original="option.original"
:autoCrop="option.autoCrop"
:fixed="option.fixed"
:fixedNumber="option.fixedNumber"
:centerBox="option.centerBox"
:infoTrue="option.infoTrue"
:fixedBox="option.fixedBox"
:high="option.high"
:mode="option.mode"
/>
<van-nav-bar
left-text="取消"
right-text="确定"
@click-left="onClickLeft"
@click-right="onClickRight"
/>
</div>
</van-popup>
</div>
</div>
</template>

<script>
import { awsImgUpload } from '@/api/editModel'
import { Toast } from 'vant'
import { VueCropper } from 'vue-cropper'
export default {
name: 'uploadAva',
components: {
VueCropper
},
props: {
showAta: {
default: false,
type: Boolean
},
avaUrl: {
default: '',
type: String
}
},
data() {
return {
ImgUrl: '',
show: true, // 上传类型的弹窗
imageFileName: '',
showCropper: false, // 裁剪的弹窗
option: {
img: '',
outputSize: 0.8,
info: false, // 裁剪框的大小信息
outputType: 'jpeg', // 裁剪生成图片的格式
canScale: true, // 图片是否允许滚轮缩放
autoCrop: true, // 是否默认生成截图框
autoCropWidth: window.innerWidth - 100 + 'px', // 默认生成截图框宽度
autoCropHeight: window.innerWidth - 100 + 'px', // 默认生成截图框高度
high: true, // 是否按照设备的dpr 输出等比例图片
fixedBox: false, // 固定截图框大小 不允许改变
fixed: true, // 是否开启截图框宽高固定比例
fixedNumber: [1, 1], // 截图框的宽高比例
full: true, // 是否输出原图比例的截图
canMoveBox: true, // 截图框能否拖动
original: false, // 上传图片按照原始比例渲染
centerBox: true, // 截图框是否被限制在图片里面
infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
mode: '100% auto' // 图片默认渲染方式
},
loadingShow: false // 是否展示loading
}
},
methods: {
beforeRead(file) {
console.log(file)
if (file.type !== 'image/jpeg' && file.type !== 'image/png') {
this.$toast('请上传 jpg/png 格式图片')
return false
}
let data = window.URL.createObjectURL(new Blob([file]))
this.option.img = data //给裁剪图片的路径
this.showCropper = true
return false
},
// 点击裁剪的选择
onClickRight() {
let that = this
this.loadingShow = true
this.$refs.cropper.getCropBlob(async (data) => {
let formData = new FormData()
formData.append('file', data)
let file = formData.get('file')
// 转为 base64
let reader = new FileReader()
reader.onload = async () => {
// base64结果
that.ImgUrl = this.result
that.loading = false
}
reader.readAsDataURL(file)
// await that.toBase64(file)
console.log(that.ImgUrl, 'dasdasd')
// 发请求
const AccessToken = localStorage.getItem('AccessToken')
that
.$axios({
method: 'post',
url: `https://smapitest.malls.iformall.com/C/api/upload/awsImgUpload`,
headers: {
// 'Content-Type': 'application/json;charset=UTF-8',
'content-type': 'multipart/form-data',
token: AccessToken,
'Access-Control-Allow-Credentials': true
},
data: { file: that.base64ToBinary(that.ImgUrl) }
})
.then((res) => {
console.log(res)
console.log(that.ImgUrl)
console.log(that.base64ToBinary(that.ImgUrl))
that.loadingShow = false
that.showCropper = false
Toast.success('上传成功')
})
})
},
// 点击取消
onClickLeft() {
this.loadingShow = false
this.showCropper = false
this.$parent.showPhotoUploader = false
},
// 上传图片
async pushImg(data) {
try {
const res = await awsImgUpload(data)
this.loadingShow = false
this.showCropper = false
Toast.success('上传成功')
} catch (error) {
console.log(error, 'error')
Toast.fail(error.message)
}
},
//图片转base64,异步
toBase64(file) {
let that = this
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = () => {
// base64结果
that.ImgUrl = this.result
that.loading = false
}
reader.onerror = reject
reader.readAsDataURL(file)
})
},
// base64 转二进制
base64ToBinary(base64) {
console.log(base64)
const binaryString = window.atob(base64)
const binaryLength = binaryString.length
const bytes = new Uint8Array(binaryLength)
for (let i = 0; i < binaryLength; i++) {
bytes[i] = binaryString.charCodeAt(i)
}
return bytes
}
}
}
</script>

<style lang="scss" scoped>
// .uploder{
// overflow: hidden;
// }
/deep/.cropper-view-box {
outline: 2px dashed #fff !important;
}
/deep/.crop-point {
background-color: auto !important;
}
/deep/.van-loading {
position: absolute;
// color: red;
z-index: 9999;
left: 50%;
top: 50%;
margin-left: -55px;
margin-top: -30px;
background: rgba(0, 0, 0, 0.3);
padding: 10px 30px;
border-radius: 25px;
}

.uploadava {
.update-avatar {
height: 100%;
text-align: center;
.update-avatar-line {
width: 100%;
height: 1px;
background-color: #979797;
}
.avatar-select-type {
background-color: #fff;
width: 346px;
border-radius: 12px;
padding-bottom: 4px;
.upload-avator {
padding: 14px;
}
}
p {
margin: 15px 0 30px;
background-color: #fff;
width: 346px;
border-radius: 12px;
padding: 15px 0 18px;
}
}
.cropper-container {
height: 94vh;
.van-nav-bar {
background-color: rgba(0, 0, 0, 0.87);
:global(.van-nav-bar__text) {
color: #fff;
// font-size: $font-size-normal-x;
}
:global(.van-nav-bar__text:nth-child(2)) {
color: #000;
font-weight: 500;
}
// :global(.van-icon) {
// color: red;
// }
}
}
.vue-cropper {
background: #000;
height: 100%;
padding-top: 46px;
box-sizing: border-box;
}
}
</style>

+ 272
- 0
src/components/CutImg copy.vue Целия файл

@@ -0,0 +1,272 @@
<template>
<div class="uploder">
<div class="change-photo-setter">
<van-uploader class="sett-item" :before-read="beforeRead">
<div style="height: 100%"><img :src="ImgUrl" alt="" /></div>
<img src="https://img01.yzcdn.cn/vant/leaf.jpg" alt="" />
</van-uploader>
</div>
<div class="uploadava">
<van-popup
duration="0"
v-model="showCropper"
position="top"
:style="{ height: '100%' }"
>
<div class="cropper-container">
<van-loading
v-show="loadingShow"
size="50"
color="#fff"
vertical
text-color="#fff"
>上传中...</van-loading
>
<vueCropper
ref="cropper"
:img="option.img"
:outputSize="option.outputSize"
:outputType="option.outputType"
:info="option.info"
:full="option.full"
:autoCropWidth="option.autoCropWidth"
:autoCropHeight="option.autoCropHeight"
:canMove="option.canMove"
:canMoveBox="option.canMoveBox"
:original="option.original"
:autoCrop="option.autoCrop"
:fixed="option.fixed"
:fixedNumber="option.fixedNumber"
:centerBox="option.centerBox"
:infoTrue="option.infoTrue"
:fixedBox="option.fixedBox"
:high="option.high"
:mode="option.mode"
/>
<van-nav-bar
left-text="取消"
right-text="选择"
@click-left="onClickLeft"
@click-right="onClickRight"
/>
</div>
</van-popup>
</div>
</div>
</template>

<script>
import { awsImgUpload } from '@/api/editModel'
import { Toast } from 'vant'
import { VueCropper } from 'vue-cropper'
export default {
name: 'uploadAva',
components: {
VueCropper
},
props: {
showAta: {
default: false,
type: Boolean
},
avaUrl: {
default: '',
type: String
}
},
data() {
return {
ImgUrl: '',
show: true, // 上传类型的弹窗
imageFileName: '',
showCropper: false, // 裁剪的弹窗
option: {
img: '',
outputSize: 0.8,
info: false, // 裁剪框的大小信息
outputType: 'jpeg', // 裁剪生成图片的格式
canScale: true, // 图片是否允许滚轮缩放
autoCrop: true, // 是否默认生成截图框
autoCropWidth: window.innerWidth - 100 + 'px', // 默认生成截图框宽度
autoCropHeight: window.innerWidth - 100 + 'px', // 默认生成截图框高度
high: true, // 是否按照设备的dpr 输出等比例图片
fixedBox: false, // 固定截图框大小 不允许改变
fixed: true, // 是否开启截图框宽高固定比例
fixedNumber: [1, 1], // 截图框的宽高比例
full: true, // 是否输出原图比例的截图
canMoveBox: true, // 截图框能否拖动
original: false, // 上传图片按照原始比例渲染
centerBox: true, // 截图框是否被限制在图片里面
infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
mode: '100% auto' // 图片默认渲染方式
},
loadingShow: false // 是否展示loading
}
},
methods: {
beforeRead(file) {
console.log(file)
if (file.type !== 'image/jpeg' && file.type !== 'image/png') {
this.$toast('请上传 jpg/png 格式图片')
return false
}

// console.log(111, file)
this.showCropper = true
this.imageToBase64(file)
this.imageFileName = file.name
},

imageToBase64(file) {
let reader = new FileReader()
console.log(reader)
reader.readAsDataURL(file)
reader.onload = () => {
this.option.img = reader.result
}
},
onClickRight() {
// let formData = new FormData()
this.loadingShow = true
console.log(this.option)
// const AccessToken = localStorage.getItem('AccessToken')
// this.$axios({
// method: 'post',
// url: `https://smapitest.malls.iformall.com/C/api/upload/awsImgUpload`,
// headers: {
// // 'Content-Type': 'application/json;charset=UTF-8',
// 'content-type': 'multipart/form-data',
// token: AccessToken,
// 'Access-Control-Allow-Credentials': true
// },
// data: { file: this.option.img }
// }).then((res) => {
// console.log(res)

// this.loadingShow = false
// this.showCropper = false
// Toast.success('上传成功')
// })
// this.pushImg({ file: this.option.img })
// this.pushImg({ file: require('../assets/icon/icon-yes.png') })

// this.$refs.cropper.getCropBlob((data) => {
console.log(this.$refs.cropper)
this.$refs.cropper.getCroppedCanvas((data) => {
this.ImgUrl = data
console.log(data, 'blob')
// let blob = window.URL.createObjectURL(data)
// console.log(blob)
// formData.append('File', data, this.imageFileName)
// formData.append('id', this.$store.getters.user.userId)
// console.log(formData.getAll('File'))
// console.log(data)
// this.pushImg({ file: blob })
// uploadAva(formData).then((res) => {
// this.showCropper = false
// this.$emit('update:showAta', false)
// this.$emit('update:avaUrl', res.data)
// })
})
// this.$refs.cropper.getCroppedCanvas().toBlob((blob) => {
// const formData = new FormData()
// formData.append('file', blob, 'avatar.png')

// this.pushImg({ file: blob })
// })
},
onClickLeft() {
this.loadingShow = false
this.showCropper = false
this.$parent.showPhotoUploader = false
},
// 上传图片
async pushImg(data) {
try {
const res = await awsImgUpload(data)
this.loadingShow = false
this.showCropper = false
Toast.success('上传成功')
} catch (error) {
console.log(error, 'error')
Toast.fail(error.message)
}
}
}
}
</script>

<style lang="scss" scoped>
// .uploder{
// overflow: hidden;
// }
/deep/.cropper-view-box {
outline: 2px dashed #fff !important;
}
/deep/.crop-point {
background-color: auto !important;
}
/deep/.van-loading {
position: absolute;
// color: red;
z-index: 9999;
left: 50%;
top: 50%;
margin-left: -55px;
margin-top: -30px;
background: rgba(0, 0, 0, 0.3);
padding: 10px 30px;
border-radius: 25px;
}

.uploadava {
.update-avatar {
height: 100%;
text-align: center;
.update-avatar-line {
width: 100%;
height: 1px;
background-color: #979797;
}
.avatar-select-type {
background-color: #fff;
width: 346px;
border-radius: 12px;
padding-bottom: 4px;
.upload-avator {
padding: 14px;
}
}
p {
margin: 15px 0 30px;
background-color: #fff;
width: 346px;
border-radius: 12px;
padding: 15px 0 18px;
}
}
.cropper-container {
height: 94vh;
.van-nav-bar {
background-color: rgba(0, 0, 0, 0.87);
:global(.van-nav-bar__text) {
color: #fff;
// font-size: $font-size-normal-x;
}
:global(.van-nav-bar__text:nth-child(2)) {
color: #000;
font-weight: 500;
}
// :global(.van-icon) {
// color: red;
// }
}
}
.vue-cropper {
background: #000;
height: 100%;
padding-top: 46px;
box-sizing: border-box;
}
}
</style>

+ 70
- 57
src/components/CutImg.vue Целия файл

@@ -2,7 +2,7 @@
<div class="uploder">
<div class="change-photo-setter">
<van-uploader class="sett-item" :before-read="beforeRead">
<div style="height: 100%"></div>
<div style="height: 100%"><img :src="ImgUrl" alt="" /></div>
<img src="https://img01.yzcdn.cn/vant/leaf.jpg" alt="" />
</van-uploader>
</div>
@@ -45,7 +45,7 @@
/>
<van-nav-bar
left-text="取消"
right-text="选择"
right-text="确定"
@click-left="onClickLeft"
@click-right="onClickRight"
/>
@@ -76,6 +76,7 @@ export default {
},
data() {
return {
ImgUrl: '',
show: true, // 上传类型的弹窗
imageFileName: '',
showCropper: false, // 裁剪的弹窗
@@ -109,67 +110,55 @@ export default {
this.$toast('请上传 jpg/png 格式图片')
return false
}
// console.log(111, file)
let data = window.URL.createObjectURL(new Blob([file]))
this.option.img = data //给裁剪图片的路径
this.showCropper = true
this.imageToBase64(file)
this.imageFileName = file.name
},

imageToBase64(file) {
let reader = new FileReader()
console.log(reader)
reader.readAsDataURL(file)
reader.onload = () => {
this.option.img = reader.result
}
return false
},
// 点击裁剪的选择
onClickRight() {
// let formData = new FormData()
let that = this
this.loadingShow = true
console.log(this.option)
const AccessToken = localStorage.getItem('AccessToken')
this.$axios({
method: 'post',
url: `https://smapitest.malls.iformall.com/C/api/upload/awsImgUpload`,
headers: {
// 'Content-Type': 'application/json;charset=UTF-8',
'content-type': 'multipart/form-data',
token: AccessToken,
'Access-Control-Allow-Credentials': true
},
data: { file: this.option.img }
}).then((res) => {
console.log(res)
this.loadingShow = false
this.showCropper = false
Toast.success('上传成功')
this.$refs.cropper.getCropBlob(async (data) => {
let formData = new FormData()
formData.append('file', data)
let file = formData.get('file')
// 转为 base64
let reader = new FileReader()
const base64Data = await new Promise((resolve, reject) => {
reader.onload = () => {
resolve(reader.result)
}
reader.readAsDataURL(file)
})
let imgBinary = await that.base64ToBinary(base64Data.substring(23))
// base64结果
that.ImgUrl = base64Data
that.loading = false
console.log(that.ImgUrl, 'dasdasd')
// 发请求
const AccessToken = localStorage.getItem('AccessToken')
that
.$axios({
method: 'post',
url: `https://smapitest.malls.iformall.com/C/api/upload/awsImgUpload`,
headers: {
'content-type': 'multipart/form-data',
token: AccessToken,
'Access-Control-Allow-Credentials': true
},
data: formData
})
.then((res) => {
console.log(res)
that.loadingShow = false
that.showCropper = false
Toast.success('上传成功')
})
})
// this.pushImg({ file: this.option.img })
// this.pushImg({ file: require('../assets/icon/icon-yes.png') })

this.$refs.cropper.getCropBlob((data) => {
console.log(data, 'blob')
// let blob = window.URL.createObjectURL(data)
// console.log(blob)
// formData.append('File', data, this.imageFileName)
// formData.append('id', this.$store.getters.user.userId)
// console.log(formData.getAll('File'))
// console.log(data)
// this.pushImg({ file: blob })
// uploadAva(formData).then((res) => {
// this.showCropper = false
// this.$emit('update:showAta', false)
// this.$emit('update:avaUrl', res.data)
// })
})
// this.$refs.cropper.getCroppedCanvas().toBlob((blob) => {
// const formData = new FormData()
// formData.append('file', blob, 'avatar.png')

// this.pushImg({ file: blob })
// })
},

// 点击取消
onClickLeft() {
this.loadingShow = false
this.showCropper = false
@@ -186,6 +175,30 @@ export default {
console.log(error, 'error')
Toast.fail(error.message)
}
},
//图片转base64,异步
toBase64(file) {
let that = this
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = () => {
// base64结果
that.ImgUrl = this.result
that.loading = false
}
reader.onerror = reject
reader.readAsDataURL(file)
})
},
// base64 转二进制
base64ToBinary(base64) {
const binaryStr = window.atob(base64)
const len = binaryStr.length
const bytes = new Uint8Array(len)
for (let i = 0; i < len; ++i) {
bytes[i] = binaryStr.charCodeAt(i)
}
return bytes
}
}
}


+ 6
- 0
src/router/index.js Целия файл

@@ -68,6 +68,12 @@ const routes = [
name: 'editPosition-chatgpt',
component: () => import("../views/model/editPosition-chatgpt"),
},
// 编辑位置new
{
path: '/videoDownload',
name: 'videoDownload',
component: () => import("../views/videoDownload/videoDownload"),
},
// 聊天首页new
{
path: '/chat',


+ 1
- 1
src/views/login/login.vue Целия файл

@@ -297,7 +297,7 @@ export default {
codeInfo: '获取验证码',
inPage: false,
codeImg: '', //随机验证码图片
loginType: 6, //显示页面字符
loginType: 1, //显示页面字符
showCodeImg: true, // 控制验证码的刷新
// 短信验证码登录
form: {


+ 12
- 26
src/views/model/chooseModel.vue Целия файл

@@ -16,21 +16,6 @@
<van-tab v-for="item in tabList" :key="item" :title="item"> </van-tab>
</van-tabs>

<!-- <div class="title">选择模板</div> -->
<!-- 老版吸顶tab栏 -->
<!-- <div class="typeOutSide">
<div class="type">
<div :class="type == 0 ? 'active' : ''" @click="chooseType(0)">
全部模板
</div>
<div :class="type == 2 ? 'active' : ''" @click="chooseType(2)">
女性模板
</div>
<div :class="type == 1 ? 'active' : ''" @click="chooseType(1)">
男性模板
</div>
</div>
</div> -->
<!-- 模板列表 -->
<div class="choose">
<div class="modeList" v-masonry item-selector=".model" column-width="170">
@@ -43,9 +28,11 @@
:key="index"
@click="selectModel(item.id)"
>
<img :src="item.coverImg" alt="" />
<div class="modelName">{{ item.title }}</div>
<div class="setPaper">录入文案</div>
<div class="model-padding">
<img :src="item.coverImg" alt="" />
<div class="modelName">{{ item.title }}</div>
<div class="setPaper">录入文案</div>
</div>
</div>
<div class="alt" v-if="modeList.length == 0">暂无可用模板</div>
</div>
@@ -62,6 +49,7 @@ import { Toast } from 'vant'
import { scrollToID } from '../../utils'
import {
getModeList,
getModeList1,
getModeDetailById,
saveOrUpdateUserVideo
} from '../../api/chooseModel'
@@ -122,7 +110,8 @@ export default {
async loadModeList(sex) {
try {
sex = sex == 0 ? '' : sex
const res = await getModeList(sex)
// const res = await getModeList(sex)
const res = await getModeList1(sex)
console.log(res, '获取模板列表')
this.modeList = res.data.list
} catch (error) {
@@ -296,18 +285,15 @@ export default {
position: relative;
text-align: left;
margin-bottom: 15px;
// border: 1px solid #00000028;
// padding: 8px;
// width: 154px;
max-width: 170px;
// height: 305px;
max-height: 310px;
// transition: all 0.3s;
opacity: 0.9;
padding: 5px;
&-padding {
}
img {
border-radius: 8px;
width: 100%;
height: 273px;
// height: 273px;
}
.modelName {
margin-top: 10px;


+ 3
- 4
src/views/model/editPosition.vue Целия файл

@@ -58,11 +58,10 @@ export default {
{
text: '小div1',
url: 'img/BG@2x.b0cf224b.png',
x: 300,
x: 300, // 相对左上角XY坐标
y: 300,
scale: 1,
zIndex: 3,
num: 1
scale: 1, //缩放
zIndex: 3 //层级
},
{
text: '小div2',


+ 30
- 21
src/views/myPage/myPage.vue Целия файл

@@ -39,25 +39,29 @@
:key="item.id ? item.id : index"
@click="goDetail(item)"
>
<img :src="index == 1 ? defaultImg : defaultImg1" alt="" />
<!-- 渐变遮罩层 -->
<div class="waterFall-item-mask">
<div>{{ item.title || '暂无' }}</div>
<div>视频时长:{{ formatSeconds(item.videoTime) }}</div>
<div>视频容量:{{ bytesToSize(item.videoSize) }}</div>
<div>
创建时间:{{ changeTime(item.createDate, 'YYYY-MM-DD hh:mm:ss') }}
<div class="waterFall-item-paddding">
<img :src="index == 1 ? defaultImg : defaultImg1" alt="" />
<!-- 渐变遮罩层 -->
<div class="waterFall-item-mask">
<div>{{ item.title || '暂无' }}</div>
<div>视频时长:{{ formatSeconds(item.videoTime) }}</div>
<div>视频容量:{{ bytesToSize(item.videoSize) }}</div>
<div>
创建时间:{{
changeTime(item.createDate, 'YYYY-MM-DD hh:mm:ss')
}}
</div>
</div>
<!-- 视频状态 草稿还是未完成还是失败 -->
<div class="waterFall-item-state">
<div v-if="item.videoStatus == 0" class="cover">草稿</div>
<div v-if="item.videoStatus == 1" class="cover">视频生成中</div>
<div v-if="item.videoStatus == 3" class="cover">视频生成失败</div>
</div>
<!-- 删除 -->
<div class="waterFall-item-del" @click.stop="goDelete(item.id)">
<img src="../../assets/icon/icon-trash.png" alt="" />
</div>
</div>
<!-- 视频状态 草稿还是未完成还是失败 -->
<div class="waterFall-item-state">
<div v-if="item.videoStatus == 0" class="cover">草稿</div>
<div v-if="item.videoStatus == 1" class="cover">视频生成中</div>
<div v-if="item.videoStatus == 3" class="cover">视频生成失败</div>
</div>
<!-- 删除 -->
<div class="waterFall-item-del" @click.stop="goDelete(item.id)">
<img src="../../assets/icon/icon-trash.png" alt="" />
</div>
</div>
</div>
@@ -677,16 +681,21 @@ export default {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin-right: -20px;
width: 100%;
&-item {
// max-width: 355px; //非瀑布流
max-width: 170px;
max-height: 300px;
// background-color: red;
padding: 5px;
border-radius: 12px;
margin-bottom: 10px;
overflow: hidden;
&-paddding {
position: relative;
border-radius: 12px;
overflow: hidden;
width: 160px;
// padding: 5px;
}
img {
max-width: 100%;
max-height: 100%;


+ 243
- 0
src/views/videoDownload/videoDownload.vue Целия файл

@@ -0,0 +1,243 @@
<template>
<div :class="inPage ? 'page active' : 'page'">
<div id="top"></div>
<HeadTop />
<div class="content">
<!-- 视频 -->
<div class="videoBox">
<video
loop
download
ref="video"
:src="videoSrc"
@loadedmetadata="onVideoLoaded"
@click.prevent="() => {}"
@play="playing = true"
@pause="playing = false"
@timeupdate="onTimeUpdate"
></video>
<!-- 控制框 -->
<div class="videoBox-controls">
<!-- 前进后退 -->
<div class="videoBox-controls-left">
<div @click="seek(-10)">
<i class="el-icon-refresh-left"></i>
</div>
<div @click="togglePlay">
<i v-show="!this.playing" class="el-icon-video-play"></i>
<i v-show="this.playing" class="el-icon-video-pause"></i>
</div>
<div @click="seek(10)">
<i class="el-icon-refresh-right"></i>
</div>
</div>
<!-- 进度条 -->
<div class="videoBox-controls-middle">
<div class="time">{{ formatTime(currentTime) }}</div>
<van-slider
active-color="#aa91a5"
v-model="progress"
:max="totalTime"
:value="currentTime"
@change="onProgressChange"
></van-slider>
<div class="time">{{ formatTime(totalTime) }}</div>
</div>
<!-- 全屏 -->
<div class="videoBox-controls-right" @click="toggleScreen">
<van-icon name="enlarge" />
</div>
</div>
<!-- 下载按钮 -->
<a :href="videoSrc" download class="videoBox-download">
<img src="../../assets/icon/icon-download.png" alt="" />
</a>
</div>
</div>
</div>
</template>

<script>
import Vue from 'vue'
import { Toast } from 'vant'
import { mapState, mapActions } from 'vuex'
import HeadTop from './../../components/common/head.vue'
// 工具
import { scrollToID } from '../../utils'
Vue.use(Toast)
export default {
components: {
HeadTop
},
data() {
return {
inPage: false,
videoSrc:
'https://wenlian.wenzhou.gov.cn:8001//upload/video/%E3%80%8A%E7%93%AF%E8%B6%8A%E4%B9%8B%E5%8D%8E%E3%80%8B%E7%89%87%E8%8A%B11.mp4',
showControls: false, // 控制台显示隐藏
playing: false, // 播放
isLandscape: false,
progress: 0,
currentTime: 0,
totalTime: 0,
progressChanging: false
}
},
computed: {
...mapState({
characters: (state) => state.publicObj.characters
})
},
mounted() {
this.inPage = true
scrollToID('top')
this.$refs.video.addEventListener('timeupdate', this.onTimeUpdate)
this.$refs.video.addEventListener('ended', this.onVideoEnded)
screen.orientation.addEventListener('change', this.onOrientationChange)
},
destroyed() {
this.$refs.video.removeEventListener('timeupdate', this.onTimeUpdate)
this.$refs.video.removeEventListener('ended', this.onVideoEnded)
screen.orientation.removeEventListener('change', this.onOrientationChange)
},
methods: {
onVideoLoaded() {
this.totalTime = this.$refs.video.duration
},
// onTimeUpdate() {
// if (!this.progressChanging) {
// this.currentTime = this.$refs.video.currentTime
// this.progress = this.currentTime
// }
// },
onVideoEnded() {
this.playing = false
},
// 播放&暂停
togglePlay() {
this.playing = !this.playing
if (this.playing) {
this.$refs.video.play()
} else {
this.$refs.video.pause()
}
},
// 横屏
toggleScreen() {
if (this.isLandscape) {
screen.orientation.unlock()
} else {
screen.orientation.lock('landscape')
}
this.isLandscape = !this.isLandscape
},
onOrientationChange() {
this.fullScreen = screen.orientation.type.includes('landscape')
},
// 控制快进后退
seek(seconds) {
const newTime = Math.max(
0,
Math.min(this.totalTime, this.currentTime + seconds)
)
this.$refs.video.currentTime = newTime
this.currentTime = newTime
},
// 拖动滚动条
onProgressChange() {
this.progressChanging = true
this.$refs.video.currentTime = this.progress
},
//实时更新时间
onTimeUpdate() {
this.currentTime = this.$refs.video.currentTime
this.progress = this.currentTime
},
// 处理时间
formatTime(time) {
const minutes = Math.floor(time / 60)
const seconds = Math.round(time % 60)
return `${minutes}:${seconds.toString().padStart(2, '0')}`
},
...mapActions(['setCharacters']),

go(url) {
this.$router.push(url)
}
}
}
</script>

<style lang="scss" scoped>
.page {
width: 375px;
height: 100vh;
overflow-y: hidden;
}
.content {
width: 100%;
height: calc(100vh - 40px);
overflow: hidden;
}
.videoBox {
position: relative;
width: 100%;
height: 627px;
background-color: #f8f9f9;
video {
width: 100%;
height: 100%;
}
&-controls {
display: flex;
justify-content: space-between;
align-items: center;
padding: 6px 11px;
position: absolute;
left: 50%;
bottom: 27px;
transform: translateX(-50%);
width: calc(100% - 20px);
height: 26px;
background: rgba(67, 68, 71, 0.7);
border-radius: 9px;
color: #fff;
&-left {
display: flex;
justify-content: space-between;
align-items: center;
div {
padding: 0 8px;
}
i {
display: block;
width: 11px;
height: 11px;
color: #fff;
}
}
&-middle {
flex: 1;
display: flex;
justify-content: space-between;
align-items: center;
.time {
padding: 0 8px;
}
::v-deep .van-slider__button {
width: 5px;
height: 5px;
border-radius: 50%;
}
}
}
&-download {
position: absolute;
right: 10px;
top: 15px;
display: inline-block;
width: 24px;
height: 24px;
}
}
</style>

+ 9218
- 8979
yarn.lock
Файловите разлики са ограничени, защото са твърде много
Целия файл


Зареждане…
Отказ
Запис