This commit is contained in:
2026-04-28 11:01:10 +08:00
parent 1b62e4d264
commit 8a5f599266
15 changed files with 419 additions and 32 deletions

View File

@@ -0,0 +1,10 @@
package com.example.defenseapplication
import android.app.Application
import com.blankj.utilcode.util.Utils;
class MyApplication : Application(){
override fun onCreate() {
super.onCreate()
Utils.init(this) // 初始化 AndroidUtilCode
}
}

View File

@@ -0,0 +1,44 @@
package com.example.defenseapplication.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.defenseapplication.R
import com.example.defenseapplication.databinding.ItemFamilyBinding
class FamilyAdapter(
private val onItemClick: (String) -> Unit
) : RecyclerView.Adapter<FamilyAdapter.FamilyViewHolder>() {
private val items = mutableListOf<String>()
private var selectedFamily: String? = null
fun submitList(familyList: List<String>, currentFamily: String) {
items.clear()
items.addAll(familyList)
selectedFamily = currentFamily
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FamilyViewHolder {
val binding = ItemFamilyBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return FamilyViewHolder(binding)
}
override fun onBindViewHolder(holder: FamilyViewHolder, position: Int) {
holder.bind(items[position])
}
override fun getItemCount(): Int = items.size
inner class FamilyViewHolder(private val binding: ItemFamilyBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(item: String) {
binding.tvFamilyName.text = item
val textColor = if (item == selectedFamily) R.color.green else R.color.black
binding.tvFamilyName.setTextColor(binding.root.context.getColor(textColor))
binding.root.setOnClickListener { onItemClick(item) }
}
}
}

View File

@@ -0,0 +1,7 @@
package com.example.defenseapplication.bean
data class GetCodeBean<T> (
val code:Int,
val msg:String,
val data:T
)

View File

@@ -0,0 +1,17 @@
package bean
//登录-bean
data class Login<T>(
val message: String,
val result: T,
val status: String
)
data class LoginBean(
val headPic: String,
val nickName: String,
val sex: Int,
val signature: String,
val token: String,
val userId: Int
)

View File

@@ -5,13 +5,39 @@ import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.defenseapplication.R
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.defenseapplication.adapter.DeviceAdapter
import com.example.defenseapplication.adapter.DeviceUi
import com.example.defenseapplication.adapter.FamilyAdapter
import com.example.defenseapplication.databinding.HomeMenuFragmentBinding
class HomeMenuFragment : Fragment() {
// ViewBinding
private var _binding: HomeMenuFragmentBinding? = null
private val binding get() = _binding!!
private val familyAdapter by lazy { FamilyAdapter(::onFamilySelected) }
private val deviceAdapter by lazy { DeviceAdapter() }
private var isFamilyExpanded = false
private var currentFamily = "我的家庭"
private val familyList = listOf("我的家庭", "工作室", "父母家")
private val familyDeviceMap = mapOf(
"我的家庭" to listOf(
DeviceUi("智能挂式防御机", true),
DeviceUi("智能防御机", false),
DeviceUi("智能轨道防御机", false)
),
"工作室" to listOf(
DeviceUi("走廊防御机", true),
DeviceUi("门禁防御机", true)
),
"父母家" to listOf(
DeviceUi("客厅防御机", false),
DeviceUi("阳台防御机", true)
)
)
override fun onCreateView(
inflater: LayoutInflater,
@@ -19,11 +45,59 @@ class HomeMenuFragment : Fragment() {
savedInstanceState: Bundle?
): View {
_binding = HomeMenuFragmentBinding.inflate(inflater, container, false)
initView()
return binding.root
}
private fun initView() {
binding.rvFamilyList.layoutManager = LinearLayoutManager(requireContext())
binding.rvFamilyList.adapter = familyAdapter
familyAdapter.submitList(familyList, currentFamily)
binding.rvDeviceList.layoutManager = GridLayoutManager(requireContext(), 2)
binding.rvDeviceList.adapter = deviceAdapter
updateDeviceList()
binding.tvCurrentFamily.text = currentFamily
binding.familyHeaderLayout.setOnClickListener {
toggleFamilyList()
}
binding.familyPopupMask.setOnClickListener {
if (isFamilyExpanded) {
toggleFamilyList()
}
}
}
private fun toggleFamilyList() {
isFamilyExpanded = !isFamilyExpanded
val visibility = if (isFamilyExpanded) View.VISIBLE else View.GONE
binding.familyPopupMask.visibility = visibility
binding.familyPopupCard.visibility = visibility
binding.ivFamilyArrow.animate()
.rotation(if (isFamilyExpanded) 180f else 0f)
.setDuration(200L)
.start()
}
private fun onFamilySelected(familyName: String) {
currentFamily = familyName
binding.tvCurrentFamily.text = familyName
familyAdapter.submitList(familyList, currentFamily)
updateDeviceList()
if (isFamilyExpanded) {
toggleFamilyList()
}
}
private fun updateDeviceList() {
deviceAdapter.submitList(familyDeviceMap[currentFamily].orEmpty())
}
override fun onDestroyView() {
super.onDestroyView()
binding.rvFamilyList.adapter = null
binding.rvDeviceList.adapter = null
_binding = null // 避免内存泄漏
}
}

View File

@@ -3,7 +3,6 @@ package com.example.defenseapplication.login
import android.os.Bundle
import android.os.CountDownTimer
import android.text.InputType
import android.text.TextUtils
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
@@ -12,6 +11,7 @@ import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.example.defenseapplication.R
import com.example.defenseapplication.databinding.ForgetPasswordActivityBinding
import com.google.firebase.crashlytics.buildtools.reloc.org.apache.http.util.TextUtils
import java.util.regex.Pattern
import kotlin.random.Random

View File

@@ -1,16 +0,0 @@
package com.example.defenseapplication.okhttp
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.IOException
object ApiService {
private const val BASE_URL = "https://stem-boozy-margarine.ngrok-free.dev"
private val client = OkHttpClient()
private val gson = Gson()
}

View File

@@ -0,0 +1,14 @@
package com.example.defenseapplication.utils
import com.google.gson.Gson
import okhttp3.OkHttpClient
import retrofit2.http.GET
interface ApiService {
// 获取登录注册验证码
@GET("/resource/sms/code")
suspend fun getCode(): String
}

View File

@@ -1,4 +1,4 @@
package com.example.defenseapplication.okhttp
package com.example.defenseapplication.utils
data class Post(
val userId: Int,

View File

@@ -0,0 +1,43 @@
package com.example.defenseapplication.utils
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
//网络工具类
object HttpUtils {
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.writeTimeout(3, TimeUnit.MINUTES)
.readTimeout(3, TimeUnit.MINUTES)
.addInterceptor(object : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val s = UserinfoUtil.getUserInfo()
val aa = chain.request().newBuilder()
.addHeader("token", s?.token ?: "")
.addHeader("userId", "${s?.userId ?: 0}")
.build()
return chain.proceed(aa)
}
})
.build()
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.baseUrl("https://stem-boozy-margarine.ngrok-free.dev")
.build()
val api = retrofit.create(ApiService::class.java)
}

View File

@@ -0,0 +1,27 @@
package com.example.defenseapplication.utils
import bean.LoginBean
import com.blankj.utilcode.util.SPUtils
import com.google.gson.Gson
//存储登录的token和userid
object UserinfoUtil {
private const val KEY_USER = "NAME_USER"
private val gson = Gson()
fun saveUserInfo(userinfo: LoginBean?) {
userinfo ?: return
val json = gson.toJson(userinfo)
SPUtils.getInstance().put(KEY_USER, json)
}
fun getUserInfo(): LoginBean? {
val string = SPUtils.getInstance().getString(KEY_USER)
if (string.isNullOrEmpty()) {
return null
}
return gson.fromJson(string, LoginBean::class.java)
}
}