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