邃芒官网、邃芒慧影、口播(H5) https://m.metavatar.cc
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

345 行
10 KiB

  1. <template>
  2. <div class="uploder">
  3. <div class="change-photo-setter" style="height: 240px; width: 160px">
  4. <van-uploader ref="uploader" class="sett-item" :before-read="beforeRead" style="height: 240px; width: 160px">
  5. <div style="height: 240px; width: 160px">
  6. <!-- <img :src="ImgUrl" alt="" /> -->
  7. </div>
  8. </van-uploader>
  9. </div>
  10. <div class="uploadava">
  11. <!-- van-popup有bug,某些1情况需要绑定app为根 -->
  12. <van-popup :get-container="this.isAndroid ? '' : '#app'" class="vanPopup" duration="0" v-model="showCropper" position="top" :style="{ height: '100%' }">
  13. <div class="cropper-container" :style="{ height: '94vh' }">
  14. <van-loading v-show="loadingShow" size="50" color="#fff" vertical text-color="#fff">上传中...</van-loading>
  15. <!-- 切图组件 -->
  16. <vueCropper
  17. style="background-image: none"
  18. ref="cropper"
  19. :img="option.img"
  20. :outputSize="option.outputSize"
  21. :outputType="option.outputType"
  22. :info="option.info"
  23. :full="option.full"
  24. :autoCropWidth="option.autoCropWidth"
  25. :autoCropHeight="option.autoCropHeight"
  26. :canMove="option.canMove"
  27. :canMoveBox="option.canMoveBox"
  28. :original="option.original"
  29. :autoCrop="option.autoCrop"
  30. :fixed="option.fixed"
  31. :fixedNumber="option.fixedNumber"
  32. :centerBox="option.centerBox"
  33. :infoTrue="option.infoTrue"
  34. :fixedBox="option.fixedBox"
  35. :high="option.high"
  36. :mode="option.mode" />
  37. <!-- <div style="display: flex; justify-content: space-between; padding: 10px; height: 8vh">
  38. <div @click="onClickLeft">取消</div>
  39. <div @click="onClickRight">确定</div>
  40. </div> -->
  41. <van-nav-bar left-text="取消" right-text="确定" @click-left="onClickLeft" @click-right="onClickRight" />
  42. </div>
  43. </van-popup>
  44. </div>
  45. </div>
  46. </template>
  47. <script>
  48. import { awsImgUpload } from '@/api/editModel';
  49. import { Toast } from 'vant';
  50. import { VueCropper } from 'vue-cropper';
  51. import { scrollToID, getDeviceType } from '../utils';
  52. import { saveImgApi } from '../api/editModel';
  53. import { watch } from 'vue';
  54. export default {
  55. name: 'uploadAva',
  56. components: {
  57. VueCropper
  58. },
  59. props: {
  60. showAta: {
  61. default: false,
  62. type: Boolean
  63. },
  64. avaUrl: {
  65. default: '',
  66. type: String
  67. },
  68. type: {
  69. default: '',
  70. type: Number
  71. },
  72. videoType: {
  73. default: null,
  74. type: Number
  75. }
  76. },
  77. data() {
  78. return {
  79. isAndroid: false, //判断是不是ios
  80. aaa: null,
  81. ImgUrl: '',
  82. show: true, // 上传类型的弹窗
  83. imageFileName: '',
  84. showCropper: false, // 裁剪的弹窗
  85. option: {
  86. img: '',
  87. outputSize: 0.8,
  88. info: false, // 裁剪框的大小信息
  89. // outputType: 'jpeg', // 裁剪生成图片的格式
  90. outputType: 'png', // 裁剪生成图片的格式
  91. canScale: true, // 图片是否允许滚轮缩放
  92. autoCrop: true, // 是否默认生成截图框
  93. autoCropWidth: window.innerWidth - 100 + 'px', // 默认生成截图框宽度
  94. autoCropHeight: window.innerWidth - 100 + 'px', // 默认生成截图框高度
  95. high: true, // 是否按照设备的dpr 输出等比例图片
  96. fixedBox: false, // 固定截图框大小 不允许改变
  97. fixed: false, // 是否开启截图框宽高固定比例
  98. // fixedNumber: [1, 1], // 截图框的宽高比例
  99. full: true, // 是否输出原图比例的截图
  100. canMoveBox: true, // 截图框能否拖动
  101. original: false, // 上传图片按照原始比例渲染
  102. centerBox: true, // 截图框是否被限制在图片里面
  103. infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
  104. mode: '100% auto' // 图片默认渲染方式
  105. },
  106. loadingShow: false // 是否展示loading
  107. };
  108. },
  109. created() {
  110. const deviceType = getDeviceType();
  111. this.isAndroid = false;
  112. if (!deviceType) {
  113. // 设备类型为pc
  114. this.isAndroid = false;
  115. } else {
  116. if (deviceType[0] == 'Android') {
  117. // 设备类型为安卓
  118. this.isAndroid = true;
  119. } else {
  120. // 其他设备
  121. this.isAndroid = false;
  122. }
  123. }
  124. if (this.type == 4 && this.videoType == 1) {
  125. this.option.autoCropWidth = 1080 + 'px'; // 默认生成截图框宽度
  126. this.option.autoCropHeight = 1920 + 'px'; // 默认生成截图框高度
  127. this.option.fixed = true;
  128. this.option.fixedNumber = [1080, 1920];
  129. }
  130. if (this.type == 4 && this.videoType == 2) {
  131. this.option.autoCropWidth = 1920 + 'px'; // 默认生成截图框宽度
  132. this.option.autoCropHeight = 1080 + 'px'; // 默认生成截图框高度
  133. this.option.fixed = true;
  134. this.option.fixedNumber = [1920, 1080];
  135. }
  136. },
  137. methods: {
  138. beforeRead(file) {
  139. // console.log(file)
  140. if (file.type !== 'image/jpeg' && file.type !== 'image/png') {
  141. this.$toast('请上传 jpg/png 格式图片');
  142. return false;
  143. }
  144. let data = window.URL.createObjectURL(new Blob([file]));
  145. this.option.img = data; //给裁剪图片的路径
  146. this.showCropper = true;
  147. return false;
  148. },
  149. // 点击裁剪的选择
  150. onClickRight() {
  151. let that = this;
  152. this.loadingShow = true;
  153. this.$refs.cropper.getCropBlob(async data => {
  154. let formData = new FormData();
  155. formData.append('file', data);
  156. let file = formData.get('file');
  157. // 转为 base64
  158. // let reader = new FileReader();
  159. // const base64Data = await new Promise((resolve, reject) => {
  160. // reader.onload = () => {
  161. // resolve(reader.result);
  162. // };
  163. // reader.readAsDataURL(file);
  164. // });
  165. // let imgBinary = await that.base64ToBinary(base64Data.substring(23));
  166. // // base64结果
  167. // that.ImgUrl = base64Data;
  168. that.loading = false;
  169. // console.log(that.ImgUrl, 'dasdasd')
  170. // 发请求
  171. const AccessToken = localStorage.getItem('AccessToken');
  172. that
  173. .$axios({
  174. method: 'post',
  175. // url: `https://smapitest.malls.iformall.com/C/api/upload/awsImgUpload`,
  176. url: `http://m.metavatar.cc/C/api/upload/awsImgUpload`,
  177. headers: {
  178. 'content-type': 'multipart/form-data',
  179. token: AccessToken,
  180. 'Access-Control-Allow-Credentials': true
  181. },
  182. data: formData
  183. })
  184. .then(async res => {
  185. // console.log(res.data.data.url)
  186. const res1 = await saveImgApi({
  187. type: that.type,
  188. videoType: that.videoType,
  189. material: res.data.data.url
  190. });
  191. // 重新获取列表
  192. await that.$parent.$parent.getMyBGIListApi();
  193. await that.$parent.$parent.getMyScListApi();
  194. if (this.type == 4) {
  195. that.$parent.$parent.changeShowBGIList(1);
  196. }
  197. if (this.type == 5) {
  198. that.$parent.$parent.changeShowBGIList(3);
  199. }
  200. that.loadingShow = false;
  201. that.showCropper = false;
  202. Toast.success('上传成功');
  203. });
  204. });
  205. },
  206. // 点击取消
  207. onClickLeft() {
  208. this.loadingShow = false;
  209. this.showCropper = false;
  210. this.$parent.showPhotoUploader = false;
  211. },
  212. // 上传图片
  213. async pushImg(data) {
  214. try {
  215. const res = await awsImgUpload(data);
  216. this.loadingShow = false;
  217. this.showCropper = false;
  218. Toast.success('上传成功');
  219. } catch (error) {
  220. console.log(error, 'error');
  221. Toast.fail(error.message);
  222. }
  223. },
  224. //图片转base64,异步
  225. toBase64(file) {
  226. let that = this;
  227. return new Promise((resolve, reject) => {
  228. const reader = new FileReader();
  229. reader.onload = () => {
  230. // base64结果
  231. that.ImgUrl = this.result;
  232. that.loading = false;
  233. };
  234. reader.onerror = reject;
  235. reader.readAsDataURL(file);
  236. });
  237. },
  238. // base64 转二进制
  239. base64ToBinary(base64) {
  240. const binaryStr = window.atob(base64);
  241. const len = binaryStr.length;
  242. const bytes = new Uint8Array(len);
  243. for (let i = 0; i < len; ++i) {
  244. bytes[i] = binaryStr.charCodeAt(i);
  245. }
  246. return bytes;
  247. }
  248. }
  249. };
  250. </script>
  251. <style lang="scss" scoped>
  252. // /deep/.cropper-container {
  253. // z-index: 2005 !important;
  254. // }
  255. // .uploder{
  256. // overflow: hidden;
  257. // }
  258. /deep/.cropper-view-box {
  259. outline: 2px dashed #fff !important;
  260. }
  261. /deep/.crop-point {
  262. background-color: auto !important;
  263. }
  264. /deep/.van-loading {
  265. position: absolute;
  266. // color: red;
  267. z-index: 9999;
  268. left: 50%;
  269. top: 50%;
  270. margin-left: -55px;
  271. margin-top: -30px;
  272. background: rgba(0, 0, 0, 0.3);
  273. padding: 10px 30px;
  274. border-radius: 25px;
  275. }
  276. .uploadava {
  277. // width: 100%;
  278. // width: 100vw;
  279. height: 94vh;
  280. .update-avatar {
  281. height: 100%;
  282. text-align: center;
  283. .update-avatar-line {
  284. width: 100%;
  285. height: 1px;
  286. background-color: #979797;
  287. }
  288. .avatar-select-type {
  289. background-color: #fff;
  290. width: 346px;
  291. border-radius: 12px;
  292. padding-bottom: 4px;
  293. .upload-avator {
  294. padding: 14px;
  295. }
  296. }
  297. p {
  298. margin: 15px 0 30px;
  299. background-color: #fff;
  300. width: 346px;
  301. border-radius: 12px;
  302. padding: 15px 0 18px;
  303. }
  304. }
  305. .cropper-container {
  306. position: relative;
  307. width: 100%;
  308. height: 94vh;
  309. // height: 100%;
  310. /deep/ .van-nav-bar {
  311. position: absolute;
  312. z-index: 999;
  313. width: 100%;
  314. bottom: 0px;
  315. left: 0px;
  316. height: 6vh;
  317. background-color: rgba(0, 0, 0, 0.87);
  318. :global(.van-nav-bar__text) {
  319. color: #000;
  320. // font-size: $font-size-normal-x;
  321. }
  322. :global(.van-nav-bar__text:nth-child(2)) {
  323. color: #000;
  324. font-weight: 500;
  325. }
  326. // :global(.van-icon) {
  327. // color: red;
  328. // }
  329. }
  330. }
  331. .vue-cropper {
  332. background: #000;
  333. width: 100%;
  334. height: 88vh;
  335. padding-top: 46px;
  336. box-sizing: border-box;
  337. }
  338. }
  339. </style>