邃芒智像(Uniapp : WX、TT、H5)
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 

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