gerson
2024-08-11 b2b8e5ed16f139597b10452df0c467b6e7cde500
miniprogram/pages/question/question.ts
@@ -19,15 +19,18 @@
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 { ComponentWithComputed, } from "miniprogram-computed";
import { uuid } from "@/utils/uuid";
import { getStorage } from "@/utils/storage";
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;
@@ -103,7 +106,9 @@
ComponentWithComputed({
Page({
  // 页面的初始数据
  data: {
@@ -126,378 +131,417 @@
    sampleList: [],
    /** @description 随机抽出最多三个例子 */
    displaySampleList: [],
    section_a_id: '',
    sample_id: '',
    userName:getStorage('username'),
  },
  computed: {
    /** @description 发送文本还是发送语音 */
    isSendTextStatus(data) {
      return !!data.sendText
    },
    /** @description 当前是否为初始聊天室 */
    currentIsInitialChatRoom(data) {
      return data.activeChatRoom?.isInitial ?? false
  onClickClear(){
    console.log('clear');
    this.setData({
      sendText:''
    })
  },
  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({
        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 = '';
    }
    // 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;
  },
  methods: {
    async getSampleList() {
      const res = await getSelectSample({
        section_b_id: '',
      });
  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({
        sampleList: res?.samples ?? []
        activeChatRoom: this.data.activeChatRoom
      })
      this.setData({
        displaySampleList: wx.$_.sampleSize(this.data.sampleList, 3)
      })
    },
    sampleClick(e) {
      const item = e.currentTarget.dataset.item;
      this.setData({
        sendText: item.sample_question
      })
    },
    queryProcess() {
      processTimer = setInterval(() => {
        if (!finishProcess) return;
        finishProcess = false;
        this.queryProcessApi();
      }, QUERY_PROCESS_INTERVAL);
    },
    async queryProcessApi() {
      const res = await getQuestionProcess({
        process_id: processId,
      /** @description 修改聊天室名称 */
      const res = await setHistoryGroupTitle({
        history_group_id: this.data.activeChatRoom.id,
        title: this.data.sendText,
      }, {
        isLoading: false
      }).catch((err) => {
        this.setData({
          processText: err
        })
      });
      this.setData({
        processText: res.process
      if (!res?.json_ok) return;
      this.data.activeChatRoom.title = this.data.sendText;
      wx.setNavigationBarTitle({
        title: this.data.activeChatRoom.title
      })
      finishProcess = true;
    },
    clearQueryProcess() {
      this.setData({
        processText: ''
        chatRoomList: this.data.chatRoomList
      })
      clearInterval(processTimer);
    },
    async questionAi(text) {
      // if (!currentSectionId) {
      //   ElMessage.warning('发送失败,未确定应用场景!');
      // }
      processId = uuid();
      // const judgeParams = !preQuestion.value
      //   ? {}
      //   : {
      //       prev_question: preQuestion.value,
      //     };
      const judgeParams = {}
      const params = {
        process_id: processId,
        question: text,
        // FIXME: 暂时这样
        section_a_id: 'knowledge_base',
        history_group_id: this.data.activeChatRoom.id,
        raw_mode: false,
        ...judgeParams,
      } as any;
      // if (currentSampleId) {
      //   params.sample_id = currentSampleId;
      // }
    }
    try {
      // if (currentLLMId) {
      //   params.llm_id = currentLLMId;
      // }
      this.clearQueryProcess();
      this.queryProcess();
      const res = await QuestionAi(params, {
        isLoading: false
      }).finally(() => {
        this.clearQueryProcess();
      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
      })
      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 {
    }
  },
  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,
        };
      });
      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;
    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({
          activeChatRoom: this.data.activeChatRoom
          toViewId: `chat-item-${this.data.chatHistory.length - 1}`,
        })
        /** @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
        })
      }, 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();
  },
  async onRouteDone() {
    const sectionAId = app.globalData.sectionAId;
    if (!sectionAId) {
      return;
    }
    this.setData(
      {
        section_a_id:sectionAId
      }
    )
    if (!this.data.activeChatRoom.isInitial) {
      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
        })
        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) {
        await this.newChatRoomClick(false)
      } finally {
        this.setData({
          isTalking: false
        })
      }
    },
    inputRighBtnClick() {
      if (this.data.isSendTextStatus) {
        this.sendText();
      } else {
      }
    },
    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
      })
      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,
          };
        });
      console.log('this.data.chatHistory:  ', this.data.chatRoomList);
      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,
            },
          }
        })
      })
      // 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++;
      });
      this.setData({
        chatHistory: this.data.chatHistory
      })
      this.scrollToBottom()
    },
    resetLastChatRoom() {
      const isInitial = this.data.activeChatRoom.isInitial;
      this.setData({
        sendText: isInitial ? '你是谁?' : '',
      })
    },
    setActiveChatRoom(room) {
      if (!room) return;
      this.setData({
        activeChatRoom: room,
      })
      this.resetLastChatRoom();
      wx.setNavigationBarTitle({
        title: this.data.activeChatRoom.title
      })
      this.getHistoryDetail();
    },
    chatRoomClick(e) {
      const item = e.currentTarget.dataset.item;
      this.setActiveChatRoom(item)
      this.setData({
        drawerIsShow: false,
      })
    },
    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,
      })
    }
  },
  lifetimes: {
    async attached() {
      const isPassed = checkAuth();
      if (!isPassed) return;
      this.getHistoryGroupData();
      this.getSampleList();
    }
  },
  pageLifetimes: {
    show() {
      if (typeof this.getTabBar === 'function' &&
        this.getTabBar()) {
        this.getTabBar().setData({
          selected: 0
        })
        wx.hideLoading();
      }
    }
    this.setData({
      sendText: app.globalData.sectionB.section_title
    })
    this.sendText();
    app.globalData.sectionAId = '';
    app.globalData.sectionB = null;
  }
  // pageLifetimes: {
  //   show() {
  //     if (typeof this.getTabBar === 'function' &&
  //       this.getTabBar()) {
  //       this.getTabBar().setData({
  //         selected: 0
  //       })
  //     }
  //   }
  // }
})