实现Android前端搭建:
entity:
package com.example.learningmanagement.entitydata class User(val userId: String,val username: String,val phoneNumber: String,val userClass: String,val password: String
) {// 校验所有字段非空private fun validateNotEmpty(): Boolean {return userId.isNotEmpty() &&username.isNotEmpty() &&phoneNumber.isNotEmpty() &&userClass.isNotEmpty() &&password.isNotEmpty()}// 校验手机号格式(简单版)private fun validatePhoneFormat(): Boolean {return phoneNumber.matches(Regex("^1[3-9]\\d{9}$"))}// 综合校验fun validateAll(): String? {return when {!validateNotEmpty() -> "所有字段不能为空"!validatePhoneFormat() -> "手机号格式不正确"password.length < 6 -> "密码至少需要6位"else -> null // 返回null表示校验通过}}
}
package com.example.learningmanagement.entitydata class ApiResponse<T>(val code: String,val msg: String,val data: T?
)
network:
package com.example.learningmanagement.networkimport com.google.gson.GsonBuilder
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactoryobject ServiceCreater {val gson = GsonBuilder().setLenient().create()// 换网修改IP地址private const val BASE_URL="http://192.168.78.220:9090/"private val retrofit=Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create(gson)).build()fun <T> create(serviceClass: Class<T>): T= retrofit.create(serviceClass)inline fun<reified T> create(): T= create(T::class.java)
}
service:
package com.example.learningmanagement.serviceimport com.example.learningmanagement.entity.ApiResponse
import com.example.learningmanagement.entity.User
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Queryinterface UserApiService {@POST("user/register")suspend fun register(@Body user: User): ApiResponse<String>@POST("user/login")suspend fun login(@Body user: User): ApiResponse<User>
}
utils:
实现记住用户名:
package com.example.learningmanagement.utilsimport android.content.Context
import android.content.SharedPreferences
import androidx.core.content.editclass PrefsHelper(context: Context) {private val sharedPref: SharedPreferences = context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)// 存储用户Namefun saveLastUserName(username: String) {sharedPref.edit() { putString("LAST_USER_NAME", username) }}// 获取最后登录的用户Namefun getLastUserName(): String? {return sharedPref.getString("LAST_USER_NAME", null)}// 清除存储的Name(可选)fun clearLastUserName() {sharedPref.edit() { remove("LAST_USER_NAME") }}
}
activity:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="16dp"><EditTextandroid:id="@+id/etUsername"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="姓名"android:inputType="text"/><EditTextandroid:id="@+id/etPassword"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="密码"android:inputType="textPassword"android:layout_marginTop="8dp"/><Buttonandroid:id="@+id/btnLogin"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="登录"android:layout_marginTop="16dp"/><TextViewandroid:id="@+id/tvToRegister"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="没有账号?立即注册"android:textColor="@color/purple_500"android:layout_gravity="center_horizontal"android:layout_marginTop="16dp"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="16dp"><EditTextandroid:id="@+id/etUserId"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="学号"android:inputType="text"/><EditTextandroid:id="@+id/etUsername"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="姓名"android:inputType="textPersonName"/><EditTextandroid:id="@+id/etPhone"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="手机号"android:inputType="phone"/><EditTextandroid:id="@+id/etClass"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="班级"android:inputType="text"/><EditTextandroid:id="@+id/etPassword"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="密码"android:inputType="textPassword"/><Buttonandroid:id="@+id/btnRegister"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="注册"android:layout_marginTop="16dp"/>
</LinearLayout>
ui:
package com.example.learningmanagement.uiimport android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.example.learningmanagement.R
import com.example.learningmanagement.entity.User
import com.example.learningmanagement.network.ServiceCreater
import com.example.learningmanagement.service.UserApiService
import com.example.learningmanagement.utils.PrefsHelper
import kotlinx.coroutines.launchclass LoginActivity : AppCompatActivity() {private val prefs by lazy { PrefsHelper(this) }private lateinit var etUsername: EditTextprivate lateinit var etPassword: EditTextprivate lateinit var btnLogin: Buttonprivate lateinit var tvToRegister: TextViewprivate val userService = ServiceCreater.create<UserApiService>()@SuppressLint("MissingInflatedId")override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_login)// 初始化视图etUsername = findViewById(R.id.etUsername)etPassword = findViewById(R.id.etPassword)btnLogin = findViewById(R.id.btnLogin)tvToRegister = findViewById(R.id.tvToRegister)//记住用户名prefs.getLastUserName()?.let { savedName ->findViewById<EditText>(R.id.etUsername).setText(savedName)}// 登录按钮点击事件btnLogin.setOnClickListener {handleLogin()}// 跳转到注册页面tvToRegister.setOnClickListener {startActivity(Intent(this, RegisterActivity::class.java))}}private fun handleLogin() {val user = User(userId = null.toString(),username = etUsername.text.toString().trim(),phoneNumber = null.toString(),userClass = null.toString(),password = etPassword.text.toString().trim())if (user.username.isEmpty() || user.password.isEmpty()) {Toast.makeText(this, "姓名和密码不能为空", Toast.LENGTH_SHORT).show()return}lifecycleScope.launch {try {val response = userService.login(user)if (response.code == "200") {Toast.makeText(this@LoginActivity,"登录成功",Toast.LENGTH_SHORT).show()// 这里可以跳转到主页面(例如HomeActivity)} else {Toast.makeText(this@LoginActivity,"登录失败: ${response.msg}",Toast.LENGTH_SHORT).show()}} catch (e: Exception) {Toast.makeText(this@LoginActivity,"网络错误: ${e.message}",Toast.LENGTH_SHORT).show()}}}
}
package com.example.learningmanagement.uiimport android.annotation.SuppressLint
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.example.learningmanagement.R
import com.example.learningmanagement.entity.User
import com.example.learningmanagement.network.ServiceCreater
import com.example.learningmanagement.service.UserApiService
import com.example.learningmanagement.utils.PrefsHelper
import kotlinx.coroutines.launchclass RegisterActivity : AppCompatActivity() {private val prefs by lazy { PrefsHelper(this) }private lateinit var etUserId: EditTextprivate lateinit var etUsername: EditTextprivate lateinit var etPhone: EditTextprivate lateinit var etClass: EditTextprivate lateinit var etPassword: EditTextprivate lateinit var btnRegister: Buttonprivate val userService = ServiceCreater.create<UserApiService>()@SuppressLint("MissingInflatedId")override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_register)// 初始化视图etUserId = findViewById(R.id.etUserId)etUsername = findViewById(R.id.etUsername)etPhone = findViewById(R.id.etPhone)etClass = findViewById(R.id.etClass)etPassword = findViewById(R.id.etPassword)btnRegister = findViewById(R.id.btnRegister)btnRegister.setOnClickListener {handleRegister()}}private fun handleRegister() {val user = User(userId = etUserId.text.toString().trim(),username = etUsername.text.toString().trim(),phoneNumber = etPhone.text.toString().trim(),userClass = etClass.text.toString().trim(),password = etPassword.text.toString().trim())// 使用实体类的校验方法user.validateAll()?.let { errorMsg ->Toast.makeText(this, errorMsg, Toast.LENGTH_SHORT).show()return}lifecycleScope.launch {try {val response = userService.register(user)if (response.code == "200") {prefs.saveLastUserName(user.username)Toast.makeText(this@RegisterActivity,response.msg,Toast.LENGTH_SHORT).show()finish()} else {Toast.makeText(this@RegisterActivity,"注册失败: ${response.msg}",Toast.LENGTH_SHORT).show()}} catch (e: Exception) {Toast.makeText(this@RegisterActivity,"网络错误: ${e.message}",Toast.LENGTH_SHORT).show()}}}
}