瀏覽代碼

处理登录逻辑

Pq 3 年之前
父節點
當前提交
c5c09c9544
共有 28 個文件被更改,包括 1102 次插入29 次删除
  1. 1 0
      BaseLibrary/src/main/java/com/cooleshow/base/common/BaseConstant.java
  2. 31 0
      BaseLibrary/src/main/java/com/cooleshow/base/utils/Utils.java
  3. 247 0
      BaseLibrary/src/main/java/com/cooleshow/base/widgets/VerifyEditText.java
  4. 5 0
      BaseLibrary/src/main/res/drawable/shape_code_input_bg.xml
  5. 6 0
      BaseLibrary/src/main/res/drawable/shape_code_input_bg_select.xml
  6. 5 0
      BaseLibrary/src/main/res/drawable/shape_login_bt_bg_unselect.xml
  7. 2 0
      BaseLibrary/src/main/res/values/colors.xml
  8. 58 0
      BaseLibrary/src/main/res/values/styles.xml
  9. 2 1
      Provider/src/main/java/com/cooleshow/provider/router/RouterPath.kt
  10. 2 1
      teacher/src/main/java/com/cooleshow/teacher/ui/splash/SplashActivity.kt
  11. 10 3
      usercenter/src/main/AndroidManifest.xml
  12. 9 0
      usercenter/src/main/java/com/cooleshow/usercenter/UserConstants.java
  13. 36 6
      usercenter/src/main/java/com/cooleshow/usercenter/data/api/UserApi.kt
  14. 30 0
      usercenter/src/main/java/com/cooleshow/usercenter/helper/PhoneCheckHelper.java
  15. 14 0
      usercenter/src/main/java/com/cooleshow/usercenter/helper/UserHelper.java
  16. 39 0
      usercenter/src/main/java/com/cooleshow/usercenter/presenter/BindPasswordPresenter.java
  17. 58 1
      usercenter/src/main/java/com/cooleshow/usercenter/presenter/VerifyLoginPresenter.java
  18. 18 0
      usercenter/src/main/java/com/cooleshow/usercenter/presenter/contract/BindPasswordContract.java
  19. 4 2
      usercenter/src/main/java/com/cooleshow/usercenter/presenter/contract/VerifyLoginContract.java
  20. 79 0
      usercenter/src/main/java/com/cooleshow/usercenter/ui/activity/BindPasswordActivity.java
  21. 1 9
      usercenter/src/main/java/com/cooleshow/usercenter/ui/activity/LoginActivity.kt
  22. 206 0
      usercenter/src/main/java/com/cooleshow/usercenter/ui/activity/VerifyCodeInputActivity.java
  23. 18 6
      usercenter/src/main/java/com/cooleshow/usercenter/ui/activity/VerifyCodeLoginActivity.java
  24. 二進制
      usercenter/src/main/res/drawable-xhdpi/icon_back_black.png
  25. 二進制
      usercenter/src/main/res/drawable-xxhdpi/icon_back_black.png
  26. 127 0
      usercenter/src/main/res/layout/activity_bind_pwd_layout.xml
  27. 85 0
      usercenter/src/main/res/layout/activity_input_code_layout.xml
  28. 9 0
      usercenter/src/main/res/values/strings.xml

+ 1 - 0
BaseLibrary/src/main/java/com/cooleshow/base/common/BaseConstant.java

@@ -8,6 +8,7 @@ import com.cooleshow.base.BuildConfig;
 public class BaseConstant {
     public final static String SERVER_ADDRESS= BuildConfig.BASE_SERVER_URL;
     public final static String TEACHER_GROUP = "api-teacher/";
+    public final static String AUTH_GROUP = "api-auth/";
 
 
 

+ 31 - 0
BaseLibrary/src/main/java/com/cooleshow/base/utils/Utils.java

@@ -3,6 +3,12 @@ package com.cooleshow.base.utils;
 import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.app.Application;
+import android.graphics.drawable.Drawable;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.ImageSpan;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
@@ -128,4 +134,29 @@ public final class Utils {
     public interface Func1<Ret, Par> {
         Ret call(Par param);
     }
+
+    public static SpannableString diffColorString(String bigSizeStr, String centerStr, String lastStr, int firstColor, int centerColor) {
+        String tmpStr = bigSizeStr + centerStr + lastStr;
+        SpannableString result = new SpannableString(tmpStr);
+        try{
+            result.setSpan(new ForegroundColorSpan(firstColor), 0, bigSizeStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            result.setSpan(new ForegroundColorSpan(centerColor), bigSizeStr.length(), bigSizeStr.length() + centerStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            result.setSpan(new ForegroundColorSpan(firstColor), bigSizeStr.length() + centerStr.length(), tmpStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+    public static SpannableString diffColorString(String bigSizeStr, String lastStr, int firstColor, int lastColor) {
+        String tmpStr = bigSizeStr + lastStr;
+        SpannableString result = new SpannableString(tmpStr);
+        try {
+            result.setSpan(new ForegroundColorSpan(firstColor), 0, bigSizeStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            result.setSpan(new ForegroundColorSpan(lastColor), bigSizeStr.length(), tmpStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
 }

+ 247 - 0
BaseLibrary/src/main/java/com/cooleshow/base/widgets/VerifyEditText.java

@@ -0,0 +1,247 @@
+package com.cooleshow.base.widgets;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.text.Editable;
+import android.text.InputFilter;
+import android.text.InputType;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.text.method.HideReturnsTransformationMethod;
+import android.text.method.PasswordTransformationMethod;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.cooleshow.base.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
+
+/**
+ * Author by pq, Date on 2022/4/24.
+ */
+public class VerifyEditText extends LinearLayout {
+    //默认 item 个数为 4 个
+    private final static int DEFAULT_ITEM_COUNT = 4;
+    //默认每个 item 的宽度为 100
+    private final static int DEFAULT_ITEM_WIDTH = 100;
+    //默认每个 item 的间距为 50
+    private final static int DEFAULT_ITEM_MARGIN = 50;
+    //默认每个 item 的字体大小为 14
+    private final static int DEFAULT_ITEM_TEXT_SIZE = 14;
+    //默认密码明文显示时间为 200ms,之后密文显示
+    private final static int DEFAULT_PASSWORD_VISIBLE_TIME = 200;
+
+    private final List<TextView> mTextViewList = new ArrayList<>();
+    private EditText mEditText;
+    private Drawable drawableNormal, drawableSelected;
+    private Context mContext;
+    //输入完成监听
+    private InputCompleteListener mInputCompleteListener;
+
+    public VerifyEditText(Context context) {
+        this(context, null);
+    }
+
+    public VerifyEditText(Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public VerifyEditText(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init(context, attrs);
+    }
+
+    private void init(Context context, @Nullable AttributeSet attrs) {
+        mContext = context;
+        setOrientation(HORIZONTAL);
+        setGravity(Gravity.CENTER);
+        @SuppressLint("CustomViewStyleable") TypedArray obtainStyledAttributes =
+                getContext().obtainStyledAttributes(attrs, R.styleable.verify_EditText);
+        drawableNormal = obtainStyledAttributes.getDrawable(R.styleable.verify_EditText_verify_background_normal);
+        drawableSelected = obtainStyledAttributes.getDrawable(R.styleable.verify_EditText_verify_background_selected);
+        int textColor = obtainStyledAttributes.getColor(R.styleable.verify_EditText_verify_textColor,
+                ContextCompat.getColor(context, android.R.color.black));
+        int count = obtainStyledAttributes.getInt(R.styleable.verify_EditText_verify_count, DEFAULT_ITEM_COUNT);
+        int inputType = obtainStyledAttributes.getInt(R.styleable.verify_EditText_verify_inputType, InputType.TYPE_CLASS_NUMBER);
+        int passwordVisibleTime = obtainStyledAttributes.getInt(R.styleable.verify_EditText_verify_password_visible_time, DEFAULT_PASSWORD_VISIBLE_TIME);
+        int width = (int) obtainStyledAttributes.getDimension(R.styleable.verify_EditText_verify_width, DEFAULT_ITEM_WIDTH);
+        int height = (int) obtainStyledAttributes.getDimension(R.styleable.verify_EditText_verify_height, 0);
+        int margin = (int) obtainStyledAttributes.getDimension(R.styleable.verify_EditText_verify_margin, DEFAULT_ITEM_MARGIN);
+        float textSize = px2sp(context,obtainStyledAttributes.getDimension(R.styleable.verify_EditText_verify_textSize, sp2px(context,DEFAULT_ITEM_TEXT_SIZE)));
+        boolean password = obtainStyledAttributes.getBoolean(R.styleable.verify_EditText_verify_password, false);
+        obtainStyledAttributes.recycle();
+        if (count < 2) count = 2;//最少 2 个 item
+
+        mEditText = new EditText(context);
+        mEditText.setInputType(inputType);
+        mEditText.setLayoutParams(new LinearLayout.LayoutParams(1, 1));
+        mEditText.setCursorVisible(false);
+        mEditText.setBackground(null);
+        mEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(count)});//限制输入长度为 count
+        mEditText.addTextChangedListener(new TextWatcher() {
+            @Override
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+            }
+
+            @Override
+            public void onTextChanged(CharSequence s, int start, int before, int count) {
+                TextView textView = mTextViewList.get(start);//获取对应的 textview
+                if (before == 0) {//输入
+                    CharSequence input = s.subSequence(start, s.length());//获取新输入的字
+                    textView.setText(input);
+                    if (password) {//如果需要密文显示
+                        textView.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
+                        //passwordVisibleTime 毫秒后设置为密文显示
+                        textView.postDelayed(() ->
+                                        textView.setTransformationMethod(PasswordTransformationMethod.getInstance()),
+                                passwordVisibleTime);
+                    }
+                    setTextViewBackground(textView, drawableSelected);
+                } else {//删除
+                    textView.setText("");
+                    setTextViewBackground(textView, drawableNormal);
+                }
+                if (mInputCompleteListener != null && s.length() == mTextViewList.size())
+                    mInputCompleteListener.complete(s.toString());
+            }
+
+            @Override
+            public void afterTextChanged(Editable s) {
+
+            }
+        });
+        addView(mEditText);
+        //点击弹出软键盘
+        setOnClickListener(v -> {
+            mEditText.requestFocus();
+            showSoftKeyBoard();
+        });
+        //遍历生成 textview
+        for (int i = 0; i < count; i++) {
+            TextView textView = new TextView(context);
+            textView.setTextSize(textSize);
+            textView.setGravity(Gravity.CENTER);
+            textView.setTextColor(textColor);
+            LayoutParams layoutParams = new LayoutParams(width, height == 0 ? ViewGroup.LayoutParams.WRAP_CONTENT : height);
+            if (i == 0)
+                layoutParams.leftMargin = -1;
+            else
+                layoutParams.leftMargin = margin;
+            textView.setLayoutParams(layoutParams);
+            setTextViewBackground(textView, drawableNormal);
+            addView(textView);
+            mTextViewList.add(textView);
+        }
+    }
+
+    /**
+     * view 添加到窗口时,延迟 500ms 弹出软键盘
+     */
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mEditText.postDelayed(this::showSoftKeyBoard, 500);
+    }
+
+    /**
+     * 设置背景
+     * @param textView
+     * @param drawable
+     */
+    private void setTextViewBackground(TextView textView, Drawable drawable) {
+        if (drawable != null)
+            textView.setBackground(drawable);
+    }
+
+    /**
+     * 获取当前输入的内容
+     *
+     * @return
+     */
+    public String getContent() {
+        Editable text = mEditText.getText();
+        if (TextUtils.isEmpty(text)) return "";
+        return mEditText.getText().toString();
+    }
+
+    /**
+     * 清除内容
+     */
+    public void clearContent() {
+        mEditText.setText("");
+        for (int i = 0; i < mTextViewList.size(); i++) {
+            TextView textView = mTextViewList.get(i);
+            textView.setText("");
+            setTextViewBackground(textView, drawableNormal);
+        }
+    }
+
+    /**
+     * 设置默认的内容
+     *
+     * @param content
+     */
+    public void setDefaultContent(String content) {
+        mEditText.setText(content);
+        mEditText.requestFocus();
+        char[] chars = content.toCharArray();
+        int min = Math.min(chars.length, mTextViewList.size());
+        for (int i = 0; i < min; i++) {
+            char aChar = chars[i];
+            String s = String.valueOf(aChar);
+            TextView textView = mTextViewList.get(i);
+            textView.setText(s);
+            setTextViewBackground(textView, drawableSelected);
+        }
+        if (mInputCompleteListener != null && min == mTextViewList.size())
+            mInputCompleteListener.complete(content.substring(0, min));
+
+    }
+
+    /**
+     * 显示软键盘
+     */
+    private void showSoftKeyBoard() {
+        InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+        imm.showSoftInput(mEditText, InputMethodManager.SHOW_FORCED);
+    }
+
+    /**
+     * 添加输入完成的监听
+     *
+     * @param inputCompleteListener
+     */
+    public void addInputCompleteListener(InputCompleteListener inputCompleteListener) {
+        mInputCompleteListener = inputCompleteListener;
+        Editable content = mEditText.getText();
+        if (!TextUtils.isEmpty(content) && content.toString().length() == mTextViewList.size()) {
+            mInputCompleteListener.complete(content.toString());
+        }
+    }
+
+    public interface InputCompleteListener {
+        void complete(String content);
+    }
+
+    private int px2sp(Context context, float pxValue) {
+        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
+        return (int) (pxValue / fontScale + 0.5f);
+    }
+
+    private int sp2px(Context context, float spValue) {
+        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
+        return (int) (spValue * fontScale + 0.5f);
+    }
+}

+ 5 - 0
BaseLibrary/src/main/res/drawable/shape_code_input_bg.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/color_f3f3f3"/>
+    <corners android:radius="6dp"/>
+</shape>

+ 6 - 0
BaseLibrary/src/main/res/drawable/shape_code_input_bg_select.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/color_f3f3f3"/>
+    <corners android:radius="6dp"/>
+    <stroke android:color="@color/color_2dc7aa" android:width="1dp"/>
+</shape>

+ 5 - 0
BaseLibrary/src/main/res/drawable/shape_login_bt_bg_unselect.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/color_d5d5d5"/>
+    <corners android:radius="39dp"/>
+</shape>

+ 2 - 0
BaseLibrary/src/main/res/values/colors.xml

@@ -43,4 +43,6 @@
     <color name="color_fff1de">#FFF1DE</color>
     <color name="color_d3d3d3">#D3D3D3</color>
     <color name="color_6a6a6a">#6A6A6A</color>
+    <color name="color_f3f3f3">#F3F3F3</color>
+    <color name="color_d5d5d5">#D5D5D5</color>
 </resources>

+ 58 - 0
BaseLibrary/src/main/res/values/styles.xml

@@ -162,4 +162,62 @@
         <item name="android:layout_height">1dp</item>
         <item name="android:background">@color/divide_color</item>
     </style>
+
+    <declare-styleable name="verify_EditText">
+        <!-- 验证码的个数 -->
+        <attr name="verify_count" format="integer"/>
+        <!--        TextView 的宽度-->
+        <attr name="verify_width" format="dimension"/>
+        <!--        TextView 的高度-->
+        <attr name="verify_height" format="dimension"/>
+        <!--        TextView 的间隔-->
+        <attr name="verify_margin" format="dimension"/>
+        <!--        TextView 的字体大小-->
+        <attr name="verify_textSize" format="dimension"/>
+        <!--        TextView 的字体颜色-->
+        <attr name="verify_textColor" format="color"/>
+        <!-- TextView 无值背景 -->
+        <attr name="verify_background_normal" format="reference"/>
+        <!-- TextView 有值背景 -->
+        <attr name="verify_background_selected" format="reference"/>
+        <!--        是否隐藏密码-->
+        <attr name="verify_password" format="boolean"/>
+        <!--        密码显示时间ms-->
+        <attr name="verify_password_visible_time" format="integer"/>
+        <!--        editText的输入类型 -->
+        <attr name="verify_inputType">
+            <flag name="none" value="0x00000000" />
+            <flag name="text" value="0x00000001" />
+            <flag name="textCapCharacters" value="0x00001001" />
+            <flag name="textCapWords" value="0x00002001" />
+            <flag name="textCapSentences" value="0x00004001" />
+            <flag name="textAutoCorrect" value="0x00008001" />
+            <flag name="textAutoComplete" value="0x00010001" />
+            <flag name="textMultiLine" value="0x00020001" />
+            <flag name="textImeMultiLine" value="0x00040001" />
+            <flag name="textNoSuggestions" value="0x00080001" />
+            <flag name="textUri" value="0x00000011" />
+            <flag name="textEmailAddress" value="0x00000021" />
+            <flag name="textEmailSubject" value="0x00000031" />
+            <flag name="textShortMessage" value="0x00000041" />
+            <flag name="textLongMessage" value="0x00000051" />
+            <flag name="textPersonName" value="0x00000061" />
+            <flag name="textPostalAddress" value="0x00000071" />
+            <flag name="textPassword" value="0x00000081" />
+            <flag name="textVisiblePassword" value="0x00000091" />
+            <flag name="textWebEditText" value="0x000000a1" />
+            <flag name="textFilter" value="0x000000b1" />
+            <flag name="textPhonetic" value="0x000000c1" />
+            <flag name="textWebEmailAddress" value="0x000000d1" />
+            <flag name="textWebPassword" value="0x000000e1" />
+            <flag name="number" value="0x00000002" />
+            <flag name="numberSigned" value="0x00001002" />
+            <flag name="numberDecimal" value="0x00002002" />
+            <flag name="numberPassword" value="0x00000012" />
+            <flag name="phone" value="0x00000003" />
+            <flag name="datetime" value="0x00000004" />
+            <flag name="date" value="0x00000014" />
+            <flag name="time" value="0x00000024" />
+        </attr>
+    </declare-styleable>
 </resources>

+ 2 - 1
Provider/src/main/java/com/cooleshow/provider/router/RouterPath.kt

@@ -18,7 +18,8 @@ object RouterPath{
         companion object {
             const val PATH_LOGIN = "/userCenter/login"
             const val PATH_VERIFY_LOGIN = "/userCenter/verifyLogin"
-
+            const val PATH_VERIFY_INPUT = "/userCenter/verifyInput"
+            const val PATH_BIND_PASSWORD = "/userCenter/bindPwd"
         }
     }
 

+ 2 - 1
teacher/src/main/java/com/cooleshow/teacher/ui/splash/SplashActivity.kt

@@ -27,6 +27,7 @@ class SplashActivity : BaseActivity<ActivitySplashLayoutBinding>() {
         } else {
             jumpLogin()
         }
+        finish()
     }
 
     private fun jumpMain() {
@@ -34,7 +35,7 @@ class SplashActivity : BaseActivity<ActivitySplashLayoutBinding>() {
     }
 
     private fun jumpLogin() {
-        ARouter.getInstance().build(RouterPath.UserCenter.PATH_LOGIN).navigation()
+        ARouter.getInstance().build(RouterPath.UserCenter.PATH_VERIFY_LOGIN).navigation()
     }
 
 }

+ 10 - 3
usercenter/src/main/AndroidManifest.xml

@@ -2,6 +2,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     package="com.cooleshow.usercenter">
+
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
 
@@ -9,13 +10,19 @@
 
         <activity
             android:name=".ui.activity.LoginActivity"
-            android:exported="true">
-        </activity>
+            android:exported="false" />
 
         <activity
             android:name=".ui.activity.VerifyCodeLoginActivity"
             android:configChanges="orientation|screenSize|keyboardHidden"
-            android:screenOrientation="portrait"/>
+            android:screenOrientation="portrait" />
+        <activity
+            android:name=".ui.activity.VerifyCodeInputActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="portrait" />
 
+        <activity android:name=".ui.activity.BindPasswordActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="portrait"/>
     </application>
 </manifest>

+ 9 - 0
usercenter/src/main/java/com/cooleshow/usercenter/UserConstants.java

@@ -0,0 +1,9 @@
+package com.cooleshow.usercenter;
+
+/**
+ * Author by pq, Date on 2022/4/24.
+ */
+public class UserConstants {
+    public static final String TEMP_TOKEN="temp_token";
+
+}

+ 36 - 6
usercenter/src/main/java/com/cooleshow/usercenter/data/api/UserApi.kt

@@ -1,20 +1,18 @@
 package com.cooleshow.usercenter.data.api
 
 
+import com.cooleshow.base.common.BaseConstant
 import com.cooleshow.base.data.net.BaseResponse
 import com.cooleshow.usercenter.bean.UserInfo
 import com.cooleshow.usercenter.data.protocol.RegisterReq
 import io.reactivex.rxjava3.core.Observable
-import retrofit2.http.Body
-import retrofit2.http.FieldMap
-import retrofit2.http.FormUrlEncoded
-import retrofit2.http.POST
+import retrofit2.http.*
 
 
 /*
     用户相关 接口
  */
-interface UserApi{
+interface UserApi {
 
     /*
         用户注册
@@ -27,9 +25,41 @@ interface UserApi{
      */
     @FormUrlEncoded
     @POST("api-auth/usernameLogin")
-    fun login(@FieldMap req: MutableMap<String?,String?>):Observable<BaseResponse<UserInfo>>
+    fun login(@FieldMap req: MutableMap<String?, String?>): Observable<BaseResponse<UserInfo>>
+
 
     /*
+       发送验证码
+    */
+    @FormUrlEncoded
+    @POST(BaseConstant.TEACHER_GROUP + "code/sendSmsCode")
+    fun sendSmsCode(@Field("mobile") mobile: String): Observable<BaseResponse<Object>>
+
+
+    /*
+          校验验证码
+       */
+    @FormUrlEncoded
+    @POST(BaseConstant.TEACHER_GROUP + "code/verifySmsCode")
+    fun checkVerifyCodeValidity(
+        @Field("phone") phone: String,
+        @Field("code") code: String
+    ): Observable<BaseResponse<Object>>
+
+    /*
+         验证码登录
+      */
+    @FormUrlEncoded
+    @POST(BaseConstant.AUTH_GROUP + "smsLogin")
+    fun loginByCode(@FieldMap req: MutableMap<String?, String?>): Observable<BaseResponse<UserInfo>>
+
+    /*
+      发送验证码
+   */
+    @FormUrlEncoded
+    @POST(BaseConstant.AUTH_GROUP + "user/setUsernameAndPassword")
+    fun bindPassword(@Field("password") password: String): Observable<BaseResponse<Object>>
+/*
         忘记密码
 //     */
 //    @POST("userCenter/forgetPwd")

+ 30 - 0
usercenter/src/main/java/com/cooleshow/usercenter/helper/PhoneCheckHelper.java

@@ -0,0 +1,30 @@
+package com.cooleshow.usercenter.helper;
+
+import android.text.TextUtils;
+
+import com.cooleshow.base.utils.ToastUtils;
+
+/**
+ * Author by pq, Date on 2022/4/24.
+ */
+public class PhoneCheckHelper {
+    public static boolean checkPhoneValidity(String phone) {
+        if (TextUtils.isEmpty(phone)) {
+            ToastUtils.showShort("手机号不可为空");
+            return false;
+        }
+        return true;
+    }
+
+    public static boolean checkPwdValidity(String pwd,String pwdAgain) {
+        if(TextUtils.isEmpty(pwd) || TextUtils.isEmpty(pwdAgain)){
+            ToastUtils.showShort("请重新输入密码");
+            return false;
+        }
+        if (!TextUtils.equals(pwd,pwd)) {
+            ToastUtils.showShort("两次输入密码不一样,请重新输入");
+            return false;
+        }
+        return true;
+    }
+}

+ 14 - 0
usercenter/src/main/java/com/cooleshow/usercenter/helper/UserHelper.java

@@ -2,7 +2,9 @@ package com.cooleshow.usercenter.helper;
 
 import android.text.TextUtils;
 
+import com.cooleshow.base.data.net.CommonParamsHelper;
 import com.cooleshow.base.utils.SPUtils;
+import com.cooleshow.usercenter.bean.UserInfo;
 
 /**
  * Author by pq, Date on 2022/4/22.
@@ -19,6 +21,18 @@ public class UserHelper {
         return tokenType + " " + token;
     }
 
+    public static void handleLoginSuccessAction(UserInfo data) {
+        String resultToken = buildToken(data.authentication.token_type, data.authentication.access_token);
+        saveUserToken(resultToken);
+        CommonParamsHelper.getInstance().addCommonHeaderParams(CommonParamsHelper.USER_TOKEN, resultToken);
+    }
+
+    public static String handleLoginSuccessActionNotSave(UserInfo data) {
+        String resultToken = buildToken(data.authentication.token_type, data.authentication.access_token);
+        CommonParamsHelper.getInstance().addCommonHeaderParams(CommonParamsHelper.USER_TOKEN, resultToken);
+        return resultToken;
+    }
+
     public static void saveUserToken(String token) {
         SPUtils.getInstance().put(USER_TOKEN_KEY, token);
     }

+ 39 - 0
usercenter/src/main/java/com/cooleshow/usercenter/presenter/BindPasswordPresenter.java

@@ -0,0 +1,39 @@
+package com.cooleshow.usercenter.presenter;
+
+import com.cooleshow.base.constanst.Constanst;
+import com.cooleshow.base.presenter.BasePresenter;
+import com.cooleshow.base.rx.BaseObserver;
+import com.cooleshow.usercenter.bean.UserInfo;
+import com.cooleshow.usercenter.data.api.UserApi;
+import com.cooleshow.usercenter.presenter.contract.BindPasswordContract;
+import com.cooleshow.usercenter.presenter.contract.VerifyLoginContract;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * Author by pq, Date on 2022/4/19.
+ */
+public class BindPasswordPresenter extends BasePresenter<BindPasswordContract.BindPwdView> implements BindPasswordContract.Presenter {
+
+    @Override
+    public void onBindPwd(String pwd) {
+        if (getView() != null) {
+            getView().showLoading();
+        }
+        addSubscribe(create(UserApi.class).bindPassword(pwd), new BaseObserver<Object>(getView()) {
+            @Override
+            protected void onSuccess(Object data) {
+                if (getView() != null) {
+                    getView().onBindSuccess();
+                }
+            }
+
+            @Override
+            public void onError(Throwable e) {
+                super.onError(e);
+            }
+        });
+    }
+}

+ 58 - 1
usercenter/src/main/java/com/cooleshow/usercenter/presenter/VerifyLoginPresenter.java

@@ -1,8 +1,16 @@
 package com.cooleshow.usercenter.presenter;
 
+import com.cooleshow.base.constanst.Constanst;
 import com.cooleshow.base.presenter.BasePresenter;
+import com.cooleshow.base.rx.BaseObserver;
+import com.cooleshow.base.utils.RequestBodyUtil;
+import com.cooleshow.usercenter.bean.UserInfo;
+import com.cooleshow.usercenter.data.api.UserApi;
 import com.cooleshow.usercenter.presenter.contract.VerifyLoginContract;
 
+import java.util.HashMap;
+import java.util.Map;
+
 
 /**
  * Author by pq, Date on 2022/4/19.
@@ -10,7 +18,56 @@ import com.cooleshow.usercenter.presenter.contract.VerifyLoginContract;
 public class VerifyLoginPresenter extends BasePresenter<VerifyLoginContract.VerifyLoginView> implements VerifyLoginContract.Presenter {
 
     @Override
-    public void onLoginByVerifyCode(String mobile, String code) {
+    public void sendVerifyCode(String mobile) {
+        if (getView() != null) {
+            getView().showLoading();
+        }
+        addSubscribe(create(UserApi.class).sendSmsCode(mobile), new BaseObserver<Object>(getView()) {
+            @Override
+            protected void onSuccess(Object data) {
+                if (getView() != null) {
+                    getView().sendVerifyCodeSuccess();
+                }
+            }
+
+            @Override
+            public void onError(Throwable e) {
+                super.onError(e);
+                if (getView() != null) {
+                    getView().sendVerifyCodeFail();
+                }
+            }
+        });
+    }
+
+    public void checkVerifyCode(String mobile, String code) {
+        if (getView() != null) {
+            getView().showLoading();
+        }
+        addSubscribe(create(UserApi.class).checkVerifyCodeValidity(mobile, code), new BaseObserver<Object>(getView()) {
+            @Override
+            protected void onSuccess(Object data) {
+            }
+        });
+    }
 
+    public void loginByVerifyCode(String mobile, String code) {
+        if (getView() != null) {
+            getView().showLoading();
+        }
+        Map<String, String> maps = new HashMap<>();
+        maps.put("clientId", Constanst.CLIENT);
+        maps.put("clientSecret", Constanst.CLIENT);
+        maps.put("phone", mobile);
+        maps.put("smsCode", code);
+        maps.put("isSurportRegister", "true");
+        addSubscribe(create(UserApi.class).loginByCode(maps), new BaseObserver<UserInfo>(getView()) {
+            @Override
+            protected void onSuccess(UserInfo data) {
+                if (getView() != null) {
+                    getView().loginByCodeSuccess(data);
+                }
+            }
+        });
     }
 }

+ 18 - 0
usercenter/src/main/java/com/cooleshow/usercenter/presenter/contract/BindPasswordContract.java

@@ -0,0 +1,18 @@
+package com.cooleshow.usercenter.presenter.contract;
+
+import com.cooleshow.base.presenter.view.BaseView;
+import com.cooleshow.usercenter.bean.UserInfo;
+
+/**
+ * Author by pq, Date on 2022/4/20.
+ */
+public interface BindPasswordContract {
+
+    interface BindPwdView extends BaseView {
+        void onBindSuccess();
+    }
+
+    interface Presenter {
+        void onBindPwd(String pwd);
+    }
+}

+ 4 - 2
usercenter/src/main/java/com/cooleshow/usercenter/presenter/contract/VerifyLoginContract.java

@@ -8,11 +8,13 @@ import com.cooleshow.usercenter.bean.UserInfo;
  */
 public interface VerifyLoginContract {
     interface VerifyLoginView extends BaseView {
-        void onLoginResult(UserInfo userInfo);
+        void sendVerifyCodeSuccess();
+        void sendVerifyCodeFail();
+        void loginByCodeSuccess(UserInfo data);
     }
 
     interface Presenter {
-        void onLoginByVerifyCode(String mobile,String code);
+        void sendVerifyCode(String mobile);
     }
 
 }

+ 79 - 0
usercenter/src/main/java/com/cooleshow/usercenter/ui/activity/BindPasswordActivity.java

@@ -0,0 +1,79 @@
+package com.cooleshow.usercenter.ui.activity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+
+import com.alibaba.android.arouter.facade.annotation.Route;
+import com.alibaba.android.arouter.launcher.ARouter;
+import com.cooleshow.base.ui.activity.BaseMVPActivity;
+import com.cooleshow.base.utils.ToastUtils;
+import com.cooleshow.base.utils.helper.QMUIStatusBarHelper;
+import com.cooleshow.provider.router.RouterPath;
+import com.cooleshow.usercenter.R;
+import com.cooleshow.usercenter.UserConstants;
+import com.cooleshow.usercenter.bean.UserInfo;
+import com.cooleshow.usercenter.databinding.ActivityBindPwdLayoutBinding;
+import com.cooleshow.usercenter.databinding.ActivityVerifyCodeLoginBinding;
+import com.cooleshow.usercenter.helper.PhoneCheckHelper;
+import com.cooleshow.usercenter.presenter.BindPasswordPresenter;
+import com.cooleshow.usercenter.presenter.VerifyLoginPresenter;
+import com.cooleshow.usercenter.presenter.contract.BindPasswordContract;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * Author by pq, Date on 2022/4/19.
+ */
+@Route(path = RouterPath.UserCenter.PATH_BIND_PASSWORD)
+public class BindPasswordActivity extends BaseMVPActivity<ActivityBindPwdLayoutBinding, BindPasswordPresenter> implements BindPasswordContract.BindPwdView, View.OnClickListener {
+
+    private String tempToken;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        QMUIStatusBarHelper.setStatusBarLightMode(this);
+    }
+
+    @NonNull
+    @Override
+    protected ActivityBindPwdLayoutBinding getLayoutView() {
+        return ActivityBindPwdLayoutBinding.inflate(getLayoutInflater());
+    }
+
+    @Override
+    protected void initView() {
+        viewBinding.tvConfirm.setOnClickListener(this);
+        tempToken = getIntent().getStringExtra(UserConstants.TEMP_TOKEN);
+
+    }
+
+
+    @Override
+    public void onBindSuccess() {
+        ToastUtils.showShort("设置成功");
+        Intent intent = new Intent();
+        intent.putExtra(UserConstants.TEMP_TOKEN, tempToken);
+        setResult(RESULT_OK, intent);
+        finish();
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == R.id.tv_confirm) {
+            String pwd = viewBinding.etPwd.getText().toString();
+            String pwdAgain = viewBinding.etPwdAgain.getText().toString();
+            if (PhoneCheckHelper.checkPwdValidity(pwd, pwdAgain)) {
+                presenter.onBindPwd(pwdAgain);
+            }
+            return;
+        }
+    }
+
+    @Override
+    protected BindPasswordPresenter createPresenter() {
+        return new BindPasswordPresenter();
+    }
+}

+ 1 - 9
usercenter/src/main/java/com/cooleshow/usercenter/ui/activity/LoginActivity.kt

@@ -4,7 +4,6 @@ import android.os.Bundle
 import android.text.TextUtils
 import com.alibaba.android.arouter.facade.annotation.Route
 import com.alibaba.android.arouter.launcher.ARouter
-import com.cooleshow.base.data.net.CommonParamsHelper
 import com.cooleshow.base.ext.onClick
 import com.cooleshow.base.ui.activity.BaseMVPActivity
 import com.cooleshow.base.utils.ToastUtils
@@ -59,14 +58,7 @@ class LoginActivity : BaseMVPActivity<ActivityLoginBinding, LoginPresenter>(),
         if (isFinishing || isDestroyed) {
             return;
         }
-        var token = UserHelper.buildToken(
-            result.authentication?.token_type,
-            result.authentication?.access_token
-        )
-        UserHelper.saveUserToken(token);
-
-        //添加公共参数
-        CommonParamsHelper.getInstance().addCommonHeaderParams(CommonParamsHelper.USER_TOKEN, token);
+        UserHelper.handleLoginSuccessAction(result)
         ARouter.getInstance().build(RouterPath.APPCenter.PATH_HOME).navigation()
     }
 

+ 206 - 0
usercenter/src/main/java/com/cooleshow/usercenter/ui/activity/VerifyCodeInputActivity.java

@@ -0,0 +1,206 @@
+package com.cooleshow.usercenter.ui.activity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.CountDownTimer;
+import android.text.SpannableString;
+import android.text.TextUtils;
+import android.view.View;
+
+import com.alibaba.android.arouter.facade.annotation.Route;
+import com.alibaba.android.arouter.launcher.ARouter;
+import com.cooleshow.base.common.AppManager;
+import com.cooleshow.base.ui.activity.BaseMVPActivity;
+import com.cooleshow.base.utils.KeyboardUtils;
+import com.cooleshow.base.utils.ToastUtils;
+import com.cooleshow.base.utils.Utils;
+import com.cooleshow.base.utils.helper.QMUIStatusBarHelper;
+import com.cooleshow.base.widgets.VerifyEditText;
+import com.cooleshow.provider.router.RouterPath;
+import com.cooleshow.usercenter.R;
+import com.cooleshow.usercenter.UserConstants;
+import com.cooleshow.usercenter.bean.UserInfo;
+import com.cooleshow.usercenter.databinding.ActivityInputCodeLayoutBinding;
+import com.cooleshow.usercenter.helper.UserHelper;
+import com.cooleshow.usercenter.presenter.VerifyLoginPresenter;
+import com.cooleshow.usercenter.presenter.contract.VerifyLoginContract;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * Author by pq, Date on 2022/4/19.
+ */
+@Route(path = RouterPath.UserCenter.PATH_VERIFY_INPUT)
+public class VerifyCodeInputActivity extends BaseMVPActivity<ActivityInputCodeLayoutBinding, VerifyLoginPresenter> implements VerifyLoginContract.VerifyLoginView, View.OnClickListener {
+    public static final String TARGET_PHONE = "target_phone";
+    public static final int TIME_COUNT_SPACE = 1000;
+    public static final int TIME_COUNT_TOTAL = 10000;
+    public static final int REQUEST_CODE_FOR_SET_PASSWORD = 100001;
+    private String mPhoneNum;
+
+    private CountDownTimer mCountDownTimer = new CountDownTimer(TIME_COUNT_TOTAL, TIME_COUNT_SPACE) {
+        @Override
+        public void onTick(long millisUntilFinished) {
+            if (viewBinding.tvResendCode != null) {
+                int lastTime = (int) (millisUntilFinished / TIME_COUNT_SPACE);
+                viewBinding.tvResendCode.setText(getString(R.string.verify_input_count_time_tip, lastTime));
+            }
+        }
+
+        @Override
+        public void onFinish() {
+            switchSendCodeButton(true);
+        }
+    };
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        QMUIStatusBarHelper.setStatusBarLightMode(this);
+    }
+
+    @NonNull
+    @Override
+    protected ActivityInputCodeLayoutBinding getLayoutView() {
+        return ActivityInputCodeLayoutBinding.inflate(getLayoutInflater());
+    }
+
+    @Override
+    protected void initView() {
+        mPhoneNum = getIntent().getStringExtra(TARGET_PHONE);
+        if (TextUtils.isEmpty(mPhoneNum)) {
+            finish();
+            return;
+        }
+        SpannableString string = Utils.diffColorString(getString(R.string.verify_input_phone_tip), mPhoneNum, getResources().getColor(R.color.black), getResources().getColor(com.cooleshow.base.R.color.color_999999));
+        viewBinding.tvTipTargetPhone.setText(string);
+        switchSendCodeButton(false);
+        viewBinding.ivBack.setOnClickListener(this);
+        viewBinding.tvResendCode.setOnClickListener(this);
+        viewBinding.editCode.addInputCompleteListener(new VerifyEditText.InputCompleteListener() {
+            @Override
+            public void complete(String content) {
+                //输入完成
+                login(content);
+            }
+        });
+    }
+
+    private void login(String content) {
+        KeyboardUtils.hideSoftInput(this);
+        if (!TextUtils.isEmpty(mPhoneNum) && !TextUtils.isEmpty(content)) {
+            presenter.loginByVerifyCode(mPhoneNum, content);
+        }
+    }
+
+    @Override
+    public void initData() {
+        super.initData();
+        sendVerifyCode();
+    }
+
+    private void sendVerifyCode() {
+        if (presenter != null && !TextUtils.isEmpty(mPhoneNum)) {
+            presenter.sendVerifyCode(mPhoneNum);
+        }
+    }
+
+    @Override
+    protected VerifyLoginPresenter createPresenter() {
+        return new VerifyLoginPresenter();
+    }
+
+
+    private void switchSendCodeButton(boolean isAble) {
+        if (viewBinding.tvResendCode != null) {
+            viewBinding.tvResendCode.setClickable(isAble);
+            viewBinding.tvResendCode.setBackgroundResource(isAble ? com.cooleshow.base.R.drawable.shape_login_bt_bg : com.cooleshow.base.R.drawable.shape_login_bt_bg_unselect);
+
+            if (isAble) {
+                viewBinding.tvResendCode.setText(getString(R.string.verify_input_resend_tip));
+            }
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if (mCountDownTimer != null) {
+            mCountDownTimer.cancel();
+            mCountDownTimer = null;
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == R.id.iv_back) {
+            //返回键
+            finish();
+            return;
+        }
+        if (v.getId() == R.id.tv_resend_code) {
+            //重新发送
+            sendVerifyCode();
+        }
+    }
+
+    /**
+     * 发送验证码成功
+     */
+    @Override
+    public void sendVerifyCodeSuccess() {
+        ToastUtils.showShort(R.string.verify_code_send_success_tip);
+        switchSendCodeButton(false);
+        if (mCountDownTimer != null) {
+            mCountDownTimer.start();
+        }
+    }
+
+    /**
+     * 发送验证码失败
+     */
+    @Override
+    public void sendVerifyCodeFail() {
+        switchSendCodeButton(true);
+        if (mCountDownTimer != null) {
+            mCountDownTimer.cancel();
+        }
+    }
+
+    @Override
+    public void loginByCodeSuccess(UserInfo data) {
+        //添加公共参数
+        if (isFinishing() || isDestroyed()) {
+            return;
+        }
+        if (data != null) {
+            if (data.password) {
+                //有设置密码
+                UserHelper.handleLoginSuccessAction(data);
+                ARouter.getInstance().build(RouterPath.APPCenter.PATH_HOME).navigation();
+                AppManager.Companion.getInstance().finishAllActivity();
+            } else {
+                //无密码,跳设置密码
+                String tempToken = UserHelper.handleLoginSuccessActionNotSave(data);
+                ARouter.getInstance().build(RouterPath.UserCenter.PATH_BIND_PASSWORD).withString(UserConstants.TEMP_TOKEN, tempToken).navigation(this, REQUEST_CODE_FOR_SET_PASSWORD);
+            }
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if (resultCode == RESULT_OK) {
+            if (requestCode == REQUEST_CODE_FOR_SET_PASSWORD) {
+                //设置密码成功
+                if(data!=null){
+                    String tokenResult = data.getStringExtra(UserConstants.TEMP_TOKEN);
+                    UserHelper.saveUserToken(tokenResult);
+                    ARouter.getInstance().build(RouterPath.APPCenter.PATH_HOME).navigation();
+                    AppManager.Companion.getInstance().finishAllActivity();
+                }
+            }
+        }
+    }
+}

+ 18 - 6
usercenter/src/main/java/com/cooleshow/usercenter/ui/activity/VerifyCodeLoginActivity.java

@@ -1,13 +1,18 @@
 package com.cooleshow.usercenter.ui.activity;
 
 import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
 
 import com.alibaba.android.arouter.facade.annotation.Route;
+import com.alibaba.android.arouter.launcher.ARouter;
 import com.cooleshow.base.ui.activity.BaseMVPActivity;
+import com.cooleshow.base.utils.ToastUtils;
 import com.cooleshow.base.utils.helper.QMUIStatusBarHelper;
 import com.cooleshow.provider.router.RouterPath;
 import com.cooleshow.usercenter.bean.UserInfo;
 import com.cooleshow.usercenter.databinding.ActivityVerifyCodeLoginBinding;
+import com.cooleshow.usercenter.helper.PhoneCheckHelper;
 import com.cooleshow.usercenter.presenter.VerifyLoginPresenter;
 import com.cooleshow.usercenter.presenter.contract.VerifyLoginContract;
 
@@ -18,7 +23,7 @@ import androidx.annotation.Nullable;
  * Author by pq, Date on 2022/4/19.
  */
 @Route(path = RouterPath.UserCenter.PATH_VERIFY_LOGIN)
-public class VerifyCodeLoginActivity extends BaseMVPActivity<ActivityVerifyCodeLoginBinding, VerifyLoginPresenter> implements VerifyLoginContract.VerifyLoginView {
+public class VerifyCodeLoginActivity extends BaseMVPActivity<ActivityVerifyCodeLoginBinding, VerifyLoginPresenter> {
 
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -34,16 +39,23 @@ public class VerifyCodeLoginActivity extends BaseMVPActivity<ActivityVerifyCodeL
 
     @Override
     protected void initView() {
-
+        viewBinding.tvSendVerifyCode.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                String phone = viewBinding.etPhoneNum.getText().toString();
+                if (PhoneCheckHelper.checkPhoneValidity(phone)) {
+                    ARouter.getInstance().build(RouterPath.UserCenter.PATH_VERIFY_INPUT)
+                            .withString(VerifyCodeInputActivity.TARGET_PHONE, phone)
+                            .navigation();
+                }
+            }
+        });
     }
 
+
     @Override
     protected VerifyLoginPresenter createPresenter() {
         return new VerifyLoginPresenter();
     }
 
-    @Override
-    public void onLoginResult(UserInfo userInfo) {
-
-    }
 }

二進制
usercenter/src/main/res/drawable-xhdpi/icon_back_black.png


二進制
usercenter/src/main/res/drawable-xxhdpi/icon_back_black.png


+ 127 - 0
usercenter/src/main/res/layout/activity_bind_pwd_layout.xml

@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/white">
+
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:scaleType="fitXY"
+        android:src="@drawable/bg_login_header"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/tv_header_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="35dp"
+        android:layout_marginTop="101dp"
+        android:includeFontPadding="false"
+        android:text="设置登录密码"
+        android:textColor="@color/black"
+        android:textSize="@dimen/sp_26"
+        android:textStyle="bold"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/tv_phone_num"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="35dp"
+        android:layout_marginTop="71dp"
+        android:includeFontPadding="false"
+        android:text="@string/please_input_pwd_str_title"
+        android:textColor="@color/black"
+        android:textSize="@dimen/sp_18"
+        android:textStyle="bold"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/tv_header_title" />
+
+
+    <EditText
+        android:textSize="@dimen/sp_16"
+        android:id="@+id/et_pwd"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/common_line_height"
+        android:layout_marginStart="35dp"
+        android:layout_marginEnd="35dp"
+        android:background="@null"
+        android:inputType="textPassword"
+        android:digits="@string/input_support"
+        android:hint="@string/please_input_pwd2"
+        android:textColorHint="@color/color_ffc1c1c1"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/tv_phone_num" />
+
+    <View
+        android:id="@+id/view_phone_divide"
+        android:layout_width="0dp"
+        android:layout_height="1px"
+        android:layout_marginTop="3dp"
+        android:background="@color/divide_color"
+        app:layout_constraintLeft_toLeftOf="@+id/et_pwd"
+        app:layout_constraintRight_toRightOf="@+id/et_pwd"
+        app:layout_constraintTop_toBottomOf="@+id/et_pwd" />
+
+    <TextView
+        android:id="@+id/tv_password_num"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dp"
+        android:includeFontPadding="false"
+        android:text="@string/please_input_again_title"
+        android:textColor="@color/black"
+        android:textSize="@dimen/sp_18"
+        android:textStyle="bold"
+        app:layout_constraintLeft_toLeftOf="@+id/tv_phone_num"
+        app:layout_constraintTop_toBottomOf="@+id/view_phone_divide" />
+
+    <EditText
+        android:textSize="@dimen/sp_16"
+        android:id="@+id/et_pwd_again"
+        android:layout_width="0dp"
+        android:layout_height="@dimen/common_line_height"
+        android:background="@null"
+        android:digits="@string/input_support"
+        android:drawablePadding="@dimen/common_padding_small"
+        android:hint="@string/please_input_pwd3"
+        android:inputType="textPassword"
+        android:paddingLeft="@dimen/common_padding_small"
+        android:textColorHint="@color/color_ffc1c1c1"
+        app:layout_constraintLeft_toLeftOf="@+id/et_pwd"
+        app:layout_constraintRight_toRightOf="@+id/et_pwd"
+        app:layout_constraintTop_toBottomOf="@+id/tv_password_num" />
+
+    <View
+        android:id="@+id/view_pw_divide"
+        android:layout_width="0dp"
+        android:layout_height="1px"
+        android:layout_marginTop="3dp"
+        android:background="@color/divide_color"
+        app:layout_constraintLeft_toLeftOf="@+id/et_pwd_again"
+        app:layout_constraintRight_toRightOf="@+id/et_pwd_again"
+        app:layout_constraintTop_toBottomOf="@+id/et_pwd_again" />
+
+    <TextView
+        android:id="@+id/tv_confirm"
+        android:layout_width="0dp"
+        android:layout_height="50dp"
+        android:layout_marginStart="35dp"
+        android:layout_marginTop="36dp"
+        android:layout_marginEnd="35dp"
+        android:background="@drawable/shape_login_bt_bg"
+        android:gravity="center"
+        android:text="@string/login_str"
+        android:textColor="@color/white"
+        android:textSize="@dimen/sp_17"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/view_pw_divide" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 85 - 0
usercenter/src/main/res/layout/activity_input_code_layout.xml

@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/white">
+
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:scaleType="fitXY"
+        android:src="@drawable/bg_login_header"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <ImageView
+        android:id="@+id/iv_back"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="15dp"
+        android:layout_marginTop="52dp"
+        android:padding="7dp"
+        android:src="@drawable/icon_back_black"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/tv_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="35dp"
+        android:layout_marginTop="85dp"
+        android:includeFontPadding="false"
+        android:text="输入验证码"
+        android:textColor="@color/black"
+        android:textSize="@dimen/sp_26"
+        android:textStyle="bold"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/iv_back" />
+
+    <TextView
+        android:id="@+id/tv_tip_target_phone"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="20dp"
+        android:includeFontPadding="false"
+        android:textColor="@color/black"
+        android:textSize="@dimen/sp_16"
+        app:layout_constraintLeft_toLeftOf="@+id/tv_title"
+        app:layout_constraintTop_toBottomOf="@+id/tv_title"
+        tools:text="已发送6位验证码至 1360000000" />
+
+    <com.cooleshow.base.widgets.VerifyEditText
+        android:id="@+id/edit_code"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="39dp"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/tv_tip_target_phone"
+        app:verify_background_normal="@drawable/shape_code_input_bg"
+        app:verify_background_selected="@drawable/shape_code_input_bg_select"
+        app:verify_count="6"
+        app:verify_height="40dp"
+        app:verify_inputType="text"
+        app:verify_margin="15dp"
+        app:verify_textSize="20sp"
+        app:verify_width="38dp" />
+
+    <TextView
+        android:id="@+id/tv_resend_code"
+        android:layout_width="160dp"
+        android:layout_height="50dp"
+        android:layout_marginTop="67dp"
+        android:background="@drawable/shape_login_bt_bg_unselect"
+        android:clickable="false"
+        android:gravity="center"
+        android:text="重新发送"
+        android:textColor="@color/white"
+        android:textSize="@dimen/sp_17"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/edit_code" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 9 - 0
usercenter/src/main/res/values/strings.xml

@@ -9,4 +9,13 @@
     <string name="please_input_phone_num">请输入手机号码</string>
     <string name="read_privacy_and_agree_str">我已阅读并同意</string>
     <string name="get_verify_code_str">获取短信验证码</string>
+    <string name="verify_input_phone_tip">已发送6位验证码至 </string>
+    <string name="verify_input_count_time_tip">重新发送(%1$d)</string>
+    <string name="verify_input_resend_tip">重新发送</string>
+    <string name="verify_code_send_success_tip">发送成功</string>
+    <string name="please_input_pwd_str_title">输入密码</string>
+    <string name="please_input_again_title">再次输入</string>
+    <string name="please_input_pwd2">请输入您的登录密码</string>
+    <string name="please_input_pwd3">请再次输入您的登录密码</string>
+    <string name="input_support">1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM.~!?@#$%^*()_=|</string>
 </resources>