haizemu преди 3 месеца
родител
ревизия
d0bec0785a
променени са 7 файла, в които са добавени 230 реда и са изтрити 19 реда
  1. 2 1
      config/dev.js
  2. 2 1
      package.json
  3. 37 1
      src/apis/userApi.ts
  4. 25 2
      src/pages/user/mine/index.scss
  5. 129 11
      src/pages/user/mine/index.tsx
  6. 22 0
      src/utils/crypto.ts
  7. 13 3
      src/utils/request.ts

+ 2 - 1
config/dev.js

@@ -5,7 +5,8 @@ module.exports = {
   defineConstants: {
     ENV: '"DEVELOPMENT"',
     // "HOST": '"http://192.168.0.168:810"',
-    HOST: '"https://api.hryk.net"',
+    "HOST": '"http://loan-web-api2.internal.jiebide.xin"',
+    // HOST: '"https://api.hryk.net"',
     APPID: '"422"',
   },
   mini: {},

+ 2 - 1
package.json

@@ -68,7 +68,8 @@
     "react-dom": "^18.0.0",
     "react-native": "^0.69.3",
     "react-redux": "^8.0.5",
-    "taro-ui": "^3.3.0"
+    "taro-ui": "^3.3.0",
+    "crypto-js": "^4.1.1"
   },
   "devDependencies": {
     "@babel/core": "^7.8.0",

+ 37 - 1
src/apis/userApi.ts

@@ -162,6 +162,32 @@ export  class HomeFetchChannelBody {
     ///
     refer: string
 }
+export  class sendCodeBody {
+    ///
+    channelCode: string;
+
+    ///
+    phone: string
+    
+    ///
+    sceneType: string
+}
+export  class loginBody {
+    ///
+    channelCode: string;
+
+    ///
+    phone: string;
+
+    ///
+    sceneType: string;
+
+    ///
+    uctrackid: string
+
+    ///
+    verifyCode: string
+}
 export  class HomeTabUsingPostResponse {
         
                 /// undefined
@@ -204,5 +230,15 @@ export  class HomeTabUsingPostResponse {
         static homeFetchChannel(options: AxiosRequestConfigFunc<HomeFetchChannelBody, any>):RequestUtil<any> {
             return new RequestUtil<any>('/h5/query/channel', 'POST', options)
         }
+
+        static sendCode(options: AxiosRequestConfigFunc<sendCodeBody, any>):RequestUtil<any> {
+            return new RequestUtil<any>('/h5/send/sms', 'POST', options)
+        }
+        static login(options: AxiosRequestConfigFunc<loginBody, any>):RequestUtil<any> {
+            return new RequestUtil<any>('/h5/login', 'POST', options)
+        }
         }
-        
+        
+
+    //     sendCode: params => post("h5/send/sms", params),
+	// login: params => post("h5/login", params),

+ 25 - 2
src/pages/user/mine/index.scss

@@ -189,6 +189,7 @@
 }
 .login-introduce{
   padding:20px;
+  margin-bottom:20px;
   .title{
     display: flex;
     justify-content: space-between;
@@ -210,8 +211,9 @@
   .blue{
     color:#007AFF;
   }
-  .fontsize{
+  .fontsize36{
     font-size:36px;
+    margin-bottom:20px;
   }
   .custom-checkbox {
     display: inline-block;
@@ -223,9 +225,10 @@
   }
   .other-login{
     text-align: center;
-    padding:20px 0;
+    margin:20px 0;
     color:#5c6e98;
     font-size: 26px;
+    
   }
   .checkd{
     display: flex;
@@ -280,4 +283,24 @@
 }
 .at-float-layout--active .at-float-layout__container{
   border-radius: 30px 30px 0 0 ; 
+}
+.bg{
+  position: fixed;
+  top:0;
+  z-index: 1000;
+  width: 100vh;
+  height: 100vh;
+  background-color:rgba(0, 0, 0, 0.3);
+  transition: all 0.3s ease;
+  .box-bg{
+    position: absolute;
+    bottom:0;
+    width: 100vh;
+    height: 30vh;
+    background-color: #fff;
+    transition: all 0.3s ease;
+  }
+  .on30{
+    // bottom:30vh;
+  }
 }

+ 129 - 11
src/pages/user/mine/index.tsx

@@ -17,6 +17,7 @@ import "./index.scss";
 import React, { useState , useEffect, useCallback} from 'react'
 import { AtFloatLayout } from "taro-ui"
 import { showToast } from "@tarojs/taro";
+import ctyptoUtil from "@/utils/crypto";
 interface IMineProps {}
 
 const Mine = (props: PropsWithChildren<IMineProps>) => {
@@ -38,10 +39,26 @@ const Mine = (props: PropsWithChildren<IMineProps>) => {
   }
   // 关闭浮动层的函数
   const handleClose = () => {
-    setIsSHow(false)
+    setIsSHow(false);
+    // setIsGetValidate(false);
+    // setTime(10); // 重置倒计时
+    setPhone('');
+    setValidate('');
+    setCheckedPhone(false);
+    setChecked(false);
+    setShowNum(0);
+
   }
   const [showNum, setShowNum] = useState(0)
   const showNumChange = (val) => {
+    if(!checked){
+      showToast({
+          title: "请确定已阅读并同意!",
+          icon: "none",
+          duration: 2000,
+      });
+      return
+    }
     setShowNum(val)
   }
   const ApplyButton = ({ isLogin }) => {
@@ -120,7 +137,26 @@ const Mine = (props: PropsWithChildren<IMineProps>) => {
   const handleCheckboxChange = () => {
     setChecked(!checked)
   }
-
+  const  quickLogin =async (e) =>{
+    if(!checked){
+      showToast({
+          title: "请确定已阅读并同意!",
+          icon: "none",
+          duration: 2000,
+      });
+      return
+    }
+    if (e.detail.code && await UserHelper.userWxLogin(e.detail.code) === true) {
+      handleClose();
+      indexInfoResult.data &&
+      RouteUtil.toWebViewPage({
+        url: indexInfoResult.data.link,
+      });
+        if (UserHelper.callback) {
+            await UserHelper.callback();
+        }
+    }
+  }
 
   // 打开浮动层的函数
   const LoginIntroduce = () =>{
@@ -166,9 +202,14 @@ const Mine = (props: PropsWithChildren<IMineProps>) => {
           <Text onClick={goRegPage} className="blue">《注册政策》</Text><Text onClick={goPrivacyPage} className="blue">《隐私政策》</Text>
         </View>
         <View>
-        <Button className='index-back-btn fontsize' onClick={() => {
-          }}
+          {
+            checked ?  <Button className='index-back-btn fontsize' openType='getPhoneNumber' 
+            onGetPhoneNumber={quickLogin}
           >一键快捷登录</Button>
+          :
+          <Button className='index-back-btn fontsize' onClick={quickLogin}>一键快捷登录</Button>
+          }
+        
         </View>
         <View onClick={showNumChange.bind(null, 1)} className="other-login">输入手机号登录</View>
       </View>
@@ -186,12 +227,16 @@ const Mine = (props: PropsWithChildren<IMineProps>) => {
   const timeChange = (val) => {
     setTime(val)
   }
-  const phoneNumChange = useCallback((e) => {
+  const phoneNumChange = (e) => {
     setPhone(e.detail.value);
-  }, [])
-  const validateChange = useCallback((e) => {
+    // setFocus1(true);
+    // setFocus2(false);
+  }
+  const validateChange = (e) => {
     setValidate(e.detail.value);
-  }, [])
+    // setFocus1(false);
+    // setFocus2(true);
+  }
   useEffect(() => {
     let intervalId = null;
     if (isGetValidate && time > 0) {
@@ -205,10 +250,35 @@ const Mine = (props: PropsWithChildren<IMineProps>) => {
     return () => clearInterval(intervalId);
   }, [isGetValidate, time]);
 
-  const isGetValidateChange = () => {
+  const isGetValidateChange = async () => {
+    if(phone == ""){
+      showToast({
+        title: "手机号不能为空!",
+        icon: "none",
+        duration: 2000,
+      });
+      return
+    }
+    // setFocus1(false);
+    // setFocus2(false);
     setIsGetValidate(!isGetValidate);
     setTime(10); // 重置倒计时
+    let obj = {
+      "channelCode":"txxcx01",
+      "phone":ctyptoUtil.AesEncode(phone),
+      "sceneType":"register"
+    }
+    UserApi.sendCode({
+      data: { ...obj },
+    }).h5toData().then((res:any) => {
+      showToast({
+        title: res.msg,
+        icon: "none",
+        duration: 2000,
+    });
+    })
   }
+
   const submitClick = () =>{
     if(!checkedPhone){
       showToast({
@@ -216,6 +286,7 @@ const Mine = (props: PropsWithChildren<IMineProps>) => {
           icon: "none",
           duration: 2000,
       });
+      return
     }
     if(phone == ""){
       showToast({
@@ -223,14 +294,43 @@ const Mine = (props: PropsWithChildren<IMineProps>) => {
         icon: "none",
         duration: 2000,
       });
+      return
     }else if(validate == ""){
       showToast({
         title: "验证码不能为空!",
         icon: "none",
         duration: 2000,
       });
+      return
     }
-
+    let obj = {
+      "channelCode":"txxcx01",
+      "phone":ctyptoUtil.AesEncode(phone),
+      sceneType:"register",
+      uctrackid: "",
+      verifyCode:validate,
+    }
+    UserApi.login({
+      data: { ...obj },
+    }).h5toData().then(async(res:any) => {
+      if(res.code == 1){
+        showToast({
+          title: res.msg,
+          icon: "none",
+          duration: 2000,
+        });
+      }else if(res.code == 0){
+        indexInfoResult.data &&
+          RouteUtil.toWebViewPage({
+            url: indexInfoResult.data.link,
+          });
+          if (UserHelper.callback) {
+            await UserHelper.callback();
+          }
+      }
+    }).catch((err)=>{
+      console.log(err)
+    })
   }
   const goRegPage = () =>{
     RouteUtil.toWebViewPage({
@@ -242,6 +342,8 @@ const Mine = (props: PropsWithChildren<IMineProps>) => {
       url: "/pages/user/aggrement/index",
     });
   }
+  // const [focus1, setFocus1] = useState(false);
+  // const [focus2, setFocus2] = useState(false);
   const PhoneLogin = () =>{
     return(
       <>
@@ -285,13 +387,29 @@ const Mine = (props: PropsWithChildren<IMineProps>) => {
             <Text onClick={goRegPage} className="blue">《注册政策》</Text><Text onClick={goRegPage} className="blue">《隐私政策》</Text>
           </View>
           <View>
-          <Button className='index-back-btn fontsize' onClick={submitClick}
+          <Button className='index-back-btn fontsize36' onClick={submitClick}
             >立即登录</Button>
           </View>
       </View>
       </>
     )
   }
+
+
+  const [isShow2, setIsShow2] = useState(false);
+  const [phone2, setPhone2] = useState('');
+  const [validate2, setValidate2] = useState('');
+  const phoneNumChange2 = (e) => {
+    setPhone2(e.detail.value);
+
+  }
+  const validateChange2 = (e) => {
+    setValidate2(e.detail.value);
+  }
+
+
+
+
   return (
     <Layout className='mine' bottomBarIndex={1}>
       <SizeBox height={statusBarHeight}></SizeBox>

+ 22 - 0
src/utils/crypto.ts

@@ -0,0 +1,22 @@
+import CryptoJS from 'crypto-js'
+const key = CryptoJS.enc.Utf8.parse('47FC4124CF94E070') // 密钥
+const iv = CryptoJS.enc.Utf8.parse('ovOh2xYoRdfATob6') // 密钥偏移量
+// 加密方法
+
+export default class ctyptoUtil {
+
+    public static AesEncode(word: string) {
+        let srcs = CryptoJS.enc.Utf8.parse(word);
+
+        // console.log('split("").reverse().join("")',word.split("").reverse().join(""))
+        // 对称加密算法主要有AES、DES、3DES / 非对称加密算法主要有RSA、DSA、RCC
+        // iv(初始变量)
+        // key(加密密钥)
+        // mode(加密模式 主要有CBC(默认)、CFB、CTR、OFB、ECB
+        // padding(填充方式 主要有Pkcs7(默认)、Iso97971、AnsiX923、Iso10126、ZeroPadding)
+
+        let encrypted = CryptoJS.AES.encrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
+        let encryptedBase64Data = CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
+        return encodeURIComponent(encryptedBase64Data);
+    }
+}

+ 13 - 3
src/utils/request.ts

@@ -7,7 +7,7 @@ import StorageUtil, { EStorage } from "./storageUtil";
 
 
 interface IRequestBaseResult<T> {
-    code?: 0;
+    code?: Number;
     data: T;
     msg: string;
 }
@@ -72,6 +72,9 @@ export default class RequestUtil<T> {
     private checkSuccessSync(data: Taro.request.SuccessCallbackResult<IRequestBaseResult<T>>) {
         return data.statusCode >= 200 && data.statusCode < 300 && data.data.code === 0;
     }
+    private h5checkSuccessSync(data: Taro.request.SuccessCallbackResult<IRequestBaseResult<T>>) {
+        return data.statusCode >= 200 && data.statusCode < 300 && data.data.code === 0 || data.data.code == 1;
+    }
 
     /**是否正确 */
     public async checkSuccess() {
@@ -87,6 +90,13 @@ export default class RequestUtil<T> {
                 return null;
             })
     }
-
-
+    public async h5toData() {
+        return this.promise
+            .then((p) => {
+                if (this.h5checkSuccessSync(p)) {
+                    return p.data;
+                }
+                return null;
+            })
+    }
 }