LoginBox.tsx 13 KB

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