Files
Android-WaterProject/app/src/main/java/com/ckkj/water/chat/ChatFragment.java
fengjignqi 1b1575eb8a first
2026-05-16 16:19:39 +08:00

901 lines
35 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.ckkj.water.chat;
import static android.app.Activity.RESULT_OK;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.widget.NestedScrollView;
import androidx.recyclerview.widget.GridLayoutManager;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.ckkj.water.AppConfig;
import com.ckkj.water.EventMessage;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.chat.adapter.ChatQuestionDetailAdapter;
import com.ckkj.water.chat.adapter.ChatZixunAdapter;
import com.ckkj.water.chat.entity.ChatQuestionEntity;
import com.ckkj.water.custom.GridSpacingItemDecoration;
import com.ckkj.water.databinding.IndexLayoutBinding;
import com.ckkj.water.chat.adapter.IndexChatAdapter;
import com.ckkj.water.chat.adapter.IndexOptionAdapter;
import com.ckkj.water.chat.adapter.IndexEnterHintAdapter;
import com.ckkj.water.chat.adapter.IndexQuickAskAdapter;
import com.ckkj.water.chat.entity.CharHistoryEntity;
import com.ckkj.water.chat.entity.ChatAiMsgEntity;
import com.ckkj.water.chat.entity.ChatMultiItem;
import com.ckkj.water.chat.entity.IndexTemplateEntity;
import com.ckkj.water.chat.mvp.IndexContract;
import com.ckkj.water.chat.mvp.IndexImpl;
import com.ckkj.water.chat.mvp.IndexPresenter;
import com.ckkj.water.dialog.ContentReportDialog;
import com.ckkj.water.login.LoginActivity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.plate.entity.BaziResultBean;
import com.ckkj.water.plate.entity.PaipanCache;
import com.ckkj.water.utils.click.ClickUtil;
import com.ckkj.water.utils.manager.ColorManage;
import com.ckkj.water.utils.show.ToastUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import de.greenrobot.event.Subscribe;
import de.greenrobot.event.ThreadMode;
import android.content.ClipData;
import android.content.ClipboardManager;
/**
* @author fengxiaoyang
* @date 2025/7/7
* @description TODO: 描述该类的作用
*/
public class ChatFragment extends BaseFragment<IndexLayoutBinding, IndexPresenter> implements IndexContract.IndexView {
//顶部 adapter
private IndexOptionAdapter mOptionAdapter;
private ChatZixunAdapter mZixunQuestAdapter;
private ChatQuestionDetailAdapter mQuesDetailAdapter;
//快速提问 adapter
private IndexQuickAskAdapter mQuickAskAdapter;
private List<IndexTemplateEntity> mQuickAskList = new ArrayList<>();
private List<ChatMultiItem> mChatMsgList = new ArrayList<>();
//聊天 adapter
private IndexChatAdapter mChatAdapter;
//欢迎语 adapter
private IndexEnterHintAdapter mHintAdapter;
//输入的内容
private String mCurrentInputContent = "";
//当前options 的 pos
private int mCurrentStreamPos = 0;
//模板数据 list
private List<IndexTemplateEntity> mIndexTemList = new ArrayList<>();
//输出是否完成
private boolean mIsStreamStop = true;
//当前选中 option 的 typeID
private String mSelectTypeID = "1";
//会话 ID
private String mSessionId = "";
// 添加流式数据累积变量
private StringBuilder mStreamContentBuilder = new StringBuilder();
private ChatAiMsgEntity mCurrentStreamEntity = null;
// 智能滚动管理
private boolean mIsUserScrolling = false;
// 优化防抖机制
private Handler mUpdateHandler = new Handler();
private Runnable mUpdateRunnable;
private List<ChatQuestionEntity> mQuesTypeList = new ArrayList<>();
private boolean mIsShowQuestions = true;
@Override
public void initData(Bundle state) {
mOptionAdapter = new IndexOptionAdapter(mContext, R.layout.index_device_list_item, mIndexTemList);
viewBinding.rvOptions.setAdapter(mOptionAdapter);
mQuickAskAdapter = new IndexQuickAskAdapter(mContext, R.layout.index_home_quick_ask_item, mQuickAskList);
viewBinding.rvQuickAsk.setAdapter(mQuickAskAdapter);
mChatAdapter = new IndexChatAdapter(mContext, mChatMsgList, viewBinding.rvChat);
viewBinding.rvChat.setAdapter(mChatAdapter);
//提问类型
GridLayoutManager manager = new GridLayoutManager(mContext, 2);
viewBinding.rvChatQuick.setLayoutManager(manager);
List<ChatQuestionEntity.SubheadingsDTO> subList = new ArrayList<>();
mQuesDetailAdapter = new ChatQuestionDetailAdapter(R.layout.chat_quest_detail_item, subList);
viewBinding.rvChatQuick.setAdapter(mQuesDetailAdapter);
viewBinding.rvChatQuick.addItemDecoration(new GridSpacingItemDecoration(2, 10, true));
mZixunQuestAdapter = new ChatZixunAdapter(mContext, R.layout.chat_zixun_type_item, mQuesTypeList);
viewBinding.rvChatType.setAdapter(mZixunQuestAdapter);
// 设置聊天RecyclerView的LayoutManager禁用滚动
androidx.recyclerview.widget.LinearLayoutManager chatLayoutManager =
new androidx.recyclerview.widget.LinearLayoutManager(mContext);
chatLayoutManager.setStackFromEnd(false);
viewBinding.rvChat.setLayoutManager(chatLayoutManager);
// 禁用RecyclerView的滚动让NestedScrollView处理滚动
viewBinding.rvChat.setNestedScrollingEnabled(false);
mHintAdapter = new IndexEnterHintAdapter(mContext, R.layout.index_enter_hint_item, new ArrayList<>());
viewBinding.rvEnterHint.setAdapter(mHintAdapter);
setAdapterClick();
// 添加EditText的焦点监听器
viewBinding.editInput.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
// EditText获取焦点时延迟滚动到底部确保键盘弹出后再滚动
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
scrollNestedScrollViewToBottom();
}
}, 300); // 延迟300ms等待键盘弹出
}
}
});
viewBinding.editInput.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) {
if (s != null) {
mCurrentInputContent = s.toString().trim();
if (TextUtils.isEmpty(s.toString().trim())) {
viewBinding.imgSend.setImageDrawable(ContextCompat.getDrawable(mContext, R.mipmap.icon_index_send));
viewBinding.editInput.setHint("请输入您的问题");
} else {
viewBinding.imgSend.setImageDrawable(ContextCompat.getDrawable(mContext, R.mipmap.icon_index_send_b));
}
}
}
});
//请求页面模板数据
mPresenter.getIndexTemplateDatas();
mPresenter.getChatTemplateDatas();
//组件增加点击区域
ClickUtil.addClickPart(viewBinding.imgCloseQuick, 30);
ClickUtil.addClickPart(viewBinding.imgRefresh, 30);
ClickUtil.addClickPart(viewBinding.imgHistory, 30);
// 设置智能滚动监听
setupSmartScrollListener();
// 设置页面点击监听,用于隐藏键盘
setupPageClickListener();
// 检查是否有传递过来的参数
checkAndHandleBundle();
}
/**
* 检查并处理传递过来的Bundle参数
*/
private void checkAndHandleBundle() {
Bundle args = getArguments();
if (args != null) {
handleBirthInfoBundle(args);
}
}
/**
* 处理出生信息Bundle参数
*
* @param bundle 包含出生信息的Bundle
*/
public void handleBirthInfoBundle(Bundle bundle) {
if (bundle != null) {
BaziResultBean baseEntity = PaipanCache.get();
// 获取出生信息
BaziResultBean.BaseInfoDTO birthInfo = baseEntity.getBaseInfo();
BaziResultBean.DetailInfoDTO.SizhuInfoDTO sizhuInfoDTO = baseEntity.getDetailInfo().getSizhuInfo();
BaziResultBean.DetailInfoDTO.DayunInfoDTO defaulLiunian = (BaziResultBean.DetailInfoDTO.DayunInfoDTO) bundle.getSerializable("defaul_liunian");
if (birthInfo != null) {
viewBinding.editInput.setText("我叫" + birthInfo.getName() + "," +
((birthInfo.getSex().equals("乾造") ? "" : "") + "," +
"生于公历" + birthInfo.getGongli() + "," + "当前大运为" + defaulLiunian.getDayunStartYear() + "--" +
defaulLiunian.getDayunEndYear() + "" + defaulLiunian.getDayunStartGanzhi() + "大运,四柱为"
+ sizhuInfoDTO.getYear().getTg() + sizhuInfoDTO.getYear().getDz() + "" +
sizhuInfoDTO.getMonth().getTg() + sizhuInfoDTO.getMonth().getDz() + "" +
sizhuInfoDTO.getDay().getTg() + sizhuInfoDTO.getDay().getDz() + "" +
sizhuInfoDTO.getHour().getTg() + sizhuInfoDTO.getHour().getDz() + "," +
"现在需要你根据我的八字,给我具体分析一下我的事业、感情、健康、财富、格局、喜用神"));
}
}
}
/**
* 当Fragment参数更新时调用用于处理onNewIntent的情况
*/
@Override
public void onResume() {
super.onResume();
// 检查是否有新的参数需要处理
Bundle args = getArguments();
if (args != null && args.getBoolean("goto_index_fragment", false)) {
// 处理参数
handleBirthInfoBundle(args);
// 清除标记,避免重复处理
args.remove("goto_index_fragment");
}
}
@Subscribe(threadMode = ThreadMode.MainThread)
public void onGetMessage(EventMessage message) {
//用户添加地址成功
if (message.getEventStrKey().equals(EventMessage.HISTORY_SESSIONID_DELETE_SUCCESS)) {
if (message.getMsg().equals(mSessionId)) {
// viewBinding.linearOptionHint.setVisibility(View.VISIBLE);
mChatMsgList.clear();
mChatAdapter.setNewData(mChatMsgList);
mSessionId = "";
}
}
}
/**
* 设置页面点击监听器
*/
private void setupPageClickListener() {
viewBinding.rvChat.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// 当用户触摸NestedScrollView时隐藏键盘并清除焦点
if (event.getAction() == MotionEvent.ACTION_DOWN) {
hideKeyboardAndClearFocus();
}
return false;
}
});
}
/**
* 隐藏键盘并清除EditText焦点
*/
private void hideKeyboardAndClearFocus() {
// 清除EditText焦点
viewBinding.editInput.clearFocus();
// 隐藏键盘
InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(viewBinding.editInput.getWindowToken(), 0);
}
}
/**
* 滚动NestedScrollView到底部
*/
private void scrollNestedScrollViewToBottom() {
if (viewBinding.nestedScrollChat != null) {
// 获取NestedScrollView的子视图RecyclerView
View childView = viewBinding.nestedScrollChat.getChildAt(0);
if (childView != null) {
// 滚动到底部
viewBinding.nestedScrollChat.smoothScrollTo(0, childView.getHeight());
}
}
}
/**
* 设置智能滚动监听器修改为监听NestedScrollView
*/
private void setupSmartScrollListener() {
// 监听NestedScrollView的滚动
viewBinding.nestedScrollChat.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
@Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
// 检测用户是否向上滑动
if (scrollY < oldScrollY) {
// 用户向上滑动
mIsUserScrolling = true;
} else if (scrollY > oldScrollY) {
// 用户向下滑动
mIsUserScrolling = true;
}
// 检查是否滚动到底部
if (scrollY >= (v.getChildAt(0).getHeight() - v.getHeight())) {
// 滚动到底部,恢复自动滚动
mIsUserScrolling = false;
}
}
});
}
private void setAdapterClick() {
//顶部的选项 adapter 点击事件
mOptionAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
if (mCurrentStreamPos != position) {
if (mIsStreamStop) {
viewBinding.rlQuickAsk.setVisibility(View.GONE);
mOptionAdapter.setSelectPos(position);
setOptionSelStyle(position);
mCurrentStreamPos = position;
mSessionId = "";
mSelectTypeID = mIndexTemList.get(position).getId();
} else {
ToastUtil.showShort(mContext, "Ai解答中请稍后操作");
}
}
}
});
//咨询类型 adapter
mZixunQuestAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
if (mIsStreamStop) {
mZixunQuestAdapter.setSelectPos(position);
mQuesDetailAdapter.setNewData(mQuesTypeList.get(position).getSubheadings());
} else {
ToastUtil.showShort(mContext, "Ai解答中请稍后操作");
}
}
});
//快速提问
mQuesDetailAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
if (!AppConfig.USER_LOGIN) {
goTo(mContext, LoginActivity.class, null);
return;
}
if (!mIsStreamStop) {
ToastUtil.showShort(mContext, "Ai解答中请稍后操作");
return;
}
String quickAskContent = mQuesTypeList.get(mZixunQuestAdapter.getmSelPos()).
getSubheadings().get(position).getContent();
sendMsgToAi(quickAskContent);
}
});
//流式输出,是否完成
mChatAdapter.setOnStreamCompleteListener(new IndexChatAdapter.OnStreamCompleteListener() {
@Override
//此时已经流式输出完成
public void onStreamComplete(int position) {
mCurrentStreamPos = position;
viewBinding.imgSend.setVisibility(View.VISIBLE);
viewBinding.imgStop.setVisibility(View.GONE);
mIsStreamStop = true;
}
@Override
public void onStreamStop() {
viewBinding.imgSend.setVisibility(View.VISIBLE);
viewBinding.imgStop.setVisibility(View.GONE);
mIsStreamStop = true;
}
});
mChatAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
@Override
public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
switch (view.getId()) {
case R.id.img_jb:
ContentReportDialog cancelDialog = new ContentReportDialog(mContext, R.layout.dialog_report_reason, "");
cancelDialog.show();
cancelDialog.setOnDialogListener(new ContentReportDialog.DialogListener() {
@Override
public void callBackDatas(String reason) {
showLoadingDialog();
//举报
mPresenter.commitReport(reason);
}
});
break;
}
}
});
// 设置长按菜单监听器
mChatAdapter.setOnItemLongClickMenuListener(new IndexChatAdapter.OnItemLongClickMenuListener() {
@Override
public void onCopyClick(ChatMultiItem item, int position) {
// 处理复制操作
String content = item.getMessage().getContent();
if (!TextUtils.isEmpty(content)) {
ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("chat_content", content);
clipboard.setPrimaryClip(clip);
ToastUtil.showShort(mContext, "内容已复制");
}
}
@Override
public void onReportClick(ChatMultiItem item, int position) {
// 处理举报操作
ContentReportDialog cancelDialog = new ContentReportDialog(mContext, R.layout.dialog_report_reason, "");
cancelDialog.show();
cancelDialog.setOnDialogListener(new ContentReportDialog.DialogListener() {
@Override
public void callBackDatas(String reason) {
showLoadingDialog();
//举报
mPresenter.commitReport(reason);
}
});
}
});
// 添加长按监听器
// mChatAdapter.setOnItemChildLongClickListener(new BaseQuickAdapter.OnItemChildLongClickListener() {
// @Override
// public boolean onItemChildLongClick(BaseQuickAdapter adapter, View view, int position) {
// switch (view.getId()) {
// case R.id.tv_text: // 文本内容的view id
// XPopup.fixLongClick(view); // 能保证弹窗弹出后下层的View无法滑动
//
// // 获取当前消息内容
// ChatMultiItem item = mChatMsgList.get(position);
// String content = item.getMessage().getContent();
//
// // 使用链式调用确保atView在asAttachList之前
// new XPopup.Builder(getContext())
// .hasShadowBg(false)
// .atView(view) // 使用atView而不是watchView
// .asAttachList(new String[]{"复制", "举报"},
// null,
// new OnSelectListener() {
// @Override
// public void onSelect(int selectPosition, String text) {
// switch (selectPosition) {
// case 0: // 复制
// if (!TextUtils.isEmpty(content)) {
// ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
// ClipData clip = ClipData.newPlainText("chat_content", content);
// clipboard.setPrimaryClip(clip);
// ToastUtil.showShort(mContext, "内容已复制");
// }
// break;
// case 1: // 举报
// ContentReportDialog cancelDialog = new ContentReportDialog(mContext, R.layout.dialog_report_reason, "");
// cancelDialog.show();
// cancelDialog.setOnDialogListener(new ContentReportDialog.DialogListener() {
// @Override
// public void callBackDatas(String reason) {
// showLoadingDialog();
// //举报
// mPresenter.commitReport(reason);
// }
// });
// break;
// }
// }
// })
// .show();
// return true;
// }
// return false;
// }
// });
}
/**
* 停止输出
*/
private void stopSteamOutput() {
// 停止当前网络请求
mPresenter.stopCurrentRequest();
// 获取当前正在流式输出的位置
int currentPosition = mChatMsgList.size() - 1;
// 标记当前消息为被停止状态
mChatAdapter.markAsStopped(currentPosition);
// 停止适配器中的流式输出
mChatAdapter.setStreamerStop(currentPosition);
// 清除当前流式输出位置
mChatAdapter.setCurrentStreamingPosition(-1);
// 强制更新当前item以显示停止标识
mChatAdapter.notifyItemChanged(currentPosition);
// 恢复UI状态
viewBinding.imgSend.setVisibility(View.VISIBLE);
viewBinding.imgStop.setVisibility(View.GONE);
mIsStreamStop = true;
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (data != null) {
if (resultCode == RESULT_OK) {
switch (requestCode) {
case REQUEST_EVENT_CODE_10001:
String sessionId = data.getStringExtra("session_id");
String numerologyType = data.getStringExtra("numerology_type");
int showSelPos = -1;
for (int i = 0; i < mIndexTemList.size(); i++) {
if (numerologyType.equals(mIndexTemList.get(i).getId())) {
showSelPos = i;
}
}
if (mCurrentStreamPos != showSelPos) {
}
if (mIsStreamStop) {
viewBinding.rlQuickAsk.setVisibility(View.GONE);
mOptionAdapter.setSelectPos(showSelPos);
setOptionSelStyle(showSelPos);
mCurrentStreamPos = showSelPos;
mSelectTypeID = mIndexTemList.get(showSelPos).getId();
if (!TextUtils.isEmpty(sessionId)) {
mPresenter.getChatDetailByID(sessionId);
}
} else {
ToastUtil.showShort(mContext, "Ai解答中请稍后操作");
}
break;
}
}
}
}
/**
* 发送消息给 AI
*/
private void sendMsgToAi(String senMsg) {
if (!AppConfig.USER_LOGIN) {
goTo(mContext, LoginActivity.class, null);
return;
}
viewBinding.cardQuestion.setVisibility(View.GONE);
viewBinding.imgClose.setImageDrawable(ContextCompat.getDrawable(mContext, R.mipmap.icon_chat_down));
mIsShowQuestions = false;
viewBinding.linearOptionHint.setVisibility(View.GONE);
// 重置滚动状态
mIsUserScrolling = false;
// 清理适配器缓存
mChatAdapter.clearCache();
// 创建用户消息
ChatAiMsgEntity chatMsgEntity = new ChatAiMsgEntity();
chatMsgEntity.setSessionId(mSessionId);
chatMsgEntity.setType(mSelectTypeID);
chatMsgEntity.setContent(senMsg);
ChatMultiItem userEntity = new ChatMultiItem(ChatMultiItem.TYPE_TEXT_RIGHT, chatMsgEntity);
mChatMsgList.add(userEntity);
mChatAdapter.notifyItemInserted(mChatMsgList.size() - 1);
// 创建AI回复消息初始为空
mCurrentStreamEntity = new ChatAiMsgEntity();
mCurrentStreamEntity.setSessionId(mSessionId);
mCurrentStreamEntity.setType(mSelectTypeID);
mCurrentStreamEntity.setContent(""); // 初始为空
ChatMultiItem aiEntity = new ChatMultiItem(ChatMultiItem.TYPE_TEXT_LEFT, mCurrentStreamEntity);
mChatMsgList.add(aiEntity);
// 设置当前流式输出位置
int aiMessagePosition = mChatMsgList.size() - 1;
mChatAdapter.setCurrentStreamingPosition(aiMessagePosition);
mChatAdapter.notifyItemInserted(aiMessagePosition);
// 重置流式数据累积器
mStreamContentBuilder.setLength(0);
// 清空输入框
viewBinding.editInput.setText("");
// 设置UI状态
viewBinding.imgSend.setVisibility(View.GONE);
viewBinding.imgStop.setVisibility(View.VISIBLE);
// 发送消息后自动滚动到底部
scrollToBottomAfterSend();
// 发起流式请求
mPresenter.talkToAi(senMsg, mSelectTypeID, mSessionId);
}
@Override
public IndexPresenter createPresenter() {
return new IndexPresenter(new IndexImpl());
}
@Override
public void getTalkResultSuccess(ChatAiMsgEntity bean) {
hideDialogLoading();
}
/**
* 首页数据获取成功
*
* @param list
*/
@Override
public void getIndexTemplateSuccess(List<IndexTemplateEntity> list) {
if (list != null && list.size() != 0) {
mIndexTemList = list;
mOptionAdapter.setNewData(mIndexTemList);
setAdapterClick();
setOptionSelStyle(0);
mSelectTypeID = mIndexTemList.get(0).getId();
}
}
/**
* 切换设置显示内容
*
* @param pos
*/
private void setOptionSelStyle(int pos) {
try {
mChatMsgList.clear();
mChatAdapter.setNewData(mChatMsgList);
// 清理缓存
mChatAdapter.clearCache();
// viewBinding.linearOptionHint.setVisibility(View.VISIBLE);
IndexTemplateEntity defaulEntity = mIndexTemList.get(pos);
viewBinding.tvTitleExpert.setText(defaulEntity.getTitle() + "专家");
viewBinding.tvSelectOptionLable.setText(defaulEntity.getTitle() + "专家");
viewBinding.tvSelectOptionSlogan.setText(defaulEntity.getSubheading());
if (ColorManage.getInstance().isParsableColor(defaulEntity.getColor())) {
viewBinding.tvSelectOptionSlogan.setTextColor(Color.parseColor(defaulEntity.getColor()));
} else {
viewBinding.tvSelectOptionSlogan.setTextColor(ContextCompat.getColor(mContext, R.color.color_zhu));
}
//提示语
List<String> hintMsgList = new ArrayList<>();
hintMsgList = Arrays.asList(defaulEntity.getIntermediateContent().split("#"));
mHintAdapter.setNewData(hintMsgList);
//快速提问
mQuickAskList.clear();
List<String> quickAskList = new ArrayList<>();
quickAskList = Arrays.asList(defaulEntity.getQuickQuestions().split("#"));
for (String content : quickAskList) {
IndexTemplateEntity entity = new IndexTemplateEntity();
entity.setColor(defaulEntity.getColor());
entity.setBlackcolor(defaulEntity.getBlackcolor());
entity.setSpliteItemContent(content);
mQuickAskList.add(entity);
}
mQuickAskAdapter.setNewData(mQuickAskList);
} catch (Exception e) {
}
}
@Override
public void onNetChange(int netModel) {
}
@Override
public void showError(String message) {
hideDialogLoading();
ToastUtil.showShort(mContext, message);
// 流式传输完成恢复UI状态
viewBinding.imgSend.setVisibility(View.VISIBLE);
viewBinding.imgStop.setVisibility(View.GONE);
mIsStreamStop = true;
// 可以在这里处理会话ID等
if (mCurrentStreamEntity != null && !TextUtils.isEmpty(mCurrentStreamEntity.getSessionId())) {
mSessionId = mCurrentStreamEntity.getSessionId();
}
// 清理当前流式实体
mCurrentStreamEntity = null;
mStreamContentBuilder.setLength(0);
}
@Override
public void logOut(BaseBean bean) {
}
// 实现流式消息接收回调
@Override
public void onStreamMessageReceived(String messageChunk) {
mIsStreamStop = false;
if (mCurrentStreamEntity != null) {
// 更新当前AI消息的内容
mCurrentStreamEntity.setContent(messageChunk);
// 取消之前的更新任务
if (mUpdateRunnable != null) {
mUpdateHandler.removeCallbacks(mUpdateRunnable);
}
mUpdateRunnable = () -> {
// 只更新最后一个item
int lastPosition = mChatMsgList.size() - 1;
if (lastPosition >= 0) {
// 使用更轻量的更新方式,避免重新布局
mChatAdapter.notifyItemChanged(lastPosition, "content_only");
// 流式输出时如果用户没有手动滑动则自动滚动NestedScrollView
if (!mIsUserScrolling) {
smoothScrollNestedScrollView();
}
}
};
// 增加延迟时间,减少更新频率
mUpdateHandler.postDelayed(mUpdateRunnable, 100);
}
}
// 实现流式完成回调
@Override
public void onStreamComplete(String complateMsg) {
// 流式传输完成恢复UI状态
viewBinding.imgSend.setVisibility(View.VISIBLE);
viewBinding.imgStop.setVisibility(View.GONE);
mIsStreamStop = true;
// 清除当前流式输出位置
mChatAdapter.setCurrentStreamingPosition(-1);
// 注意:这里不标记为停止状态,因为这是正常完成
// 可以在这里处理会话ID等
if (mCurrentStreamEntity != null && !TextUtils.isEmpty(mCurrentStreamEntity.getSessionId())) {
mSessionId = mCurrentStreamEntity.getSessionId();
}
// 清理当前流式实体
mCurrentStreamEntity = null;
mStreamContentBuilder.setLength(0);
// 假设你最后一个消息是流式的 placeholder现在替换它
ChatMultiItem lastMessage = mChatMsgList.get(mChatMsgList.size() - 1);
lastMessage.getMessage().setContent(complateMsg); // 你可以解析 Markdown 变 PlainText或保留 Markdown 渲染
// mChatAdapter.notifyItemChanged(mChatMsgList.size() - 1); // 更新 UI
int lastPos = mChatAdapter.getItemCount() - 1;
mChatAdapter.updateTipsVisibility(lastPos);
}
/**
* 根据会话 id 查询对话详情
*
* @param list
*/
@Override
public void getChatDetailSuccess(List<ChatAiMsgEntity> list) {
mChatMsgList.clear();
if (list != null && list.size() != 0) {
mSessionId = list.get(0).getSessionId();
}
for (ChatAiMsgEntity entity : list) {
ChatMultiItem item;
if (entity.getRole().equals("user")) {
item = new ChatMultiItem(ChatMultiItem.TYPE_TEXT_RIGHT, entity);
} else {
item = new ChatMultiItem(ChatMultiItem.TYPE_TEXT_LEFT, entity);
}
mChatMsgList.add(item);
}
mChatAdapter.setNewData(mChatMsgList);
viewBinding.linearOptionHint.setVisibility(View.GONE);
}
@Override
public void loginLost() {
if (isFragmentVisible()) {
handleLoginLost();
}
stopSteamOutput();
if (mChatAdapter != null) {
mChatAdapter.remove(mChatMsgList.size() - 1);
}
}
/**
* 获取咨询模板成功
*
* @param list
*/
@Override
public void getChatZixunSuccess(List<ChatQuestionEntity> list) {
this.mQuesTypeList = list;
if (list != null) {
mZixunQuestAdapter.setNewData(list);
mQuesDetailAdapter.setNewData(list.get(0).getSubheadings());
setAdapterClick();
}
}
/**
* 举报成功
* @param bean
*/
@Override
public void commitReportSuccess(BaseBean bean) {
ToastUtil.showShort(mContext, "星语明灯感谢您的反馈");
hideDialogLoading();
}
// 实现sessionId接收回调
@Override
public void onSessionReceived(String sessionId) {
// 保存sessionId
mSessionId = sessionId;
}
@Override
public void getHistoryDataSuccess(CharHistoryEntity entity) {
}
@Override
public void deleteHistorySuccess(BaseBean bean, int delPos) {
}
/**
* 平滑滚动NestedScrollView到底部
*/
private void smoothScrollNestedScrollView() {
if (mChatAdapter != null && mChatAdapter.getItemCount() > 0) {
// 直接滚动NestedScrollView到底部
viewBinding.nestedScrollChat.post(() -> {
viewBinding.nestedScrollChat.fullScroll(View.FOCUS_DOWN);
});
}
}
/**
* 发送消息后滚动到底部
*/
private void scrollToBottomAfterSend() {
new Handler().postDelayed(() -> {
if (isFragmentVisible()) {
viewBinding.nestedScrollChat.fullScroll(View.FOCUS_DOWN);
}
}, 100);
}
@Override
public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
}
@Override
public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
}
}