LoginBox.tsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. import "./LoginBox.scss";
  2. import UserApi from "@/apis/userApi";
  3. import Button from "@/component/button";
  4. import APPConfig from "@/config";
  5. import UserHelper from "@/helper/userHelper";
  6. import RouteUtil from "@/utils/routeUtil";
  7. import StorageUtil, { EStorage } from "@/utils/storageUtil";
  8. import Taro from "@tarojs/taro";
  9. import { Image, View, Text, Input } from "@tarojs/components";
  10. import { useRequest } from "ahooks";
  11. import {
  12. parseQueryParams,
  13. isOuterLink,
  14. replaceQueryParam,
  15. } from "../../../utils/toolsUtil";
  16. import { useState, useEffect, useImperativeHandle, forwardRef } from "react";
  17. import { AtFloatLayout } from "taro-ui";
  18. import { showToast } from "@tarojs/taro";
  19. import ctyptoUtil from "@/utils/crypto";
  20. // @ts-ignore
  21. const LoginBox = forwardRef((props, ref) => {
  22. const channelCode: any = StorageUtil.get(EStorage.channelCode) || "";
  23. useImperativeHandle(ref, () => ({
  24. handleOpen() {
  25. handleOpen();
  26. },
  27. }));
  28. const indexInfoResult: any = useRequest(() => {
  29. return UserApi.getIndexInfoUsingPost({
  30. params: { appId: APPConfig.APPID },
  31. }).toData();
  32. });
  33. const postJumpUrlResult = () => {
  34. const params: any = parseQueryParams(indexInfoResult.data.link);
  35. return UserApi.getJumpUrlPost({
  36. loading: true,
  37. data: {
  38. appId: APPConfig.APPID,
  39. channelCode: params.channelCode,
  40. productId: params.productId,
  41. },
  42. })
  43. .toData()
  44. .then((res: any) => {
  45. console.log("获取跳转链接结果", res);
  46. RouteUtil.toWebViewPage({ url: res?.adJumpLink });
  47. });
  48. };
  49. const loginFlowHandler = async () => {
  50. await UserHelper.UpdateOpenId();
  51. if (isOuterLink(indexInfoResult?.data.link)) {
  52. // 如果是外部链接,不用管
  53. await postJumpUrlResult();
  54. } else {
  55. const jumpUrl = channelCode
  56. ? replaceQueryParam(
  57. indexInfoResult.data.link,
  58. "channelCode",
  59. channelCode
  60. )
  61. : indexInfoResult.data.link;
  62. RouteUtil.toWebViewPage({
  63. url: jumpUrl,
  64. });
  65. }
  66. };
  67. const [isSHow, setIsSHow] = useState(false);
  68. // 打开浮动层的函数
  69. const handleOpen = () => {
  70. setShowNum(0);
  71. setIsSHow(true);
  72. };
  73. // 关闭浮动层的函数
  74. const handleClose = () => {
  75. setIsSHow(false);
  76. // setIsGetValidate(false);
  77. // setTime(10); // 重置倒计时
  78. setPhone("");
  79. setValidate("");
  80. setCheckedPhone(false);
  81. setChecked(false);
  82. };
  83. const [showNum, setShowNum] = useState(0);
  84. let appName: any = useState("惠融钱包");
  85. const showNumChange = (val) => {
  86. if (!checked) {
  87. showToast({
  88. title: "请确定已阅读并同意!",
  89. icon: "none",
  90. duration: 2000,
  91. });
  92. return;
  93. }
  94. const appInfo: any = Taro.getAccountInfoSync();
  95. const appId = appInfo.appId;
  96. switch (appId) {
  97. case "wxc7ed88182aa77a68":
  98. appName = "惠融钱包";
  99. break;
  100. case "wxaca93174bcaa6453":
  101. appName = "惠融好借";
  102. break;
  103. case "wxf7762282683395d1":
  104. appName = "诚易融";
  105. break;
  106. default:
  107. // 默认惠融钱包
  108. appName = "惠融钱包";
  109. break;
  110. }
  111. setShowNum(val);
  112. };
  113. const [checked, setChecked] = useState(false);
  114. const handleCheckboxChange = () => {
  115. setChecked(!checked);
  116. };
  117. const quickLogin = async (e) => {
  118. if (!checked) {
  119. showToast({
  120. title: "请确定已阅读并同意!",
  121. icon: "none",
  122. duration: 2000,
  123. });
  124. return;
  125. }
  126. if (
  127. e.detail.code &&
  128. (await UserHelper.userWxLogin(e.detail.code, channelCode)) === true
  129. ) {
  130. handleClose();
  131. // indexInfoResult.data &&
  132. // RouteUtil.toWebViewPage({
  133. // url: indexInfoResult.data.link,
  134. // });
  135. // if (UserHelper.callback) {
  136. // await UserHelper.callback();
  137. // }
  138. loginFlowHandler();
  139. }
  140. };
  141. const [time, setTime] = useState(60);
  142. const [isGetValidate, setIsGetValidate] = useState(false);
  143. const [validate, setValidate] = useState("");
  144. const [phone, setPhone] = useState("");
  145. const [checkedPhone, setCheckedPhone] = useState(false);
  146. const phoneChange = () => {
  147. setCheckedPhone(!checkedPhone);
  148. };
  149. const timeChange = (val) => {
  150. setTime(val);
  151. };
  152. const phoneNumChange = (e) => {
  153. setPhone(e.detail.value);
  154. };
  155. const validateChange = (e) => {
  156. setValidate(e.detail.value);
  157. };
  158. useEffect(() => {
  159. let intervalId: any = null;
  160. if (isGetValidate && time > 0) {
  161. intervalId = setInterval(() => {
  162. timeChange((prevCount) => prevCount - 1);
  163. }, 1000);
  164. } else if (time === 0) {
  165. setIsGetValidate(false);
  166. clearInterval(intervalId);
  167. }
  168. return () => clearInterval(intervalId);
  169. }, [isGetValidate, time]);
  170. const isGetValidateChange = async () => {
  171. if (phone == "") {
  172. showToast({
  173. title: "请输入本人实名认证手机号!",
  174. icon: "none",
  175. duration: 2000,
  176. });
  177. return;
  178. }
  179. if (isPhoneAvailable(phone)) {
  180. setIsGetValidate(!isGetValidate);
  181. setTime(60); // 重置倒计时
  182. let obj = {
  183. channelCode: channelCode || APPConfig.CHANNELCODE,
  184. phone: ctyptoUtil.AesEncode(phone),
  185. sceneType: "register",
  186. };
  187. UserApi.sendCode({
  188. data: { ...obj },
  189. })
  190. .h5toData()
  191. .then((res: any) => {
  192. showToast({
  193. title: res.msg,
  194. icon: "none",
  195. duration: 2000,
  196. });
  197. });
  198. } else {
  199. showToast({
  200. title: "手机号有误!",
  201. icon: "none",
  202. duration: 2000,
  203. });
  204. }
  205. };
  206. const isPhoneAvailable = (value) => {
  207. let phoneReg = /^[1][3,4,5,7,8,9][0-9]{9}$/;
  208. return phoneReg.test(value);
  209. };
  210. const submitClick = () => {
  211. if (!checkedPhone) {
  212. showToast({
  213. title: "请确定已阅读并同意",
  214. icon: "none",
  215. duration: 2000,
  216. });
  217. return;
  218. }
  219. if (phone == "") {
  220. showToast({
  221. title: "请输入本人实名认证手机号",
  222. icon: "none",
  223. duration: 2000,
  224. });
  225. return;
  226. } else if (!isPhoneAvailable(phone)) {
  227. showToast({
  228. title: "手机号有误",
  229. icon: "none",
  230. duration: 2000,
  231. });
  232. return;
  233. } else if (validate == "") {
  234. showToast({
  235. title: "验证码不能为空",
  236. icon: "none",
  237. duration: 2000,
  238. });
  239. return;
  240. }
  241. let obj = {
  242. channelCode: channelCode || APPConfig.CHANNELCODE,
  243. phone: ctyptoUtil.AesEncode(phone),
  244. sceneType: "register",
  245. uctrackid: "",
  246. verifyCode: validate,
  247. };
  248. UserApi.login({
  249. data: { ...obj },
  250. })
  251. .h5toData()
  252. .then(async (res: any) => {
  253. if (res.code == 1) {
  254. showToast({
  255. title: res.msg,
  256. icon: "none",
  257. duration: 2000,
  258. });
  259. } else if (res.code == 0) {
  260. handleClose();
  261. let obj: any = {
  262. userId: res.data.userId,
  263. token: res.data.token,
  264. userMobile: phone,
  265. };
  266. UserHelper.cacheUserInfo(obj);
  267. // indexInfoResult.data &&
  268. // RouteUtil.toWebViewPage({
  269. // url: indexInfoResult.data.link,
  270. // });
  271. // if (UserHelper.callback) {
  272. // await UserHelper.callback();
  273. // }
  274. loginFlowHandler();
  275. }
  276. })
  277. .catch((err) => {
  278. console.log(err);
  279. });
  280. };
  281. const aggrement = useRequest(() => {
  282. return UserApi.agreementsUsingPost({
  283. data: { pageView: "user_center_view" },
  284. }).toData();
  285. });
  286. const goRegPage = () => {
  287. aggrement.data?.map((p) => {
  288. if (p.name == "用户服务协议") {
  289. RouteUtil.toWebViewPage({ url: p.url });
  290. }
  291. });
  292. };
  293. const goPrivacyPage = () => {
  294. console.log(aggrement);
  295. aggrement.data?.map((p) => {
  296. if (p.name == "隐私政策") {
  297. RouteUtil.toWebViewPage({ url: p.url });
  298. }
  299. });
  300. };
  301. const goStudentPage = () => {
  302. console.log(aggrement);
  303. aggrement.data?.map((p) => {
  304. if (p.name == "非学生承诺函") {
  305. RouteUtil.toWebViewPage({ url: p.url });
  306. }
  307. });
  308. };
  309. return (
  310. <AtFloatLayout isOpened={isSHow} onClose={handleClose}>
  311. {showNum == 0 && (
  312. <Image
  313. src={require("@/assets/box-bg.png")}
  314. className="avatar-image-bg"
  315. />
  316. )}
  317. {showNum == 0 ? (
  318. <View className="login-introduce">
  319. <View className="title">
  320. 登录方式选择及隐私政策告知
  321. <View onClick={handleClose}>
  322. <Image
  323. src={require("@/assets/close.png")}
  324. className="avatar-image"
  325. />
  326. </View>
  327. </View>
  328. <View className="text">
  329. 为了您正常的使用我们的小程序服务,我们需要处理您的个人信息,具体详见{" "}
  330. <Text onClick={goPrivacyPage} className="blue">
  331. 《隐私政策》
  332. </Text>
  333. 。 在您未确认
  334. <Text onClick={goPrivacyPage} className="blue">
  335. 《隐私政策》
  336. </Text>
  337. 前,我们不会搜集您的任何信息。
  338. {/* 当您勾选协议后即标识您已阅读并同意
  339. <Text onClick={goPrivacyPage} className="blue">
  340. 《隐私政策》
  341. </Text>
  342. <Text onClick={goRegPage} className="blue">
  343. 《注册政策》
  344. </Text>
  345. 上的全部内容 */}
  346. </View>
  347. <View className="checkd">
  348. <View className="checkbox">
  349. {checked ? (
  350. <Image
  351. onClick={handleCheckboxChange}
  352. src={require("@/assets/checkd.png")}
  353. className="avatar-image"
  354. />
  355. ) : (
  356. <Image
  357. onClick={handleCheckboxChange}
  358. src={require("@/assets/check.png")}
  359. className="avatar-image"
  360. />
  361. )}
  362. <Text className="agree" onClick={handleCheckboxChange}>
  363. 请确定已阅读并同意
  364. </Text>
  365. </View>
  366. <Text onClick={goPrivacyPage} className="blue">
  367. 《隐私政策》
  368. </Text>
  369. <Text onClick={goRegPage} className="blue">
  370. 《用户服务协议》
  371. </Text>
  372. <Text className="agree">和</Text>
  373. <Text onClick={goStudentPage} className="blue">
  374. 《非学生承诺函》
  375. </Text>
  376. </View>
  377. <View>
  378. {checked ? (
  379. <Button
  380. className="index-quck-btn fontsize36"
  381. openType="getPhoneNumber"
  382. onGetPhoneNumber={quickLogin}
  383. >
  384. 一键快捷登录
  385. </Button>
  386. ) : (
  387. <Button
  388. className="index-quck-btn fontsize36"
  389. onClick={quickLogin}
  390. >
  391. 一键快捷登录
  392. </Button>
  393. )}
  394. </View>
  395. <View onClick={showNumChange.bind(null, 1)} className="other-login">
  396. 输入手机号登录
  397. </View>
  398. </View>
  399. ) : (
  400. <View className="login-introduce phone-login">
  401. <View className="title">
  402. <Text className="text-title">登录{appName}</Text>
  403. <View onClick={handleClose} className="float">
  404. <Image
  405. src={require("@/assets/close.png")}
  406. className="avatar-image"
  407. />
  408. </View>
  409. </View>
  410. <View className="input-box">
  411. <View className="input-phone">
  412. <Input
  413. type="text"
  414. placeholderClass="gray"
  415. onInput={phoneNumChange}
  416. value={phone}
  417. placeholder="请输入本人实名认证手机号"
  418. maxlength={11}
  419. />
  420. </View>
  421. <View className="input-password">
  422. <Input
  423. type="text"
  424. placeholderClass="gray"
  425. onInput={validateChange}
  426. value={validate}
  427. placeholder="请输入验证码"
  428. maxlength={6}
  429. />
  430. {isGetValidate ? (
  431. <View className="gray">重新发送 ({time}S)</View>
  432. ) : (
  433. <View className="gettime" onClick={isGetValidateChange}>
  434. 获取验证码
  435. </View>
  436. )}
  437. </View>
  438. </View>
  439. <View className="checkd">
  440. <View className="checkbox">
  441. {checkedPhone ? (
  442. <Image
  443. onClick={phoneChange}
  444. src={require("@/assets/checkd.png")}
  445. className="avatar-image"
  446. />
  447. ) : (
  448. <Image
  449. onClick={phoneChange}
  450. src={require("@/assets/check.png")}
  451. className="avatar-image"
  452. />
  453. )}
  454. <Text className="agree" onClick={phoneChange}>
  455. 请确定已阅读并同意
  456. </Text>
  457. </View>
  458. <Text onClick={goPrivacyPage} className="blue">
  459. 《隐私政策》
  460. </Text>
  461. <Text onClick={goRegPage} className="blue">
  462. 《用户服务协议》
  463. </Text>
  464. <Text onClick={goStudentPage} className="blue">
  465. 《非学生承诺函》
  466. </Text>
  467. </View>
  468. <View>
  469. <Button className="index-quck-btn fontsize36" onClick={submitClick}>
  470. 立即登录
  471. </Button>
  472. </View>
  473. </View>
  474. )}
  475. </AtFloatLayout>
  476. );
  477. });
  478. export default LoginBox;