邃芒智像(Uniapp : WX、TT、H5)
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

382 líneas
9.3 KiB

  1. <template>
  2. <view class="page">
  3. <view class="title">
  4. <!-- 提示文字 -->
  5. <text v-show="uploadState == 1" class="tips">请添加一张正面照片</text>
  6. <text v-show="uploadState == 2" class="tips">请点击上传</text>
  7. <text v-show="uploadState == 3" class="tips">数字形象生成中</text>
  8. <text v-show="uploadState == 4" class="tips"
  9. >照片不符合规范,请重新上传</text
  10. >
  11. <text v-show="uploadState == 5" class="tips">上传失败,请重新上传</text>
  12. </view>
  13. <!-- 上传图片和展示 -->
  14. <view class="uploadBox imgContenBox scan">
  15. <!-- 扫描线 -->
  16. <view v-show="uploadState == 3" class="scan-line"></view>
  17. <image
  18. class="scan-border"
  19. src="../../assets/img/scanBorder.png"
  20. mode="aspectFit"
  21. />
  22. <!-- 上传按钮 -->
  23. <image
  24. class="addImg"
  25. v-show="!showImgUrl"
  26. src="../../assets/icon/add.png"
  27. alt=""
  28. @click="chooseImage"
  29. />
  30. <image
  31. class="showImg"
  32. v-show="showImgUrl"
  33. :src="showImgUrl"
  34. alt=""
  35. @click="chooseImage"
  36. mode="aspectFit"
  37. />
  38. </view>
  39. <view @click="toCloseStyle" class="uploadBtn">
  40. <text>上传我的照片</text>
  41. <view class="free">
  42. <image src="../../assets/icon/blackBG.png" mode="aspectFit" />
  43. <text>新用户免费制作</text>
  44. </view>
  45. </view>
  46. <!-- 底部盒子 -->
  47. <view class="bottomBox">
  48. <view class="tips2">请按照样片上传您五官清晰的正面照片</view>
  49. <view class="demoImgBox">
  50. <view class="imgBox">
  51. <image src="../../assets/img/img1.png" mode="aspectFit" />
  52. <view class="icon">
  53. <image src="../../assets/icon/error.png" mode="aspectFit" />
  54. </view>
  55. </view>
  56. <view class="imgBox">
  57. <image
  58. class="rightImg"
  59. src="../../assets/img/img2.png"
  60. mode="aspectFit"
  61. />
  62. <view class="icon">
  63. <image src="../../assets/icon/correct.png" mode="aspectFit" />
  64. </view>
  65. </view>
  66. <view class="imgBox">
  67. <image src="../../assets/img/img3.png" mode="aspectFit" />
  68. <view class="icon">
  69. <image src="../../assets/icon/error.png" mode="aspectFit" />
  70. </view>
  71. </view>
  72. </view>
  73. </view>
  74. </view>
  75. </template>
  76. <script setup>
  77. //#region 导入
  78. import { ref, reactive } from "vue";
  79. import { addImageApi } from "../../api/uploadphoto.js";
  80. import { userInfoModules } from "@/store/modules/userInfo";
  81. import imageCompression from "browser-image-compression"; //压缩图片插件
  82. //#endregion
  83. const userInfoModulesPinia = userInfoModules();
  84. //#region 选择图片
  85. const uploadState = ref(1); //上传状态
  86. const showImgUrl = ref(null); //回显路径
  87. const showImgUrl2 = ref(null); //回显路径
  88. const showImgData = ref(null); //上传数据
  89. function chooseImage() {
  90. // 调用uni.chooseImage方法选择图片
  91. uni.chooseImage({
  92. count: 1, // 最多可以选择的图片张数,这里设置为1,只选择一张图片
  93. success: async (res) => {
  94. uploadState.value = 2;
  95. // 图片压缩
  96. console.log(res.tempFiles[0].size);
  97. showImgUrl2.value = res.tempFiles[0];
  98. if (userInfoModulesPinia.platForm != 1) {
  99. uni.compressImage({
  100. src: res.tempFilePaths[0],
  101. quality: 80,
  102. success: (res2) => {
  103. showImgUrl.value = res2.tempFilePath;
  104. },
  105. });
  106. } else {
  107. const options = {
  108. maxSizeMB: 2, // 最大压缩大小为 4MB
  109. useWebWorker: true, // 使用 Web Worker 进行压缩,提高性能
  110. };
  111. const compressedFile = await imageCompression(
  112. res.tempFiles[0],
  113. options
  114. );
  115. //compressedFile是一个blob对象
  116. showImgUrl.value = URL.createObjectURL(compressedFile);
  117. showImgData.value = compressedFile;
  118. }
  119. },
  120. fail: (err) => {
  121. console.error("选择图片失败", err);
  122. },
  123. });
  124. }
  125. //#endregion ---------------------
  126. //#region 上传图片
  127. // console.log(userInfoModulesPinia.token, "token");
  128. async function toCloseStyle() {
  129. if (!showImgUrl.value) {
  130. uni.showToast({
  131. title: "请先上传图片",
  132. icon: "none",
  133. });
  134. return;
  135. }
  136. uploadState.value = 3;
  137. // 人脸识别接口
  138. uni.uploadFile({
  139. url: "https://test.metavatar.cc/C/api/userDigital/checkPhoto", //上传图片api
  140. filePath: showImgUrl.value,
  141. name: "file",
  142. formData: {
  143. user: "test",
  144. },
  145. header: {
  146. // Authorization: userInfoModulesPinia.token,
  147. token: userInfoModulesPinia.token,
  148. },
  149. success: (res) => {
  150. if (JSON.parse(res.data).code != 200) {
  151. uploadState.value = 4;
  152. return;
  153. }
  154. // 上传接口
  155. uni.uploadFile({
  156. url: "https://test.metavatar.cc/C/api/upload/awsImgUpload", //上传图片api
  157. filePath: showImgUrl.value,
  158. name: "file",
  159. formData: {
  160. user: "test",
  161. },
  162. header: {
  163. "Content-Type": "multipart/form-data",
  164. token: userInfoModulesPinia.token,
  165. },
  166. success: async (res2) => {
  167. if (JSON.parse(res2.data).code != 200) {
  168. uploadState.value = 5;
  169. uni.showToast({
  170. title: "网络被数字人偷走了, 请稍后重试",
  171. icon: "none",
  172. });
  173. return;
  174. }
  175. // 保存接口
  176. const res3 = await addImageApi({
  177. image: JSON.parse(res2.data).data.url,
  178. });
  179. if (res3.code == 200) {
  180. uni.redirectTo({
  181. url: "/pages/uploadPhoto/success",
  182. });
  183. } else {
  184. uni.showToast({
  185. title: "网络被数字人偷走了, 请稍后重试",
  186. icon: "none",
  187. });
  188. }
  189. },
  190. fail: () => {
  191. uploadState.value = 5;
  192. },
  193. });
  194. },
  195. fail: () => {
  196. uploadState.value = 4;
  197. },
  198. });
  199. }
  200. //#endregion ---------------------
  201. //#region
  202. //#endregion ---------------------
  203. </script>
  204. <style lang="scss">
  205. .page {
  206. position: relative;
  207. min-height: 100vh;
  208. background-color: rgba(0, 0, 0, 0.8);
  209. .bgc {
  210. position: absolute;
  211. width: 750rpx;
  212. height: 750rpx;
  213. transform: scale(1.5);
  214. top: 187rpx;
  215. left: 0;
  216. object-fit: cover;
  217. z-index: -2;
  218. backdrop-filter: blur(3px);
  219. }
  220. }
  221. .title {
  222. margin-bottom: 40rpx;
  223. .tips {
  224. margin-top: 20rpx;
  225. color: #fff;
  226. font-size: 44rpx;
  227. font-weight: 900;
  228. }
  229. }
  230. .uploadBox {
  231. position: relative;
  232. width: 420rpx;
  233. height: 560rpx;
  234. background-color: rgba(255, 255, 255, 0.1);
  235. border-radius: 50rpx;
  236. .scan-border {
  237. position: absolute;
  238. top: 50%;
  239. left: 50%;
  240. transform: translate(-50%, -50%);
  241. width: 360rpx;
  242. height: 480rpx;
  243. }
  244. .addImg {
  245. width: 80rpx;
  246. height: 80rpx;
  247. }
  248. .showImg {
  249. max-width: 90%;
  250. max-height: 90%;
  251. }
  252. .u-upload {
  253. position: absolute;
  254. top: 0;
  255. left: 0;
  256. width: 600rpx;
  257. height: 600rpx;
  258. opacity: 0;
  259. }
  260. }
  261. // 扫描
  262. .scan {
  263. overflow: hidden;
  264. .scan-line {
  265. position: absolute;
  266. top: 0;
  267. left: 0;
  268. width: 100%;
  269. height: 40%;
  270. background: linear-gradient(180deg, rgba(0, 255, 51, 0) 50%, #00ff33 300%);
  271. border-bottom: 2px solid #00ff33;
  272. animation: scanAnimation 2s linear infinite;
  273. z-index: 9;
  274. }
  275. @keyframes scanAnimation {
  276. 0% {
  277. transform: translateY(-150%);
  278. }
  279. 100% {
  280. transform: translateY(150%);
  281. }
  282. }
  283. }
  284. // 上传
  285. .uploadBtn {
  286. position: relative;
  287. margin-top: 75rpx;
  288. width: 520rpx;
  289. height: 100rpx;
  290. line-height: 100rpx;
  291. text-align: center;
  292. background: #ff4f00;
  293. border-radius: 50rpx;
  294. font-size: 30rpx;
  295. color: #fff;
  296. font-weight: 900;
  297. .free {
  298. position: absolute;
  299. top: -25rpx;
  300. right: -80rpx;
  301. width: 185rpx;
  302. height: 50rpx;
  303. image {
  304. position: absolute;
  305. top: 0;
  306. left: 0;
  307. width: 100%;
  308. height: 100%;
  309. z-index: 1;
  310. }
  311. text {
  312. position: absolute;
  313. top: -25rpx;
  314. left: 50%;
  315. transform: translate(-50%, 0);
  316. width: 100%;
  317. height: 100%;
  318. font-size: 22rpx;
  319. font-weight: 900;
  320. z-index: 2;
  321. }
  322. }
  323. }
  324. // 底部盒子
  325. .bottomBox {
  326. flex: 1;
  327. width: 100%;
  328. display: flex;
  329. flex-direction: column;
  330. align-items: center;
  331. justify-content: flex-end;
  332. padding: 0 0 90rpx 0;
  333. .tips2 {
  334. margin-top: 20rpx;
  335. margin-bottom: 15rpx;
  336. font-size: 22rpx;
  337. }
  338. .demoImgBox {
  339. display: flex;
  340. justify-content: space-between;
  341. align-items: flex-end;
  342. padding: 0 20rpx;
  343. width: 100%;
  344. .imgBox {
  345. position: relative;
  346. image {
  347. width: 180rpx;
  348. height: 180rpx;
  349. }
  350. .rightImg {
  351. width: 200rpx;
  352. height: 200rpx;
  353. }
  354. .icon {
  355. position: absolute;
  356. top: -8rpx;
  357. right: -8rpx;
  358. width: 36rpx;
  359. height: 36rpx;
  360. image {
  361. width: 100%;
  362. height: 100%;
  363. }
  364. }
  365. }
  366. }
  367. }
  368. </style>