LoginBox.tsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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 "wxf7762282683395d1":
  101. appName = "诚易融";
  102. break;
  103. default:
  104. // 默认惠融钱包
  105. appName = "惠融钱包";
  106. break;
  107. }
  108. setShowNum(val);
  109. };
  110. const [checked, setChecked] = useState(false);
  111. const handleCheckboxChange = () => {
  112. setChecked(!checked);
  113. };
  114. const quickLogin = async (e) => {
  115. if (!checked) {
  116. showToast({
  117. title: "请确定已阅读并同意!",
  118. icon: "none",
  119. duration: 2000,
  120. });
  121. return;
  122. }
  123. if (
  124. e.detail.code &&
  125. (await UserHelper.userWxLogin(e.detail.code, channelCode)) === true
  126. ) {
  127. handleClose();
  128. // indexInfoResult.data &&
  129. // RouteUtil.toWebViewPage({
  130. // url: indexInfoResult.data.link,
  131. // });
  132. // if (UserHelper.callback) {
  133. // await UserHelper.callback();
  134. // }
  135. loginFlowHandler();
  136. }
  137. };
  138. const [time, setTime] = useState(60);
  139. const [isGetValidate, setIsGetValidate] = useState(false);
  140. const [validate, setValidate] = useState("");
  141. const [phone, setPhone] = useState("");
  142. const [checkedPhone, setCheckedPhone] = useState(false);
  143. const phoneChange = () => {
  144. setCheckedPhone(!checkedPhone);
  145. };
  146. const timeChange = (val) => {
  147. setTime(val);
  148. };
  149. const phoneNumChange = (e) => {
  150. setPhone(e.detail.value);
  151. };
  152. const validateChange = (e) => {
  153. setValidate(e.detail.value);
  154. };
  155. useEffect(() => {
  156. let intervalId: any = null;
  157. if (isGetValidate && time > 0) {
  158. intervalId = setInterval(() => {
  159. timeChange((prevCount) => prevCount - 1);
  160. }, 1000);
  161. } else if (time === 0) {
  162. setIsGetValidate(false);
  163. clearInterval(intervalId);
  164. }
  165. return () => clearInterval(intervalId);
  166. }, [isGetValidate, time]);
  167. const isGetValidateChange = async () => {
  168. if (phone == "") {
  169. showToast({
  170. title: "请输入本人实名认证手机号!",
  171. icon: "none",
  172. duration: 2000,
  173. });
  174. return;
  175. }
  176. if (isPhoneAvailable(phone)) {
  177. setIsGetValidate(!isGetValidate);
  178. setTime(60); // 重置倒计时
  179. let obj = {
  180. channelCode: channelCode || "hrqbxcx",
  181. phone: ctyptoUtil.AesEncode(phone),
  182. sceneType: "register",
  183. };
  184. UserApi.sendCode({
  185. data: { ...obj },
  186. })
  187. .h5toData()
  188. .then((res: any) => {
  189. showToast({
  190. title: res.msg,
  191. icon: "none",
  192. duration: 2000,
  193. });
  194. });
  195. } else {
  196. showToast({
  197. title: "手机号有误!",
  198. icon: "none",
  199. duration: 2000,
  200. });
  201. }
  202. };
  203. const isPhoneAvailable = (value) => {
  204. let phoneReg = /^[1][3,4,5,7,8,9][0-9]{9}$/;
  205. return phoneReg.test(value);
  206. };
  207. const submitClick = () => {
  208. if (!checkedPhone) {
  209. showToast({
  210. title: "请确定已阅读并同意",
  211. icon: "none",
  212. duration: 2000,
  213. });
  214. return;
  215. }
  216. if (phone == "") {
  217. showToast({
  218. title: "请输入本人实名认证手机号",
  219. icon: "none",
  220. duration: 2000,
  221. });
  222. return;
  223. } else if (!isPhoneAvailable(phone)) {
  224. showToast({
  225. title: "手机号有误",
  226. icon: "none",
  227. duration: 2000,
  228. });
  229. return;
  230. } else if (validate == "") {
  231. showToast({
  232. title: "验证码不能为空",
  233. icon: "none",
  234. duration: 2000,
  235. });
  236. return;
  237. }
  238. let obj = {
  239. channelCode: channelCode || "hrqbxcx",
  240. phone: ctyptoUtil.AesEncode(phone),
  241. sceneType: "register",
  242. uctrackid: "",
  243. verifyCode: validate,
  244. };
  245. UserApi.login({
  246. data: { ...obj },
  247. })
  248. .h5toData()
  249. .then(async (res: any) => {
  250. if (res.code == 1) {
  251. showToast({
  252. title: res.msg,
  253. icon: "none",
  254. duration: 2000,
  255. });
  256. } else if (res.code == 0) {
  257. handleClose();
  258. let obj: any = {
  259. userId: res.data.userId,
  260. token: res.data.token,
  261. userMobile: phone,
  262. };
  263. UserHelper.cacheUserInfo(obj);
  264. // indexInfoResult.data &&
  265. // RouteUtil.toWebViewPage({
  266. // url: indexInfoResult.data.link,
  267. // });
  268. // if (UserHelper.callback) {
  269. // await UserHelper.callback();
  270. // }
  271. loginFlowHandler();
  272. }
  273. })
  274. .catch((err) => {
  275. console.log(err);
  276. });
  277. };
  278. const aggrement = useRequest(() => {
  279. return UserApi.agreementsUsingPost({
  280. data: { pageView: "user_center_view" },
  281. }).toData();
  282. });
  283. const goRegPage = () => {
  284. aggrement.data?.map((p) => {
  285. if (p.name == "用户服务协议") {
  286. RouteUtil.toWebViewPage({ url: p.url });
  287. }
  288. });
  289. };
  290. const goPrivacyPage = () => {
  291. console.log(aggrement);
  292. aggrement.data?.map((p) => {
  293. if (p.name == "隐私政策") {
  294. RouteUtil.toWebViewPage({ url: p.url });
  295. }
  296. });
  297. };
  298. const goStudentPage = () => {
  299. console.log(aggrement);
  300. aggrement.data?.map((p) => {
  301. if (p.name == "非学生承诺函") {
  302. RouteUtil.toWebViewPage({ url: p.url });
  303. }
  304. });
  305. };
  306. return (
  307. <AtFloatLayout isOpened={isSHow} onClose={handleClose}>
  308. {showNum == 0 && (
  309. <Image
  310. src={require("@/assets/box-bg.png")}
  311. className="avatar-image-bg"
  312. />
  313. )}
  314. {showNum == 0 ? (
  315. <View className="login-introduce">
  316. <View className="title">
  317. 登录方式选择及隐私政策告知
  318. <View onClick={handleClose}>
  319. <Image
  320. src={require("@/assets/close.png")}
  321. className="avatar-image"
  322. />
  323. </View>
  324. </View>
  325. <View className="text">
  326. 为了您正常的使用我们的小程序服务,我们需要处理您的个人信息,具体详见{" "}
  327. <Text onClick={goPrivacyPage} className="blue">
  328. 《隐私政策》
  329. </Text>
  330. 。 在您未确认
  331. <Text onClick={goPrivacyPage} className="blue">
  332. 《隐私政策》
  333. </Text>
  334. 前,我们不会搜集您的任何信息。
  335. {/* 当您勾选协议后即标识您已阅读并同意
  336. <Text onClick={goPrivacyPage} className="blue">
  337. 《隐私政策》
  338. </Text>
  339. <Text onClick={goRegPage} className="blue">
  340. 《注册政策》
  341. </Text>
  342. 上的全部内容 */}
  343. </View>
  344. <View className="checkd">
  345. <View className="checkbox">
  346. {checked ? (
  347. <Image
  348. onClick={handleCheckboxChange}
  349. src={require("@/assets/checkd.png")}
  350. className="avatar-image"
  351. />
  352. ) : (
  353. <Image
  354. onClick={handleCheckboxChange}
  355. src={require("@/assets/check.png")}
  356. className="avatar-image"
  357. />
  358. )}
  359. <Text className="agree" onClick={handleCheckboxChange}>
  360. 请确定已阅读并同意
  361. </Text>
  362. </View>
  363. <Text onClick={goPrivacyPage} className="blue">
  364. 《隐私政策》
  365. </Text>
  366. <Text onClick={goRegPage} className="blue">
  367. 《用户服务协议》
  368. </Text>
  369. <Text className="agree">和</Text>
  370. <Text onClick={goStudentPage} className="blue">
  371. 《非学生承诺函》
  372. </Text>
  373. </View>
  374. <View>
  375. {checked ? (
  376. <Button
  377. className="index-quck-btn fontsize36"
  378. openType="getPhoneNumber"
  379. onGetPhoneNumber={quickLogin}
  380. >
  381. 一键快捷登录
  382. </Button>
  383. ) : (
  384. <Button
  385. className="index-quck-btn fontsize36"
  386. onClick={quickLogin}
  387. >
  388. 一键快捷登录
  389. </Button>
  390. )}
  391. </View>
  392. <View onClick={showNumChange.bind(null, 1)} className="other-login">
  393. 输入手机号登录
  394. </View>
  395. </View>
  396. ) : (
  397. <View className="login-introduce phone-login">
  398. <View className="title">
  399. <Text className="text-title">登录{appName}</Text>
  400. <View onClick={handleClose} className="float">
  401. <Image
  402. src={require("@/assets/close.png")}
  403. className="avatar-image"
  404. />
  405. </View>
  406. </View>
  407. <View className="input-box">
  408. <View className="input-phone">
  409. <Input
  410. type="text"
  411. placeholderClass="gray"
  412. onInput={phoneNumChange}
  413. value={phone}
  414. placeholder="请输入本人实名认证手机号"
  415. maxlength={11}
  416. />
  417. </View>
  418. <View className="input-password">
  419. <Input
  420. type="text"
  421. placeholderClass="gray"
  422. onInput={validateChange}
  423. value={validate}
  424. placeholder="请输入验证码"
  425. maxlength={6}
  426. />
  427. {isGetValidate ? (
  428. <View className="gray">重新发送 ({time}S)</View>
  429. ) : (
  430. <View className="gettime" onClick={isGetValidateChange}>
  431. 获取验证码
  432. </View>
  433. )}
  434. </View>
  435. </View>
  436. <View className="checkd">
  437. <View className="checkbox">
  438. {checkedPhone ? (
  439. <Image
  440. onClick={phoneChange}
  441. src={require("@/assets/checkd.png")}
  442. className="avatar-image"
  443. />
  444. ) : (
  445. <Image
  446. onClick={phoneChange}
  447. src={require("@/assets/check.png")}
  448. className="avatar-image"
  449. />
  450. )}
  451. <Text className="agree" onClick={phoneChange}>
  452. 请确定已阅读并同意
  453. </Text>
  454. </View>
  455. <Text onClick={goPrivacyPage} className="blue">
  456. 《隐私政策》
  457. </Text>
  458. <Text onClick={goRegPage} className="blue">
  459. 《用户服务协议》
  460. </Text>
  461. <Text onClick={goStudentPage} className="blue">
  462. 《非学生承诺函》
  463. </Text>
  464. </View>
  465. <View>
  466. <Button className="index-quck-btn fontsize36" onClick={submitClick}>
  467. 立即登录
  468. </Button>
  469. </View>
  470. </View>
  471. )}
  472. </AtFloatLayout>
  473. );
  474. });
  475. export default LoginBox;