feat(chat): 优化群聊功能和界面组件

- 添加群成员头像基地址配置和统一管理
- 重构群成员列表布局和样式调整
- 添加群成员加入提示消息监听和处理机制
- 优化群聊头像加载和默认图标显示
- 重构群聊页面导航和界面元素
- 添加急救订单选择对话框功能
- 优化通话和定位分享功能实现
- 新增文件基地址辅助类和接口定义
- 重构群聊输入组件和布局配置
This commit is contained in:
2026-07-21 18:49:19 +08:00
parent aee280cf86
commit c504f23052
7 changed files with 242 additions and 16 deletions
@@ -28,7 +28,9 @@ import com.tencent.mm.opensdk.openapi.WXAPIFactory
import com.tencent.qcloud.tuicore.TUICore
import com.tencent.qcloud.tuikit.tuichat.TUIChatService
import com.tencent.qcloud.tuikit.tuichat.classicui.event.IMChatEvent
import com.tencent.qcloud.tuikit.tuichat.interfaces.FileBaseUrlListener
import com.tencent.qcloud.tuikit.tuichat.interfaces.ShareToWeChatListener
import com.tencent.qcloud.tuikit.tuichat.presenter.FileBaseUrlHelper
import com.tencent.qcloud.tuikit.tuichat.presenter.WeChatShareHelper
import com.xjjk.healthyclients.base.BaseVMBActivity
import com.xjjk.healthyclients.bean.CardInfoBean
@@ -40,6 +42,7 @@ import com.xjjk.healthyclients.fragment.EmergencyFragment
import com.xjjk.healthyclients.fragment.GuidanceFragment
import com.xjjk.healthyclients.fragment.HomeFragment
import com.xjjk.healthyclients.fragment.MonitorFragment
import com.xjjk.healthyclients.retrofit.UrlConfig
import com.xjjk.healthyclients.superfuntion.loginIm
import com.xjjk.healthyclients.superfuntion.startAllDoctorActivity
import com.xjjk.healthyclients.superfuntion.startLoginActivity
@@ -97,10 +100,13 @@ class MainActivity : BaseVMBActivity<MainViewModel, ActivityMainBinding>(R.layou
api?.sendReq(req)
}
private val fileBaseUrlListener = FileBaseUrlListener { UrlConfig.IMAGE_BASE_URL }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
regToWx()
WeChatShareHelper.getInstance().setListener(shareToWeChatListener)
FileBaseUrlHelper.getInstance().setListener(fileBaseUrlListener)
}
private fun regToWx() {
@@ -1,6 +1,7 @@
package com.xjjk.healthyclients.fragment
import android.Manifest
import android.app.Dialog
import android.content.Intent
import android.graphics.BitmapFactory
import android.graphics.Color
@@ -9,7 +10,9 @@ import android.os.Build
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import androidx.annotation.RequiresApi
import androidx.core.util.Consumer
import androidx.lifecycle.Lifecycle
@@ -40,9 +43,12 @@ import com.tencent.qcloud.tuikit.tuichat.presenter.ParamedicOperateHelper
import com.xjjk.healthyclients.R
import com.xjjk.healthyclients.base.BaseVMBFragment
import com.xjjk.healthyclients.bean.emergency.EmergencyDictBean
import com.xjjk.healthyclients.bean.emergency.GroupInfo
import com.xjjk.healthyclients.bean.emergency.LocationResourceBean
import com.xjjk.healthyclients.data.repository.EmergencyRepository
import com.xjjk.healthyclients.databinding.DialogGroupInfoListBinding
import com.xjjk.healthyclients.databinding.FragmentEmergencyBinding
import com.xjjk.healthyclients.fragment.adapter.GroupInfoAdapter
import com.xjjk.healthyclients.superfuntion.getMarkerInfo
import com.xjjk.healthyclients.superfuntion.startGroupChat
import com.xjjk.healthyclients.ui.viewmodel.EmergencyViewModel
@@ -50,6 +56,8 @@ import com.xjjk.healthyclients.utils.IMInputActionSettingUtils
import com.xjjk.healthyclients.utils.MapUtils
import com.xjjk.healthyclients.utils.SystemFuntion.goNavigation
import com.xjjk.healthyclients.utils.TUIUtils
import androidx.recyclerview.widget.LinearLayoutManager
import com.tencent.qcloud.tuicore.util.ToastUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.collectLatest
@@ -197,9 +205,9 @@ class EmergencyFragment :
ParamedicOperateHelper.getInstance().setListener(paramedicOperateListener)
mViewModel.isLiaisonUser { result ->
/*if (!result) {
if (result) {
mBinding.fragmentEmergencyParamedic.visibility = View.GONE
}*/
}
}
}
@@ -403,20 +411,37 @@ class EmergencyFragment :
}
R.id.fragment_emergency_paramedic -> {
mViewModel.getParamedicGroupInfo(
getString(R.string.title_paramedic_group),
mCurrentLon,
mCurrentLat,
successCall = {
IMInputActionSettingUtils.createEmergencySetting()
activity?.startGroupChat(
it.groupId,
getString(R.string.title_paramedic_group),
false,
it.member,
workBean = WorkBean(it.id, TUIUtils.WORK_TYPE_EMERGENCY)
)
})
mViewModel.getParticipatedOrders { result ->
if (result.records.isNullOrEmpty()) {
ToastUtil.toastLongMessage("暂无参与的应急就医工单")
} else if(result.records.size == 1){
showChatListDialog(result.records,onChatSelected = {groupInfo ->
mViewModel.getActualGroupMemberList(groupInfo.sessionId, successCall = {groupMemberBeans->
IMInputActionSettingUtils.createEmergencySetting()
activity?.startGroupChat(
groupInfo.sessionId,
getString(R.string.title_paramedic_group),
false,
groupMemberBeans.map { it1 -> it1.userId }.toList() as ArrayList<String>?,
workBean = WorkBean(groupInfo.orderId, TUIUtils.WORK_TYPE_EMERGENCY)
)
})
})
}else{
showChatListDialog(result.records,onChatSelected = {groupInfo ->
mViewModel.getActualGroupMemberList(groupInfo.sessionId, successCall = {groupMemberBeans->
IMInputActionSettingUtils.createEmergencySetting()
activity?.startGroupChat(
groupInfo.sessionId,
getString(R.string.title_paramedic_group),
false,
groupMemberBeans.map { it1 -> it1.userId }.toList() as ArrayList<String>?,
workBean = WorkBean(groupInfo.orderId, TUIUtils.WORK_TYPE_EMERGENCY)
)
})
})
}
}
}
R.id.fragment_emergency_marker_info -> {
@@ -452,6 +477,41 @@ class EmergencyFragment :
}
}
/**
* 展示急救订单列表Dialog,供用户选择历史订单继续聊天
*/
private fun showChatListDialog(
records: List<GroupInfo>,
onChatSelected: (GroupInfo) -> Unit
) {
context?.let { ctx ->
val dialog = Dialog(ctx, com.xjjk.healthyclients.R.style.DialogTheme)
val binding = DialogGroupInfoListBinding.inflate(layoutInflater)
binding.rvGroupList.layoutManager = LinearLayoutManager(ctx)
binding.rvGroupList.adapter = GroupInfoAdapter(records) { groupInfo ->
onChatSelected(groupInfo)
dialog.dismiss()
}
binding.tvCancel.setOnClickListener { dialog.dismiss() }
dialog.setContentView(binding.root)
dialog.setCanceledOnTouchOutside(true)
dialog.setCancelable(true)
dialog.window?.let { window ->
window.setGravity(Gravity.BOTTOM)
window.setWindowAnimations(com.xjjk.healthyclients.R.style.main_menu_animStyle)
window.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT
)
}
dialog.show()
}
}
fun setMarker(markerList: MutableList<LocationResourceBean>) {
mAMap?.clear() //清除点位
if (markerList.isNullOrEmpty()) {
@@ -0,0 +1,45 @@
package com.xjjk.healthyclients.fragment.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.xjjk.healthyclients.bean.emergency.GroupInfo
import com.xjjk.healthyclients.databinding.ItemGroupInfoBinding
/**
* 急救订单列表适配器
*/
class GroupInfoAdapter(
private val items: List<GroupInfo>,
private val onItemClick: (GroupInfo) -> Unit
) : RecyclerView.Adapter<GroupInfoAdapter.ViewHolder>() {
inner class ViewHolder(private val binding: ItemGroupInfoBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(groupInfo: GroupInfo) {
binding.tvUserName.text = groupInfo.salvageUserName
val sex = when (groupInfo.salvageUserSex) {
"1" -> ""
"2" -> ""
else -> "--"
}
binding.tvUserSex.text = sex
binding.tvOrgName.text = groupInfo.orgName
binding.root.setOnClickListener { onItemClick(groupInfo) }
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemGroupInfoBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position])
}
override fun getItemCount(): Int = items.size
}
@@ -5,7 +5,9 @@ import com.tencent.qcloud.tuikit.tuichat.bean.ExpertBean
import com.tencent.qcloud.tuikit.tuichat.bean.GroupMemberBean
import com.xjjk.healthyclients.base.viewmodel.BaseViewModel
import com.xjjk.healthyclients.bean.emergency.EmergencyGroupInfo
import com.xjjk.healthyclients.bean.emergency.GroupInfo
import com.xjjk.healthyclients.bean.emergency.LocationResourceBean
import com.xjjk.healthyclients.data.bean.PageBean
import com.xjjk.healthyclients.data.repository.EmergencyRepository
import com.xjjk.healthyclients.superfuntion.handleRequest
import com.xjjk.healthyclients.superfuntion.launch
@@ -59,6 +61,21 @@ class EmergencyViewModel : BaseViewModel() {
)
}
fun getParticipatedOrders(successCall: (PageBean<GroupInfo>) -> Unit = {}){
launch(
{
handleRequest(
EmergencyRepository.getParticipatedOrders(),
successBlock = {
it.result?.let { it1 ->
successCall.invoke(it1)
}
})
}
)
}
fun getEmergencyCall(
callType: String,
resourceId: String,
@@ -11,6 +11,8 @@ object ConstantUtils {
var mCurrentLon = 87.627704
var mNutritionMonitor = false
var mIsCloseDialog = false
val APP_ID: String = "wxb33cd60beda0a212"
var mPrivacy = "本平台由西安联链科技有限公司开发和运维,平台深知个人信息对您的重要性,并会尽全力保护您的个人信息安全可靠。我们致力于维持您对我们的信任,恪守以下原则,保护您的个人信息:权责一致原则、目的明确原则、选择同意原则、最少够用原则、确保安全原则、主体参与原则、公开透明原则等。同时,我们承诺将采取相应的安全保护措施来保护您的个人信息。请在使用平台服务前,仔细阅读并了解本隐私权政策,我们将按照本政策收集、处理及披露您的信息。\n" +
"本政策将帮助您了解以下内容:\n" +
"1、定义\n" +
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/rectangle_top_round_corner20_white">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/dp_20"
android:text="请选择应急就医对话"
android:textColor="@color/text_black_33"
android:textSize="@dimen/txt16"
android:textStyle="bold" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_group_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_18"
android:maxHeight="@dimen/dp_300"
tools:listitem="@layout/item_group_info" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/dp_0_5"
android:background="@color/theme_color" />
<TextView
android:id="@+id/tv_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingVertical="@dimen/dp_20"
android:text="取消"
android:textColor="@color/text_black_66"
android:textSize="@dimen/txt14"
android:background="?attr/selectableItemBackground" />
</LinearLayout>
</layout>
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="@dimen/dp_16"
android:paddingVertical="@dimen/dp_16"
android:gravity="center_vertical"
android:background="?attr/selectableItemBackground">
<TextView
android:id="@+id/tv_user_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="center"
android:textColor="@color/text_black_33"
android:textSize="@dimen/txt14"
android:ellipsize="end"
android:maxLines="1"
tools:text="张三" />
<TextView
android:id="@+id/tv_user_sex"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_weight="1"
android:layout_marginHorizontal="@dimen/dp_12"
android:textColor="@color/text_black_66"
android:textSize="@dimen/txt13"
tools:text="男" />
<TextView
android:id="@+id/tv_org_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="5"
android:textColor="@color/text_black_99"
android:textSize="@dimen/txt13"
android:maxLines="1"
android:ellipsize="end"
tools:text="某某科技有限公司" />
</LinearLayout>
</layout>