diff --git a/app/src/main/java/com/xjjk/healthexpertclient/MyApplication.kt b/app/src/main/java/com/xjjk/healthexpertclient/MyApplication.kt index 49692ef..472992d 100644 --- a/app/src/main/java/com/xjjk/healthexpertclient/MyApplication.kt +++ b/app/src/main/java/com/xjjk/healthexpertclient/MyApplication.kt @@ -56,14 +56,22 @@ class MyApplication : BaseApp() { DataStoreManager.initialize(this) DebuggerUtils.checkDebuggableInNotDebugModel(this) TUIChatConfigs.getConfigs().imInputViewActionListener = - IMInputViewActionListener { workType, workId -> - var activity = CustomActivityManager.getInstance().currentActivity() - if(activity is AppCompatActivity){ - activity?.showLoading() + object : IMInputViewActionListener { + override fun finishAction(workType: Int, workId: String) { + var activity = CustomActivityManager.getInstance().currentActivity() + if(activity is AppCompatActivity){ + activity?.showLoading() + } + appViewModel.finishIMChat(workType, workId, finallyCall = { + hideLoading() + }) + } + + override fun appraiseAction(chatId: String, workType: Int, workId: String) { + } + + override fun finishActivityToGuidanceHome(workType: Int) { } - appViewModel.finishIMChat(workType, workId, finallyCall = { - hideLoading() - }) } registerActivityLifecycleCallbacks(AdjustLifecycleCallbacks()) } diff --git a/app/src/main/java/com/xjjk/healthexpertclient/bean/PageBean.kt b/app/src/main/java/com/xjjk/healthexpertclient/bean/PageBean.kt new file mode 100644 index 0000000..de64d1a --- /dev/null +++ b/app/src/main/java/com/xjjk/healthexpertclient/bean/PageBean.kt @@ -0,0 +1,12 @@ +package com.xjjk.healthexpertclient.bean + +/** + * 通用分页数据包装类(MyBatis-Plus 风格) + */ +data class PageBean( + val records: List?, + val total: Int = 0, + val size: Int = 0, + val current: Int = 0, + val pages: Int = 0 +) diff --git a/app/src/main/java/com/xjjk/healthexpertclient/bean/emergency/GroupInfo.kt b/app/src/main/java/com/xjjk/healthexpertclient/bean/emergency/GroupInfo.kt new file mode 100644 index 0000000..26f58c5 --- /dev/null +++ b/app/src/main/java/com/xjjk/healthexpertclient/bean/emergency/GroupInfo.kt @@ -0,0 +1,15 @@ +package com.xjjk.healthexpertclient.bean.emergency + +data class GroupInfo( + val orderId: String, + val sessionId: String, + val salvageUserName: String, + val salvageUserSex: String, + val salvageUserAvatar: String, + val salvageUserAge: Int, + val salvageUserMobile: String, + val orgName: String, + val deptName: String, + val orderStatus: String, + val initTime: String +) diff --git a/app/src/main/java/com/xjjk/healthexpertclient/bean/emergency/GroupMemberBean.kt b/app/src/main/java/com/xjjk/healthexpertclient/bean/emergency/GroupMemberBean.kt new file mode 100644 index 0000000..616081c --- /dev/null +++ b/app/src/main/java/com/xjjk/healthexpertclient/bean/emergency/GroupMemberBean.kt @@ -0,0 +1,10 @@ +package com.xjjk.healthexpertclient.bean.emergency + +/** + * 应急群组成员信息 + */ +data class GroupMemberBean( + val userId: String, + val userName: String = "", + val userAvatar: String = "" +) diff --git a/app/src/main/java/com/xjjk/healthexpertclient/data/api/WorkbenchApi.kt b/app/src/main/java/com/xjjk/healthexpertclient/data/api/WorkbenchApi.kt index 305b5e0..b17885f 100644 --- a/app/src/main/java/com/xjjk/healthexpertclient/data/api/WorkbenchApi.kt +++ b/app/src/main/java/com/xjjk/healthexpertclient/data/api/WorkbenchApi.kt @@ -1,6 +1,8 @@ package com.xjjk.healthexpertclient.data.api import com.btpj.lib_base.data.bean.ApiResponse +import com.tencent.qcloud.tuikit.tuichat.bean.EmployeeBean +import com.tencent.qcloud.tuikit.tuichat.bean.ExpertBean import com.xjjk.healthexpertclient.bean.AppUpdateBean import com.xjjk.healthexpertclient.bean.workbench.ArchivesDetailResultBean import com.xjjk.healthexpertclient.bean.workbench.AudioVideoCallBean @@ -11,6 +13,9 @@ import com.xjjk.healthexpertclient.bean.workbench.HealthInfoBean import com.xjjk.healthexpertclient.bean.workbench.MessageBean import com.xjjk.healthexpertclient.bean.workbench.PhysicalExaminationReportBean import com.xjjk.healthexpertclient.bean.workbench.RefuseReasonBean +import com.xjjk.healthexpertclient.bean.PageBean +import com.xjjk.healthexpertclient.bean.emergency.GroupInfo +import com.tencent.qcloud.tuikit.tuichat.bean.GroupMemberBean import com.xjjk.healthexpertclient.bean.workbench.WorkBenchConsultNumBean import okhttp3.RequestBody import retrofit2.http.Body @@ -136,4 +141,40 @@ interface WorkbenchApi { */ @GET("/health-system/version/getSysVersionDetailByPackageName") suspend fun getAppUpdateInfo(@QueryMap params: MutableMap): ApiResponse + + /** + * 当前登录人参与的应急工单列表 + */ + @GET("/health-emergency/api/emergency/order/myParticipatedOrders") + suspend fun getParticipatedOrders(): ApiResponse> + + /** + * 实际群成员列表 + */ + @GET("/health-emergency/api/emergency/order/getActualGroupMemberList") + suspend fun getActualGroupMemberList(@QueryMap params: MutableMap): ApiResponse> + + /** + * 邀请进群 + */ + @POST("/health-emergency/api/emergency/addGroupUser") + suspend fun addGroupUser(@Body requestBody: RequestBody): ApiResponse + + /** + * 移除群成员 + */ + @POST("/health-emergency/api/emergency/removeGroupUser") + suspend fun removeGroupUser(@Body requestBody: RequestBody): ApiResponse + + /** + * 搜索专家(专业人员) + */ + @GET("/health-emergency/api/emergency/order/searchExpert") + suspend fun searchExpert(@QueryMap params: MutableMap): ApiResponse> + + /** + * 搜索员工 + */ + @GET("/health-emergency/api/emergency/order/searchEmployee") + suspend fun searchEmployee(@QueryMap params: MutableMap): ApiResponse> } \ No newline at end of file diff --git a/app/src/main/java/com/xjjk/healthexpertclient/data/repository/WorkbenchRepository.kt b/app/src/main/java/com/xjjk/healthexpertclient/data/repository/WorkbenchRepository.kt index 540b9ec..fa4e49d 100644 --- a/app/src/main/java/com/xjjk/healthexpertclient/data/repository/WorkbenchRepository.kt +++ b/app/src/main/java/com/xjjk/healthexpertclient/data/repository/WorkbenchRepository.kt @@ -7,6 +7,11 @@ import com.btpj.lib_base.http.RetrofitManager import com.btpj.lib_base.http.RetrofitManager.toRequestBody import com.xjjk.healthexpertclient.BuildConfig import com.xjjk.healthexpertclient.bean.AppUpdateBean +import com.xjjk.healthexpertclient.bean.PageBean +import com.xjjk.healthexpertclient.bean.emergency.GroupInfo +import com.tencent.qcloud.tuikit.tuichat.bean.EmployeeBean +import com.tencent.qcloud.tuikit.tuichat.bean.ExpertBean +import com.tencent.qcloud.tuikit.tuichat.bean.GroupMemberBean import com.xjjk.healthexpertclient.bean.workbench.ArchivesDetailResultBean import com.xjjk.healthexpertclient.bean.workbench.AudioVideoCallBean import com.xjjk.healthexpertclient.bean.workbench.CheckRecordUserInfoBean @@ -190,4 +195,51 @@ object WorkbenchRepository : BaseRepository() { params["packageName"] = BuildConfig.APPLICATION_ID return apiCall { service.getAppUpdateInfo(params) } } + + suspend fun getParticipatedOrders(): ApiResponse> { + return apiCall { service.getParticipatedOrders() } + } + + suspend fun getActualGroupMemberList(sessionId: String): ApiResponse> { + val map = mutableMapOf() + map["sessionId"] = sessionId + return apiCall { service.getActualGroupMemberList(map) } + } + + suspend fun addGroupUser(groupId: String, memberList: List, memberType: Int): ApiResponse { + val map = mutableMapOf() + map["groupId"] = groupId + map["memberList"] = memberList + map["memberType"] = memberType + return apiCall { service.addGroupUser(map.toJson().toRequestBody()) } + } + + suspend fun removeGroupUser(groupId: String, memberList: List): ApiResponse { + val map = mutableMapOf() + map["groupId"] = groupId + map["memberList"] = memberList + return apiCall { service.removeGroupUser(map.toJson().toRequestBody()) } + } + + suspend fun searchExpert(realname: String, centerId: String, excludeSessionId: String, pageNo: Int, pageSize: Int): ApiResponse> { + val map = mutableMapOf() + map["realname"] = realname + map["centerId"] = centerId + map["excludeSessionId"] = excludeSessionId + map["pageNo"] = pageNo + map["pageSize"] = pageSize + return apiCall { service.searchExpert(map) } + } + + suspend fun searchEmployee(realname: String, orgCode: String, workNo: String, phone: String, excludeSessionId: String, pageNo: Int, pageSize: Int): ApiResponse> { + val map = mutableMapOf() + map["realname"] = realname + map["orgCode"] = orgCode + map["workNo"] = workNo + map["phone"] = phone + map["excludeSessionId"] = excludeSessionId + map["pageNo"] = pageNo + map["pageSize"] = pageSize + return apiCall { service.searchEmployee(map) } + } } \ No newline at end of file diff --git a/app/src/main/java/com/xjjk/healthexpertclient/ext/IMManager.kt b/app/src/main/java/com/xjjk/healthexpertclient/ext/IMManager.kt index c754b9f..381b094 100644 --- a/app/src/main/java/com/xjjk/healthexpertclient/ext/IMManager.kt +++ b/app/src/main/java/com/xjjk/healthexpertclient/ext/IMManager.kt @@ -19,6 +19,7 @@ import com.tencent.qcloud.tuikit.tuicallkit.TUICallKit import com.tencent.qcloud.tuikit.tuicallkit.base.Constants import com.tencent.qcloud.tuikit.tuicallkit.config.OfflinePushInfoConfig import com.tencent.qcloud.tuikit.tuichat.bean.WorkBean +import com.tencent.qcloud.tuikit.tuichat.classicui.setting.InputActionSetting import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -111,13 +112,13 @@ fun Context.startC2CChat(chatId: String, groupName: String, workBean: WorkBean? } } -fun Context.startGroupChat(groupId: String, groupName: String = "", workBean: WorkBean? = null) { +fun Context.startGroupChat(groupId: String, groupName: String = "", workBean: WorkBean? = null, + inputActionSetting: InputActionSetting? = null) { if (TUILogin.isUserLogined()) { - // TUIUtils.createGroup("VHMQIUMM", "android测试组", V2TIMConversation.V2TIM_GROUP) - TUIUtils.startChat(groupId, groupName, V2TIMConversation.V2TIM_GROUP, workBean) + TUIUtils.startChat(groupId, groupName, V2TIMConversation.V2TIM_GROUP, workBean, inputActionSetting) } else { loginIm(successCall = { - TUIUtils.startChat(groupId, groupName, V2TIMConversation.V2TIM_GROUP, workBean) + TUIUtils.startChat(groupId, groupName, V2TIMConversation.V2TIM_GROUP, workBean, inputActionSetting) }) } } diff --git a/app/src/main/java/com/xjjk/healthexpertclient/ui/im/utils/IMInputActionSettingUtils.kt b/app/src/main/java/com/xjjk/healthexpertclient/ui/im/utils/IMInputActionSettingUtils.kt index e640af8..c2696fe 100644 --- a/app/src/main/java/com/xjjk/healthexpertclient/ui/im/utils/IMInputActionSettingUtils.kt +++ b/app/src/main/java/com/xjjk/healthexpertclient/ui/im/utils/IMInputActionSettingUtils.kt @@ -1,5 +1,6 @@ package com.xjjk.healthexpertclient.ui.im.utils +import com.xjjk.healthexpertclient.BuildConfig import com.tencent.qcloud.tuikit.tuichat.classicui.setting.InputActionSetting object IMInputActionSettingUtils { @@ -26,4 +27,22 @@ object IMInputActionSettingUtils { inputActionSetting.isDisableMedicalExaminationReport = true inputActionSetting.isDisableSendMessage = false } + + /** + * 应急求助IM功能配置 + */ + fun createEmergencySetting(): InputActionSetting { + var inputActionSetting = InputActionSetting() + inputActionSetting.isDisableAudioCall = true + inputActionSetting.isDisableVideoCall = false + inputActionSetting.isDisableArchives = true + inputActionSetting.isDisableMedicalExaminationReport = true + inputActionSetting.isDisableSendMessage = false + inputActionSetting.isDisableFinishName = true + inputActionSetting.isDisableEvaluate = true + inputActionSetting.isDisableFinishSession = true + inputActionSetting.packageName = BuildConfig.APPLICATION_ID + InputActionSetting.setsInstance(inputActionSetting) + return inputActionSetting + } } \ No newline at end of file diff --git a/app/src/main/java/com/xjjk/healthexpertclient/ui/workbench/adapter/GroupInfoAdapter.kt b/app/src/main/java/com/xjjk/healthexpertclient/ui/workbench/adapter/GroupInfoAdapter.kt new file mode 100644 index 0000000..07bdb7b --- /dev/null +++ b/app/src/main/java/com/xjjk/healthexpertclient/ui/workbench/adapter/GroupInfoAdapter.kt @@ -0,0 +1,117 @@ +package com.xjjk.healthexpertclient.ui.workbench.adapter + +import android.content.res.ColorStateList +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.RecyclerView +import com.xjjk.healthexpertclient.R +import com.xjjk.healthexpertclient.bean.emergency.GroupInfo +import com.xjjk.healthexpertclient.databinding.ItemGroupInfoBinding + +/** + * 急救工单选择适配器,支持单选 + */ +class GroupInfoAdapter( + private val items: List, + private val onSelectionChanged: (Int) -> Unit +) : RecyclerView.Adapter() { + + /** 当前选中位置,-1 表示无选中 */ + var selectedPosition = -1 + private set + + /** 获取当前选中的工单 */ + val selectedItem: GroupInfo? + get() = if (selectedPosition in items.indices) items[selectedPosition] else null + + /** 选中主色 */ + private var colorPrimary = 0 + /** 未选中灰色 */ + private var colorGray = 0 + private var colorDark = 0 + private var colorBody = 0 + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val binding = ItemGroupInfoBinding.inflate( + LayoutInflater.from(parent.context), parent, false + ) + if (colorPrimary == 0) { + colorPrimary = ContextCompat.getColor(parent.context, R.color.emergency_primary) + colorGray = ContextCompat.getColor(parent.context, R.color.emergency_text_gray) + colorDark = ContextCompat.getColor(parent.context, R.color.emergency_text_dark) + colorBody = ContextCompat.getColor(parent.context, R.color.emergency_text_body) + } + return ViewHolder(binding) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(items[position], position == selectedPosition) + } + + override fun getItemCount(): Int = items.size + + inner class ViewHolder(private val binding: ItemGroupInfoBinding) : + RecyclerView.ViewHolder(binding.root) { + + private var currentPosition = -1 + + init { + binding.rootItem.setOnClickListener { + val oldPos = selectedPosition + if (oldPos == currentPosition) { + // 取消选中 + selectedPosition = -1 + notifyItemChanged(currentPosition) + onSelectionChanged(-1) + } else { + selectedPosition = currentPosition + notifyItemChanged(oldPos) + notifyItemChanged(currentPosition) + onSelectionChanged(currentPosition) + } + } + } + + fun bind(groupInfo: GroupInfo, isSelected: Boolean) { + currentPosition = adapterPosition + val ctx = binding.root.context + + // 姓名 + binding.tvUserName.text = groupInfo.salvageUserName + + // 部门标签 + binding.tvDeptName.text = groupInfo.deptName + + // 地址 + binding.tvOrgName.text = groupInfo.orgName + + // 时间 + binding.tvInitTime.text = "求助时间:${groupInfo.initTime}" + + if (isSelected) { + // 选中态 + binding.rootItem.setBackgroundResource(R.drawable.bg_emergency_item_selected) + binding.ivRadio.setImageResource(R.drawable.ic_emergency_radio_selected) + + binding.tvDeptName.setTextColor(colorPrimary) + binding.tvDeptName.setBackgroundResource(R.drawable.bg_dept_badge_selected) + + binding.tvInitTime.setTextColor(colorPrimary) + binding.ivLocation.imageTintList = ColorStateList.valueOf(colorPrimary) + binding.ivClock.imageTintList = ColorStateList.valueOf(colorPrimary) + } else { + // 未选中态 + binding.rootItem.setBackgroundResource(R.drawable.bg_emergency_item_unselected) + binding.ivRadio.setImageResource(R.drawable.ic_emergency_radio_unselected) + + binding.tvDeptName.setTextColor(colorGray) + binding.tvDeptName.setBackgroundResource(R.drawable.bg_dept_badge_unselected) + + binding.tvInitTime.setTextColor(colorGray) + binding.ivLocation.imageTintList = ColorStateList.valueOf(colorGray) + binding.ivClock.imageTintList = ColorStateList.valueOf(colorGray) + } + } + } +} diff --git a/app/src/main/java/com/xjjk/healthexpertclient/ui/workbench/fragment/WorkbenchFragment.kt b/app/src/main/java/com/xjjk/healthexpertclient/ui/workbench/fragment/WorkbenchFragment.kt index 89ba4b1..d907c46 100644 --- a/app/src/main/java/com/xjjk/healthexpertclient/ui/workbench/fragment/WorkbenchFragment.kt +++ b/app/src/main/java/com/xjjk/healthexpertclient/ui/workbench/fragment/WorkbenchFragment.kt @@ -3,17 +3,29 @@ package com.xjjk.healthexpertclient.ui.workbench.fragment import android.os.Bundle import android.os.SystemClock import android.view.View +import android.app.Dialog +import android.graphics.Color +import android.graphics.Rect +import android.graphics.drawable.ColorDrawable +import android.view.WindowManager +import androidx.core.util.Consumer import androidx.fragment.app.activityViewModels import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.btpj.lib_base.data.local.DataStoreManager import com.btpj.lib_base.ext.initColors import com.btpj.lib_base.ext.loadCircle +import com.btpj.lib_base.utils.ToastUtil import com.buddy.kredit.android.base.BaseFragment import com.xjjk.healthexpertclient.R +import com.xjjk.healthexpertclient.bean.emergency.GroupInfo import com.xjjk.healthexpertclient.bean.mine.DoctorBean +import com.xjjk.healthexpertclient.data.repository.WorkbenchRepository +import com.xjjk.healthexpertclient.databinding.DialogGroupInfoListBinding import com.xjjk.healthexpertclient.databinding.FragmentWorkbenchBinding import com.xjjk.healthexpertclient.event.WorkbenchEvent import com.xjjk.healthexpertclient.ext.loginIm @@ -24,14 +36,24 @@ import com.xjjk.healthexpertclient.ext.startSimulateUserActivity import com.xjjk.healthexpertclient.ui.im.utils.IMInputActionSettingUtils import com.xjjk.healthexpertclient.ui.main.viewmodel.MainViewModel import com.xjjk.healthexpertclient.ui.workbench.ConsultRecordActivity +import com.xjjk.healthexpertclient.ui.workbench.adapter.GroupInfoAdapter import com.xjjk.healthexpertclient.ui.workbench.viewmodel.WorkbenchViewModel import com.xjjk.healthexpertclient.utils.CommonUtils import com.xjjk.healthexpertclient.utils.TUIUtils import com.xjjk.healthexpertclient.utils.orEmptyDefault import com.xjjk.healthexpertclient.utils.orNullDefault +import com.tencent.qcloud.tuikit.tuichat.bean.EmployeeBean +import com.tencent.qcloud.tuikit.tuichat.bean.ExpertBean +import com.tencent.qcloud.tuikit.tuichat.bean.GroupMemberBean import com.tencent.qcloud.tuikit.tuichat.bean.WorkBean +import com.tencent.qcloud.tuikit.tuichat.classicui.interfaces.OnParamedicOperateListener +import com.tencent.qcloud.tuikit.tuichat.presenter.ParamedicOperateHelper +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeoutOrNull import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode @@ -43,12 +65,93 @@ class WorkbenchFragment : } private val mainViewModel by activityViewModels() + private val paramedicOperateListener = object : OnParamedicOperateListener { + override fun getActualGroupMemberList(sessionId: String): List? { + return runBlocking(Dispatchers.IO) { + try { + val deferred = async { + WorkbenchRepository.getActualGroupMemberList(sessionId) + } + val response = withTimeoutOrNull(10000L) { deferred.await() } + ?: return@runBlocking emptyList() + response.takeIf { it.success }?.result ?: emptyList() + } catch (e: Exception) { + emptyList() + } + } + } + + override fun addGroupUser( + groupId: String, + memberList: List, + memberType: Int, + callback: Consumer + ) { + mViewModel.addGroupUser(groupId, memberList, memberType) { success -> + callback.accept(success) + } + } + + override fun removeGroupUser(groupId: String, memberList: List) { + mViewModel.removeGroupUser(groupId, memberList) + } + + override fun searchExpert( + realname: String?, + centerId: String?, + excludeSessionId: String?, + pageNo: Int, + pageSize: Int + ): List? { + return runBlocking(Dispatchers.IO) { + try { + val deferred = async { + WorkbenchRepository.searchExpert( + realname ?: "", centerId ?: "", excludeSessionId ?: "", pageNo, pageSize + ) + } + val response = withTimeoutOrNull(10000L) { deferred.await() } + ?: return@runBlocking emptyList() + response.takeIf { it.success }?.result?.records ?: emptyList() + } catch (e: Exception) { + emptyList() + } + } + } + + override fun searchEmployee( + realname: String?, + orgCode: String?, + workNo: String?, + phone: String?, + excludeSessionId: String?, + pageNo: Int, + pageSize: Int + ): List? { + return runBlocking(Dispatchers.IO) { + try { + val deferred = async { + WorkbenchRepository.searchEmployee( + realname ?: "", orgCode ?: "", workNo ?: "", phone ?: "", + excludeSessionId ?: "", pageNo, pageSize + ) + } + val response = withTimeoutOrNull(10000L) { deferred.await() } + ?: return@runBlocking emptyList() + response.takeIf { it.success }?.result?.records ?: emptyList() + } catch (e: Exception) { + emptyList() + } + } + } + } + var time: Long = 3000 var mCount = 5 var mLastTime = 0L var mHits = LongArray(mCount) override fun initView(view: View, savedInstanceState: Bundle?) { -// setToolBarRightText(getString(R.string.doctor_homepage_message)) + ParamedicOperateHelper.getInstance().setListener(paramedicOperateListener) mBinding.swipeRefresh.initColors() mBinding.swipeRefresh.setOnRefreshListener(this@WorkbenchFragment) } @@ -101,6 +204,7 @@ class WorkbenchFragment : clImageTextConsultLay, clAudioVideoConsultLay, clAssistantConsultLay, + clAssistanceEmergencyLay, layImageTextConsultStatus.llLeftLay, layImageTextConsultStatus.llCenterLay, layImageTextConsultStatus.llRightLay, @@ -151,6 +255,36 @@ class WorkbenchFragment : requireContext().startGroupChat(it.groupId, getString(R.string.title_assistant_consult), WorkBean(it.id, TUIUtils.WORK_TYPE_ASSISTANT)) }) } + clAssistanceEmergencyLay -> { + mViewModel.getParticipatedOrders { result -> + if (result.records.isNullOrEmpty()) { + ToastUtil.showShort(requireContext(), "暂无参与的应急就医工单") + + } else if (result.records.size == 1) { + mViewModel.getActualGroupMemberList(result.records[0].sessionId) { groupMemberBeans -> + val setting = IMInputActionSettingUtils.createEmergencySetting() + requireContext().startGroupChat( + result.records[0].sessionId, + getString(R.string.title_paramedic_group), + WorkBean(result.records[0].orderId, TUIUtils.WORK_TYPE_EMERGENCY), + setting + ) + } + } else { + showChatListDialog(result.records!!) { groupInfo -> + mViewModel.getActualGroupMemberList(groupInfo.sessionId) { groupMemberBeans -> + val setting = IMInputActionSettingUtils.createEmergencySetting() + requireContext().startGroupChat( + groupInfo.sessionId, + getString(R.string.title_paramedic_group), + WorkBean(groupInfo.orderId, TUIUtils.WORK_TYPE_EMERGENCY), + setting + ) + } + } + } + } + } toolbarLay.tvRight -> { startMessageListActivity(requireContext()) } @@ -169,6 +303,67 @@ class WorkbenchFragment : } } } + /** + * 展示应急工单选择Dialog + */ + private fun showChatListDialog( + records: List, + onChatSelected: (GroupInfo) -> Unit + ) { + context?.let { ctx -> + val dialog = Dialog(ctx) + val binding = DialogGroupInfoListBinding.inflate(layoutInflater) + + val adapter = GroupInfoAdapter(records) { selectedPos -> + val hasSelection = selectedPos >= 0 + binding.tvConfirm.isEnabled = hasSelection + binding.tvConfirm.alpha = if (hasSelection) 1.0f else 0.4f + } + + binding.rvGroupList.layoutManager = LinearLayoutManager(ctx) + binding.rvGroupList.adapter = adapter.apply { + binding.tvConfirm.isEnabled = false + binding.tvConfirm.alpha = 0.4f + } + + val spacing = ctx.resources.getDimensionPixelSize(R.dimen.dp_12) + binding.rvGroupList.addItemDecoration(object : RecyclerView.ItemDecoration() { + override fun getItemOffsets( + outRect: Rect, + view: View, + parent: RecyclerView, + state: RecyclerView.State + ) { + outRect.bottom = spacing + } + }) + + binding.tvConfirm.setOnClickListener { + adapter.selectedItem?.let { item -> + onChatSelected(item) + dialog.dismiss() + } + } + + binding.ivClose.setOnClickListener { dialog.dismiss() } + binding.flRoot.setOnClickListener { dialog.dismiss() } + + dialog.setContentView(binding.root) + dialog.setCanceledOnTouchOutside(true) + dialog.setCancelable(true) + + dialog.window?.let { window -> + window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + window.decorView.setBackgroundColor(Color.TRANSPARENT) + window.setLayout( + WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.MATCH_PARENT + ) + } + dialog.show() + } + } + @Subscribe(threadMode = ThreadMode.MAIN) fun onEvent(event: WorkbenchEvent) { onRefresh() diff --git a/app/src/main/java/com/xjjk/healthexpertclient/ui/workbench/viewmodel/WorkbenchViewModel.kt b/app/src/main/java/com/xjjk/healthexpertclient/ui/workbench/viewmodel/WorkbenchViewModel.kt index 32ae4c6..24b36a4 100644 --- a/app/src/main/java/com/xjjk/healthexpertclient/ui/workbench/viewmodel/WorkbenchViewModel.kt +++ b/app/src/main/java/com/xjjk/healthexpertclient/ui/workbench/viewmodel/WorkbenchViewModel.kt @@ -6,8 +6,11 @@ import com.btpj.lib_base.base.BaseViewModel import com.btpj.lib_base.ext.handleRequest import com.btpj.lib_base.ext.launch import com.btpj.lib_base.utils.DateUtil +import com.xjjk.healthexpertclient.bean.PageBean +import com.xjjk.healthexpertclient.bean.emergency.GroupInfo import com.xjjk.healthexpertclient.bean.workbench.WorkBenchConsultNumBean import com.xjjk.healthexpertclient.data.repository.WorkbenchRepository +import com.tencent.qcloud.tuikit.tuichat.bean.GroupMemberBean import com.tencent.imsdk.v2.V2TIMConversation import com.tencent.imsdk.v2.V2TIMConversationListFilter import com.tencent.imsdk.v2.V2TIMConversationListener @@ -121,4 +124,34 @@ class WorkbenchViewModel: BaseViewModel() { }) }) } + + fun getParticipatedOrders(successCall: (PageBean) -> Unit){ + launch(false, { + handleRequest(WorkbenchRepository.getParticipatedOrders(), successBlock = { + it.result?.let { result -> successCall.invoke(result) } + }) + }) + } + + fun getActualGroupMemberList(sessionId: String, successCall: (List) -> Unit){ + launch(false, { + handleRequest(WorkbenchRepository.getActualGroupMemberList(sessionId), successBlock = { + it.result?.let { result -> successCall.invoke(result) } + }) + }) + } + + fun addGroupUser(groupId: String, memberList: List, memberType: Int, successCall: (Boolean) -> Unit){ + launch(false, { + handleRequest(WorkbenchRepository.addGroupUser(groupId, memberList, memberType), successBlock = { + successCall.invoke(it.success) + }) + }) + } + + fun removeGroupUser(groupId: String, memberList: List){ + launch(false, { + handleRequest(WorkbenchRepository.removeGroupUser(groupId, memberList), successBlock = {}) + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/xjjk/healthexpertclient/utils/TUIUtils.java b/app/src/main/java/com/xjjk/healthexpertclient/utils/TUIUtils.java index 427d5fb..3346966 100644 --- a/app/src/main/java/com/xjjk/healthexpertclient/utils/TUIUtils.java +++ b/app/src/main/java/com/xjjk/healthexpertclient/utils/TUIUtils.java @@ -16,6 +16,7 @@ import com.tencent.qcloud.tuicore.TUICore; import com.tencent.qcloud.tuicore.interfaces.TUILoginConfig; import com.tencent.qcloud.tuicore.util.TUIBuild; import com.tencent.qcloud.tuikit.tuichat.bean.WorkBean; +import com.tencent.qcloud.tuikit.tuichat.classicui.setting.InputActionSetting; import java.util.Locale; @@ -23,6 +24,7 @@ import java.util.Locale; public class TUIUtils { public static final int WORK_TYPE_IMAGE_TEXT_CONSULT = 2; public static final int WORK_TYPE_ASSISTANT = 3; + public static final int WORK_TYPE_EMERGENCY = 4; public static final String TAG = TUIUtils.class.getSimpleName(); public static void startActivity(String activityName, Bundle param) { @@ -30,6 +32,11 @@ public class TUIUtils { } public static void startChat(String chatId, String chatName, int chatType, WorkBean workBean) { + startChat(chatId, chatName, chatType, workBean, null); + } + + public static void startChat(String chatId, String chatName, int chatType, WorkBean workBean, + InputActionSetting inputActionSetting) { Bundle bundle = new Bundle(); bundle.putString(TUIConstants.TUIChat.CHAT_ID, chatId); if(!TextUtils.isEmpty(chatId)){ @@ -38,6 +45,9 @@ public class TUIUtils { } bundle.putInt(TUIConstants.TUIChat.CHAT_TYPE, chatType); bundle.putSerializable(TUIConstants.TUIChat.WORK_BEAN, workBean); + if (inputActionSetting != null) { + bundle.putSerializable("inputActionSetting", inputActionSetting); + } if (chatType == V2TIMConversation.V2TIM_C2C) { TUICore.startActivity(TUIConstants.TUIChat.C2C_CHAT_ACTIVITY_NAME, bundle); } else if (chatType == V2TIMConversation.V2TIM_GROUP) { diff --git a/app/src/main/res-workbench/drawable-xxhdpi/icon_consult_emergency.png b/app/src/main/res-workbench/drawable-xxhdpi/icon_consult_emergency.png new file mode 100644 index 0000000..c35a3c6 Binary files /dev/null and b/app/src/main/res-workbench/drawable-xxhdpi/icon_consult_emergency.png differ diff --git a/app/src/main/res-workbench/layout/fragment_workbench.xml b/app/src/main/res-workbench/layout/fragment_workbench.xml index d9a1d32..b4ecdd6 100644 --- a/app/src/main/res-workbench/layout/fragment_workbench.xml +++ b/app/src/main/res-workbench/layout/fragment_workbench.xml @@ -323,7 +323,7 @@ app:layout_constraintTop_toBottomOf="@+id/cl_audio_video_consult_lay" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" - app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintBottom_toTopOf="@+id/cl_assistance_emergency_lay" android:background="@drawable/rectangle_round_corner10_white" android:elevation="@dimen/dp_3" android:layout_marginHorizontal="@dimen/dp_15" @@ -394,6 +394,58 @@ app:layout_constraintTop_toBottomOf="@+id/tv_assistant_consult_title" android:text="@string/doctor_homepage_assistant_consult_explain" /> + + + + + + + + diff --git a/app/src/main/res/drawable/bg_dept_badge_selected.xml b/app/src/main/res/drawable/bg_dept_badge_selected.xml new file mode 100644 index 0000000..092e1da --- /dev/null +++ b/app/src/main/res/drawable/bg_dept_badge_selected.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/src/main/res/drawable/bg_dept_badge_unselected.xml b/app/src/main/res/drawable/bg_dept_badge_unselected.xml new file mode 100644 index 0000000..0d21655 --- /dev/null +++ b/app/src/main/res/drawable/bg_dept_badge_unselected.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/src/main/res/drawable/bg_emergency_close_btn.xml b/app/src/main/res/drawable/bg_emergency_close_btn.xml new file mode 100644 index 0000000..c5e68ca --- /dev/null +++ b/app/src/main/res/drawable/bg_emergency_close_btn.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/bg_emergency_confirm_btn.xml b/app/src/main/res/drawable/bg_emergency_confirm_btn.xml new file mode 100644 index 0000000..461bf60 --- /dev/null +++ b/app/src/main/res/drawable/bg_emergency_confirm_btn.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/src/main/res/drawable/bg_emergency_dialog_card.xml b/app/src/main/res/drawable/bg_emergency_dialog_card.xml new file mode 100644 index 0000000..a8ae65b --- /dev/null +++ b/app/src/main/res/drawable/bg_emergency_dialog_card.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/src/main/res/drawable/bg_emergency_item_selected.xml b/app/src/main/res/drawable/bg_emergency_item_selected.xml new file mode 100644 index 0000000..dc1c306 --- /dev/null +++ b/app/src/main/res/drawable/bg_emergency_item_selected.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/app/src/main/res/drawable/bg_emergency_item_unselected.xml b/app/src/main/res/drawable/bg_emergency_item_unselected.xml new file mode 100644 index 0000000..f763ee4 --- /dev/null +++ b/app/src/main/res/drawable/bg_emergency_item_unselected.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_emergency_clock.xml b/app/src/main/res/drawable/ic_emergency_clock.xml new file mode 100644 index 0000000..769e61c --- /dev/null +++ b/app/src/main/res/drawable/ic_emergency_clock.xml @@ -0,0 +1,19 @@ + + + + diff --git a/app/src/main/res/drawable/ic_emergency_close.xml b/app/src/main/res/drawable/ic_emergency_close.xml new file mode 100644 index 0000000..563c85d --- /dev/null +++ b/app/src/main/res/drawable/ic_emergency_close.xml @@ -0,0 +1,12 @@ + + + diff --git a/app/src/main/res/drawable/ic_emergency_location.xml b/app/src/main/res/drawable/ic_emergency_location.xml new file mode 100644 index 0000000..a666090 --- /dev/null +++ b/app/src/main/res/drawable/ic_emergency_location.xml @@ -0,0 +1,15 @@ + + + + diff --git a/app/src/main/res/drawable/ic_emergency_radio_selected.xml b/app/src/main/res/drawable/ic_emergency_radio_selected.xml new file mode 100644 index 0000000..226186d --- /dev/null +++ b/app/src/main/res/drawable/ic_emergency_radio_selected.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_emergency_radio_unselected.xml b/app/src/main/res/drawable/ic_emergency_radio_unselected.xml new file mode 100644 index 0000000..8005b40 --- /dev/null +++ b/app/src/main/res/drawable/ic_emergency_radio_unselected.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/src/main/res/layout/dialog_group_info_list.xml b/app/src/main/res/layout/dialog_group_info_list.xml new file mode 100644 index 0000000..e05c8ff --- /dev/null +++ b/app/src/main/res/layout/dialog_group_info_list.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_group_info.xml b/app/src/main/res/layout/item_group_info.xml new file mode 100644 index 0000000..ddc25ac --- /dev/null +++ b/app/src/main/res/layout/item_group_info.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index f5af710..98bc23f 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -111,6 +111,7 @@ #FF00B0FF #66000000 #21BEBD + #1A21BEBD #EFEFEF #E0E0E0 @@ -122,4 +123,15 @@ #16C716 #21BEBD + + #0F2EB8B2 + #802EB8B2 + #E6E6EA + #EAECFA + #252535 + #394356 + #77859E + #2EB8B2 + #F1F5F9 + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 99018ff..b1ecda1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -28,6 +28,7 @@ 擅长病种 体检详情 全科医生 + 应急求助 位置 消息 选择位置 diff --git a/lib_base/src/main/java/com/btpj/lib_base/data/local/IpManager.kt b/lib_base/src/main/java/com/btpj/lib_base/data/local/IpManager.kt index 54c2295..a186984 100644 --- a/lib_base/src/main/java/com/btpj/lib_base/data/local/IpManager.kt +++ b/lib_base/src/main/java/com/btpj/lib_base/data/local/IpManager.kt @@ -20,8 +20,11 @@ object IpManager { /** 常用的IP */ private const val DEBUG_DEFAULT_IP_ADDRESS_REMOTE = "http://cqyt.dev.yg.dt.io/" // 开发环境 - private const val TEST_DEFAULT_IP_ADDRESS_REMOTE = "https://xjgateway.mcrm.vip:8888/" // 测试环境 -// private const val PRODUCT_DEFAULT_IP_ADDRESS_REMOTE = "https://api.xjygjk.com/" // 线上环境 +// private const val TEST_DEFAULT_IP_ADDRESS_REMOTE = "https://xjgateway.mcrm.vip:8888/" // 测试环境 +// private const val TEST_DEFAULT_IP_ADDRESS_REMOTE = "https://xjxc-api.mcrm.vip:8888/" // 测试环境 + private const val TEST_DEFAULT_IP_ADDRESS_REMOTE = "https://xj-api.yixiong-tech.com:8081/" + + // private const val PRODUCT_DEFAULT_IP_ADDRESS_REMOTE = "https://api.xjygjk.com/" // 线上环境 private const val PRODUCT_DEFAULT_IP_ADDRESS_REMOTE = "https://api-jkglpt.iosp.ydpt.tech/" // 线上环境 private const val DEBUG_H5_ADDRESS_REMOTE = "http://cms.dev.yg.dt.io" // 开发环境 @@ -34,7 +37,7 @@ object IpManager { private const val KEY_DEFAULT_IP_AND_PORT = "data_default_ip_and_port" private lateinit var dataStore: DataStoreUtils - val baseUrlType: BaseUrlType = BaseUrlType.PRODUCT + val baseUrlType: BaseUrlType = BaseUrlType.TEST fun initialize(context: Context?) { if (context == null) { Log.w(TAG, "initialize: context is null") diff --git a/system/tuichat/src/main/AndroidManifest.xml b/system/tuichat/src/main/AndroidManifest.xml index 60652a2..0f0e3e1 100644 --- a/system/tuichat/src/main/AndroidManifest.xml +++ b/system/tuichat/src/main/AndroidManifest.xml @@ -44,6 +44,10 @@ android:screenOrientation="portrait" android:windowSoftInputMode="adjustNothing|stateHidden"/> + + diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/TUIChatConstants.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/TUIChatConstants.java index 142ba25..01f5eef 100644 --- a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/TUIChatConstants.java +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/TUIChatConstants.java @@ -38,6 +38,8 @@ public class TUIChatConstants { public static final int GET_MESSAGE_LOCATE = 3; public static final String CHAT_INFO = "chatInfo"; + public static final String WEEK_STATE = "weekState"; + public static final String CHAT_IS_LIAISON_USER = "chat_is_liaison_user"; public static final String MESSAGE_BEAN = "messageBean"; diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/ChatInfo.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/ChatInfo.java index 6ecac01..ae8df43 100644 --- a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/ChatInfo.java +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/ChatInfo.java @@ -194,4 +194,23 @@ public class ChatInfo implements Serializable { public void setInputActionSetting(InputActionSetting inputActionSetting) { this.inputActionSetting = inputActionSetting; } + + private String autoSendMessage; + private String consultantId; + + public String getAutoSendMessage() { + return autoSendMessage; + } + + public void setAutoSendMessage(String autoSendMessage) { + this.autoSendMessage = autoSendMessage; + } + + public String getConsultantId() { + return consultantId; + } + + public void setConsultantId(String consultantId) { + this.consultantId = consultantId; + } } diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/EmployeeBean.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/EmployeeBean.java new file mode 100644 index 0000000..71e6d9d --- /dev/null +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/EmployeeBean.java @@ -0,0 +1,67 @@ +package com.tencent.qcloud.tuikit.tuichat.bean; + +public class EmployeeBean { + private String userId; + private String realname; + private String avatar; + private String orgCode; + private String orgName; + private String deptName; + private String phone; + private String workNo; + public void setUserId(String userId) { + this.userId = userId; + } + public String getUserId() { + return userId; + } + + public void setRealname(String realname) { + this.realname = realname; + } + public String getRealname() { + return realname; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + public String getAvatar() { + return avatar; + } + + public void setOrgCode(String orgCode) { + this.orgCode = orgCode; + } + public String getOrgCode() { + return orgCode; + } + + public void setOrgName(String orgName) { + this.orgName = orgName; + } + public String getOrgName() { + return orgName; + } + + public void setDeptName(String deptName) { + this.deptName = deptName; + } + public String getDeptName() { + return deptName; + } + + public void setPhone(String phone) { + this.phone = phone; + } + public String getPhone() { + return phone; + } + + public void setWorkNo(String workNo) { + this.workNo = workNo; + } + public String getWorkNo() { + return workNo; + } +} diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/ExpertBean.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/ExpertBean.java new file mode 100644 index 0000000..5b1163f --- /dev/null +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/ExpertBean.java @@ -0,0 +1,112 @@ +package com.tencent.qcloud.tuikit.tuichat.bean; + +public class ExpertBean { + private String userId; + private String realname; + private String avatar; + private String type; + private String centerId; + private String post; + private String post_dictText; + private String school; + private String edu; + private String goodAt; + private String deptName; + private String phone; + + public String getPost_dictText() { + return post_dictText; + } + + public void setPost_dictText(String post_dictText) { + this.post_dictText = post_dictText; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getRealname() { + return realname; + } + + public void setRealname(String realname) { + this.realname = realname; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getCenterId() { + return centerId; + } + + public void setCenterId(String centerId) { + this.centerId = centerId; + } + + public String getPost() { + return post; + } + + public void setPost(String post) { + this.post = post; + } + + public String getSchool() { + return school; + } + + public void setSchool(String school) { + this.school = school; + } + + public String getEdu() { + return edu; + } + + public void setEdu(String edu) { + this.edu = edu; + } + + public String getGoodAt() { + return goodAt; + } + + public void setGoodAt(String goodAt) { + this.goodAt = goodAt; + } + + public String getDeptName() { + return deptName; + } + + public void setDeptName(String deptName) { + this.deptName = deptName; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } +} diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/GroupInfo.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/GroupInfo.java index 35bc028..b66876f 100644 --- a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/GroupInfo.java +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/GroupInfo.java @@ -21,7 +21,7 @@ public class GroupInfo extends ChatInfo { private int memberCount; private String groupName; private String notice; - private List memberDetails = new ArrayList<>(); + private List memberDetails = new ArrayList<>(); private int joinType; private String owner; private boolean messageReceiveOption; @@ -125,7 +125,7 @@ public class GroupInfo extends ChatInfo { * * @return */ - public List getMemberDetails() { + public List getMemberDetails() { return memberDetails; } @@ -136,7 +136,7 @@ public class GroupInfo extends ChatInfo { * * @param memberDetails */ - public void setMemberDetails(List memberDetails) { + public void setMemberDetails(List memberDetails) { this.memberDetails = memberDetails; } @@ -223,4 +223,14 @@ public class GroupInfo extends ChatInfo { setMessageReceiveOption(infoResult.getGroupInfo().getRecvOpt() == V2TIMMessage.V2TIM_RECEIVE_NOT_NOTIFY_MESSAGE ? true : false); return this; } + + private boolean initiateVideoCall; + + public boolean isInitiateVideoCall() { + return initiateVideoCall; + } + + public void setInitiateVideoCall(boolean initiateVideoCall) { + this.initiateVideoCall = initiateVideoCall; + } } diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/GroupMember.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/GroupMember.java new file mode 100644 index 0000000..0b0b0cd --- /dev/null +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/GroupMember.java @@ -0,0 +1,109 @@ +package com.tencent.qcloud.tuikit.tuichat.bean; + +import java.util.ArrayList; +import java.util.List; + +/** + * 群成员信息扩展类,在 GroupMemberInfo 基础上补充 GroupMemberBean 中的业务字段 + */ +public class GroupMember extends GroupMemberInfo { + + private String orderId; + private String userId; + private String userName; + private String avatar; + private String phone; + private int isGroupMember; + private int isSelf; + + public String getOrderId() { + return orderId; + } + + public void setOrderId(String orderId) { + this.orderId = orderId; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public int getIsGroupMember() { + return isGroupMember; + } + + public void setIsGroupMember(int isGroupMember) { + this.isGroupMember = isGroupMember; + } + + public int getIsSelf() { + return isSelf; + } + + public void setIsSelf(int isSelf) { + this.isSelf = isSelf; + } + + /** + * 将 GroupMemberBean 转换为 GroupMember + */ + public static GroupMember convertFromBean(GroupMemberBean bean) { + if (bean == null) { + return null; + } + GroupMember member = new GroupMember(); + // 映射到父类字段 + member.setAccount(bean.getUserId()); + member.setMemberType(bean.getMemberType()); + // 映射到自身扩展字段 + member.setOrderId(bean.getOrderId()); + member.setUserId(bean.getUserId()); + member.setUserName(bean.getUserName()); + member.setAvatar(bean.getAvatar()); + member.setPhone(bean.getPhone()); + member.setIsGroupMember(bean.getIsGroupMember()); + member.setIsSelf(bean.getIsSelf()); + return member; + } + + /** + * 批量将 List 转换为 List + */ + public static List convertFromBeanList(List beans) { + List members = new ArrayList<>(); + if (beans != null) { + for (GroupMemberBean bean : beans) { + members.add(convertFromBean(bean)); + } + } + return members; + } +} diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/GroupMemberBean.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/GroupMemberBean.java new file mode 100644 index 0000000..7fa1887 --- /dev/null +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/bean/GroupMemberBean.java @@ -0,0 +1,76 @@ +package com.tencent.qcloud.tuikit.tuichat.bean; + +public class GroupMemberBean { + private String orderId; + private String userId; + private String userName; + private String avatar; + private String phone; + private int isGroupMember; + private int memberType; + private int isSelf; + + public int getIsSelf() { + return isSelf; + } + + public void setIsSelf(int isSelf) { + this.isSelf = isSelf; + } + + public String getOrderId() { + return orderId; + } + + public void setOrderId(String orderId) { + this.orderId = orderId; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public int getIsGroupMember() { + return isGroupMember; + } + + public void setIsGroupMember(int isGroupMember) { + this.isGroupMember = isGroupMember; + } + + public int getMemberType() { + return memberType; + } + + public void setMemberType(int memberType) { + this.memberType = memberType; + } +} diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/event/CustomMessageEvent.kt b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/event/CustomMessageEvent.kt new file mode 100644 index 0000000..99726a3 --- /dev/null +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/event/CustomMessageEvent.kt @@ -0,0 +1,9 @@ +package com.tencent.qcloud.tuikit.tuichat.classicui.event + +/** + * @author nanfeifei + * @time 2023/7/5 14:32 + * @description + */ +class CustomMessageEvent(var chatId: String, var messageJson: String) { +} diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/event/IMChatEvent.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/event/IMChatEvent.java new file mode 100644 index 0000000..8698475 --- /dev/null +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/event/IMChatEvent.java @@ -0,0 +1,79 @@ +package com.tencent.qcloud.tuikit.tuichat.classicui.event; + +public class IMChatEvent { + public int type;//0 医生卡片 1 仅提示message信息 2聊天头像id + public String doctor; + public String message = ""; + public long time; + + //新疆项目新增字段 + public String groupId = ""; + public String fromAccount = "";//小助手id + public String toAccount = "";//当前登录用户id + public String msgId = ""; + + + public String getMessage() { + return message == null ? "" : message; + } + + public void setMessage(String message) { + this.message = message; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getDoctor() { + return doctor == null ? "" : doctor; + } + + public void setDoctor(String doctor) { + this.doctor = doctor; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getFromAccount() { + return fromAccount; + } + + public void setFromAccount(String fromAccount) { + this.fromAccount = fromAccount; + } + + public String getToAccount() { + return toAccount; + } + + public void setToAccount(String toAccount) { + this.toAccount = toAccount; + } + + public String getMsgId() { + return msgId; + } + + public void setMsgId(String msgId) { + this.msgId = msgId; + } +} diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/interfaces/OnParamedicOperateListener.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/interfaces/OnParamedicOperateListener.java new file mode 100644 index 0000000..2a1994b --- /dev/null +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/interfaces/OnParamedicOperateListener.java @@ -0,0 +1,70 @@ +package com.tencent.qcloud.tuikit.tuichat.classicui.interfaces; + +import androidx.core.util.Consumer; + +import com.tencent.qcloud.tuikit.tuichat.bean.EmployeeBean; +import com.tencent.qcloud.tuikit.tuichat.bean.ExpertBean; +import com.tencent.qcloud.tuikit.tuichat.bean.GroupMemberBean; + +import java.util.List; + +/** + * 急救调度相关操作的对外接口。 + * 由宿主 App(如 EmergencyFragment)实现并注册到 {@link com.tencent.qcloud.tuikit.tuichat.presenter.ParamedicOperateHelper}, + * 供 tuichat 模块反向调用宿主能力(加成员、查专家/员工、移除成员等)。 + */ +public interface OnParamedicOperateListener { + + /** + * 获取指定会话(群组)当前实际成员列表。 + * + * @param sessionId 群组会话 ID + * @return 成员列表,可能为空,但不为 null + */ + List getActualGroupMemberList(String sessionId); + + /** + * 邀请一批用户加入指定群组。操作为异步执行,结果通过 callback 回传。 + * + * @param groupId 目标群组 ID + * @param memberList 待加入成员的 userId 列表 + * @param memberType 成员类型,由业务侧约定语义 + * @param callback 操作结果回调:true 表示服务器侧写入成功;false 表示失败(含网络异常、业务错误等)。 + * 回调触发线程不限定,调用方需自行切回主线程操作 UI。不允许传 null。 + */ + void addGroupUser(String groupId, List memberList, int memberType, Consumer callback); + + /** + * 按条件检索专家。 + * + * @param realname 真实姓名关键字,可空 + * @param centerId 中心 ID,可空 + * @param excludeSessionId 需排除的会话 ID(避免重复添加),可空 + * @param pageNo 页码 + * @param pageSize 每页条数 + * @return 专家列表,可能为空 + */ + List searchExpert(String realname, String centerId, String excludeSessionId, int pageNo, int pageSize); + + /** + * 按条件检索员工。 + * + * @param realname 真实姓名关键字,可空 + * @param orgCode 机构编码,可空 + * @param workNo 工号,可空 + * @param phone 电话,可空 + * @param excludeSessionId 需排除的会话 ID,可空 + * @param pageNo 页码 + * @param pageSize 每页条数 + * @return 员工列表,可能为空 + */ + List searchEmployee(String realname, String orgCode, String workNo, String phone, String excludeSessionId, int pageNo, int pageSize); + + /** + * 从指定群组移除一批成员。当前为 fire-and-forget,无回调。 + * + * @param groupId 目标群组 ID + * @param memberList 待移除成员的 userId 列表 + */ + void removeGroupUser(String groupId, List memberList); +} diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/AddMemberActivity.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/AddMemberActivity.java new file mode 100644 index 0000000..5c1211a --- /dev/null +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/AddMemberActivity.java @@ -0,0 +1,267 @@ +package com.tencent.qcloud.tuikit.tuichat.classicui.page; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.tabs.TabLayout; +import com.tencent.qcloud.tuicore.component.activities.BaseLightActivity; +import com.tencent.qcloud.tuikit.tuichat.R; +import com.tencent.qcloud.tuikit.tuichat.bean.EmployeeBean; +import com.tencent.qcloud.tuikit.tuichat.bean.ExpertBean; + +import java.util.ArrayList; +import java.util.List; + +public class AddMemberActivity extends BaseLightActivity { + + public static final int REQUEST_CODE_ADD_MEMBER = 12; + public static final String EXTRA_SELECTED_USER_IDS = "extra_selected_user_ids"; + + private static final int TAB_EMPLOYEE = 0; + private static final int TAB_EXPERT = 1; + private LinearLayout llBack; + private TabLayout tabLayout; + private EditText etSearch; + private RecyclerView rvMembers; + private TextView tvConfirm; + private TextView tvSearchAction; + + private AddMemberViewModel viewModel; + private AddMemberAdapter expertAdapter; + private AddMemberAdapter employeeAdapter; + private int currentTab = TAB_EMPLOYEE; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_add_member); + + viewModel = new ViewModelProvider(this).get(AddMemberViewModel.class); + + initViews(); + initAdapters(); + initObservers(); + initListeners(); + + viewModel.loadExperts(""); + viewModel.loadEmployees(""); + } + + private void initViews() { + llBack = findViewById(R.id.ll_back); + tabLayout = findViewById(R.id.tab_layout); + etSearch = findViewById(R.id.et_search); + rvMembers = findViewById(R.id.rv_members); + tvConfirm = findViewById(R.id.tv_confirm); + tvSearchAction = findViewById(R.id.tv_search_action); + + rvMembers.setLayoutManager(new LinearLayoutManager(this)); + rvMembers.setHasFixedSize(false); + + tabLayout.addTab(tabLayout.newTab().setText(R.string.add_member_tab_employee)); + tabLayout.addTab(tabLayout.newTab().setText(R.string.add_member_tab_expert)); + + setupSearchBox(); + } + + private void setupSearchBox() { + etSearch.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_search, 0, 0, 0); + + etSearch.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) {} + @Override + public void afterTextChanged(Editable s) { + updateClearIconVisibility(s.length() > 0); + } + }); + + etSearch.setOnEditorActionListener((v, actionId, event) -> { + if (actionId == EditorInfo.IME_ACTION_SEARCH + || (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER + && event.getAction() == KeyEvent.ACTION_DOWN)) { + onSearch(v.getText().toString().trim()); + return true; + } + return false; + }); + + etSearch.setOnTouchListener((v, event) -> { + if (event.getAction() != MotionEvent.ACTION_UP) { + return false; + } + Drawable clearIcon = etSearch.getCompoundDrawables()[2]; + if (clearIcon == null) { + return false; + } + int iconWidth = clearIcon.getIntrinsicWidth(); + int rightEdge = etSearch.getWidth() - etSearch.getPaddingRight(); + int leftEdge = rightEdge - iconWidth; + float touchX = event.getX(); + if (touchX >= leftEdge && touchX <= rightEdge) { + etSearch.setText(""); + if (currentTab == TAB_EXPERT) { + viewModel.loadExperts(""); + } else { + viewModel.loadEmployees(""); + } + return true; + } + return false; + }); + } + + private void updateClearIconVisibility(boolean hasText) { + etSearch.setCompoundDrawablesWithIntrinsicBounds( + R.drawable.ic_search, 0, + hasText ? R.drawable.ic_clear : 0, 0); + } + + protected void onSearch(String keyword) { + if (currentTab == TAB_EXPERT) { + viewModel.loadExperts(keyword); + } else { + viewModel.loadEmployees(keyword); + } + } + + private void initAdapters() { + expertAdapter = new AddMemberAdapter<>(new AddMemberAdapter.ItemBinder() { + @Override + public String getUserId(@NonNull ExpertBean item) { + return item.getUserId(); + } + @Override + public String getDisplayName(@NonNull ExpertBean item) { + return item.getRealname(); + } + @Override + public String getDeptName(@NonNull ExpertBean item) { + return item.getDeptName(); + } + @Override + public String getAvatar(@NonNull ExpertBean item) { + return item.getAvatar(); + } + @Override + public String getPost(@NonNull ExpertBean item) { + return item.getPost_dictText(); + } + }); + expertAdapter.setOnItemClickListener((item, position) -> onItemClicked(item.getUserId())); + + employeeAdapter = new AddMemberAdapter<>(new AddMemberAdapter.ItemBinder() { + @Override + public String getUserId(@NonNull EmployeeBean item) { + return item.getUserId(); + } + @Override + public String getDisplayName(@NonNull EmployeeBean item) { + return item.getRealname(); + } + @Override + public String getDeptName(@NonNull EmployeeBean item) { + return item.getDeptName(); + } + @Override + public String getAvatar(@NonNull EmployeeBean item) { + return item.getAvatar(); + } + @Override + public String getPost(@NonNull EmployeeBean item) { + return null; + } + }); + employeeAdapter.setOnItemClickListener((item, position) -> onItemClicked(item.getUserId())); + + rvMembers.setAdapter(employeeAdapter); + } + + private void initObservers() { + viewModel.getExpertsLiveData().observe(this, this::applyExpertData); + viewModel.getEmployeesLiveData().observe(this, this::applyEmployeeData); + } + + private void initListeners() { + llBack.setOnClickListener(v -> finish()); + + tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { + @Override + public void onTabSelected(TabLayout.Tab tab) { + int position = tab.getPosition(); + currentTab = position; + if (position == TAB_EXPERT) { + rvMembers.setAdapter(expertAdapter); + expertAdapter.setSelectedIds(viewModel.getSelectedUserIds()); + } else if (position == TAB_EMPLOYEE) { + rvMembers.setAdapter(employeeAdapter); + employeeAdapter.setSelectedIds(viewModel.getSelectedUserIds()); + } + } + @Override + public void onTabUnselected(TabLayout.Tab tab) {} + @Override + public void onTabReselected(TabLayout.Tab tab) {} + }); + + tvSearchAction.setOnClickListener(v -> onSearch(etSearch.getText().toString().trim())); + tvConfirm.setOnClickListener(v -> onConfirm()); + } + + private void onItemClicked(String userId) { + viewModel.toggleSelected(userId); + refreshSelectionUi(); + } + + private void applyExpertData(List experts) { + expertAdapter.setData(experts); + expertAdapter.setSelectedIds(viewModel.getSelectedUserIds()); + } + + private void applyEmployeeData(List employees) { + employeeAdapter.setData(employees); + employeeAdapter.setSelectedIds(viewModel.getSelectedUserIds()); + } + + private void refreshSelectionUi() { + int count = viewModel.getSelectedCount(); + tvConfirm.setText(count > 0 ? getString(R.string.add_member_confirm) + " (" + count + ")" : getString(R.string.add_member_confirm)); + if (currentTab == TAB_EXPERT) { + expertAdapter.setSelectedIds(viewModel.getSelectedUserIds()); + } else { + employeeAdapter.setSelectedIds(viewModel.getSelectedUserIds()); + } + } + + private void onConfirm() { + ArrayList selected = viewModel.snapshotSelectedUserIds(); + if (selected.isEmpty()) { + Toast.makeText(this, R.string.add_member_empty, Toast.LENGTH_SHORT).show(); + return; + } + Intent data = new Intent(); + data.putStringArrayListExtra(EXTRA_SELECTED_USER_IDS, selected); + setResult(Activity.RESULT_OK, data); + finish(); + } +} diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/AddMemberAdapter.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/AddMemberAdapter.java new file mode 100644 index 0000000..39af3a8 --- /dev/null +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/AddMemberAdapter.java @@ -0,0 +1,126 @@ +package com.tencent.qcloud.tuikit.tuichat.classicui.page; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.tencent.qcloud.tuicore.component.imageEngine.impl.GlideEngine; +import com.tencent.qcloud.tuikit.tuichat.R; +import com.tencent.qcloud.tuikit.tuichat.presenter.FileBaseUrlHelper; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class AddMemberAdapter extends RecyclerView.Adapter { + + private final List data = new ArrayList<>(); + private final ItemBinder binder; + private final Set selectedIds = new HashSet<>(); + private OnItemClickListener itemClickListener; + + public AddMemberAdapter(@NonNull ItemBinder binder) { + this.binder = binder; + } + + public void setData(List items) { + data.clear(); + if (items != null) { + data.addAll(items); + } + notifyDataSetChanged(); + } + + public void setSelectedIds(Set ids) { + selectedIds.clear(); + if (ids != null) { + selectedIds.addAll(ids); + } + notifyDataSetChanged(); + } + + public void setOnItemClickListener(OnItemClickListener listener) { + this.itemClickListener = listener; + } + + @NonNull + @Override + public MemberViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View itemView = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_add_member, parent, false); + return new MemberViewHolder(itemView); + } + + @Override + public void onBindViewHolder(@NonNull MemberViewHolder holder, int position) { + T item = data.get(position); + if (item == null) { + return; + } + final String userId = binder.getUserId(item); + String name = binder.getDisplayName(item); + String dept = binder.getDeptName(item); + String avatar = binder.getAvatar(item); + String post = binder.getPost(item); + + holder.tvName.setText(name); + holder.tvDept.setText(dept == null ? "" : dept); + holder.tvPost.setText(post == null ? "" : post); + String avatarFullPath = FileBaseUrlHelper.getInstance().getIconBaseUrl() + avatar; + GlideEngine.loadUserCircleIcon(holder.ivAvatar, avatarFullPath, R.drawable.default_user_icon); + + boolean checked = userId != null && selectedIds.contains(userId); + holder.cbSelect.setChecked(checked); + + holder.itemView.setOnClickListener(v -> { + if (itemClickListener != null) { + int adapterPosition = holder.getBindingAdapterPosition(); + if (adapterPosition == RecyclerView.NO_POSITION) { + return; + } + itemClickListener.onItemClick(item, adapterPosition); + } + }); + } + + @Override + public int getItemCount() { + return data.size(); + } + + static class MemberViewHolder extends RecyclerView.ViewHolder { + ImageView ivAvatar; + TextView tvName; + TextView tvDept; + TextView tvPost; + CheckBox cbSelect; + + MemberViewHolder(@NonNull View itemView) { + super(itemView); + ivAvatar = itemView.findViewById(R.id.iv_avatar); + tvName = itemView.findViewById(R.id.tv_name); + tvDept = itemView.findViewById(R.id.tv_dept); + cbSelect = itemView.findViewById(R.id.cb_select); + tvPost = itemView.findViewById(R.id.tv_post); + } + } + + public interface ItemBinder { + String getUserId(@NonNull T item); + String getDisplayName(@NonNull T item); + String getDeptName(@NonNull T item); + String getAvatar(@NonNull T item); + String getPost(@NonNull T item); + } + + public interface OnItemClickListener { + void onItemClick(@NonNull T item, int position); + } +} diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/AddMemberViewModel.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/AddMemberViewModel.java new file mode 100644 index 0000000..1004bb6 --- /dev/null +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/AddMemberViewModel.java @@ -0,0 +1,68 @@ +package com.tencent.qcloud.tuikit.tuichat.classicui.page; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +import com.tencent.qcloud.tuikit.tuichat.bean.EmployeeBean; +import com.tencent.qcloud.tuikit.tuichat.bean.ExpertBean; +import com.tencent.qcloud.tuikit.tuichat.presenter.ParamedicOperateHelper; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class AddMemberViewModel extends ViewModel { + + private final MutableLiveData> expertsLiveData = new MutableLiveData<>(); + private final MutableLiveData> employeesLiveData = new MutableLiveData<>(); + private final Set selectedUserIds = new HashSet<>(); + + public LiveData> getExpertsLiveData() { + return expertsLiveData; + } + + public LiveData> getEmployeesLiveData() { + return employeesLiveData; + } + + public Set getSelectedUserIds() { + return Collections.unmodifiableSet(selectedUserIds); + } + + public boolean isSelected(String userId) { + return userId != null && selectedUserIds.contains(userId); + } + + public boolean toggleSelected(String userId) { + if (userId == null) { + return false; + } + if (selectedUserIds.contains(userId)) { + selectedUserIds.remove(userId); + return false; + } + selectedUserIds.add(userId); + return true; + } + + public int getSelectedCount() { + return selectedUserIds.size(); + } + + public ArrayList snapshotSelectedUserIds() { + return new ArrayList<>(selectedUserIds); + } + + public void loadExperts(String searchKey) { + List experts = ParamedicOperateHelper.getInstance().searchExpert(searchKey, "", "", 1, 10); + expertsLiveData.postValue(experts); + } + + public void loadEmployees(String searchKey) { + List employees = ParamedicOperateHelper.getInstance().searchEmployee(searchKey, "", "", "", "", 1, 50); + employeesLiveData.postValue(employees); + } +} diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIBaseChatActivity.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIBaseChatActivity.java index bf7dd73..03d8de2 100644 --- a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIBaseChatActivity.java +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIBaseChatActivity.java @@ -1,46 +1,99 @@ package com.tencent.qcloud.tuikit.tuichat.classicui.page; +import static com.tencent.qcloud.tuikit.tuichat.TUIChatConstants.CHAT_IS_LIAISON_USER; + import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; import androidx.annotation.Nullable; +import androidx.core.view.GravityCompat; +import androidx.drawerlayout.widget.DrawerLayout; +import androidx.recyclerview.widget.RecyclerView; +import com.google.android.material.navigation.NavigationView; import com.tencent.imsdk.v2.V2TIMGroupAtInfo; import com.tencent.imsdk.v2.V2TIMMessage; import com.tencent.qcloud.tuicore.TUIConstants; import com.tencent.qcloud.tuicore.TUICore; import com.tencent.qcloud.tuicore.TUILogin; import com.tencent.qcloud.tuicore.component.activities.BaseLightActivity; +import com.tencent.qcloud.tuicore.util.SPUtils; import com.tencent.qcloud.tuicore.util.ToastUtil; import com.tencent.qcloud.tuikit.tuichat.R; import com.tencent.qcloud.tuikit.tuichat.bean.ChatInfo; import com.tencent.qcloud.tuikit.tuichat.bean.DraftInfo; import com.tencent.qcloud.tuikit.tuichat.bean.GroupInfo; +import com.tencent.qcloud.tuikit.tuichat.bean.GroupMember; +import com.tencent.qcloud.tuikit.tuichat.bean.GroupMemberBean; import com.tencent.qcloud.tuikit.tuichat.bean.GroupMemberInfo; import com.tencent.qcloud.tuikit.tuichat.bean.WorkBean; import com.tencent.qcloud.tuikit.tuichat.bean.message.TUIMessageBean; +import com.tencent.qcloud.tuikit.tuichat.classicui.event.CustomMessageEvent; import com.tencent.qcloud.tuikit.tuichat.classicui.setting.InputActionSetting; +import com.tencent.qcloud.tuikit.tuichat.config.TUIChatConfigs; +import com.tencent.qcloud.tuikit.tuichat.presenter.ParamedicOperateHelper; import com.tencent.qcloud.tuikit.tuichat.util.ChatMessageBuilder; +import com.tencent.qcloud.tuikit.tuichat.util.ChatMessageParser; import com.tencent.qcloud.tuikit.tuichat.util.TUIChatLog; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; import java.util.HashMap; import java.util.List; public abstract class TUIBaseChatActivity extends BaseLightActivity { private static final String TAG = TUIBaseChatActivity.class.getSimpleName(); + private int mWirkState = -1; public InputActionSetting inputActionSetting; + private DrawerLayout drawerLayout; + public TextView tvTitle; + /** 右侧抽屉中的群成员列表,供子类(如 TUIGroupChatActivity)绑定 Adapter */ + public RecyclerView rvMembers; + public TextView tvAddMember; + public TextView tvUpdateMember; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { TUIChatLog.i(TAG, "onCreate " + this); super.onCreate(savedInstanceState); - setContentView(R.layout.chat_activity); + setContentView(R.layout.chat_activity_with_navigation); + drawerLayout = findViewById(R.id.drawer_layout); + NavigationView navigationView = findViewById(R.id.nav_view_right); + View headerView = navigationView.getHeaderView(0); + tvTitle = headerView.findViewById(R.id.tv_title); + rvMembers = headerView.findViewById(R.id.rv_members); + tvAddMember = headerView.findViewById(R.id.tv_add_member); + tvUpdateMember = headerView.findViewById(R.id.tv_update_member); + chat(getIntent()); } + public void openDrawer() { + if (drawerLayout != null) { + drawerLayout.openDrawer(GravityCompat.END); + } + } + + public boolean closeDrawer() { + if (drawerLayout != null && drawerLayout.isDrawerOpen(GravityCompat.END)) { + drawerLayout.closeDrawer(GravityCompat.END); + return true; + } + return false; + } + + public int getmWirkState() { + return mWirkState; + } + @Override protected void onNewIntent(Intent intent) { TUIChatLog.i(TAG, "onNewIntent"); @@ -48,12 +101,47 @@ public abstract class TUIBaseChatActivity extends BaseLightActivity { chat(intent); } + @Override + protected void onStart() { + super.onStart(); + if (!EventBus.getDefault().isRegistered(this)) { + EventBus.getDefault().register(this); + } + } + @Override protected void onResume() { TUIChatLog.i(TAG, "onResume"); super.onResume(); } + @Override + protected void onStop() { + super.onStop(); + if (!EventBus.getDefault().isRegistered(this)) { + EventBus.getDefault().unregister(this); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMessageEvent(CustomMessageEvent event) { + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + @Override + public void onBackPressed() { + if (!closeDrawer()) { + if (mWirkState != -1) { + TUIChatConfigs.getConfigs().getImInputViewActionListener().finishActivityToGuidanceHome(mWirkState); + } + super.onBackPressed(); + } + } + private void chat(Intent intent) { Bundle bundle = intent.getExtras(); TUIChatLog.i(TAG, "bundle: " + bundle + " intent: " + intent); @@ -62,11 +150,16 @@ public abstract class TUIBaseChatActivity extends BaseLightActivity { finish(); return; } - if(inputActionSetting == null){ - inputActionSetting = InputActionSetting.createInstance().copy(); + if (inputActionSetting == null) { + InputActionSetting fromIntent = (InputActionSetting) intent.getSerializableExtra("inputActionSetting"); + if (fromIntent != null) { + inputActionSetting = fromIntent; + } else { + inputActionSetting = InputActionSetting.createInstance().copy(); + } } + startVideoCall(intent); ChatInfo chatInfo = getChatInfo(intent); - chatInfo.setInputActionSetting(inputActionSetting); TUIChatLog.i(TAG, "start chatActivity chatInfo: " + chatInfo); if (chatInfo != null) { @@ -85,6 +178,8 @@ public abstract class TUIBaseChatActivity extends BaseLightActivity { super.onActivityResult(requestCode, resultCode, data); if (resultCode == 3 && data != null) { if (requestCode == 11) { + ArrayList stringList2 = data.getStringArrayListExtra("user_namecard_select"); + ChatMessageParser.setSelectName(stringList2); List stringList = data.getStringArrayListExtra("list"); if (stringList != null && !stringList.isEmpty()) { String[] stringArray = stringList.toArray(new String[]{}); @@ -101,6 +196,12 @@ public abstract class TUIBaseChatActivity extends BaseLightActivity { } + /** + * 添加成员回传结果处理:由子类(如 TUIGroupChatActivity)实现具体逻辑 + */ + protected void onAddMemberResult(ArrayList selectedUserIds) { + } + private ChatInfo getChatInfo(Intent intent) { int chatType = intent.getIntExtra(TUIConstants.TUIChat.CHAT_TYPE, ChatInfo.TYPE_INVALID); ChatInfo chatInfo; @@ -125,7 +226,13 @@ public abstract class TUIBaseChatActivity extends BaseLightActivity { chatInfo.setLocateMessage(messageInfo); chatInfo.setAtInfoList((List) intent.getSerializableExtra(TUIConstants.TUIChat.AT_INFO_LIST)); chatInfo.setFaceUrl(intent.getStringExtra(TUIConstants.TUIChat.FACE_URL)); - chatInfo.setWorkBean((WorkBean) intent.getSerializableExtra(TUIConstants.TUIChat.WORK_BEAN)); + chatInfo.setAutoSendMessage(intent.getStringExtra(TUIConstants.TUIChat.AUTO_SEND_MESSAGE)); + chatInfo.setConsultantId(intent.getStringExtra(TUIConstants.TUIChat.CONSULTANT_ID)); + WorkBean woekBean = (WorkBean) intent.getSerializableExtra(TUIConstants.TUIChat.WORK_BEAN); + chatInfo.setWorkBean(woekBean); + if (woekBean != null) { + mWirkState = woekBean.getWorkState(); + } if (chatType == ChatInfo.TYPE_GROUP) { GroupInfo groupInfo = (GroupInfo) chatInfo; groupInfo.setGroupName(intent.getStringExtra(TUIConstants.TUIChat.GROUP_NAME)); @@ -136,11 +243,35 @@ public abstract class TUIBaseChatActivity extends BaseLightActivity { groupInfo.setNotice(intent.getStringExtra(TUIConstants.TUIChat.NOTICE)); groupInfo.setOwner(intent.getStringExtra(TUIConstants.TUIChat.OWNER)); groupInfo.setMemberDetails((List) intent.getSerializableExtra(TUIConstants.TUIChat.MEMBER_DETAILS)); + List list = ParamedicOperateHelper.getInstance().getActualGroupMemberList(chatInfo.getId()); + if (list != null && !list.isEmpty()) { + groupInfo.setMemberDetails(GroupMember.convertFromBeanList(list)); + } } - if (TextUtils.isEmpty(chatInfo.getId())) { return null; } return chatInfo; } + + /** + * 跳转视频通话 + */ + private void startVideoCall(Intent intent) { + Boolean initiateVideoCall = intent.getBooleanExtra(TUIConstants.TUIChat.INITIATE_VIDEO_CALL, false); + if (!initiateVideoCall) { + return; + } + String groupId = intent.getStringExtra(TUIConstants.TUIChat.CHAT_ID); + List userIDs = intent.getStringArrayListExtra(TUIConstants.TUICalling.PARAM_NAME_USERIDS); + if (userIDs == null || userIDs.isEmpty()) { + return; + } + HashMap hashMap = new HashMap<>(); + hashMap.put(TUIConstants.TUICalling.PARAM_NAME_GROUPID, groupId); + hashMap.put(TUIConstants.TUICalling.PARAM_NAME_USERIDS, userIDs.toArray(new String[]{})); + hashMap.put(TUIConstants.TUICalling.PARAM_NAME_TYPE, TUIConstants.TUICalling.TYPE_VIDEO); + TUICore.callService(TUIConstants.TUICalling.SERVICE_NAME, + TUIConstants.TUICalling.METHOD_NAME_CALL, hashMap); + } } diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIBaseChatFragment.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIBaseChatFragment.java index 3dba30a..5bb6d94 100644 --- a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIBaseChatFragment.java +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIBaseChatFragment.java @@ -22,6 +22,8 @@ import com.bumptech.glide.Glide; import com.bumptech.glide.request.target.CustomTarget; import com.bumptech.glide.request.transition.Transition; import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import com.tencent.imsdk.v2.V2TIMMessage; import com.tencent.qcloud.tuicore.TUIConfig; import com.tencent.qcloud.tuicore.TUIConstants; @@ -33,22 +35,30 @@ import com.tencent.qcloud.tuicore.component.interfaces.IUIKitCallback; import com.tencent.qcloud.tuicore.util.ToastUtil; import com.tencent.qcloud.tuikit.tuichat.R; import com.tencent.qcloud.tuikit.tuichat.TUIChatConstants; +import com.tencent.qcloud.tuikit.tuichat.TUIChatService; import com.tencent.qcloud.tuikit.tuichat.bean.ChatInfo; import com.tencent.qcloud.tuikit.tuichat.bean.message.CallingMessageBean; import com.tencent.qcloud.tuikit.tuichat.bean.message.LocationMessageBean; import com.tencent.qcloud.tuikit.tuichat.bean.message.TUIMessageBean; +import com.tencent.qcloud.tuikit.tuichat.classicui.event.CustomMessageEvent; import com.tencent.qcloud.tuikit.tuichat.classicui.setting.ChatLayoutSetting; +import com.tencent.qcloud.tuikit.tuichat.classicui.setting.InputActionSetting; import com.tencent.qcloud.tuikit.tuichat.component.AudioPlayer; import com.tencent.qcloud.tuikit.tuichat.classicui.interfaces.OnItemClickListener; import com.tencent.qcloud.tuikit.tuichat.classicui.widget.ChatView; import com.tencent.qcloud.tuikit.tuichat.classicui.widget.input.InputView; import com.tencent.qcloud.tuikit.tuichat.classicui.widget.message.MessageRecyclerView; +import com.tencent.qcloud.tuikit.tuichat.config.TUIChatConfigs; import com.tencent.qcloud.tuikit.tuichat.presenter.ChatPresenter; import com.tencent.qcloud.tuikit.tuichat.util.ChatMessageBuilder; import com.tencent.qcloud.tuikit.tuichat.util.DataStoreUtil; import com.tencent.qcloud.tuikit.tuichat.util.TUIChatLog; import com.tencent.qcloud.tuikit.tuichat.util.TUIChatUtils; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -86,6 +96,17 @@ public class TUIBaseChatFragment extends BaseFragment { return baseView; } + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + if (!EventBus.getDefault().isRegistered(this)) { + EventBus.getDefault().register(this); + } + } + + protected void finishEvent(){ + } + protected void initView() { chatView = baseView.findViewById(R.id.chat_layout); chatView.setFragment(TUIBaseChatFragment.this); @@ -97,6 +118,7 @@ public class TUIBaseChatFragment extends BaseFragment { public void onClick(View view) { InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(chatView.getWindowToken(), 0); + finishEvent(); getActivity().finish(); } }); @@ -267,6 +289,10 @@ public class TUIBaseChatFragment extends BaseFragment { String messageJson = data.getStringExtra(ChatLayoutSetting.KEY_CUSTOM_MESSAGE); if (ChatLayoutSetting.RESULT_CODE_LOCATION == resultCode) { sendLocationMessage(messageJson); + } else if (ChatLayoutSetting.RESULT_CODE_ARCHIVES == resultCode) { + sendCustomMessage(messageJson); + } else if (ChatLayoutSetting.RESULT_CODE_MEDICAL_EXAMINATION_REPORT == resultCode) { + sendCustomMessage(messageJson); } } } @@ -319,6 +345,49 @@ public class TUIBaseChatFragment extends BaseFragment { public ChatPresenter getPresenter() { return null; } + public InputActionSetting getInputActionSetting(){ + return null; + } + + @Override + public void onStart() { + super.onStart(); + TUIChatLog.e(TAG, "onStart"); + if (!EventBus.getDefault().isRegistered(this)) { + EventBus.getDefault().register(this); + } + } + + @Override + public void onStop() { + super.onStop(); + TUIChatLog.e(TAG, "onStop"); + if (!EventBus.getDefault().isRegistered(this)) { + EventBus.getDefault().unregister(this); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMessageEvent(CustomMessageEvent customMessageEvent) { + if (customMessageEvent == null) { + return; + } + if (isVisible() && customMessageEvent.getChatId().equals(getChatInfo().getId())) { + sendCustomMessage(customMessageEvent.getMessageJson()); + } + } + + public void sendCustomMessage(String messageJson) { + if (chatView != null && !TextUtils.isEmpty(messageJson)) { + JsonObject tuiMessageObj = new Gson().fromJson(messageJson, JsonObject.class); + TUIChatLog.i(TAG, "customMessageEvent msgContent:" + new Gson().toJson(tuiMessageObj)); + JsonElement extensionJson = tuiMessageObj.get("extension"); + String extension = extensionJson == null ? TUIChatService.getAppContext().getString(R.string.custom_msg) : extensionJson.getAsString(); + TUIMessageBean info = ChatMessageBuilder.buildCustomMessage(messageJson, extension + , extension.getBytes()); + chatView.sendMessage(info, false); + } + } protected void initChatViewBackground() { if (getChatInfo() == null) { diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIGroupChatActivity.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIGroupChatActivity.java index 8e5294e..54c7285 100644 --- a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIGroupChatActivity.java +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIGroupChatActivity.java @@ -1,21 +1,38 @@ package com.tencent.qcloud.tuikit.tuichat.classicui.page; +import static com.tencent.qcloud.tuicore.util.ToastUtil.toastShortMessage; +import static com.tencent.qcloud.tuikit.tuichat.classicui.page.AddMemberActivity.EXTRA_SELECTED_USER_IDS; + +import android.content.Intent; import android.os.Bundle; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.LinearLayoutManager; + import com.tencent.qcloud.tuicore.util.ToastUtil; import com.tencent.qcloud.tuikit.tuichat.R; import com.tencent.qcloud.tuikit.tuichat.TUIChatConstants; import com.tencent.qcloud.tuikit.tuichat.bean.ChatInfo; import com.tencent.qcloud.tuikit.tuichat.bean.GroupInfo; +import com.tencent.qcloud.tuikit.tuichat.bean.GroupMember; +import com.tencent.qcloud.tuikit.tuichat.bean.GroupMemberBean; +import com.tencent.qcloud.tuikit.tuichat.bean.message.TipsMessageBean; +import com.tencent.qcloud.tuikit.tuichat.classicui.widget.ChatView; +import com.tencent.qcloud.tuikit.tuichat.classicui.widget.GroupMemberNavAdapter; import com.tencent.qcloud.tuikit.tuichat.presenter.GroupChatPresenter; +import com.tencent.qcloud.tuikit.tuichat.presenter.ParamedicOperateHelper; import com.tencent.qcloud.tuikit.tuichat.util.TUIChatLog; import com.tencent.qcloud.tuikit.tuichat.util.TUIChatUtils; +import java.util.List; + public class TUIGroupChatActivity extends TUIBaseChatActivity { private static final String TAG = TUIGroupChatActivity.class.getSimpleName(); private TUIGroupChatFragment chatFragment; private GroupChatPresenter presenter; + private GroupInfo groupInfo; + private GroupMemberNavAdapter adapter; @Override public void initChat(ChatInfo chatInfo) { @@ -25,15 +42,84 @@ public class TUIGroupChatActivity extends TUIBaseChatActivity { TUIChatLog.e(TAG, "init group chat failed , chatInfo = " + chatInfo); ToastUtil.toastShortMessage("init group chat failed."); } - GroupInfo groupInfo = (GroupInfo) chatInfo; + groupInfo = (GroupInfo) chatInfo; chatFragment = new TUIGroupChatFragment(); Bundle bundle = new Bundle(); bundle.putSerializable(TUIChatConstants.CHAT_INFO, groupInfo); + bundle.putSerializable("inputActionSetting", inputActionSetting); + bundle.putInt(TUIChatConstants.WEEK_STATE, getmWirkState()); chatFragment.setArguments(bundle); presenter = new GroupChatPresenter(); presenter.initListener(); chatFragment.setPresenter(presenter); getSupportFragmentManager().beginTransaction().replace(R.id.empty_view, chatFragment).commitAllowingStateLoss(); + + if (tvTitle != null) { + tvTitle.setText(String.format("群成员 (%d)", groupInfo.getMemberCount())); + } + + // 绑定群成员列表 Adapter,数据来源于 GroupInfo.memberDetails + if (rvMembers != null) { + rvMembers.setLayoutManager(new LinearLayoutManager(this)); + adapter = new GroupMemberNavAdapter(); + List memberList = (List) groupInfo.getMemberDetails(); + adapter.setMembers(memberList); + rvMembers.setAdapter(adapter); + } + if (tvAddMember != null) { + tvAddMember.setOnClickListener(v -> { + // 跳转添加成员页面 + Intent intent = new Intent(TUIGroupChatActivity.this, AddMemberActivity.class); + intent.putExtra(TUIChatConstants.GROUP_ID, groupInfo.getId()); + startActivityForResult(intent, AddMemberActivity.REQUEST_CODE_ADD_MEMBER); + }); + } + if (tvUpdateMember != null) { + tvUpdateMember.setOnClickListener(v -> { + List list = ParamedicOperateHelper.getInstance() + .getActualGroupMemberList(groupInfo.getId()); + runOnUiThread(() -> { + adapter.setMembers(GroupMember.convertFromBeanList(list)); + tvTitle.setText(String.format("群成员 (%d)", list.size())); + toastShortMessage("群成员已更新"); + }); + }); + } + + // OnGroupTipsListener:群成员加入时自动刷新列表 + ChatView.OnGroupTipsListener onGroupTipsListener = new ChatView.OnGroupTipsListener() { + @Override + public void onGroupJoin(TipsMessageBean message) { + List list = ParamedicOperateHelper.getInstance() + .getActualGroupMemberList(groupInfo.getId()); + runOnUiThread(() -> { + adapter.setMembers(GroupMember.convertFromBeanList(list)); + tvTitle.setText(String.format("群成员 (%d)", list.size())); + }); + } + }; + chatFragment.setOnGroupTipsListener(onGroupTipsListener); } -} \ No newline at end of file + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == AddMemberActivity.REQUEST_CODE_ADD_MEMBER && resultCode == RESULT_OK) { + if (data != null) { + List memberList = (List) data.getSerializableExtra(EXTRA_SELECTED_USER_IDS); + if (memberList != null && !memberList.isEmpty() && adapter != null && groupInfo != null) { + ParamedicOperateHelper.getInstance().addGroupUser(groupInfo.getId(), memberList, 0, success -> { + if (!success) { + runOnUiThread(() -> ToastUtil.toastShortMessage("添加群成员失败")); + return; + } + List list = ParamedicOperateHelper.getInstance() + .getActualGroupMemberList(groupInfo.getId()); + runOnUiThread(() -> adapter.setMembers(GroupMember.convertFromBeanList(list))); + }); + } + } + } + } +} diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIGroupChatFragment.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIGroupChatFragment.java index bae69ff..5ec3e29 100644 --- a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIGroupChatFragment.java +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/page/TUIGroupChatFragment.java @@ -1,29 +1,61 @@ package com.tencent.qcloud.tuikit.tuichat.classicui.page; +import android.app.Dialog; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.net.Uri; import android.os.Bundle; +import android.text.TextUtils; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.TextView; import androidx.annotation.Nullable; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import com.tencent.imsdk.v2.V2TIMMessage; import com.tencent.qcloud.tuicore.TUIConstants; import com.tencent.qcloud.tuicore.TUICore; +import com.tencent.qcloud.tuicore.TUILogin; +import com.tencent.qcloud.tuicore.component.imageEngine.impl.GlideEngine; +import com.tencent.qcloud.tuicore.component.interfaces.IUIKitCallback; +import com.tencent.qcloud.tuikit.tuichat.R; import com.tencent.qcloud.tuikit.tuichat.TUIChatConstants; +import com.tencent.qcloud.tuikit.tuichat.TUIChatService; import com.tencent.qcloud.tuikit.tuichat.bean.ChatInfo; import com.tencent.qcloud.tuikit.tuichat.bean.GroupInfo; +import com.tencent.qcloud.tuikit.tuichat.bean.GroupMember; +import com.tencent.qcloud.tuikit.tuichat.bean.GroupMemberInfo; import com.tencent.qcloud.tuikit.tuichat.bean.message.TUIMessageBean; import com.tencent.qcloud.tuikit.tuichat.classicui.interfaces.OnItemClickListener; +import com.tencent.qcloud.tuikit.tuichat.classicui.setting.InputActionSetting; +import com.tencent.qcloud.tuikit.tuichat.classicui.widget.ChatView; +import com.tencent.qcloud.tuikit.tuichat.config.TUIChatConfigs; +import com.tencent.qcloud.tuikit.tuichat.presenter.FileBaseUrlHelper; import com.tencent.qcloud.tuikit.tuichat.presenter.GroupChatPresenter; +import com.tencent.qcloud.tuikit.tuichat.util.ChatMessageBuilder; import com.tencent.qcloud.tuikit.tuichat.util.TUIChatLog; -import com.tencent.qcloud.tuikit.tuichat.util.TUIChatUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; public class TUIGroupChatFragment extends TUIBaseChatFragment { private static final String TAG = TUIGroupChatFragment.class.getSimpleName(); private GroupChatPresenter presenter; private GroupInfo groupInfo; + private InputActionSetting inputActionSetting; + private int mWeekState = -1; + private ChatView.OnGroupTipsListener cachedGroupTipsListener; @Nullable @Override @@ -35,7 +67,9 @@ public class TUIGroupChatFragment extends TUIBaseChatFragment { if (bundle == null) { return baseView; } + mWeekState = bundle.getInt(TUIChatConstants.WEEK_STATE); groupInfo = (GroupInfo) bundle.getSerializable(TUIChatConstants.CHAT_INFO); + inputActionSetting = (InputActionSetting) bundle.getSerializable("inputActionSetting"); if (groupInfo == null) { return baseView; } @@ -44,17 +78,30 @@ public class TUIGroupChatFragment extends TUIBaseChatFragment { return baseView; } + @Override + protected void finishEvent() { + if (mWeekState != -1) { + TUIChatConfigs.getConfigs().getImInputViewActionListener().finishActivityToGuidanceHome(mWeekState); + } + super.finishEvent(); + } + + public void setOnGroupTipsListener(ChatView.OnGroupTipsListener listener){ + // 始终缓存 listener,避免因 commitAllowingStateLoss() 异步导致的时序问题 + this.cachedGroupTipsListener = listener; + } + @Override protected void initView() { super.initView(); chatView.setPresenter(presenter); presenter.setGroupInfo(groupInfo); chatView.setChatInfo(groupInfo); + autoSendMessage(); chatView.getMessageLayout().setOnItemClickListener(new OnItemClickListener() { @Override public void onMessageLongClick(View view, int position, TUIMessageBean messageBean) { // 因为adapter中第一条为加载条目,位置需减1 - // Because the first entry in the adapter is the load entry, the position needs to be decremented by 1 chatView.getMessageLayout().showItemPopMenu(position - 1, messageBean, view); } @@ -63,14 +110,13 @@ public class TUIGroupChatFragment extends TUIBaseChatFragment { if (null == messageBean) { return; } - //当前项目不需要跳转个人信息 -// ChatInfo info = new ChatInfo(); -// info.setId(messageBean.getSender()); -// -// Bundle bundle = new Bundle(); -// bundle.putString(TUIConstants.TUIChat.CHAT_ID, info.getId()); -// TUICore.startActivity("FriendProfileActivity", bundle); - + String id = messageBean.getSender(); + for (GroupMemberInfo groupMemberInfo : groupInfo.getMemberDetails()) { + if (groupMemberInfo.getAccount().equals(id)) { + showPhoneCallDialog((GroupMember) groupMemberInfo); + break; + } + } } @Override @@ -86,7 +132,7 @@ public class TUIGroupChatFragment extends TUIBaseChatFragment { return; } int messageType = messageInfo.getMsgType(); - if (messageType == V2TIMMessage.V2TIM_ELEM_TYPE_TEXT){ + if (messageType == V2TIMMessage.V2TIM_ELEM_TYPE_TEXT) { chatView.getInputLayout().appendText(messageInfo.getV2TIMMessage().getTextElem().getText()); } else { TUIChatLog.e(TAG, "error type: " + messageType); @@ -105,21 +151,23 @@ public class TUIGroupChatFragment extends TUIBaseChatFragment { } }); - chatView.getTitleBar().setOnRightClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (TUIChatUtils.isTopicGroup(groupInfo.getId())) { - Bundle bundle = new Bundle(); - bundle.putString(TUIConstants.TUICommunity.TOPIC_ID, groupInfo.getId()); - TUICore.startActivity(getContext(), "TopicInfoActivity", bundle); - } else { - Bundle bundle = new Bundle(); - bundle.putString(TUIChatConstants.Group.GROUP_ID, groupInfo.getId()); - bundle.putString(TUIConstants.TUIChat.CHAT_BACKGROUND_URI, mChatBackgroundThumbnailUrl); - TUICore.startActivity(getContext(), "GroupInfoActivity", bundle); - } + chatView.getTitleBar().setOnRightClickListener(view -> { + // 打开右侧抽屉 + TUIGroupChatActivity activity = (TUIGroupChatActivity) getActivity(); + if (activity != null) { + activity.openDrawer(); } }); + + titleBar.getRightGroup().setVisibility(View.VISIBLE); + titleBar.getRightTitle().setVisibility(View.GONE); + titleBar.getRightIcon().setVisibility(View.VISIBLE); + titleBar.getRightIcon().setImageResource(R.drawable.chat_title_bar_more_menu_lively); + + // 应用缓存的 OnGroupTipsListener,解决 Activity 中提前设置 listener 的时序问题 + if (cachedGroupTipsListener != null && chatView != null) { + chatView.setOnGroupTipsListener(cachedGroupTipsListener); + } } public void setPresenter(GroupChatPresenter presenter) { @@ -135,4 +183,139 @@ public class TUIGroupChatFragment extends TUIBaseChatFragment { public ChatInfo getChatInfo() { return groupInfo; } + + @Override + public InputActionSetting getInputActionSetting() { + return inputActionSetting; + } + + private void autoSendMessage() { + String message = groupInfo.getAutoSendMessage(); + if (TextUtils.isEmpty(message)) { + return; + } + JsonObject tuiMessageObj = new Gson().fromJson(message, JsonObject.class); + JsonElement extensionJson = tuiMessageObj.get("extension"); + String extension = extensionJson == null ? TUIChatService.getAppContext().getString(R.string.custom_msg) : extensionJson.getAsString(); + TUIMessageBean info = ChatMessageBuilder.buildCustomMessage(message, extension + , extension.getBytes()); + chatView.sendMessage(info, false); + + } + + /** + * 显示电话拨打弹窗 + */ + private void showPhoneCallDialog(GroupMember groupMember) { + if (groupMember == null || getActivity() == null) { + return; + } + String phone = groupMember.getPhone(); + + Dialog dialog = new Dialog(getActivity()); + dialog.setContentView(R.layout.dialog_phone_call); + + Window window = dialog.getWindow(); + if (window != null) { + // 背景透明,使用布局自身的圆角白色背景 + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.WRAP_CONTENT; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + params.gravity = Gravity.CENTER; + window.setAttributes(params); + } + dialog.setCancelable(true); + dialog.setCanceledOnTouchOutside(true); + + // 绑定视图 + ImageView ivAvatar = dialog.findViewById(R.id.iv_avatar); + ImageView ivClose = dialog.findViewById(R.id.iv_close); + TextView tvName = dialog.findViewById(R.id.tv_name); + TextView tvPhone = dialog.findViewById(R.id.tv_phone); + View btnCall = dialog.findViewById(R.id.btn_call); + View btnCancel = dialog.findViewById(R.id.btn_cancel); + + // 头像加载(圆形) + String avatar = FileBaseUrlHelper.getInstance().getIconBaseUrl() + groupMember.getAvatar(); + GlideEngine.loadUserCircleIcon(ivAvatar, avatar, R.drawable.default_user_icon); + // 姓名 + String name = groupMember.getUserName(); + if (groupMember.getIsSelf() == 1) { + name = "我"; + } + tvName.setText(name); + // 电话号码占位 + tvPhone.setText(phone); + + // 关闭按钮与取消按钮 + ivClose.setOnClickListener(v -> dialog.dismiss()); + btnCancel.setOnClickListener(v -> dialog.dismiss()); + + // 拨打电话:拉起系统拨号界面 + btnCall.setOnClickListener(v -> { + try { + Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phone)); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } catch (Exception e) { + TUIChatLog.e(TAG, "拉起系统拨号失败: " + e.getMessage()); + } + dialog.dismiss(); + }); + + dialog.show(); + } + + /** + * 发起视频通话 + */ + private void initiateVideoCall() { + presenter.loadGroupMembers(groupInfo.getId(), new IUIKitCallback>() { + @Override + public void onSuccess(List data) { + startVideoCall(data); + } + }); + } + + /** + * 跳转视频通话 + */ + private void startVideoCall(List data) { + if (data == null || data.isEmpty()) { + return; + } + data = filterMember(data); + HashMap hashMap = new HashMap<>(); + hashMap.put(TUIConstants.TUICalling.PARAM_NAME_GROUPID, groupInfo.getId()); + hashMap.put(TUIConstants.TUICalling.PARAM_NAME_USERIDS, getMembersAccount(data).toArray(new String[]{})); + hashMap.put(TUIConstants.TUICalling.PARAM_NAME_TYPE, TUIConstants.TUICalling.TYPE_VIDEO); + TUICore.callService(TUIConstants.TUICalling.SERVICE_NAME, + TUIConstants.TUICalling.METHOD_NAME_CALL, hashMap); + } + + private List filterMember(List list) { + for (int i = list.size() - 1; i >= 0; i--) { + if (TUILogin.getUserId().equals(list.get(i).getAccount())) { + list.remove(i); + } + if ("000000".equals(list.get(i).getAccount())) { + list.remove(i); + } + } + return list; + } + + private List getMembersAccount(List mMembers) { + if (mMembers.size() == 0) { + return new ArrayList<>(); + } + + List friendIdList = new ArrayList<>(); + for (int i = 0; i < mMembers.size(); i++) { + friendIdList.add(mMembers.get(i).getAccount()); + } + return friendIdList; + } } diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/setting/ChatLayoutSetting.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/setting/ChatLayoutSetting.java index 1e05218..6979a80 100644 --- a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/setting/ChatLayoutSetting.java +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/setting/ChatLayoutSetting.java @@ -61,7 +61,7 @@ public class ChatLayoutSetting { } } - public void customizeChatLayout(final ChatView layout) { + public void customizeChatLayout(final ChatView layout, InputActionSetting inputActionSetting) { // //====== NoticeLayout使用范例 ======// //====== NoticeLayout example======// @@ -187,6 +187,13 @@ public class ChatLayoutSetting { //====== InputLayout使用范例 ======// //====== InputLayout example ======// final InputView inputView = layout.getInputLayout(); + InputActionSetting mInputActionSetting = inputActionSetting; + if (mInputActionSetting == null){ + mInputActionSetting = InputActionSetting.getsInstance(); + if (mInputActionSetting == null) { + mInputActionSetting = new InputActionSetting(); + } + } // // TODO 隐藏音频输入的入口,可以打开下面代码测试 // // To hide the entrance of audio input, you can open the following code to test @@ -220,7 +227,7 @@ public class ChatLayoutSetting { //隐藏音频通话 inputView.disableAudioCall(true); //隐藏视频通话 - inputView.disableVideoCall(true); + inputView.disableVideoCall(mInputActionSetting.isDisableVideoCall()); // 增加名片 InputMoreActionUnit businessCardUnit = new InputMoreActionUnit() { @@ -291,7 +298,9 @@ public class ChatLayoutSetting { actionClick(layout, endConsultUnit.getActionId()); } }); - inputView.addAction(endConsultUnit); + if(!mInputActionSetting.isDisableFinishSession()){ + inputView.addAction(endConsultUnit); + } // 评价 InputMoreActionUnit evaluationUnit = new InputMoreActionUnit() { }; diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/setting/InputActionSetting.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/setting/InputActionSetting.java index fddbd66..48c8419 100644 --- a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/setting/InputActionSetting.java +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/setting/InputActionSetting.java @@ -26,6 +26,43 @@ public class InputActionSetting implements Serializable { private boolean disableAudioCall = false; private boolean disableVideoCall = false; private boolean disableSendMessage = false; + private boolean disableFinishSession = false; + public boolean disableFinishName = false; + public String packageName=""; + public String CurrentResourceHost=""; + public boolean disableEvaluate = false; + + public String getCurrentResourceHost() { + return CurrentResourceHost == null ? "" : CurrentResourceHost; + } + + public void setCurrentResourceHost(String currentResourceHost) { + CurrentResourceHost = currentResourceHost; + } + + public String getPackageName() { + return packageName == null ? "" : packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public static InputActionSetting getsInstance() { + return sInstance; + } + + public static void setsInstance(InputActionSetting sInstance) { + InputActionSetting.sInstance = sInstance; + } + + public boolean isDisableEvaluate() { + return disableEvaluate; + } + + public void setDisableEvaluate(boolean disableEvaluate) { + this.disableEvaluate = disableEvaluate; + } public boolean isDisableVideoRecord() { return disableVideoRecord; @@ -74,6 +111,23 @@ public class InputActionSetting implements Serializable { public void setDisableSendMessage(boolean disableSendMessage) { this.disableSendMessage = disableSendMessage; } + + public boolean isDisableFinishSession() { + return disableFinishSession; + } + + public void setDisableFinishSession(boolean disableFinishSession) { + this.disableFinishSession = disableFinishSession; + } + + public boolean isDisableFinishName() { + return disableFinishName; + } + + public void setDisableFinishName(boolean disableFinishName) { + this.disableFinishName = disableFinishName; + } + public InputActionSetting copy(){ InputActionSetting inputActionSetting = new InputActionSetting(); inputActionSetting.setDisableArchives(disableArchives); @@ -82,6 +136,8 @@ public class InputActionSetting implements Serializable { inputActionSetting.setDisableVideoCall(disableVideoCall); inputActionSetting.setDisableVideoRecord(disableVideoRecord); inputActionSetting.setDisableMedicalExaminationReport(disableMedicalExaminationReport); + inputActionSetting.setDisableFinishSession(disableFinishSession); + inputActionSetting.setDisableFinishName(disableFinishName); return inputActionSetting; } } diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/widget/ChatView.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/widget/ChatView.java index a7d569b..7e76177 100644 --- a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/widget/ChatView.java +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/widget/ChatView.java @@ -51,6 +51,7 @@ import com.tencent.qcloud.tuikit.tuichat.bean.MessageTyping; import com.tencent.qcloud.tuikit.tuichat.bean.ReplyPreviewBean; import com.tencent.qcloud.tuikit.tuichat.bean.message.ReplyMessageBean; import com.tencent.qcloud.tuikit.tuichat.bean.message.SystemMessageBean; +import com.tencent.qcloud.tuikit.tuichat.bean.message.TipsMessageBean; import com.tencent.qcloud.tuikit.tuichat.bean.message.TUIMessageBean; import com.tencent.qcloud.tuikit.tuichat.classicui.setting.InputActionSetting; import com.tencent.qcloud.tuikit.tuichat.component.AudioPlayer; @@ -148,6 +149,7 @@ public class ChatView extends LinearLayout implements IChatLayout { private boolean isSupportTyping = false; private ChatPresenter presenter; + private OnGroupTipsListener onGroupTipsListener; ChatLayoutSetting chatLayoutSetting; public ChatView(Context context) { @@ -261,6 +263,15 @@ public class ChatView extends LinearLayout implements IChatLayout { public void setFragment(Fragment fragment) { this.fragment = fragment; } + + public interface OnGroupTipsListener { + void onGroupJoin(TipsMessageBean message); + } + + public void setOnGroupTipsListener(OnGroupTipsListener onGroupTipsListener) { + this.onGroupTipsListener = onGroupTipsListener; + } + private void initGroupAtInfoLayout() { if (mChatInfo != null) { List groupAtInfos = mChatInfo.getAtInfoList(); @@ -458,6 +469,14 @@ public class ChatView extends LinearLayout implements IChatLayout { goneInputLayout(); } } + + if (message instanceof TipsMessageBean) { + TipsMessageBean tips = (TipsMessageBean) message; + if (tips.getTipType() == TipsMessageBean.MSG_TYPE_GROUP_JOIN + && onGroupTipsListener != null) { + onGroupTipsListener.onGroupJoin(tips); + } + } } @Override @@ -923,7 +942,7 @@ public class ChatView extends LinearLayout implements IChatLayout { mMessageRecyclerView.setAdapter(mAdapter); } chatLayoutSetting = new ChatLayoutSetting(getContext()); - chatLayoutSetting.customizeChatLayout(this); + chatLayoutSetting.customizeChatLayout(this,inputActionSetting); initListener(); resetForwardState(""); if(inputActionSetting != null&&inputActionSetting.isDisableSendMessage()){ diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/widget/GroupMemberNavAdapter.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/widget/GroupMemberNavAdapter.java new file mode 100644 index 0000000..24ac237 --- /dev/null +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/classicui/widget/GroupMemberNavAdapter.java @@ -0,0 +1,100 @@ +package com.tencent.qcloud.tuikit.tuichat.classicui.widget; + +import android.content.Intent; +import android.net.Uri; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.tencent.qcloud.tuicore.component.imageEngine.impl.GlideEngine; +import com.tencent.qcloud.tuikit.tuichat.R; +import com.tencent.qcloud.tuikit.tuichat.bean.GroupMember; +import com.tencent.qcloud.tuikit.tuichat.presenter.FileBaseUrlHelper; +import com.tencent.qcloud.tuikit.tuichat.util.TUIChatLog; + +import java.util.ArrayList; +import java.util.List; + +/** + * NavigationView 右侧抽屉中群成员列表的适配器。 + */ +public class GroupMemberNavAdapter extends RecyclerView.Adapter { + + private final List members = new ArrayList<>(); + + public void setMembers(List data) { + members.clear(); + if (data != null) { + members.addAll(data); + } + notifyDataSetChanged(); + } + + @NonNull + @Override + public MemberViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View itemView = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_group_member_nav, parent, false); + return new MemberViewHolder(itemView); + } + + @Override + public void onBindViewHolder(@NonNull MemberViewHolder holder, int position) { + GroupMember member = members.get(position); + if (member == null) { + return; + } + String avatar = FileBaseUrlHelper.getInstance().getIconBaseUrl() + member.getAvatar(); + GlideEngine.loadUserCircleIcon(holder.ivAvatar, avatar, R.drawable.default_user_icon); + String name = member.getUserName(); + if (member.getIsSelf() == 1) { + name = "我"; + } + holder.tvName.setText(name); + String type = "员工"; + if (member.getMemberType() == 1) { + type = "专业人员"; + } else if (member.getMemberType() == 2) { + type = "员工"; + } else if (member.getMemberType() == 0) { + type = "操作人员"; + } else if (member.getMemberType() == -1) { + type = "发起人"; + } + holder.tvType.setText(type); + holder.ivCall.setOnClickListener(v -> { + try { + Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + member.getPhone())); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + v.getContext().startActivity(intent); + } catch (Exception e) { + TUIChatLog.e("GroupMemberNavAdapter", "拉起系统拨号失败: " + e.getMessage()); + } + }); + } + + @Override + public int getItemCount() { + return members.size(); + } + + static class MemberViewHolder extends RecyclerView.ViewHolder { + ImageView ivAvatar; + ImageView ivCall; + TextView tvName; + TextView tvType; + + MemberViewHolder(@NonNull View itemView) { + super(itemView); + ivAvatar = itemView.findViewById(R.id.iv_avatar); + tvName = itemView.findViewById(R.id.tv_name); + tvType = itemView.findViewById(R.id.tv_type); + ivCall = itemView.findViewById(R.id.iv_call); + } + } +} diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/interfaces/FileBaseUrlListener.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/interfaces/FileBaseUrlListener.java new file mode 100644 index 0000000..d0d0954 --- /dev/null +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/interfaces/FileBaseUrlListener.java @@ -0,0 +1,5 @@ +package com.tencent.qcloud.tuikit.tuichat.interfaces; + +public interface FileBaseUrlListener { + String getIconBaseUrl(); +} diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/interfaces/IMInputViewActionListener.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/interfaces/IMInputViewActionListener.java index 9de93c0..711e53c 100644 --- a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/interfaces/IMInputViewActionListener.java +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/interfaces/IMInputViewActionListener.java @@ -6,4 +6,6 @@ package com.tencent.qcloud.tuikit.tuichat.interfaces; */ public interface IMInputViewActionListener { void finishAction(int workType, String workId); + void appraiseAction(String chatId, int workType, String workId); + void finishActivityToGuidanceHome(int workType); } diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/presenter/FileBaseUrlHelper.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/presenter/FileBaseUrlHelper.java new file mode 100644 index 0000000..0b2a235 --- /dev/null +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/presenter/FileBaseUrlHelper.java @@ -0,0 +1,31 @@ +package com.tencent.qcloud.tuikit.tuichat.presenter; + +import com.tencent.qcloud.tuikit.tuichat.interfaces.FileBaseUrlListener; + +public class FileBaseUrlHelper { + private FileBaseUrlListener listener; + private static FileBaseUrlHelper instance; + + public void setListener(FileBaseUrlListener listener) { + this.listener = listener; + } + + private FileBaseUrlHelper() { + // 私有构造 + } + + public static synchronized FileBaseUrlHelper getInstance() { + if (instance == null) { + instance = new FileBaseUrlHelper(); + } + return instance; + } + + public String getIconBaseUrl() { + if (listener != null) { + return listener.getIconBaseUrl(); + } else { + return null; + } + } +} diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/presenter/ParamedicOperateHelper.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/presenter/ParamedicOperateHelper.java new file mode 100644 index 0000000..9731cac --- /dev/null +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/presenter/ParamedicOperateHelper.java @@ -0,0 +1,74 @@ +package com.tencent.qcloud.tuikit.tuichat.presenter; + +import androidx.core.util.Consumer; + +import com.tencent.qcloud.tuikit.tuichat.bean.EmployeeBean; +import com.tencent.qcloud.tuikit.tuichat.bean.ExpertBean; +import com.tencent.qcloud.tuikit.tuichat.bean.GroupMemberBean; +import com.tencent.qcloud.tuikit.tuichat.classicui.interfaces.OnParamedicOperateListener; + +import java.util.List; + +public class ParamedicOperateHelper { + private OnParamedicOperateListener listener; + private static ParamedicOperateHelper instance; + + public void setListener(OnParamedicOperateListener listener) { + this.listener = listener; + } + + private ParamedicOperateHelper() { + // 私有构造 + } + + public static synchronized ParamedicOperateHelper getInstance() { + if (instance == null) { + instance = new ParamedicOperateHelper(); + } + return instance; + } + + public List getActualGroupMemberList(String sessionId) { + if (listener != null) { + return listener.getActualGroupMemberList(sessionId); + } + return null; + } + + + /** + * 邀请成员加入群组。操作异步执行,结果通过 callback 回传。 + * + * @param groupId 目标群组 ID + * @param memberList 待加入成员的 userId 列表 + * @param memberType 成员类型 + * @param callback 结果回调;当未注册 listener 时直接回调 false,避免调用方无限等待 + */ + public void addGroupUser(String groupId, List memberList, int memberType, Consumer callback) { + if (listener != null) { + listener.addGroupUser(groupId, memberList, memberType, callback); + } else if (callback != null) { + callback.accept(false); + } + } + + public List searchExpert(String realname, String centerId, String excludeSessionId, int pageNo, int pageSize) { + if (listener != null) { + return listener.searchExpert(realname, centerId, excludeSessionId, pageNo, pageSize); + } + return null; + } + + public List searchEmployee(String realname, String orgCode, String workNo, String phone, String excludeSessionId, int pageNo, int pageSize) { + if (listener != null) { + return listener.searchEmployee(realname, orgCode, workNo, phone, excludeSessionId, pageNo, pageSize); + } + return null; + } + + public void removeGroupUser(String groupId, List memberList) { + if (listener != null) { + listener.removeGroupUser(groupId, memberList); + } + } +} diff --git a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/util/ChatMessageParser.java b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/util/ChatMessageParser.java index 10cf2b7..7d9fed3 100644 --- a/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/util/ChatMessageParser.java +++ b/system/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/util/ChatMessageParser.java @@ -46,6 +46,12 @@ import java.util.Map; public class ChatMessageParser { private static final String TAG = ChatMessageParser.class.getSimpleName(); + private static ArrayList mSelectName = new ArrayList(); + + public static void setSelectName(ArrayList list) { + mSelectName.clear(); + mSelectName.addAll(list); + } public static TUIMessageBean parseMessage(V2TIMMessage v2TIMMessage) { System.out.println("聊天消息接受"+v2TIMMessage); diff --git a/system/tuichat/src/main/res/drawable-xxhdpi/chat_phone_call.png b/system/tuichat/src/main/res/drawable-xxhdpi/chat_phone_call.png new file mode 100644 index 0000000..91c7244 Binary files /dev/null and b/system/tuichat/src/main/res/drawable-xxhdpi/chat_phone_call.png differ diff --git a/system/tuichat/src/main/res/drawable-xxhdpi/default_user_icon.png b/system/tuichat/src/main/res/drawable-xxhdpi/default_user_icon.png new file mode 100644 index 0000000..68bb06f Binary files /dev/null and b/system/tuichat/src/main/res/drawable-xxhdpi/default_user_icon.png differ diff --git a/system/tuichat/src/main/res/drawable-xxhdpi/ic_plus_circle.png b/system/tuichat/src/main/res/drawable-xxhdpi/ic_plus_circle.png new file mode 100644 index 0000000..ba75131 Binary files /dev/null and b/system/tuichat/src/main/res/drawable-xxhdpi/ic_plus_circle.png differ diff --git a/system/tuichat/src/main/res/drawable-xxhdpi/ic_update_circle.png b/system/tuichat/src/main/res/drawable-xxhdpi/ic_update_circle.png new file mode 100644 index 0000000..a05c0af Binary files /dev/null and b/system/tuichat/src/main/res/drawable-xxhdpi/ic_update_circle.png differ diff --git a/system/tuichat/src/main/res/drawable/bg_add_member_button.xml b/system/tuichat/src/main/res/drawable/bg_add_member_button.xml new file mode 100644 index 0000000..2507e44 --- /dev/null +++ b/system/tuichat/src/main/res/drawable/bg_add_member_button.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/system/tuichat/src/main/res/drawable/bg_gray_round_8.xml b/system/tuichat/src/main/res/drawable/bg_gray_round_8.xml new file mode 100644 index 0000000..e758f61 --- /dev/null +++ b/system/tuichat/src/main/res/drawable/bg_gray_round_8.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/system/tuichat/src/main/res/drawable/bg_phone_call_btn.xml b/system/tuichat/src/main/res/drawable/bg_phone_call_btn.xml new file mode 100644 index 0000000..fca7405 --- /dev/null +++ b/system/tuichat/src/main/res/drawable/bg_phone_call_btn.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/system/tuichat/src/main/res/drawable/bg_phone_call_dialog.xml b/system/tuichat/src/main/res/drawable/bg_phone_call_dialog.xml new file mode 100644 index 0000000..23bf50a --- /dev/null +++ b/system/tuichat/src/main/res/drawable/bg_phone_call_dialog.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/system/tuichat/src/main/res/drawable/bg_tab_selected_white.xml b/system/tuichat/src/main/res/drawable/bg_tab_selected_white.xml new file mode 100644 index 0000000..cc9eccc --- /dev/null +++ b/system/tuichat/src/main/res/drawable/bg_tab_selected_white.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/system/tuichat/src/main/res/drawable/bg_theme_round_24.xml b/system/tuichat/src/main/res/drawable/bg_theme_round_24.xml new file mode 100644 index 0000000..fba2a3f --- /dev/null +++ b/system/tuichat/src/main/res/drawable/bg_theme_round_24.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/system/tuichat/src/main/res/drawable/bg_update_member_button.xml b/system/tuichat/src/main/res/drawable/bg_update_member_button.xml new file mode 100644 index 0000000..d676e80 --- /dev/null +++ b/system/tuichat/src/main/res/drawable/bg_update_member_button.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/system/tuichat/src/main/res/drawable/checkbox_custom.xml b/system/tuichat/src/main/res/drawable/checkbox_custom.xml new file mode 100644 index 0000000..d88bbc3 --- /dev/null +++ b/system/tuichat/src/main/res/drawable/checkbox_custom.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/system/tuichat/src/main/res/drawable/ic_check_circle.xml b/system/tuichat/src/main/res/drawable/ic_check_circle.xml new file mode 100644 index 0000000..f4bdfab --- /dev/null +++ b/system/tuichat/src/main/res/drawable/ic_check_circle.xml @@ -0,0 +1,14 @@ + + + + diff --git a/system/tuichat/src/main/res/drawable/ic_circle_stroke.xml b/system/tuichat/src/main/res/drawable/ic_circle_stroke.xml new file mode 100644 index 0000000..aac1e08 --- /dev/null +++ b/system/tuichat/src/main/res/drawable/ic_circle_stroke.xml @@ -0,0 +1,11 @@ + + + diff --git a/system/tuichat/src/main/res/drawable/ic_clear.xml b/system/tuichat/src/main/res/drawable/ic_clear.xml new file mode 100644 index 0000000..99e1f44 --- /dev/null +++ b/system/tuichat/src/main/res/drawable/ic_clear.xml @@ -0,0 +1,14 @@ + + + + diff --git a/system/tuichat/src/main/res/drawable/ic_phone_call.xml b/system/tuichat/src/main/res/drawable/ic_phone_call.xml new file mode 100644 index 0000000..34ee0b5 --- /dev/null +++ b/system/tuichat/src/main/res/drawable/ic_phone_call.xml @@ -0,0 +1,10 @@ + + + diff --git a/system/tuichat/src/main/res/drawable/ic_phone_call_close.xml b/system/tuichat/src/main/res/drawable/ic_phone_call_close.xml new file mode 100644 index 0000000..9b5c846 --- /dev/null +++ b/system/tuichat/src/main/res/drawable/ic_phone_call_close.xml @@ -0,0 +1,9 @@ + + + diff --git a/system/tuichat/src/main/res/drawable/ic_search.xml b/system/tuichat/src/main/res/drawable/ic_search.xml new file mode 100644 index 0000000..9d64dbb --- /dev/null +++ b/system/tuichat/src/main/res/drawable/ic_search.xml @@ -0,0 +1,15 @@ + + + + diff --git a/system/tuichat/src/main/res/drawable/selector_tab_bg.xml b/system/tuichat/src/main/res/drawable/selector_tab_bg.xml new file mode 100644 index 0000000..2253e63 --- /dev/null +++ b/system/tuichat/src/main/res/drawable/selector_tab_bg.xml @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/system/tuichat/src/main/res/layout/activity_add_member.xml b/system/tuichat/src/main/res/layout/activity_add_member.xml new file mode 100644 index 0000000..8669fbe --- /dev/null +++ b/system/tuichat/src/main/res/layout/activity_add_member.xml @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/system/tuichat/src/main/res/layout/chat_activity_with_navigation.xml b/system/tuichat/src/main/res/layout/chat_activity_with_navigation.xml new file mode 100644 index 0000000..b970c46 --- /dev/null +++ b/system/tuichat/src/main/res/layout/chat_activity_with_navigation.xml @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/system/tuichat/src/main/res/layout/chat_navigation_header.xml b/system/tuichat/src/main/res/layout/chat_navigation_header.xml new file mode 100644 index 0000000..9be87e6 --- /dev/null +++ b/system/tuichat/src/main/res/layout/chat_navigation_header.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + diff --git a/system/tuichat/src/main/res/layout/dialog_phone_call.xml b/system/tuichat/src/main/res/layout/dialog_phone_call.xml new file mode 100644 index 0000000..0fcae38 --- /dev/null +++ b/system/tuichat/src/main/res/layout/dialog_phone_call.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/system/tuichat/src/main/res/layout/item_add_member.xml b/system/tuichat/src/main/res/layout/item_add_member.xml new file mode 100644 index 0000000..2df2f9f --- /dev/null +++ b/system/tuichat/src/main/res/layout/item_add_member.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/system/tuichat/src/main/res/layout/item_group_member_nav.xml b/system/tuichat/src/main/res/layout/item_group_member_nav.xml new file mode 100644 index 0000000..77856da --- /dev/null +++ b/system/tuichat/src/main/res/layout/item_group_member_nav.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/system/tuichat/src/main/res/values/colors.xml b/system/tuichat/src/main/res/values/colors.xml index d929aea..89f9735 100644 --- a/system/tuichat/src/main/res/values/colors.xml +++ b/system/tuichat/src/main/res/values/colors.xml @@ -59,4 +59,10 @@ #4A4A4A #F19927 + + #F2F3F5 + #252535 + #808080 + #77849E + #B6B6B6 \ No newline at end of file diff --git a/system/tuichat/src/main/res/values/strings.xml b/system/tuichat/src/main/res/values/strings.xml index 876ce2b..f2b9769 100644 --- a/system/tuichat/src/main/res/values/strings.xml +++ b/system/tuichat/src/main/res/values/strings.xml @@ -263,4 +263,20 @@ 去完善 服务评价 + + + 拨打电话 + 取消 + + + 返回 + 选择联系人 + 邀请专家 + 邀请员工 + 已选择 0 人 + 确定 + 暂无数据 + 搜索联系人 + 搜索 + diff --git a/system/tuicontact/src/main/java/com/tencent/qcloud/tuikit/tuicontact/classicui/pages/StartGroupMemberSelectActivity.java b/system/tuicontact/src/main/java/com/tencent/qcloud/tuikit/tuicontact/classicui/pages/StartGroupMemberSelectActivity.java index 3f3ce15..b9cf4c6 100644 --- a/system/tuicontact/src/main/java/com/tencent/qcloud/tuikit/tuicontact/classicui/pages/StartGroupMemberSelectActivity.java +++ b/system/tuicontact/src/main/java/com/tencent/qcloud/tuikit/tuicontact/classicui/pages/StartGroupMemberSelectActivity.java @@ -85,6 +85,7 @@ public class StartGroupMemberSelectActivity extends BaseLightActivity { limit = getIntent().getIntExtra(TUIContactConstants.Selection.LIMIT, Integer.MAX_VALUE); alreadySelectedList = getIntent().getStringArrayListExtra(TUIContactConstants.Selection.SELECTED_LIST); mTitleBar = findViewById(R.id.group_create_title_bar); + mTitleBar.setTitle(getString(R.string.select_group_member), ITitleBarLayout.Position.MIDDLE); mTitleBar.setTitle(getResources().getString(com.tencent.qcloud.tuicore.R.string.sure), ITitleBarLayout.Position.RIGHT); mTitleBar.getRightIcon().setVisibility(View.GONE); mTitleBar.setOnRightClickListener(new View.OnClickListener() { diff --git a/system/tuicontact/src/main/res/layout/contact_selecable_adapter_item.xml b/system/tuicontact/src/main/res/layout/contact_selecable_adapter_item.xml index ed0f0ce..4757f41 100644 --- a/system/tuicontact/src/main/res/layout/contact_selecable_adapter_item.xml +++ b/system/tuicontact/src/main/res/layout/contact_selecable_adapter_item.xml @@ -16,12 +16,13 @@ android:paddingLeft="15.36dp"> @@ -30,24 +31,24 @@ android:layout_width="45dp" android:layout_height="@dimen/contact_avatar_width"> - + + android:elevation="4dp" + android:visibility="gone" /> @@ -62,13 +63,13 @@ android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerInParent="true" - android:singleLine="true" - android:ellipsize="end" - android:textSize="17.28sp" - android:lineHeight="23.04sp" android:clickable="false" + android:ellipsize="end" android:focusable="false" + android:lineHeight="23.04sp" + android:singleLine="true" android:textColor="@color/black_font_color" + android:textSize="17.28sp" tools:text="@string/default_friend" /> Edit Group Name Add Member + 选择群成员 Group Joining Method Prohibited from Joining Admin Approval diff --git a/system/tuicore/src/main/java/com/tencent/qcloud/tuicore/TUIConstants.java b/system/tuicore/src/main/java/com/tencent/qcloud/tuicore/TUIConstants.java index 4038559..885cc45 100644 --- a/system/tuicore/src/main/java/com/tencent/qcloud/tuicore/TUIConstants.java +++ b/system/tuicore/src/main/java/com/tencent/qcloud/tuicore/TUIConstants.java @@ -113,6 +113,9 @@ public final class TUIConstants { public static final String FACE_URL_LIST = "faceUrlList"; /*当下公司业务传输数据使用*/ public static final String WORK_BEAN = "workBean"; + public static final String INITIATE_VIDEO_CALL = "initiateVideoCall"; + public static final String AUTO_SEND_MESSAGE = "autoSendMessage"; + public static final String CONSULTANT_ID = "consultantId"; public static final String JOIN_TYPE = "joinType"; public static final String MEMBER_COUNT = "memberCount"; public static final String RECEIVE_OPTION = "receiveOption";