关联用户2

This commit is contained in:
2026-05-20 16:30:24 +08:00
parent 133ea5a88b
commit 246b39ca1a
15 changed files with 254 additions and 172 deletions

View File

@@ -6,6 +6,7 @@ import bean.LoginBean
import com.blankj.utilcode.util.Utils
import com.example.defenseapplication.bean.BaseInfo
import com.example.defenseapplication.utils.ApiConfig
import com.example.defenseapplication.utils.LanguageHeaderManager
import com.example.defenseapplication.utils.LanguageUtil
import com.example.defenseapplication.utils.UserinfoUtil
import com.google.gson.Gson

View File

@@ -1,25 +1,36 @@
package com.example.defenseapplication.adapter
import android.graphics.Color
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.defenseapplication.R
import com.example.defenseapplication.databinding.ItemAddLinkedUserBinding
data class UserItem(val name: String, val phone: String)
data class UserItem(val name: String, val phone: String, val userId: String = "")
class AddLinkedUserAdapter(
private val data: List<UserItem>,
private val selectedIds: MutableSet<String>,
private val onItemClick: (String, Boolean) -> Unit
private val selectedUserIdMap: MutableMap<String, String>,
private val onItemClick: (String, Boolean, String?) -> Unit
) : RecyclerView.Adapter<AddLinkedUserAdapter.ViewHolder>() {
inner class ViewHolder(val binding: ItemAddLinkedUserBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: UserItem) {
binding.tvUserName.text = "${item.name}-${item.phone}"
binding.cbSelect.isChecked = selectedIds.contains(item.phone)
binding.cbSelect.setOnClickListener {
val isChecked = binding.cbSelect.isChecked
onItemClick(item.phone, isChecked)
val isChecked = selectedIds.contains(item.phone)
binding.cbSelect.isChecked = isChecked
binding.cbSelect.setOnCheckedChangeListener { _, checked ->
if (checked) {
binding.cbSelect.buttonTintList = android.content.res.ColorStateList.valueOf(Color.parseColor("#09C2BD"))
} else {
binding.cbSelect.buttonTintList = null
}
onItemClick(item.phone, checked, item.userId)
}
if (isChecked) {
binding.cbSelect.buttonTintList = android.content.res.ColorStateList.valueOf(Color.parseColor("#09C2BD"))
}
}
}

View File

@@ -56,10 +56,10 @@ class LinkedUserAdapter(
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: LinkedUser, position: Int) {
binding.tvPhone.text ="手机号码:${item.phone}"
binding.tvIdCard.text ="身份证号:${item.idCard}"
binding.llContent.translationX = 0f
binding.tvUserName.text = item.name
binding.tvPhone.text = "手机号码:${item.phone}"
binding.tvIdCard.text = "身份证号:${item.idCard}"
binding.tvTime.text = item.time
//设置删除按钮的文字
binding.tvDeleteAction.text = deleteText

View File

@@ -0,0 +1,8 @@
package com.example.defenseapplication.bean
data class AddDeviceUserRequest(
val deviceId: String,
val deviceNo: String? = null,
val deviceName: String? = null,
val userId: String
)

View File

@@ -1,9 +1,9 @@
package com.example.defenseapplication.bean
data class DeviceUserBean(
val createDept: String? = null, //创建部门
val createBy: String? = null, //创建人
val updateBy: String? = null, //更新者
val createDept: Int ? = null, //创建部门
val createBy: Int? = null, //创建人
val updateBy: Int? = null, //更新者
val updateTime: String? = null, //更新时间
val paramskeykey: String? = null,
val deviceId: String? = null, // 设备 ID

View File

@@ -0,0 +1,20 @@
package com.example.defenseapplication.bean
data class FamilyMembersBean(
val id: String? = null, // ID
val parentId: String? = null, // 家长 id
val parentName: String? = null, // 家长昵称
val userId: String? = null, // 成员 id
val nickName: String? = null, // 成员昵称
val idCard: String? = null, // 身份证号
val phonenumber: String? = null, // 手机号码
val status: String? = null, // 账号状态0 正常 1 停用)
val role: String? = null, // 角色
val createTime: String? = null, // 创建时间
val inviteCode: String? = null, // 邀请码
val createDept: Int? = null, // 创建部门
val createBy: Int? = null, // 创建人
val updateBy: Int? = null, // 更新者
val updateTime: String? = null, // 更新时间
val paramskeykey: String? = null
)

View File

@@ -3,16 +3,27 @@ package com.example.defenseapplication.liveVideo
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.defenseapplication.R
import com.example.defenseapplication.adapter.AddLinkedUserAdapter
import com.example.defenseapplication.adapter.UserItem
import com.example.defenseapplication.bean.AddDeviceUserRequest
import com.example.defenseapplication.bean.FamilyMembersBean
import com.example.defenseapplication.databinding.AddLinkedUserActivityBinding
import com.example.defenseapplication.utils.DeviceIdEvent
import com.example.defenseapplication.utils.DeviceUserUpdateEvent
import com.example.defenseapplication.utils.RetrofitNetwork
import com.gyf.immersionbar.ImmersionBar
//添加关联用户
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class AddLinkedUserActivity : AppCompatActivity() {
private lateinit var binding: AddLinkedUserActivityBinding
private val selectedPhoneSet = mutableSetOf<String>()
private val userItemList = mutableListOf<UserItem>()
private val selectedUserIdMap = mutableMapOf<String, String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -26,36 +37,112 @@ class AddLinkedUserActivity : AppCompatActivity() {
initRecyclerView()
initListener()
fetchFamilyMembers()
}
private fun initRecyclerView() {
val mockData = listOf(
UserItem("王五", "13566666666"),
UserItem("赵六", "15733333333")
)
binding.rvAddLinkedUser.layoutManager = LinearLayoutManager(this)
binding.rvAddLinkedUser.adapter =
AddLinkedUserAdapter(mockData, selectedPhoneSet) { phone, isChecked ->
AddLinkedUserAdapter(userItemList, selectedPhoneSet, selectedUserIdMap) { phone, isChecked, userId ->
if (isChecked) {
selectedPhoneSet.add(phone)
userId?.let { selectedUserIdMap[phone] = it }
} else {
selectedPhoneSet.remove(phone)
selectedUserIdMap.remove(phone)
}
}
}
private fun fetchFamilyMembers() {
lifecycleScope.launch {
try {
val response = RetrofitNetwork.getNetworkService().getFamilyMembers()
withContext(Dispatchers.Main) {
if (response.code == 200) {
if (response.data != null && response.data.isNotEmpty()) {
updateFamilyMemberList(response.data)
} else {
Toast.makeText(this@AddLinkedUserActivity, "暂无家庭成员数据", Toast.LENGTH_SHORT).show()
}
} else {
Toast.makeText(this@AddLinkedUserActivity, "请求失败: ${response.msg}", Toast.LENGTH_SHORT).show()
}
}
} catch (e: Exception) {
android.util.Log.e("AddLinkedUserActivity", "网络请求异常", e)
withContext(Dispatchers.Main) {
Toast.makeText(this@AddLinkedUserActivity, "网络请求失败: ${e.message}", Toast.LENGTH_SHORT).show()
}
}
}
}
private fun updateFamilyMemberList(familyMembersList: List<FamilyMembersBean>) {
userItemList.clear()
familyMembersList.forEach { member ->
userItemList.add(
UserItem(
name = member.nickName ?: member.parentName ?: "未知用户",
phone = member.phonenumber ?: "",
userId = member.userId ?: ""
)
)
}
binding.rvAddLinkedUser.adapter?.notifyDataSetChanged()
}
private fun initListener() {
binding.btnAddLinkedUser.setOnClickListener {
if (selectedPhoneSet.isEmpty()) {
Toast.makeText(this, getString(R.string.please_select_at_least_one_user), Toast.LENGTH_SHORT).show()
} else {
val message = getString(R.string.selected_users_voice, selectedPhoneSet.size)
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
addDeviceUser()
}
}
binding.ivBack.setOnClickListener {
finish()
}
}
private fun addDeviceUser() {
val deviceId = DeviceIdEvent.getDeviceId()
if (deviceId.isNullOrEmpty()) {
Toast.makeText(this, "设备ID为空", Toast.LENGTH_SHORT).show()
return
}
lifecycleScope.launch {
var successCount = 0
for ((phone, userId) in selectedUserIdMap) {
try {
val request = AddDeviceUserRequest(
deviceId = deviceId,
userId = userId
)
val response = RetrofitNetwork.getNetworkService().addDeviceUser(request)
withContext(Dispatchers.Main) {
if (response.code == 200) {
successCount++
} else {
Toast.makeText(this@AddLinkedUserActivity, "添加用户 $phone 失败: ${response.msg}", Toast.LENGTH_SHORT).show()
}
}
} catch (e: Exception) {
e.printStackTrace()
withContext(Dispatchers.Main) {
Toast.makeText(this@AddLinkedUserActivity, "添加用户 $phone 失败: 网络错误", Toast.LENGTH_SHORT).show()
}
}
}
withContext(Dispatchers.Main) {
if (successCount > 0) {
Toast.makeText(this@AddLinkedUserActivity, "成功添加 $successCount 个用户", Toast.LENGTH_SHORT).show()
DeviceUserUpdateEvent.notifyUpdate()
finish()
}
}
}
}
}

View File

@@ -15,8 +15,10 @@ import com.example.defenseapplication.adapter.LinkedUser
import com.example.defenseapplication.adapter.LinkedUserAdapter
import com.example.defenseapplication.bean.DeleteDeviceUserRequest
import com.example.defenseapplication.bean.DeviceUserBean
import com.example.defenseapplication.bean.FamilyMembersBean
import com.example.defenseapplication.databinding.LinkedUserActivityBinding
import com.example.defenseapplication.utils.DeviceIdEvent
import com.example.defenseapplication.utils.DeviceUserUpdateEvent
import com.example.defenseapplication.utils.RetrofitNetwork
import com.example.defenseapplication.view.CustomDialogFragmentText
import com.gyf.immersionbar.ImmersionBar
@@ -55,6 +57,18 @@ class LinkedUserActivity : AppCompatActivity() {
initData()
initListener()
setupModeUI()
DeviceUserUpdateEvent.addListener(deviceUserUpdateListener)
}
private val deviceUserUpdateListener = object : DeviceUserUpdateEvent.DeviceUserUpdateListener {
override fun onDeviceUserUpdated() {
fetchUserList()
}
}
override fun onDestroy() {
super.onDestroy()
DeviceUserUpdateEvent.removeListener(deviceUserUpdateListener)
}
private fun initView() {
@@ -222,22 +236,29 @@ class LinkedUserActivity : AppCompatActivity() {
}
private fun initData() {
fetchDeviceUserList()
fetchUserList()
}
private fun fetchDeviceUserList() {
val deviceId = DeviceIdEvent.getDeviceId()
if (deviceId.isNullOrEmpty()) {
Toast.makeText(this, "设备 ID 为空", Toast.LENGTH_SHORT).show()
return
}
private fun fetchUserList() {
lifecycleScope.launch {
try {
val response = RetrofitNetwork.getNetworkService().getDeviceUserList(deviceId)
val response = if (mode == MODE_SETTINGS) {
val deviceId = DeviceIdEvent.getDeviceId()
if (deviceId.isNullOrEmpty()) {
Toast.makeText(this@LinkedUserActivity, "设备 ID 为空", Toast.LENGTH_SHORT).show()
return@launch
}
RetrofitNetwork.getNetworkService().getDeviceUserList(deviceId)
} else {
RetrofitNetwork.getNetworkService().getFamilyMembers()
}
withContext(Dispatchers.Main) {
if (response.code == 200 && response.data != null) {
updateDeviceUserList(response.data)
if (mode == MODE_SETTINGS) {
updateDeviceUserList(response.data as List<DeviceUserBean>)
} else {
updateFamilyMembersList(response.data as List<FamilyMembersBean>)
}
} else {
Toast.makeText(this@LinkedUserActivity, response.msg, Toast.LENGTH_SHORT).show()
}
@@ -267,14 +288,29 @@ class LinkedUserActivity : AppCompatActivity() {
adapter.submitList(userList)
}
private fun updateFamilyMembersList(familyMembersList: List<FamilyMembersBean>) {
userList.clear()
familyMembersList.forEach { member ->
userList.add(
LinkedUser(
userId = member.userId ?: "",
name = member.nickName ?: member.parentName ?: "未知用户",
phone = member.phonenumber ?: "",
idCard = member.idCard ?: "",
time = member.createTime ?: ""
)
)
}
adapter.submitList(userList)
}
private fun initListener() {
binding.ivBack.setOnClickListener {
finish()
}
binding.searchLayout.setOnClickListener {
val intent = Intent(this, LinkedUserSearchActivity::class.java)
startActivityForResult(intent, REQUEST_CODE_SEARCH)
}
binding.btnAddLinkedUser.setOnClickListener {

View File

@@ -1,45 +0,0 @@
package com.example.defenseapplication.liveVideo
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.defenseapplication.databinding.LinkedUserSearchActivityBinding
import com.gyf.immersionbar.ImmersionBar
//搜索
class LinkedUserSearchActivity : AppCompatActivity() {
private lateinit var binding: LinkedUserSearchActivityBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = LinkedUserSearchActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
ImmersionBar.with(this)
.statusBarDarkFont(true)
.titleBar(binding.topBar)
.init()
initListener()
initData()
}
private fun initListener() {
binding.ivBack.setOnClickListener {
finish()
}
binding.btnSearch.setOnClickListener {
initData()
}
}
private fun initData() {
val searchText = binding.etSearch.text.toString().trim()
binding.rvSearchResult.layoutManager = LinearLayoutManager(this)
}
}

View File

@@ -163,19 +163,17 @@ object ApiConfig {
val requestBuilder = chain.request().newBuilder()
val token = authToken
val langHeader = LanguageHeaderManager.getLanguageHeaderValue()
// 添加必要的请求头
requestBuilder.header("clientid", "428a8310cd442757ae699df5d894f051")
requestBuilder.header("content-language", langHeader)
// 如果有 token添加 Authorization 头
if (token.isNotBlank()) {
Log.d("ApiConfig", buildAuthorizationValue(token))
requestBuilder.header("Authorization", buildAuthorizationValue(token))
requestBuilder.header("clientid", "428a8310cd442757ae699df5d894f051")
requestBuilder.header("content-language", langHeader)
}
requestBuilder
// .header("Client-Toc", "Y")
// .header("Accept-Language", LanguageHelper.getLanguageServiceStr(BrightApp.getInstance()))
// .header("model", "Android")
// .header("X-App-Version", AppUtils.getAppVersionName())
chain.proceed(requestBuilder.build())
}

View File

@@ -8,8 +8,10 @@ import com.example.defenseapplication.bean.GetCodeBean
import bean.LoginBean
import bean.LoginRequest
import bean.RegisterRequest
import com.example.defenseapplication.bean.AddDeviceUserRequest
import com.example.defenseapplication.bean.DeleteBean
import com.example.defenseapplication.bean.DeleteDeviceUserRequest
import com.example.defenseapplication.bean.FamilyMembersBean
import com.example.defenseapplication.bean.MessageGroup
import com.example.defenseapplication.bean.SwitchFamilyRequest
import retrofit2.http.Body
@@ -104,5 +106,29 @@ interface ApiService {
@POST("/app/deleteDeviceUser")
suspend fun deleteDeviceUser(@Body request: DeleteDeviceUserRequest): GetCodeBean<Any>
/**
* 查看家庭成员表
*/
@GET("/app/familyMembers/list")
suspend fun getFamilyMembers(
@Query("createDept") createDept: Long? = null,
@Query("createBy") createBy: Long? = null,
@Query("createTime") createTime: String? = null,
@Query("updateBy") updateBy: Long? = null,
@Query("updateTime") updateTime: String? = null,
@Query("params.key.key") paramsKey: String? = null,
@Query("id") id: Long? = null,
@Query("parentId") parentId: Long? = null,
@Query("parentName") parentName: String? = null,
@Query("userId") userId: Long? = null,
@Query("status") status: String? = null
): GetCodeBean<List<FamilyMembersBean>>
/**
* 添加设备关联用户
*/
@POST("/app/addDeviceUser")
suspend fun addDeviceUser(@Body request: AddDeviceUserRequest): GetCodeBean<Any>
}

View File

@@ -0,0 +1,23 @@
package com.example.defenseapplication.utils
object DeviceUserUpdateEvent {
private val listeners = mutableListOf<DeviceUserUpdateListener>()
interface DeviceUserUpdateListener {
fun onDeviceUserUpdated()
}
fun addListener(listener: DeviceUserUpdateListener) {
if (!listeners.contains(listener)) {
listeners.add(listener)
}
}
fun removeListener(listener: DeviceUserUpdateListener) {
listeners.remove(listener)
}
fun notifyUpdate() {
listeners.forEach { it.onDeviceUserUpdated() }
}
}

View File

@@ -1,3 +1,5 @@
package com.example.defenseapplication.utils
import android.content.Context
import androidx.core.content.edit
@@ -6,7 +8,7 @@ enum class AppLanguage(val code: String) {
SIMPLIFIED_CHINESE("zh_CN"),
TRADITIONAL_CHINESE("zh_TW")
}
//语言枚举与管理器
object LanguageHeaderManager {
private const val PREF_NAME = "app_lang_pref"
private const val KEY_LANGUAGE = "selected_language"