| @@ -11,7 +11,17 @@ export function getModeList(sex) { | |||||
| method: 'get' | 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获取模板详情 | * @description:根据id获取模板详情 | ||||
| * @param {number} 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="uploder"> | ||||
| <div class="change-photo-setter"> | <div class="change-photo-setter"> | ||||
| <van-uploader class="sett-item" :before-read="beforeRead"> | <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="" /> | <img src="https://img01.yzcdn.cn/vant/leaf.jpg" alt="" /> | ||||
| </van-uploader> | </van-uploader> | ||||
| </div> | </div> | ||||
| @@ -45,7 +45,7 @@ | |||||
| /> | /> | ||||
| <van-nav-bar | <van-nav-bar | ||||
| left-text="取消" | left-text="取消" | ||||
| right-text="选择" | |||||
| right-text="确定" | |||||
| @click-left="onClickLeft" | @click-left="onClickLeft" | ||||
| @click-right="onClickRight" | @click-right="onClickRight" | ||||
| /> | /> | ||||
| @@ -76,6 +76,7 @@ export default { | |||||
| }, | }, | ||||
| data() { | data() { | ||||
| return { | return { | ||||
| ImgUrl: '', | |||||
| show: true, // 上传类型的弹窗 | show: true, // 上传类型的弹窗 | ||||
| imageFileName: '', | imageFileName: '', | ||||
| showCropper: false, // 裁剪的弹窗 | showCropper: false, // 裁剪的弹窗 | ||||
| @@ -109,67 +110,55 @@ export default { | |||||
| this.$toast('请上传 jpg/png 格式图片') | this.$toast('请上传 jpg/png 格式图片') | ||||
| return false | return false | ||||
| } | } | ||||
| // console.log(111, file) | |||||
| let data = window.URL.createObjectURL(new Blob([file])) | |||||
| this.option.img = data //给裁剪图片的路径 | |||||
| this.showCropper = true | 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() { | onClickRight() { | ||||
| // let formData = new FormData() | |||||
| let that = this | |||||
| this.loadingShow = true | 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() { | onClickLeft() { | ||||
| this.loadingShow = false | this.loadingShow = false | ||||
| this.showCropper = false | this.showCropper = false | ||||
| @@ -186,6 +175,30 @@ export default { | |||||
| console.log(error, 'error') | console.log(error, 'error') | ||||
| Toast.fail(error.message) | 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', | name: 'editPosition-chatgpt', | ||||
| component: () => import("../views/model/editPosition-chatgpt"), | component: () => import("../views/model/editPosition-chatgpt"), | ||||
| }, | }, | ||||
| // 编辑位置new | |||||
| { | |||||
| path: '/videoDownload', | |||||
| name: 'videoDownload', | |||||
| component: () => import("../views/videoDownload/videoDownload"), | |||||
| }, | |||||
| // 聊天首页new | // 聊天首页new | ||||
| { | { | ||||
| path: '/chat', | path: '/chat', | ||||
| @@ -297,7 +297,7 @@ export default { | |||||
| codeInfo: '获取验证码', | codeInfo: '获取验证码', | ||||
| inPage: false, | inPage: false, | ||||
| codeImg: '', //随机验证码图片 | codeImg: '', //随机验证码图片 | ||||
| loginType: 6, //显示页面字符 | |||||
| loginType: 1, //显示页面字符 | |||||
| showCodeImg: true, // 控制验证码的刷新 | showCodeImg: true, // 控制验证码的刷新 | ||||
| // 短信验证码登录 | // 短信验证码登录 | ||||
| form: { | form: { | ||||
| @@ -16,21 +16,6 @@ | |||||
| <van-tab v-for="item in tabList" :key="item" :title="item"> </van-tab> | <van-tab v-for="item in tabList" :key="item" :title="item"> </van-tab> | ||||
| </van-tabs> | </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="choose"> | ||||
| <div class="modeList" v-masonry item-selector=".model" column-width="170"> | <div class="modeList" v-masonry item-selector=".model" column-width="170"> | ||||
| @@ -43,9 +28,11 @@ | |||||
| :key="index" | :key="index" | ||||
| @click="selectModel(item.id)" | @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> | ||||
| <div class="alt" v-if="modeList.length == 0">暂无可用模板</div> | <div class="alt" v-if="modeList.length == 0">暂无可用模板</div> | ||||
| </div> | </div> | ||||
| @@ -62,6 +49,7 @@ import { Toast } from 'vant' | |||||
| import { scrollToID } from '../../utils' | import { scrollToID } from '../../utils' | ||||
| import { | import { | ||||
| getModeList, | getModeList, | ||||
| getModeList1, | |||||
| getModeDetailById, | getModeDetailById, | ||||
| saveOrUpdateUserVideo | saveOrUpdateUserVideo | ||||
| } from '../../api/chooseModel' | } from '../../api/chooseModel' | ||||
| @@ -122,7 +110,8 @@ export default { | |||||
| async loadModeList(sex) { | async loadModeList(sex) { | ||||
| try { | try { | ||||
| sex = sex == 0 ? '' : sex | sex = sex == 0 ? '' : sex | ||||
| const res = await getModeList(sex) | |||||
| // const res = await getModeList(sex) | |||||
| const res = await getModeList1(sex) | |||||
| console.log(res, '获取模板列表') | console.log(res, '获取模板列表') | ||||
| this.modeList = res.data.list | this.modeList = res.data.list | ||||
| } catch (error) { | } catch (error) { | ||||
| @@ -296,18 +285,15 @@ export default { | |||||
| position: relative; | position: relative; | ||||
| text-align: left; | text-align: left; | ||||
| margin-bottom: 15px; | margin-bottom: 15px; | ||||
| // border: 1px solid #00000028; | |||||
| // padding: 8px; | |||||
| // width: 154px; | |||||
| max-width: 170px; | max-width: 170px; | ||||
| // height: 305px; | |||||
| max-height: 310px; | |||||
| // transition: all 0.3s; | |||||
| opacity: 0.9; | opacity: 0.9; | ||||
| padding: 5px; | |||||
| &-padding { | |||||
| } | |||||
| img { | img { | ||||
| border-radius: 8px; | border-radius: 8px; | ||||
| width: 100%; | width: 100%; | ||||
| height: 273px; | |||||
| // height: 273px; | |||||
| } | } | ||||
| .modelName { | .modelName { | ||||
| margin-top: 10px; | margin-top: 10px; | ||||
| @@ -58,11 +58,10 @@ export default { | |||||
| { | { | ||||
| text: '小div1', | text: '小div1', | ||||
| url: 'img/BG@2x.b0cf224b.png', | url: 'img/BG@2x.b0cf224b.png', | ||||
| x: 300, | |||||
| x: 300, // 相对左上角XY坐标 | |||||
| y: 300, | y: 300, | ||||
| scale: 1, | |||||
| zIndex: 3, | |||||
| num: 1 | |||||
| scale: 1, //缩放 | |||||
| zIndex: 3 //层级 | |||||
| }, | }, | ||||
| { | { | ||||
| text: '小div2', | text: '小div2', | ||||
| @@ -39,25 +39,29 @@ | |||||
| :key="item.id ? item.id : index" | :key="item.id ? item.id : index" | ||||
| @click="goDetail(item)" | @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> | |||||
| <!-- 视频状态 草稿还是未完成还是失败 --> | |||||
| <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> | </div> | ||||
| </div> | </div> | ||||
| @@ -677,16 +681,21 @@ export default { | |||||
| display: flex; | display: flex; | ||||
| flex-wrap: wrap; | flex-wrap: wrap; | ||||
| justify-content: space-between; | justify-content: space-between; | ||||
| margin-right: -20px; | |||||
| width: 100%; | width: 100%; | ||||
| &-item { | &-item { | ||||
| // max-width: 355px; //非瀑布流 | // max-width: 355px; //非瀑布流 | ||||
| max-width: 170px; | max-width: 170px; | ||||
| max-height: 300px; | max-height: 300px; | ||||
| // background-color: red; | |||||
| padding: 5px; | |||||
| border-radius: 12px; | border-radius: 12px; | ||||
| margin-bottom: 10px; | |||||
| overflow: hidden; | overflow: hidden; | ||||
| &-paddding { | |||||
| position: relative; | |||||
| border-radius: 12px; | |||||
| overflow: hidden; | |||||
| width: 160px; | |||||
| // padding: 5px; | |||||
| } | |||||
| img { | img { | ||||
| max-width: 100%; | max-width: 100%; | ||||
| max-height: 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> | |||||