登录相关,首次提交

This commit is contained in:
fengjignqi
2026-09-18 09:59:43 +08:00
parent 6e9b97e42e
commit f7cf112dc9
45 changed files with 2362 additions and 177 deletions

View File

@@ -1,20 +1,35 @@
package com.juhabi.birds.login
import android.os.Bundle
import android.content.Intent
import android.os.Bundle
import android.os.CountDownTimer
import android.text.InputType
import android.view.LayoutInflater
import android.view.View
import com.gyf.immersionbar.ImmersionBar
import com.juhabi.birds.AppConfig
import com.juhabi.birds.R
import com.juhabi.birds.base.BaseActivity
import com.juhabi.birds.databinding.ActivityLoginBinding
import com.juhabi.birds.login.model.LoginUser
import com.juhabi.birds.login.model.UserEntity
import com.juhabi.birds.login.mvp.LoginContract
import com.juhabi.birds.login.mvp.LoginImpl
import com.juhabi.birds.login.mvp.LoginPresenter
import com.juhabi.birds.network.TokenManager
import com.juhabi.birds.mine.MineCenterActivity
import com.juhabi.birds.network.TokenManager
import com.juhabi.birds.util.SharedPreferencesUtil
import com.juhabi.birds.util.ToastUtil
/**
* 登录
*/
class LoginActivity : BaseActivity<ActivityLoginBinding, LoginPresenter>(),
LoginContract.LoginView {
LoginContract.LoginView, View.OnClickListener {
/** 是否使用密码登录;false 为手机号 + 验证码登录 */
private var loginByPassword = true
private var isPasswordVisible = false
private var codeCountDownTimer: CountDownTimer? = null
override fun createBinding(inflater: LayoutInflater): ActivityLoginBinding {
return ActivityLoginBinding.inflate(inflater)
@@ -24,48 +39,176 @@ class LoginActivity : BaseActivity<ActivityLoginBinding, LoginPresenter>(),
return LoginPresenter(LoginImpl())
}
override fun initWindows() {
ImmersionBar.with(this)
.navigationBarColor(R.color.color_zhu)
.navigationBarDarkIcon(true)
.init()
}
override fun initView(savedInstanceState: Bundle?) {
// if (TokenManager.get(this).isNotBlank()) {
// startActivity(Intent(this, MineCenterActivity::class.java))
// finish()
// return
// }
if(binding.usernameEditText.text.toString().isNotBlank()){
ToastUtil.showShort(mContext,"");
return
listOf(
binding.tvChangeCode,
binding.forgotPasswordButton,
binding.passwordVisibilityButton,
binding.getCodeButton,
binding.loginButton,
binding.registerButton,
).forEach { button ->
button.setOnClickListener(this)
}
binding.loginButton.setOnClickListener {
presenter?.login(
binding.usernameEditText.text?.toString().orEmpty(),
binding.passwordEditText.text?.toString().orEmpty()
)
}
override fun onClick(view: View) {
when (view.id) {
R.id.tvChangeCode -> {//更换登录方式
if (loginByPassword) {
binding.linearCode.visibility = View.VISIBLE
binding.linearPsd.visibility = View.GONE
loginByPassword = false
binding.tvChangeCode.setText(R.string.register_change_psd_login)
} else {
binding.linearCode.visibility = View.GONE
binding.linearPsd.visibility = View.VISIBLE
loginByPassword = true
binding.tvChangeCode.setText(R.string.register_change_code_login)
}
}
R.id.getCodeButton -> {//获取验证码
val phone = binding.accountEditText.text.toString().trim()
if (phone.isBlank()) {
ToastUtil.showShort(mContext, "手机号不能为空")
return
}
presenter?.getPhoneSmsCode(phone, AppConfig.SEND_CODE_SCENE_LOGIN)
}
R.id.registerButton -> {//注册
goTo(RegisterActivity::class.java, null)
}
R.id.forgotPasswordButton -> {//忘记密码
goTo(ForgetPsdActivity::class.java, null)
}
R.id.passwordVisibilityButton -> {
togglePasswordVisibility()
}
R.id.loginButton -> {//登录
val account = binding.accountEditText.text.toString().trim()
if (account.isBlank()) {
ToastUtil.showShort(mContext, "账号不能为空")
return
}
if (loginByPassword) {
val password = binding.passwordEditText.text.toString()
if (password.isBlank()) {
ToastUtil.showShort(mContext, "密码不能为空")
return
}
presenter?.loginByPhonePsd(account, password)
} else {
val code = binding.codeEditText.text.toString().trim()
if (code.isBlank()) {
ToastUtil.showShort(mContext, "验证码不能为空")
return
}
presenter?.loginByPhoneSms(account, code)
}
}
}
}
private fun togglePasswordVisibility() {
isPasswordVisible = !isPasswordVisible
val selection = binding.passwordEditText.selectionEnd
binding.passwordEditText.inputType = if (isPasswordVisible) {
InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
} else {
InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
}
// 保持光标位置,并触发 typeface 刷新
binding.passwordEditText.setSelection(selection.coerceAtLeast(0))
binding.passwordEditText.typeface = binding.accountEditText.typeface
}
override fun sendCodeSuccess(message: String) {
hideLoading()
ToastUtil.showShort(mContext, message)
codeCountDownTimer?.cancel()
binding.getCodeButton.apply {
isEnabled = false
isClickable = false
setBackgroundResource(R.drawable.shape_register_code_disabled_bg)
text = getString(R.string.register_code_countdown, CODE_COUNTDOWN_SECONDS)
}
codeCountDownTimer = object : CountDownTimer(CODE_COUNTDOWN_MILLIS, 1_000L) {
override fun onTick(millisUntilFinished: Long) {
val secondsRemaining = (millisUntilFinished + 999L) / 1_000L
binding.getCodeButton.text = getString(
R.string.register_code_countdown,
secondsRemaining
)
}
override fun onFinish() {
codeCountDownTimer = null
binding.getCodeButton.apply {
isEnabled = true
isClickable = true
setBackgroundResource(R.drawable.shape_register_code_bg)
setText(R.string.register_get_code)
}
}
}.start()
}
override fun onRegisterSuccess(message: String) {
}
override fun onForgetPsdSuccess(message: String) {
}
override fun showUsernameError(message: String) {
binding.usernameLayout.error = message
binding.usernameEditText.requestFocus()
ToastUtil.showShort(mContext, message)
}
override fun showPasswordError(message: String) {
binding.passwordLayout.error = message
binding.passwordEditText.requestFocus()
ToastUtil.showShort(mContext, message)
}
override fun clearInputErrors() {
binding.usernameLayout.error = null
binding.passwordLayout.error = null
}
override fun onLoginSuccess(user: LoginUser) {
TokenManager.save(this, user.accessToken)
binding.resultTextView.text = "登录成功,Token 已保存"
showMessage("登录成功")
override fun onLoginSuccess(user: UserEntity) {
val token = user.token.trim()
// SharedPreferences 持久化 token,并同步到内存 AppConfig.userToken
TokenManager.save(this, token)
AppConfig.USER_LOGIN = token.isNotBlank()
SharedPreferencesUtil.putBoolean(this, KEY_USER_LOGIN, AppConfig.USER_LOGIN)
ToastUtil.showShort(mContext, "登录成功")
startActivity(Intent(this, MineCenterActivity::class.java))
finish()
}
override fun showError(message: String) {
ToastUtil.showShort(mContext,message)
hideLoading()
ToastUtil.showShort(mContext, message)
}
override fun onDestroy() {
codeCountDownTimer?.cancel()
codeCountDownTimer = null
super.onDestroy()
}
private companion object {
const val CODE_COUNTDOWN_SECONDS = 60L
const val CODE_COUNTDOWN_MILLIS = CODE_COUNTDOWN_SECONDS * 1_000L
const val KEY_USER_LOGIN = "user_login"
}
}