wujingjing
2024-08-12 9de6cf5226f7df076449a39c5adeb431b12fe923
miniprogram/pages/question/question.ts
@@ -2,27 +2,33 @@
  AnswerState,
  AnswerType,
  ChatContent,
  ChatMessage,
  RoleEnum,
  roleImageMap
} from "@/model/chat/types";
import {
  CHAT_GROUP_DATA,
  TEST_DATA
} from "./testData";
import {
  TAB_BAR_HEIGHT
} from "@/custom-tab-bar/constants";
import {
  checkAuth
} from "@/utils/http";
import { GetHistoryAnswer, QueryHistoryDetail } from "@/api/chat";
import { CreateHistoryGroup, DeleteHistoryGroups, extCallQuery, GetHistoryAnswer, GetHistoryGroups, getQuestionProcess, getSelectSample, QueryHistoryDetail, QuestionAi, setHistoryGroupTitle } from "@/api/chat";
import { ErrorCode } from "@/utils/http";
import { ComponentWithComputed, } from "miniprogram-computed";
import { uuid } from "@/utils/uuid";
import { getStorage } from "@/utils/storage";
import { getCurrentUrl } from "@/utils/common";
import { SHARE_CONFIG } from "@/config/constants";
const app = getApp();
// pages/question/question.js
const getAnswerById = async (historyId: string) => {
  return await GetHistoryAnswer({
    history_id: historyId,
  });
};
const DEFAULT_SECTION_A_ID = 'knowledge_base'
const parseContent = (res) => {
  if (!res) return null;
@@ -57,6 +63,7 @@
        type: AnswerType.Summary,
        values: res.summary,
      };
      break;
    case AnswerType.Url:
      content = {
@@ -83,127 +90,481 @@
  content.origin = res;
  return content;
};
Component({
let processId = '';
const QUERY_PROCESS_INTERVAL = 1000;
let processTimer = null;
let finishProcess = true;
Page({
  // 页面的初始数据
  data: {
    isTalking: false,
    AnswerType,
    sendText: '',
    sendText: '你是谁?',
    chatHistory: [],
    roleImageMap,
    RoleEnum,
    drawerIsShow: false,
    displayChatRoom: CHAT_GROUP_DATA,
    chatRoomList: [],
    toViewId: '',
    TAB_BAR_HEIGHT: TAB_BAR_HEIGHT,
    ErrorCode,
    questionRes: null,
    activeChatRoom: {
      "group_id": "a8197e731f704943974946e0d260bd5c",
      "group_title": "查询控江路压流一体设备的昨日瞬时流量",
      "chat_count": "8",
      "create_time": "2024-07-19 20:56:24"
    },
  },
  methods: {
    onSendTextChange: function (e) {
      // this.setData({
      //   sendText:e.detail.value
      // })
    },
    chatRoomClick(e) {
      const item = e.currentTarget.dataset.item;
      this.setData({
        activeChatRoom: item,
      })
    },
    delChatRoomClick(e) {
      const id = e.currentTarget.dataset.id;
      wx.modal({
        content: '确定删除当前聊天室吗?'
      }).then(val => {
        if (!val) return;
      })
    },
    processText: '',
    /** @description 所有得sample */
    sampleList: [],
    /** @description 随机抽出最多三个例子 */
    displaySampleList: [],
    section_a_id: '',
    sample_id: '',
    userName: getStorage('username'),
    keyboardHeight: 0,
    // 聊天室图标点击
    chatRoomListClick() {
  },
  onClickClear() {
    console.log('clear');
    this.setData({
      sendText: ''
    })
  },
  inputFocus(e) {
    if (e.detail.height > 0) {
      this.setData({
        drawerIsShow: true,
      })
    },
    drawerCloseClick() {
      this.setData({
        drawerIsShow: false,
        keyboardHeight: e.detail.height - 55
      })
    }
  },
  lifetimes: {
    async attached() {
      const isPassed = checkAuth();
      if (!isPassed) return;
      const res = await QueryHistoryDetail({
        history_group_id: this.data.activeChatRoom.group_id,
      });
  changeInputBlur(e) {
    this.setData({
      keyboardHeight: 0
    })
  },
  async getSampleList() {
    const res = await getSelectSample({
      section_b_id: '',
    });
    this.setData({
      sampleList: res?.samples ?? []
    })
    this.setData({
      displaySampleList: wx.$_.sampleSize(this.data.sampleList, 3)
    })
  },
  sampleClick(e) {
    const item = e.currentTarget.dataset.item;
    this.setData({
      sample_id: item.sample_id,
      sendText: item.sample_question,
      section_a_id: item.section_a_id,
    })
  },
  queryProcess() {
    processTimer = setInterval(() => {
      if (!finishProcess) return;
      finishProcess = false;
      this.queryProcessApi();
    }, QUERY_PROCESS_INTERVAL);
  },
  async queryProcessApi() {
    const res = await getQuestionProcess({
      process_id: processId,
    }, {
      isLoading: false
    }).catch((err) => {
      this.setData({
        chatHistory: (res.details ?? []).map((item) => {
          return {
            historyId: item.history_id,
            role: RoleEnum.user,
            content: {
              type: AnswerType.Text,
              values: item.question,
            },
          }
        })
        processText: err
      })
    });
    this.setData({
      processText: res.process
    })
    finishProcess = true;
  },
  clearQueryProcess() {
    this.setData({
      processText: ''
    })
    clearInterval(processTimer);
  },
  async questionAi(text) {
    // if (!currentSectionId) {
    //   ElMessage.warning('发送失败,未确定应用场景!');
    // }
    processId = uuid();
    // const judgeParams = !preQuestion.value
    //   ? {}
    //   : {
    //       prev_question: preQuestion.value,
    //     };
    let currentSectionAId = '';
    if (this.data.section_a_id) {
      currentSectionAId = this.data.section_a_id;
      this.data.section_a_id = '';
    } else {
      const lastSectionAItem = wx.$_.findLast(this.data.chatHistory, (item) => item.role === RoleEnum.assistant && !!item.sectionAId);
      currentSectionAId = lastSectionAItem?.sectionAId ?? DEFAULT_SECTION_A_ID;
    }
    const judgeParams = {}
    const params = {
      process_id: processId,
      question: text,
      section_a_id: currentSectionAId,
      history_group_id: this.data.activeChatRoom.id,
      raw_mode: false,
      ...judgeParams,
    } as any;
    if (this.data.sample_id) {
      params.sample_id = this.data.sample_id;
      this.data.sample_id = '';
    }
      // currentSectionId = res?.details?.[0]?.section_a_id;
      // currentSampleId = res?.details?.[0]?.sample_id;
      const resList: any[] = await Promise.all((res.details ?? []).map((item) => getAnswerById(item.history_id)));
      let i = 0;
      resList.map((item, index) => {
        const insertIndex = index + 1 + i;
        this.data.chatHistory.splice(
          insertIndex,
          0,
          item.answer === null ?
            null :
            {
              historyId: item.answer?.history_id,
              role: RoleEnum.assistant,
              content: parseContent(item.answer),
              state: item.answer_state,
            }
        );
        i++;
    // if (currentLLMId) {
    //   params.llm_id = currentLLMId;
    // }
    this.clearQueryProcess();
    this.queryProcess();
    const res = await QuestionAi(params, {
      isLoading: false
    }).finally(() => {
      this.clearQueryProcess();
    });
    this.questionRes = res;
    const content = parseContent(res);
    return content;
  },
  async sendText(cb?: any, callExtParams?: any) {
    if (!this.data.sendText || this.data.isTalking) return;
    let resMsgContent: ChatContent = null;
    const isInitial = this.data.activeChatRoom.isInitial;
    if (isInitial) {
      this.data.activeChatRoom.isInitial = false;
      this.setData({
        activeChatRoom: this.data.activeChatRoom
      })
      /** @description 修改聊天室名称 */
      const res = await setHistoryGroupTitle({
        history_group_id: this.data.activeChatRoom.id,
        title: this.data.sendText,
      }, {
        isLoading: false
      });
      if (!res?.json_ok) return;
      this.data.activeChatRoom.title = this.data.sendText;
      wx.setNavigationBarTitle({
        title: this.data.activeChatRoom.title
      })
      this.setData({
        chatRoomList: this.data.chatRoomList
      })
    }
    try {
      const userItem: ChatMessage = {
        role: RoleEnum.user, content: {
          type: AnswerType.Text,
          values: this.data.sendText
        }
      } as any;
      const assistantItem: ChatMessage = { role: RoleEnum.assistant, content: null, state: AnswerState.Null } as any;
      // 发送当前
      this.data.chatHistory.push(userItem);
      const currentText = this.data.sendText;
      // 清空输入框
      this.setData({
        sendText: '',
      })
      // 出现回复,等待恢复对话
      this.setData({
        isTalking: true
      })
      this.data.chatHistory.push(assistantItem);
      this.setData({
        chatHistory: this.data.chatHistory
      })
      // if (messageList.value.length === 0) {
      //   messageContent.value = {
      //     type: AnswerType.Text,
      //     values: activeChatRoom.value.title,
      //   };
      //   sendChatMessage();
      // }
      this.scrollToBottom();
      if (callExtParams) {
        const extRes = await extCallQuery(callExtParams);
        this.questionRes = extRes;
        resMsgContent = parseContent(extRes);
      } else {
        resMsgContent = await this.questionAi(currentText);
      }
      userItem.historyId = this.questionRes.history_id;
      assistantItem.historyId = this.questionRes.history_id;
      this.data.chatHistory[this.data.chatHistory.length - 1].content = resMsgContent
      this.setData({
        chatHistory: this.data.chatHistory
      })
      this.scrollToBottom();
    } catch (error: any) {
    } finally {
      this.setData({
        isTalking: false
      })
    }
  },
  inputRighBtnClick() {
    if (this.data.sendText) {
      this.sendText();
    } else {
  pageLifetimes: {
    show() {
      if (typeof this.getTabBar === 'function' &&
        this.getTabBar()) {
        this.getTabBar().setData({
          selected: 0
    }
  },
  async newChatRoomClick(isLoading = true) {
    const res = await CreateHistoryGroup({
      group_title: 'chat room',
    }, {
      isLoading: isLoading
    });
    const newRoom = {
      id: res.history_group_id,
      isInitial: true,
      title: 'chat room',
    };
    if (!this.data.chatRoomList) {
      this.data.chatRoomList = [newRoom];
    } else {
      this.data.chatRoomList.unshift(newRoom);
    }
    this.setData({
      chatRoomList: this.data.chatRoomList
    })
    await this.setActiveChatRoom(newRoom);
  },
  async getHistoryGroupData() {
    const res = await GetHistoryGroups();
    const resData = (res?.groups || []) as any[];
    // 按最晚时间到最早时间
    this.data.chatRoomList = wx.$_.orderBy(resData, ['create_time'], ['desc'])
      .map((item) => {
        return {
          id: item.group_id,
          title: item.group_title,
          createTime: item.create_time,
          isInitial: Number(item.chat_count) === 0,
        };
      });
    if (!this.data.chatRoomList || this.data.chatRoomList.length === 0 || !this.data.chatRoomList?.[0].isInitial) {
      await this.newChatRoomClick(false);
    } else {
      this.setActiveChatRoom(this.data.chatRoomList[0]);
      this.setData(
        {
          chatRoomList: this.data.chatRoomList
        }
      )
    }
  },
  onSendTextChange: function (e) {
    // this.setData({
    //   sendText:e.detail.value
    // })
  },
  scrollToBottom() {
    wx.nextTick(() => {
      setTimeout(() => {
        this.setData({
          toViewId: `chat-item-${this.data.chatHistory.length - 1}`,
        })
      }, 300);
    })
  },
  async getHistoryDetail() {
    const res = await QueryHistoryDetail({
      history_group_id: this.data.activeChatRoom.id,
    });
    this.setData({
      chatHistory: (res.details ?? []).map((item) => {
        return {
          historyId: item.history_id,
          role: RoleEnum.user,
          content: {
            type: AnswerType.Text,
            values: item.question,
          },
        }
      })
    })
    // currentSampleId = res?.details?.[0]?.sample_id;
    const sectionAIdMap = new Map();
    const resList: any[] = await Promise.all((res.details ?? []).map((item) => {
      sectionAIdMap.set(item.history_id, item.section_a_id)
      return getAnswerById(item.history_id)
    }));
    let i = 0;
    resList.map((item, index) => {
      const insertIndex = index + 1 + i;
      this.data.chatHistory.splice(
        insertIndex,
        0,
        item.answer === null ?
          null :
          {
            historyId: item.answer?.history_id,
            role: RoleEnum.assistant,
            content: parseContent(item.answer),
            state: item.answer_state,
            sectionAId: sectionAIdMap.get(item.answer.history_id)
          }
      );
      i++;
    });
    // 过滤为null的结果
    this.setData({
      chatHistory: this.data.chatHistory.filter(item => !!item)
    })
    this.scrollToBottom()
  },
  resetLastChatRoom() {
    const isInitial = this.data.activeChatRoom.isInitial;
    this.setData({
      sendText: isInitial ? '你是谁?' : '',
    })
  },
  async setActiveChatRoom(room) {
    if (!room) return;
    this.setData({
      activeChatRoom: room,
    })
    this.resetLastChatRoom();
    wx.setNavigationBarTitle({
      title: this.data.activeChatRoom.title
    })
    await this.getHistoryDetail();
  },
  async chatRoomClick(e) {
    const item = e.currentTarget.dataset.item;
    this.setData({
      drawerIsShow: false,
    })
    this.setActiveChatRoom(item)
  },
  delChatRoomClick(e) {
    const id = e.currentTarget.dataset.item.id;
    wx.modal({
      content: '确定删除当前聊天室吗?'
    }).then(async (val) => {
      if (!val) return;
      const res = await DeleteHistoryGroups({
        history_group_id: id,
      });
      if (!res?.json_ok) return;
      const foundIndex = this.data.chatRoomList.findIndex((item) => item.id === id);
      this.data.chatRoomList.splice(foundIndex, 1);
      if (this.data.chatRoomList.length === 0) {
        await this.newChatRoomClick();
      } else {
        this.setActiveChatRoom(this.data.chatRoomList[0]);
        this.setData({
          chatRoomList: this.data.chatRoomList
        })
      }
    })
  },
  // 聊天室图标点击
  chatRoomListClick() {
    this.setData({
      drawerIsShow: true,
    })
  },
  drawerCloseClick() {
    this.setData({
      drawerIsShow: false,
    })
  },
  onLoad(option) {
    const isPassed = checkAuth();
    if (!isPassed) return;
    this.getHistoryGroupData();
    this.getSampleList();
  },
  onShow() {
    this.setData({
      userName: getStorage('username')
    })
  },
  async onRouteDone() {
    const sectionAId = app.globalData.sectionAId;
    if (!sectionAId) {
      return;
    }
    this.setData(
      {
        section_a_id: sectionAId
      }
    )
    if (!this.data.activeChatRoom.isInitial) {
      try {
        await this.newChatRoomClick(false)
      } finally {
        wx.hideLoading();
      }
    }
    this.setData({
      sendText: app.globalData.sectionB.section_title
    })
    this.sendText();
    app.globalData.sectionAId = '';
    app.globalData.sectionB = null;
  },
  onShareAppMessage() {
    return wx.$_.defaults(SHARE_CONFIG, {
      // path: getCurrentUrl(),
    })
  }
  // pageLifetimes: {
  //   show() {
  //     if (typeof this.getTabBar === 'function' &&
  //       this.getTabBar()) {
  //       this.getTabBar().setData({
  //         selected: 0
  //       })
  //     }
  //   }
  // }
})