邃芒官网、邃芒慧影、口播(H5) https://m.metavatar.cc
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 

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