邃芒智像(Uniapp : WX、TT、H5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

537 line
14 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" @click.stop="chooseImage">
  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. />
  29. <!-- @click.prevent="chooseImage" -->
  30. <image
  31. class="showImg"
  32. v-show="showImgUrl"
  33. :src="showImgUrl"
  34. alt=""
  35. mode="aspectFit"
  36. />
  37. </view>
  38. <view class="uploadBtn">
  39. <view @click="toCloseStyle" class="orangeBtn">上传新头像</view>
  40. <view
  41. class="grayBtn"
  42. v-if="userInfoModulesPinia.myAvatar"
  43. @click="goOtherPage('/pages/closeStyle/closeStyle')"
  44. >已有形象,直接创作</view
  45. >
  46. <view class="free">
  47. <image src="../../assets/icon/blackBG.png" mode="aspectFit" />
  48. <text>新用户免费制作</text>
  49. </view>
  50. </view>
  51. <!-- 底部盒子 -->
  52. <view class="bottomBox">
  53. <view class="tips2">请按照样片上传您五官清晰的正面照片</view>
  54. <view class="demoImgBox">
  55. <view class="imgBox">
  56. <image src="../../assets/img/img1.png" mode="aspectFit" />
  57. <view class="icon">
  58. <image src="../../assets/icon/error.png" mode="aspectFit" />
  59. </view>
  60. </view>
  61. <view class="imgBox">
  62. <image
  63. class="rightImg"
  64. src="../../assets/img/img2.png"
  65. mode="aspectFit"
  66. />
  67. <view class="icon">
  68. <image src="../../assets/icon/correct.png" mode="aspectFit" />
  69. </view>
  70. </view>
  71. <view class="imgBox">
  72. <image src="../../assets/img/img3.png" mode="aspectFit" />
  73. <view class="icon">
  74. <image src="../../assets/icon/error.png" mode="aspectFit" />
  75. </view>
  76. </view>
  77. </view>
  78. </view>
  79. </view>
  80. </template>
  81. <script setup>
  82. //#region 导入
  83. import { ref, reactive } from "vue";
  84. import { onLoad } from "@dcloudio/uni-app";
  85. import { loginApi } from "../../api/login";
  86. import { addImageApi } from "../../api/uploadphoto.js";
  87. import { userInfoModules } from "@/store/modules/userInfo";
  88. import imageCompression from "browser-image-compression"; //压缩图片插件
  89. import { findImageApi, findGlodApi } from "../../api/home";
  90. //#endregion
  91. const userInfoModulesPinia = userInfoModules();
  92. //#region 选择图片
  93. const uploadState = ref(1); //上传状态
  94. const showImgUrl = ref(""); //回显路径 压缩
  95. const showImgUrl2 = ref(null); //回显路径 未压缩
  96. const showImgData = ref(null); //上传数据
  97. // 点击上传图片
  98. function chooseImage() {
  99. // 检查token
  100. if (!userInfoModulesPinia.token) {
  101. uni.showModal({
  102. title: "提示",
  103. content: "登录以体验完整功能",
  104. success: function (res) {
  105. if (res.confirm) {
  106. uni.navigateTo({
  107. url: "/pages/login/index",
  108. });
  109. return;
  110. } else if (res.cancel) {
  111. console.log("用户点击取消");
  112. return;
  113. }
  114. },
  115. });
  116. } else {
  117. // 调用uni.chooseImage方法选择图片
  118. uni.chooseImage({
  119. count: 1, // 最多可以选择的图片张数,这里设置为1,只选择一张图片
  120. success: async (res) => {
  121. uploadState.value = 2;
  122. // 图片压缩
  123. console.log(res.tempFiles[0].size);
  124. showImgUrl2.value = res.tempFiles[0];
  125. if (userInfoModulesPinia.platForm != 1) {
  126. uni.compressImage({
  127. src: res.tempFilePaths[0],
  128. quality: 40,
  129. success: (res2) => {
  130. showImgUrl.value = res2.tempFilePath;
  131. },
  132. });
  133. } else {
  134. const options = {
  135. maxSizeMB: 2, // 最大压缩大小为 4MB
  136. useWebWorker: true, // 使用 Web Worker 进行压缩,提高性能
  137. };
  138. const compressedFile = await imageCompression(
  139. res.tempFiles[0],
  140. options
  141. );
  142. //compressedFile是一个blob对象
  143. showImgUrl.value = URL.createObjectURL(compressedFile);
  144. showImgData.value = compressedFile;
  145. }
  146. },
  147. fail: (err) => {
  148. console.error("选择图片失败", err);
  149. },
  150. });
  151. }
  152. }
  153. //#endregion ---------------------
  154. //#region 上传图片
  155. // console.log(userInfoModulesPinia.token, "token");
  156. async function toCloseStyle() {
  157. // 检查token
  158. if (!userInfoModulesPinia.token) {
  159. uni.showModal({
  160. title: "提示",
  161. content: "登录以体验完整功能",
  162. success: function (res) {
  163. if (res.confirm) {
  164. uni.navigateTo({
  165. url: "/pages/login/index",
  166. });
  167. return;
  168. } else if (res.cancel) {
  169. console.log("用户点击取消");
  170. return;
  171. }
  172. },
  173. });
  174. } else {
  175. if (!showImgUrl.value) {
  176. uni.showToast({
  177. title: "请先上传图片",
  178. icon: "none",
  179. });
  180. chooseImage();
  181. return;
  182. }
  183. uploadState.value = 3;
  184. console.log(showImgUrl.value);
  185. console.log(showImgUrl2.value.path);
  186. // 人脸识别接口
  187. uni.uploadFile({
  188. url: "https://test.metavatar.cc/C/api/userDigital/checkPhoto", //上传图片api
  189. filePath: showImgUrl2.value.path,
  190. name: "file",
  191. formData: {
  192. user: "test",
  193. },
  194. header: {
  195. // Authorization: userInfoModulesPinia.token,
  196. token: userInfoModulesPinia.token,
  197. },
  198. success: (res) => {
  199. if (JSON.parse(res.data).code != 200) {
  200. uploadState.value = 4;
  201. return;
  202. }
  203. // 上传接口
  204. uni.uploadFile({
  205. url: "https://test.metavatar.cc/C/api/upload/awsImgUpload", //上传图片api
  206. filePath: showImgUrl2.value.path,
  207. name: "file",
  208. formData: {
  209. user: "test",
  210. },
  211. header: {
  212. "Content-Type": "multipart/form-data",
  213. token: userInfoModulesPinia.token,
  214. },
  215. success: async (res2) => {
  216. let moment = res2;
  217. if (JSON.parse(res2.data).code != 200) {
  218. uploadState.value = 5;
  219. uni.showToast({
  220. title: "网络被数字人偷走了, 请稍后重试",
  221. icon: "none",
  222. });
  223. return;
  224. }
  225. // 保存接口
  226. const res3 = await addImageApi({
  227. image: JSON.parse(res2.data).data.url,
  228. });
  229. if (res3.code == 200) {
  230. // 改变全局的头像
  231. userInfoModulesPinia.myAvatar = JSON.parse(moment.data).data.url;
  232. uni.redirectTo({
  233. url: "/pages/uploadPhoto/success",
  234. });
  235. } else {
  236. uni.showToast({
  237. title: "网络被数字人偷走了, 请稍后重试",
  238. icon: "none",
  239. });
  240. }
  241. },
  242. fail: () => {
  243. uploadState.value = 5;
  244. },
  245. });
  246. },
  247. fail: () => {
  248. uploadState.value = 1;
  249. uni.showToast({
  250. title: "网络被数字人偷走了, 请稍后重试",
  251. icon: "none",
  252. });
  253. },
  254. });
  255. }
  256. }
  257. //#endregion ---------------------
  258. //#region 页面初始化
  259. onLoad((options) => {
  260. // showImgUrl.value = userInfoModulesPinia.myAvatar;
  261. // 微信登录授权
  262. if (userInfoModulesPinia.platForm != 1) {
  263. uni.login({
  264. provider: "weixin", // 使用微信登录授权
  265. success: async (res) => {
  266. console.log(res);
  267. if (res.code) {
  268. console.log(res.code);
  269. try {
  270. uni.showLoading({
  271. title: "加载中...",
  272. mask: true,
  273. });
  274. const data = {
  275. appId: "wx75cf14e3a0d45821",
  276. code: res.code,
  277. };
  278. const res2 = await loginApi(data);
  279. userInfoModulesPinia.openId = res2.data.openId;
  280. if (res2.data.token) {
  281. userInfoModulesPinia.token = res2.data.token;
  282. console.log(userInfoModulesPinia.openId, "获取openid");
  283. // 获取头像和金币
  284. const res3 = await findImageApi();
  285. userInfoModulesPinia.myAvatar =
  286. res3.data && res3.data.image ? res3.data.image : "";
  287. const res4 = await findGlodApi();
  288. if (!res4.data) {
  289. userInfoModulesPinia.myGlod = 0;
  290. } else {
  291. userInfoModulesPinia.myGlod = res4.data.digitalAvatarResidueGlod
  292. ? res4.data.digitalAvatarResidueGlod
  293. : 0;
  294. }
  295. uni.hideLoading();
  296. if (res2.data.token) {
  297. // uni.redirectTo({
  298. // url: "/pages/index/index",
  299. // });
  300. } else {
  301. uni.redirectTo({
  302. url: "/pages/login/index",
  303. });
  304. console.log("error1");
  305. uni.showToast({
  306. title: "登录失败,请重试",
  307. icon: "none",
  308. });
  309. }
  310. }
  311. uni.hideLoading();
  312. } catch (error) {
  313. // uni.redirectTo({
  314. // url: "pages/index/index",
  315. // });
  316. console.log(error, "error2");
  317. uni.showToast({
  318. title: "登录失败,请重试",
  319. icon: "none",
  320. });
  321. }
  322. } else {
  323. // uni.redirectTo({
  324. // url: "pages/index/index",
  325. // });
  326. console.log("error3");
  327. uni.showToast({
  328. title: "登录失败,请重试",
  329. icon: "none",
  330. });
  331. }
  332. },
  333. fail: (err) => {
  334. // uni.redirectTo({
  335. // url: "pages/index/index",
  336. // });
  337. console.log("error4");
  338. uni.showToast({
  339. title: "登录失败,请重试",
  340. icon: "none",
  341. });
  342. },
  343. });
  344. }
  345. });
  346. //#endregion ---------------------
  347. //#region
  348. function goOtherPage(url) {
  349. uni.navigateTo({
  350. url: url,
  351. });
  352. }
  353. //#endregion ---------------------
  354. //#region
  355. //#endregion ---------------------
  356. </script>
  357. <style lang="scss">
  358. .page {
  359. position: relative;
  360. min-height: 100vh;
  361. background-color: #222527;
  362. // background-color: rgba(0, 0, 0, 0.8);
  363. .bgc {
  364. position: absolute;
  365. width: 750rpx;
  366. height: 750rpx;
  367. transform: scale(1.5);
  368. top: 187rpx;
  369. left: 0;
  370. object-fit: cover;
  371. z-index: -2;
  372. backdrop-filter: blur(3px);
  373. }
  374. }
  375. .title {
  376. margin-bottom: 40rpx;
  377. .tips {
  378. margin-top: 20rpx;
  379. color: #fff;
  380. font-size: 44rpx;
  381. font-weight: 900;
  382. }
  383. }
  384. .uploadBox {
  385. position: relative;
  386. width: 420rpx;
  387. height: 560rpx;
  388. background-color: rgba(255, 255, 255, 0.1);
  389. border-radius: 50rpx;
  390. .scan-border {
  391. position: absolute;
  392. top: 50%;
  393. left: 50%;
  394. transform: translate(-50%, -50%);
  395. width: 360rpx;
  396. height: 480rpx;
  397. }
  398. .addImg {
  399. width: 80rpx;
  400. height: 80rpx;
  401. }
  402. .showImg {
  403. max-width: 90%;
  404. max-height: 90%;
  405. }
  406. .u-upload {
  407. position: absolute;
  408. top: 0;
  409. left: 0;
  410. width: 600rpx;
  411. height: 600rpx;
  412. opacity: 0;
  413. }
  414. }
  415. // 扫描
  416. .scan {
  417. overflow: hidden;
  418. .scan-line {
  419. position: absolute;
  420. top: 0;
  421. left: 0;
  422. width: 100%;
  423. height: 40%;
  424. background: linear-gradient(180deg, rgba(0, 255, 51, 0) 50%, #00ff33 300%);
  425. border-bottom: 2px solid #00ff33;
  426. animation: scanAnimation 2s linear infinite;
  427. z-index: 9;
  428. }
  429. @keyframes scanAnimation {
  430. 0% {
  431. transform: translateY(-150%);
  432. }
  433. 100% {
  434. transform: translateY(150%);
  435. }
  436. }
  437. }
  438. // 上传
  439. .uploadBtn {
  440. position: relative;
  441. margin-top: 75rpx;
  442. width: 520rpx;
  443. // height: 100rpx;
  444. line-height: 100rpx;
  445. text-align: center;
  446. // background: #ff4f00;
  447. border-radius: 50rpx;
  448. font-size: 30rpx;
  449. color: #fff;
  450. font-weight: 900;
  451. .free {
  452. position: absolute;
  453. top: -25rpx;
  454. right: -80rpx;
  455. width: 185rpx;
  456. height: 50rpx;
  457. image {
  458. position: absolute;
  459. top: 0;
  460. left: 0;
  461. width: 100%;
  462. height: 100%;
  463. z-index: 1;
  464. }
  465. text {
  466. position: absolute;
  467. top: -25rpx;
  468. left: 50%;
  469. transform: translate(-50%, 0);
  470. width: 100%;
  471. height: 100%;
  472. font-size: 22rpx;
  473. font-weight: 900;
  474. z-index: 2;
  475. }
  476. }
  477. }
  478. // 底部盒子
  479. .bottomBox {
  480. flex: 1;
  481. width: 100%;
  482. display: flex;
  483. flex-direction: column;
  484. align-items: center;
  485. justify-content: flex-end;
  486. padding: 0 0 90rpx 0;
  487. .tips2 {
  488. margin-top: 20rpx;
  489. margin-bottom: 15rpx;
  490. font-size: 22rpx;
  491. }
  492. .demoImgBox {
  493. display: flex;
  494. justify-content: space-between;
  495. align-items: flex-end;
  496. padding: 0 20rpx;
  497. width: 100%;
  498. .imgBox {
  499. position: relative;
  500. image {
  501. width: 180rpx;
  502. height: 180rpx;
  503. }
  504. .rightImg {
  505. width: 200rpx;
  506. height: 200rpx;
  507. }
  508. .icon {
  509. position: absolute;
  510. top: -8rpx;
  511. right: -8rpx;
  512. width: 36rpx;
  513. height: 36rpx;
  514. image {
  515. width: 100%;
  516. height: 100%;
  517. }
  518. }
  519. }
  520. }
  521. }
  522. </style>