<template>
  <div class="chat bg-white">
    <div class="flex flex-col items-center justify-start h-screen"
      style="height: 100vh; height: calc(var(--vh, 1vh) * 100);">
      <!-- <img class="absolute h-full" :src="baseApi + info.picture" alt=""> -->
      <div class="top bg-white px-2 flex justify-between">
        <el-button class="tm_button" type="info" icon="el-icon-arrow-left" circle @click="goBack"></el-button>
        <div v-if="sceneId" class=" text-sm" style="max-width: 50%;">已进入场景：{{ sceneInfo.sceneName }}</div>
        <div class="flex">
          <el-button class="tm_button" type="info" circle>
            <i class="fa-solid fa-volume-high text-sm"></i>
            <!-- <i class="fa-solid fa-volume-xmark text-sm"></i> -->
          </el-button>
          <el-dropdown trigger="click" @command="rtHandleCommand">
            <el-button class="tm_button ml-2" type="info" icon="el-icon-more" circle></el-button>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item command="1" icon="el-icon-warning-outline">查看详情</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </div>
      </div>
      <audio ref="audio" muted v-show="false" :src="audioUrl" autoplay="" @ended="audioEnd" controls></audio>
      <div class="chatContent" :style="`background-image: url(${baseApi + sceneInfo.background})`">
        <!-- <div class="leftImg">
          <img :src="baseApi + info.picture" alt="">
          <div class="aiInfo">
            <span class="photo">
              <img :src="baseApi + info.picture">
            </span>
            <div class="info">
              <div class="name">{{ info.characterName }}</div>
              <div class="tags">
                <span class="tag" v-for="(item, index) in info.labelArr" :key="index">
                  {{ item }}
                </span>
              </div>
              <div class="infoContent">{{ info.prologue }}</div>
            </div>
          </div>
        </div> -->
        <div class="chat-box relative " :class="sceneId && 'mask'">
          <div class="messages" ref="messages">
            <template v-for="(item, index) in returnMessage ">
              <div v-if="item.role == 'assistant'" class="text-white mb-4 flex" :key="index">
                <!-- ai返回的信息 -->
                <div class="pt-2 photo">
                  <img :src="baseApi + info.picture" class="rounded-full w-12 h-12 object-cover" @click="toDetail"
                    @error="$AIPohotoError" />
                </div>
                <div class="message fex-1 ml-2 mt-3 p-2 rounded-r-md rounded-bl-md text-base">
                  <div v-show="!item.content" class="loadingMessage">
                    <div v-loading="!item.content" element-loading-background="rgba(0, 0, 0, 0.0)"></div>
                  </div>
                  <p style="white-space: pre-line;" v-show="item.content">{{ item.content }} </p>
                </div>
              </div>
              <!-- 用户发送的信息 -->
              <div v-if="item.role == 'user'" class="text-white mb-4 flex me" :key="index">
                <div class="pt-2 photo">
                  <img src="@/assets/images/default_avatar_user.png" @error="$userPohotoError"
                    class="rounded-full w-12 h-12 object-cover" />
                </div>
                <div class="message2 fex-1 mr-2 mt-3 p-2 rounded-l-md rounded-br-md text-base">
                  <p>{{ item.content }}</p>
                </div>
              </div>
            </template>
          </div>
        </div>
      </div>
      <div class="fixed bottom-0 bg-white w-full px-2 pt-2 pb-4 border-t border-gray-100">
        <!-- <div class="flex items-center text-gray-400 text-xs mb-4 ">
          <span>@Leon S Kennedy - Resident Evil</span>
        </div> -->
        <div class="flex">
          <el-button class="bgColor1 mButton" @click="showBottomPopup = true" style="margin-right: 5px;" type="primary"
            round icon="el-icon-plus"></el-button>
          <input type="text" placeholder="输入消息..." class="flex-1 py-2 px-4 rounded-l-lg text-sm focus:outline-none"
            style="background: #ffffff0f; border: 1px solid #5b5b5e;" v-model="content" @keydown="Enterkey" />
          <button @click.prevent="getStreamChatWithWeb" class="bgColor1 text-white px-4 rounded-r-lg text-sm"
            style="width: 60px;">
            发送
          </button>
        </div>
      </div>
      <el-dialog :visible.sync="showBottomPopup" :show-close="false" width="100%" class="phoneBottomPopup">
        <transition name="el-zoom-in-bottom">
          <div class="popupContent popup1" v-show="showBottomPopup">
            <div class="configForm w-full flex flex-col overflow-y-auto" style="height: calc(100% - 75px)">
              <div class="row">
                <p class="text-base mt-3">选择模型</p>
                <p class="text-sm text-gray-200">每个模型可能有不同的效果，仅对当前对话有影响</p>
                <div class="flex items-start py-3 border-b border-gray-200">
                  <el-radio-group class="radio" v-model="configForm.radio2" @input="formModelChange">
                    <el-radio-button v-for="(item, index) in modelList" :key="index" :label="item.id">{{ item.model
                    }}</el-radio-button>
                  </el-radio-group>
                </div>
              </div>
            </div>
            <div class="bottom px-2">
              <div v-if="!sceneId" class="button text-white" @click="() => {
                this.showBottomPopup = false
                this.newStart()
              }
                ">
                <i class="icon iconfont icon-xinduihua"></i>
                <div>新的对话</div>
              </div>
              <div v-if="sceneId" class="button text-white" @click="() => {
                this.showBottomPopup = false
                this.handleCommand3(2)
              }
                ">
                <i class="icon iconfont icon-xinduihua"></i>
                <div>新建场景对话</div>
              </div>
              <div v-if="sceneId" class="button text-white" @click="() => {
                this.showBottomPopup = false
                this.handleCommand3(3)
              }
                ">
                <i class="icon iconfont icon-xinduihua"></i>
                <div>返回常规对话</div>
              </div>
              <div class="button text-white" @click="() => {
                this.showBottomPopup = false
                this.showHistory()
              }
                ">
                <i class="icon iconfont icon-lishi"></i>
                <div>历史对话</div>
              </div>
            </div>
          </div>
        </transition>
      </el-dialog>
      <el-dialog :visible.sync="showBottomPopup2" :show-close="false" width="100%" class="phoneBottomPopup">
        <transition name="el-zoom-in-bottom">
          <div class="popupContent popup2" v-show="showBottomPopup2">
            <div class=" w-full text-center py-2 text-base font-semibold">历史对话</div>
            <div class="historyRow py-2 cursor-pointer" v-for="( item, index ) in  historyList " :key="index" @click="() => {
              showBottomPopup2 = false
              clickDialogue(jsHistory, item, index)
            }
              ">
              <div class="flex justify-between">
                <div class="name text-base">{{ item.chatTitle }}</div>
                <div class="time">{{ item.createTime }}</div>
              </div>
              <!-- <div class="info">
                {{ item. }}
              </div> -->
            </div>
          </div>
        </transition>
      </el-dialog>
    </div>
  </div>
</template>

<script>
import Cookies from 'js-cookie'
import {
  streamChatWithWebApi,
  getGuidanceApi,
  getModelListApi,
  addChatApi,
  getChatCharacterRecordsApi,
  getChatRecordApi,
  updateTitleApi,
  clearRecordApi,
  queryVoiceListApi,
  updateRecordApi,
  deleteRecordApi
} from "@/api/chat.js"
import { detailApi } from "@/api/detail.js"
import { queryUserBalanceApi } from "@/api/user.js"
import { Message, MessageBox, Notification, Loading } from 'element-ui'
import 'vue-awesome/icons/paper-plane'
import 'vue-awesome/icons/fire'

export default {
  components: {
  },
  data() {
    return {
      // 对话请求超时参数
      timeOut: null,
      showBottomPopup: false,
      showBottomPopup2: false,
      jsHistory: null,
      historyList: [],
      // 聊天等待
      chatLoading: false,
      // 是否全屏
      fullScreen: false,
      // 角色所有聊天列表
      allRecords: [],
      // 聊天记录id
      recordId: null,
      // 选中的角色聊天记录
      historyRes: [],
      recordsIndex: null,
      showDetail: true,
      showConfig: false,
      messageOptions: [],
      info: {},
      messageLoading: false,
      returnMessage: [],
      content: '',
      audioPlayIndex: null,
      configForm: {
        radio1: null,
        radio2: null,
        radio3: null,
      },
      // 对话接口是否返回错误状态
      resError: false,
      // 模型列表
      modelList: [],
      setting: {
        value1: false,
        value2: false,
      },
      //音频相关↓
      //音频地址
      audioUrl: '',
      audioUrlArr: [],
      audioUrlArrIndx: 0,
      videoLoop: null,
      videoLoopTime: 0,
      loopPlay: false,
      //场景下拉菜单
      dropdown3Show: false,
      // 场景对话相关
      sceneId: null,
      sceneInfo: {},
    }
  },
  computed: {
    canChat() {
      console.log(this.info, 'this.info');
      if (!this.sceneId) {
        if (this.info.isDelete == 1) {
          console.log(1);
          return false
        } else {
          console.log(2);
          return true
        }
      } else {
        if (this.sceneInfo.isDelete == 1) {
          return false
        } else {
          return true
        }
      }
    },
    notChatSend() {
      console.log(this.audioPlayIndex, 'this.audioPlayIndex>>>>>>>>>>>');
      // 对话结束切语音已经播放完毕
      // return this.chatLoading != false || this.audioPlayIndex != null
      return this.chatLoading != false
    },
    showNodata() {
      return this.allRecords.length == 0 && !this.$route.query.characterId
    }
  },
  mounted() {
    this.init()
  },
  watch: {
    returnMessage: {
      handler(newVal, lodVal) {
        this.$nextTick(() => {
          let messages = this.$refs.messages
          messages.scrollTop = messages.scrollHeight
        })
      },
      deep: true
    }
  },
  methods: {
    async init() {
      // 获取模型列表
      this.getModelList()
      // 获取用户所有聊天记录
      await this.getChatCharacterRecords()
      // 如果用角色id获取角色详情
      if (this.$route.query.characterId) {
        if (this.$route.query.sceneId) {
          this.sceneId = this.$route.query.sceneId
        }
        await this.getDetail(this.$route.query.characterId)
      } else {
        this.allRecords[0].open = true
        await this.getDetail(this.allRecords[0].id)
      }
      // 查找当前角色是否有对话记录
      this.searchHistory(this.info.id)
    },
    rtHandleCommand(value) {
      // console.log(value);
      if (value == 1) {
        this.toDetail()
      }
    },
    toDetail() {
      this.$router.push({
        path: '/detailH5',
        query: {
          id: this.info.id
        }
      })
    },
    // 显示历史聊天记录
    showHistory() {
      this.showBottomPopup2 = true
    },

    formModelChange() {
      // 在浏览器缓存用户的配置
      Cookies.set(`userConfig_${this.$store.state.user.userId}_${this.info.id}`, JSON.stringify(this.configForm))
    },
    // 全屏
    clickFullScreen() {
      this.fullScreen = !this.fullScreen
    },
    // 点击聊天记录切换聊天
    async clickDialogue(value1, value2, index) {
      console.log(value2, 'value2');
      let _this = this
      this.audioUrl = ""
      this.messageOptions = []
      this.returnMessage = []
      if (this.$route.query.characterId) {
        this.$route.query.characterId = value1.id
      }
      if (!value2) {
        return
      }
      // 如果点击的是场景聊天
      if (value2.sceneId) {
        this.sceneId = value2.sceneId
        await this.getDetail(value1.id)
        // 从角色详情中获取场景列表
        let sceneList = this.info.sceneList
        // 获取当前聊天对应的场景
        for (let i = 0; i < sceneList.length; i++) {
          const element = sceneList[i];
          if (element.sceneId == value2.sceneId) {
            _this.sceneInfo = element
          }
        }
      } else {
        this.sceneId = null
        this.sceneInfo = {}
        await this.getDetail(value1.id)
      }

      this.recordId = value2.id
      this.getChatRecord(value2.id)
      this.recordsIndex = index
    },
    // 场景下拉菜单
    handleCommand3(value) {
      if (value == 1) {
      } else if (value == 2) {
        // 清空聊天记录
        this.returnMessage = []
        // 新建场景对话
        this.newStart()
        // 增加开场白
        this.returnMessage.push({
          role: 'assistant',
          content: this.sceneInfo.sceneWelcome
        })
      } else if (value == 3) {
        // 回到常规对话
        // 遍历当前聊天记录是否有常规对话
        let messages = null
        for (let i = 0; i < this.allRecords.length; i++) {
          const element = this.allRecords[i];
          if (element.id == this.info.id) {
            messages = element
          }
        }
        console.log(messages, 'messages');
        let flag = false
        for (let i = 0; i < messages.chatCharacterList.length; i++) {
          const element = messages.chatCharacterList[i];
          if (!element.sceneId) {
            flag = true
            this.clickDialogue(messages, element, i)
            break
          }
        }
        // 如果聊天记录里没有常规对话，则新增一个常规对话
        if (!flag) {
          this.sceneId = null
          this.sceneInfo = {}
          this.newStart()
        }
      }
    },
    // 聊天记录列表-角色下拉菜单
    handleCommand2(value, value1) {
      if (value == 2) {
        this.$confirm('此操作将永久删除该角色所有聊天记录, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.clearRecord(value1)
        })
      }
    },
    // 聊天记录列表-角色-聊天记录下拉菜单
    handleCommand(value, value1, value2) {
      console.log(value, 'value');
      if (value == 1) {
        this.editDialogueTitle(value1, value2)
      } else if (value == 2) {
        this.$confirm('此操作将永久删除该聊天记录, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.clearRecord(value1, value2)
        })
      }
    },
    // 聊天记录操作相关↓
    handleCommand4(value1, value2, value3) {
      console.log(value1, 'value1');
      console.log(value2, 'value2');
      if (value1 == 1) {
        // 编辑
        let height = this.$refs[`message${value3}`][0].offsetHeight
        let width = this.$refs[`message${value3}`][0].offsetWidth

        value2.edit = true
        this.$nextTick(() => {
          this.$refs[`messageEditInput${value3}`][0].$el.children[0].style.height = height + 'px'
          this.$refs[`messageEdit${value3}`][0].style.width = width + 'px'
        })
      } else if (value1 == 2) {
        // 删除
        this.$confirm('此操作将永久删除该聊天记录, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.deleteRecord(value2, value3)
        })
      } else if (value1 == 3) {
        // 重新生成最后一句对话
        this.resetChat(value2, value3)
      }
    },
    // 重新生成最后一条聊天记录
    resetChat(value, index) {
      let params = {
        recordId: value.id,
        role: value.role,
      }
      deleteRecordApi(params).then(res => {
        this.returnMessage.splice(index, 1)
        this.getStreamChatWithWeb()
      })
    },
    // 编辑单条聊天记录-取消
    editCancel(value, index) {
      value.edit = false
      value.editContent = value.content
    },
    // 编辑单条聊天记录-保存
    editSave(value, index) {
      console.log(value, 'value');
      let params = {
        content: value.editContent,
        recordId: value.id,
        role: value.role,
      }
      updateRecordApi(params).then(res => {
        console.log(res, 'ressss');
        value.edit = false
        this.getChatRecord(this.recordId)
      })

    },
    // 删除单条聊天记录
    deleteRecord(value, index) {
      let params = {
        recordId: value.id,
        role: value.role,
      }
      deleteRecordApi(params).then(res => {
        this.$message({
          message: '删除成功',
          type: 'success'
        });
        this.getChatRecord(this.recordId)
      })
    },

    // 聊天记录新增对话
    async newStart_juese(value) {
      console.log(value, 'value');
      this.audioUrl = ""
      this.sceneId = null
      this.sceneInfo = {}
      this.messageOptions = []
      this.returnMessage = []
      // 点击聊天记录切换聊天
      if (this.$route.query.characterId) {
        this.$route.query.characterId = value.id
      }
      await this.getDetail(value.id)
      this.recordId = await this.addChat()
      for (let i = 0; i < this.allRecords.length; i++) {
        const element = this.allRecords[i];
        if (element.id == this.info.id) {
          element.chatCharacterList.push({
            chatTitle: "常规聊天",
            createTime: '',
            id: this.recordId
          })
          this.recordsIndex = element.chatCharacterList.length - 1
        }
      }
    },
    // 修改聊天记录标题
    editDialogueTitle(value1, value2) {
      this.$prompt('新标题名称', '修改标题', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
      }).then(({ value }) => {
        let params = {
          chatTitle: value,
          id: value2.id
        }
        updateTitleApi(params).then(res => {
          console.log(res, '修改标题');
          this.$message({
            type: 'success',
            message: '修改成功!'
          });
          this.getChatCharacterRecords()
        })
      })
    },
    clearRecord(value1, value2) {
      let params = {
        characterId: value1.id,
      }
      if (value2) {
        params.recordId = value2.id
      }
      clearRecordApi(params).then(res => {
        this.$message({
          type: 'success',
          message: '删除成功!'
        });
        this.getChatCharacterRecords()
      })
    },
    async getChatRecord(recordId) {
      let params = {
        characterId: this.info.id,
        recordId: recordId
      }
      getChatRecordApi(params).then(res => {
        console.log(res, '查询到的聊天记录');
        let array = res.data
        // this.returnMessage
        this.historyRes = res.data
        if (this.returnMessage.length > 1) {
          this.returnMessage = this.returnMessage.splice(0, 1)
        }
        for (let i = 0; i < array.length; i++) {
          const element = array[i];
          let history = JSON.parse(element.history)
          history.map(item => {
            item.id = element.id
            item.uuid = element.uuid
            item.edit = false
            item.editContent = item.content
            if (item.role == 'assistant') {
              item.voiceFilePosition = element.voiceFilePosition
            }
          })
          this.returnMessage = [...this.returnMessage, ...history]
        }
        this.configForm.radio2 = this.modelList[0].id
        this.modelList.map(item => {
          if (item.id == array[array.length - 1].modelId) {
            this.configForm.radio2 = item.id
          }
        })
      })
    },
    searchHistory(characterId) {
      // 查看对话记录是否有选中的角色
      // console.log('查看对话记录是否有选中的角色');
      let flg = false
      for (let i = 0; i < this.allRecords.length; i++) {
        const element = this.allRecords[i];
        // 如果有则选中角色的最新一条记录并获取对话聊天记录
        if (element.id == characterId) {
          // 当前角色的聊天记录列表
          this.historyList = element.chatCharacterList
          this.jsHistory = element
          console.log(element, '查看对话记录是否有选中的角色');
          flg = true
          element.open = true
          // 二级对话判断当前是普通对话还是场景对话
          // 取对应的最后一条消息记录
          let chatCharacterList = element.chatCharacterList
          let chatCharacter = null
          let index = null
          for (let i = 0; i < chatCharacterList.length; i++) {
            const element2 = chatCharacterList[i];
            if (this.$route.query.sceneId == element2.sceneId) {
              chatCharacter = element2
              index = i
              break;
            } else if (!this.$route.query.sceneId && !element2.sceneId) {
              chatCharacter = element2
              index = i
              break;
            }
          }
          // 如果有聊天记录则点击
          if (chatCharacter) {
            this.clickDialogue(element, chatCharacter, index)
          } else {
            // 如果没有场景聊天记录则新增场景聊天
            // 从角色详情中获取场景列表
            let sceneList = this.info.sceneList
            // 获取当前聊天对应的场景
            for (let i = 0; i < sceneList.length; i++) {
              const element = sceneList[i];
              if (element.sceneId == this.$route.query.sceneId) {
                this.sceneInfo = element
              }
            }
          }
          // this.recordsIndex = element.chatCharacterList.length - 1
          // let recordId = element.chatCharacterList[element.chatCharacterList.length - 1].id
          // this.recordId = recordId
          // this.getChatRecord(recordId)
        }
      }
      // 如果没有聊天记录，则增加开场聊天引导
      if (!flg) {
        this.getGuidance(this.info.id)
      }
    },
    async getChatCharacterRecords() {
      let res = await getChatCharacterRecordsApi()
      console.log(res, '聊天记录');
      if (res.data) {
        for (let i = 0; i < res.data.length; i++) {
          const element = res.data[i];
          if (this.info.id == element.id) {
            element.open = true
          } else {
            element.open = false
          }
        }
        this.allRecords = res.data
      }
    },
    // 新增对话记录
    async addChat() {
      let params = {
        characterId: this.info.id,
        chatTitle: ""
      }
      if (this.sceneId) {
        params.sceneId = this.sceneId
      }
      let res = await addChatApi(params)
      console.log(res, '新增对话记录');
      return res.data
    },
    getModelList() {
      getModelListApi().then(res => {
        console.log(res, '模型列表');
        this.modelList = res.data
      })
    },
    inputBoxClick() {
      this.$refs.input.focus()
    },
    async getDetail(id) {
      let res = await detailApi(id)
      console.log(res, '角色详情');
      this.info = res.data
      // 模型选中角色默认模型
      this.configForm.radio2 = this.info.modelId
      // 如果用户有设置过模型使用用户设置模型
      let userConfig = Cookies.get(`userConfig_${this.$store.state.user.userId}_${this.info.id}`)
      if (userConfig) {
        userConfig = JSON.parse(userConfig)
      }
      if (userConfig && userConfig.radio2) {
        this.configForm.radio2 = userConfig.radio2
      }
      // let HistoryMessage = JSON.parse(localStorage.getItem(`[userId:${123},aiId:${this.info.id}]`));
      // if (HistoryMessage) {
      //   this.returnMessage = HistoryMessage
      // } else {
      //   this.returnMessage.push({
      //     role: 'assistant',
      //     content: this.info.firstContent
      //   })
      //   localStorage.setItem(`[userId:${123},aiId:${this.info.id}]`, JSON.stringify(this.returnMessage));
      // }
      if (this.sceneId) {
        console.log(this.sceneId);
        let sceneList = this.info.sceneList
        for (let i = 0; i < sceneList.length; i++) {
          const element = sceneList[i];
          if (element.sceneId == this.sceneId) {
            this.sceneInfo = element
            this.configForm.radio2 = element.modelId
            this.returnMessage.push({
              role: 'assistant',
              content: element.sceneWelcome
            })
          }
        }
      } else {
        this.returnMessage.push({
          role: 'assistant',
          content: this.info.firstContent
        })
      }
    },
    getGuidance(id) {
      getGuidanceApi(id).then(res => {
        console.log(res, '聊天引导');
        this.messageOptions = res.data
      })
    },
    goBack() {
      this.$router.back()
    },
    async newStart() {
      // 新业务，创建一个新的对话记录
      this.recordId = await this.addChat()
      for (let i = 0; i < this.allRecords.length; i++) {
        const element = this.allRecords[i];
        if (element.id == this.info.id) {
          if (this.sceneId) {
            element.chatCharacterList.push({
              chatTitle: "场景聊天",
              createTime: '',
              id: this.recordId,
              sceneIcon: true
            })
          } else {
            element.chatCharacterList.push({
              chatTitle: "常规聊天",
              createTime: '',
              id: this.recordId
            })
          }
          this.recordsIndex = element.chatCharacterList.length - 1
        }
      }

      this.returnMessage = []
      this.getDetail(this.info.id)
      // 废弃》》
      // 清空历史数据
      // localStorage.removeItem(`[userId:${123},aiId:${this.info.id}]`);
      // this.returnMessage = []
      // this.getDetail(this.info.id)
    },
    Enterkey(e) {
      if (e.keyCode == 13) {
        console.log(this.notChatSend, 'this.notChatSend');
        if (this.notChatSend) {
          return
        }
        if (!this.content) {
          return
        }
        this.getStreamChatWithWeb()
      }
    },
    // 前往创建场景
    toCreateScene() {
      this.$router.push({
        name: 'CreateScene',
        query: {
          characterId: this.info.id,
        }
      })
    },
    async getStreamChatWithWeb_old() {
      this.messageLoading = true
      if (!this.content) {
        return
      }
      this.returnMessage.push({
        role: 'user',
        content: this.content
      })
      let HistoryMessage = JSON.parse(localStorage.getItem(`[userId:${123},aiId:${this.info.id}]`));
      // 历史记录取最新的20条传给后端
      if (HistoryMessage && HistoryMessage.length > 20) {
        HistoryMessage = HistoryMessage.slice(HistoryMessage.length - 1, 20)
      }
      let params = {
        historyMessage: HistoryMessage || [],
        characterId: this.info.id,
        prompt: JSON.parse(JSON.stringify(this.content))
      }
      // 清空输入框的值
      this.content = ''
      // 新增一条ai信息
      this.returnMessage.push({
        role: 'assistant',
        content: ''
      })
      let res = await streamChatWithWebApi(params)
      console.log(res.data.message.content, 'res');
      let content = res.data.message.content
      let index = 0
      let xing = 1
      let messageInterval = setInterval(() => {
        if (index > content.length - 1) {
          console.log('结束');
          // 消息全部显示后存到历史localStorage
          let HistoryMessage = []
          // 历史只存100条，长度超出截取最新的
          if (this.returnMessage.length > 100) {
            HistoryMessage = JSON.stringify(this.returnMessage.slice(this.returnMessage.length - 100, 100))
          } else {
            HistoryMessage = JSON.stringify(this.returnMessage)
          }
          localStorage.setItem(`[userId:${123},aiId:${this.info.id}]`, HistoryMessage);

          clearInterval(messageInterval)
          return
        }
        console.log(content[index], 'content[index]');
        if (content[index] == "*") {
          if (xing == 1) {
            xing = 2
            this.returnMessage[this.returnMessage.length - 1].content += "("
          } else if (xing == 2) {
            xing = 1
            this.returnMessage[this.returnMessage.length - 1].content += ")"
          }
        } else {
          this.returnMessage[this.returnMessage.length - 1].content += content[index]
        }
        index += 1
      }, 50)
    },
    async getStreamChatWithWeb() {
      if (this.chatLoading) {
        return
      }
      this.audioUrl = []
      this.audioUrlArrIndx = 0
      this.textCache = ''
      this.resError = false
      this.messageLoading = true
      this.chatLoading = true
      // 初始化定时器和audio的状态
      if (this.videoLoop) {
        clearInterval(this.videoLoop)
        this.videoLoop = null
        this.audioUrl = ''
        this.$refs.audio.currentTime = 0;
        this.$refs.audio.pause()
      }
      // 如果没有对话记录id，新增对话记录
      if (!this.recordId) {
        this.recordId = await this.addChat()
      }
      if (this.content) {
        this.returnMessage.push({
          role: 'user',
          content: this.content
        })
      }
      let HistoryMessage = JSON.parse(JSON.stringify(this.returnMessage))
      console.log(HistoryMessage, 'HistoryMessage1');
      HistoryMessage = HistoryMessage.splice(1, HistoryMessage.length)
      console.log(HistoryMessage, 'HistoryMessage2');
      // 历史记录取最新的20条传给后端
      if (HistoryMessage && HistoryMessage.length > 20) {
        HistoryMessage = HistoryMessage.slice(HistoryMessage.length - 1, 20)
      }
      let params = {
        historyMessage: HistoryMessage,
        characterId: this.info.id,
        prompt: this.content,
        modelId: this.configForm.radio2,
        recordId: this.recordId,
      }
      // 如果当前是场景对话则需要传sceneId
      if (this.sceneId) {
        params.sceneId = this.sceneId
      }
      // 新增一条ai信息
      this.returnMessage.push({
        role: 'assistant',
        content: '',
        voiceFilePosition: '',
      })

      // 清空输入框的值
      this.content = ''
      this.timeOut = 'start'
      let res = await streamChatWithWebApi(params)
      console.log(res, 'res');
      this.messageLoading = false

      if (res.status != 200) {
        this.$message.error(res.statusText)
        this.returnMessage.splice(this.returnMessage.length - 1, 2)
        this.chatLoading = false
        return
      }
      const reader = res.body.getReader()
      const decoder = new TextDecoder()
      while (1) {
        const { done, value } = await reader.read()
        // console.log(done, 'done');
        if (done) {
          console.log(value, '结束value');
          this.chatLoading = false
          // if (typeof(value) == "undefined") {
          //   this.$message.error('错误')
          //   this.returnMessage.splice(this.returnMessage.length - 1, 1)
          // }
          // 每次对话完刷新聊天记录
          this.getChatCharacterRecords()
          let params = {
            characterId: this.info.id,
            recordId: this.recordId
          }
          let historyRes = await getChatRecordApi(params)
          this.historyRes = historyRes.data
          // 如果开启自动播放，则查询并播放语音
          // this.audioUrl = ""
          // if (!this.resError) {

          // }
          console.log('结束');
          if (this.timeOut) {
            clearTimeout(this.timeOut)
            this.timeOut = null
          }
          break;
        }
        //txt就是一个一个的字 然后添加到页面上就可以了
        const txt = decoder.decode(value).split('data:')
        // const txt = decoder.decode(value)
        if (this.timeOut) {
          clearTimeout(this.timeOut)
          this.timeOut = setTimeout(() => {
            this.returnMessage[this.returnMessage.length - 1].content = 'AI智能累得打起了小盹儿，咱们让他缓一缓，再来试试！'
            this.chatLoading = false
          }, 10000)
        }
        // console.log(txt, 'txt');
        this.addMessage(txt)
        // let data = JSON.parse(txt).message.content
        // console.log(txt, 'txt');
        // if (this.isJSON(txt) && JSON.parse(txt).code != 200) {
        //   let data = JSON.parse(txt)
        //   this.$message.error(data.msg)
        //   this.returnMessage.splice(this.returnMessage.length - 1, 1)
        //   break;
        // }
      }
    },
    addMessage(text) {
      for (let i = 0; i < text.length; i++) {
        const element = text[i];
        if (this.isJSON(element)) {
          let value = JSON.parse(element)
          if (value.code == 401) {
            this.returnMessage.splice(this.returnMessage.length - 1, 1)
            this.noLogin(element)
            this.chatLoading = false
            break;
          }
          if (value.code == 500) {
            // console.log(value, 'JSON.parse(element)');
            this.returnMessage.splice(this.returnMessage.length - 2, 2)
            // this.$message.error(value.content || 'AI智能没有理解你的意思，换个说法试试吧！')
            this.returnMessage[this.returnMessage.length - 1].content = 'AI智能可能没有理解你的意思，换个说法试试吧！'
            this.resError = true
            this.chatLoading = false
            break;
          }
          // 获取语音id
          if (value.code == -1) {
            this.returnMessage[this.returnMessage.length - 1].uuid = value.content
            // 如果开启了自动播放开始轮巡查询语音
            if (this.setting.value1) {
              this.audioUrlArrIndx = 0
              this.videoLoopTime = 0
              this.audioUrlArr = []
              this.loopPlay = false
              this.audioPlayIndex = this.returnMessage.length - 1
              this.loopGetVoice(value.content, this.returnMessage.length - 1)
            }
            break;
          }
          if (!value.done) {
            let txt = value.content
            this.returnMessage[this.returnMessage.length - 1].content += txt
          } else {
            // 对话流结束
            // 临时插入的ai对话记录和用户记录插入聊天id
            this.returnMessage[this.returnMessage.length - 1].id = value.content
            this.returnMessage[this.returnMessage.length - 2].id = value.content
          }
        }
      }
    },
    noLogin(value) {
      let _this = this
      MessageBox.confirm(
        value.content,
        "系统提示",
        {
          confirmButtonText: "前往登录",
          cancelButtonText: "取消",
          type: "warning",
        }
      )
        .then(() => {
          // isRelogin.show = false;
          this.$store.dispatch("LogOut").then(() => {
            // location.href = "/";

            _this.$refs.Header.showLogin()
          });
        })
        .catch(() => {
          // isRelogin.show = false;
        });
    },
    isJSON(str) {
      if (typeof str == 'string') {
        try {
          JSON.parse(str);
          return true;
        } catch (e) {
          // console.log(e);
          return false;
        }
      }
    },
    messageOptionClick(value) {
      this.content = value
      this.getStreamChatWithWeb()
    },
    // 播放聊天语音
    initAudio(index) {
      // 从聊天记录获取id
      console.log(this.returnMessage[index], 'swssssssss');
      let id = this.returnMessage[index].id
      let history = this.historyRes.map((item) => {
        if (item.id == id) {
          return item
        }
      })
      console.log(history, 'history');
      return

      this.loopGetVoice(history.id, index)
    },
    playAudio(index) {
      if (index) {
        this.audioPlayIndex = index
      }
      // this.audioUrlArrIndx = 0
      console.log(this.audioUrlArrIndx, 'this.audioUrlArrIndx');
      console.log(this.audioUrlArr, 'this.audioUrlArr');
      // console.log(audioUrlArr[this.audioUrlArrIndx].voiceAddress, 'audioUrlArr[this.audioUrlArrIndx].voiceAddress');
      // 如果当前播放的语音地址为空，则等待2秒后重新获取
      if (!this.audioUrlArr[this.audioUrlArrIndx].voiceAddress && this.videoLoopTime <= 50) {
        setTimeout(() => {
          this.playAudio(index)
        }, 2000)
        return
      }
      // 如果当前播放的语音地址为false，则跳过当前语音
      if (this.audioUrlArr[this.audioUrlArrIndx].voiceAddress == 'false' && this.audioUrlArrIndx < this.audioUrlArr.length - 1) {
        this.audioUrlArrIndx += 1
        this.playAudio(index)
        return
      } else if (this.audioUrlArrIndx > this.audioUrlArr.length - 1) {
        this.audioUrl = ''
        this.audioUrlArrIndx = 0
        this.videoLoopTime = 0
        this.audioUrlArr = []
        return
      }
      this.audioUrl = this.audioUrlArr[this.audioUrlArrIndx].voiceAddress
      console.log(this.audioUrl, 'this.audioUrl');
      setTimeout(() => {

        if (this.audioUrl) {
          this.$refs.audio.play()
        }
      }, 1000)
    },
    async historyGetVoice(value, index) {
      console.log(value, 'value');
      if (!value.uuid) {
        return
      }
      let params = {
        uuid: value.uuid
      }
      let fileRes = await queryVoiceListApi(params)
      console.log(fileRes.data, 'file>>>');
      this.audioUrlArr = fileRes.data.voices
      this.audioUrlArrIndx = 0
      this.videoLoopTime = 0
      this.loopPlay = false
      this.playAudio(index)
    },
    async loopGetVoice(id, index) {
      this.videoLoopTime += 1
      // 获取语音文件
      let params = {
        uuid: id
      }
      let fileRes = await queryVoiceListApi(params)
      console.log(fileRes.data, 'file>>>');
      let voices = fileRes.data.voices
      let _continue = fileRes.data.continue
      this.apiHaveVideo = _continue
      // 判断语音文件是否获取完毕
      let trueLength = 0
      for (let i = 0; i < voices.length; i++) {
        const element = voices[i];
        if (element.voiceAddress) {
          trueLength += 1
        }
      }
      if (!_continue && trueLength == voices.length) {
        if (this.videoLoop) {
          clearTimeout(this.videoLoop)
          this.videoLoop = null
        }
        // this.returnMessage[index].voiceFilePosition = fileRes.data.voiceFilePosition
        // 有语音文件则开始播放
        if (voices.length > 0) {
          this.audioUrlArr = voices
          console.log(this.audioUrlArr, '进入播放流程1');
          if (this.$refs.audio.paused || this.audioUrlArrIndx > this.audioUrlArr.length - 1) {
            if (this.loopPlay == false) {
              this.playAudio(index)
              this.loopPlay = true
            }
          }
        }
      } else {
        if (voices.length > 0) {
          this.audioUrlArr = voices
          console.log(this.audioUrlArr, '进入播放流程2');
          if (this.$refs.audio.paused || this.audioUrlArrIndx > this.audioUrlArr.length - 1) {
            if (this.loopPlay == false) {
              this.playAudio(index)
              this.loopPlay = true
            }
          }
        }
        // 没有语音文件则开启定时器每两秒查询一次
        if (this.videoLoopTime > 50) {
          // 如果调用次数超过30次则停止
          return
        }
        this.videoLoop = setTimeout(() => {
          this.loopGetVoice(id, index)
        }, 2000)
      }
    },
    audioEnd() {
      this.audioUrlArrIndx += 1
      console.log(this.audioUrlArrIndx, 'audioUrlArrIndx');
      if (this.audioUrlArrIndx < this.audioUrlArr.length && this.videoLoopTime <= 50) {
        // 如果当前播放的语音地址为空，则等待2秒后重新获取
        if (!this.audioUrlArr[this.audioUrlArrIndx].voiceAddress) {
          setTimeout(() => {
            this.playAudio()
          }, 2000)
          return
        }
        // 如果当前播放的语音地址为false，则跳过当前语音
        if (this.audioUrlArr[this.audioUrlArrIndx].voiceAddress == 'false' && this.audioUrlArrIndx < this.audioUrlArr.length - 1) {
          this.audioUrlArrIndx += 1
          this.playAudio()
          return
        }
        this.audioUrl = this.audioUrlArr[this.audioUrlArrIndx].voiceAddress
        setTimeout(() => {
          if (this.audioUrl) {
            this.$refs.audio.play()
          }
        }, 100)
      } else {
        this.audioUrlArrIndx = []
        this.audioUrlArrIndx = 0
        console.log('播放结束');
        this.audioPlayIndex = null
      }
    },
    ChangeSettingValue1(value) {
      console.log(value, 'value');
      if (value) {
        queryUserBalanceApi().then(res => {
          console.log(res, '用户余额');
          if (res.data <= 0) {
            this.setting.value1 = false
            this.$message({
              message: '余额不足，无法开启次功能',
              type: 'error'
            });
          }
        })
      }
    },
    // 场景业务相关↓
    async sceneChange(item) {
      console.log(item, 'item');
      this.$message({
        message: `已进入场景${item.sceneName}`,
        type: 'success'
      });
      // 当用户选中场景
      this.sceneInfo = item
      // 切换当前场景id
      this.sceneId = item.sceneId
      // 情况聊天记录
      this.returnMessage = []
      // 新建场景对话
      this.newStart()
      // 增加开场白
      // this.returnMessage.push({
      //   role: 'assistant',
      //   content: item.sceneWelcome
      // })
    }
  }
}
</script>
<style lang="scss" scoped>
.chat {
  min-height: 100vh;
}

.top {
  position: relative;
  width: 100%;
  height: 50px;
  display: flex;
  align-items: center;
}

.chatContent {
  // margin-top: 30px;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  display: flex;
  height: calc(100% - 50px - 63px);
  justify-content: center;
  width: 100vw;
  // margin-bottom: 63px;

  >.leftImg {
    border-radius: 16px 16px 16px 16px;
    height: 95%;
    position: relative;
    min-width: 380px;

    >img {
      border: 6px solid;
      border-image: linear-gradient(180deg, #b48733, #e8cf97, #b48733) 6 6;
      height: 99%;
      margin-right: 5px;
    }

    >.aiInfo {
      background-color: #ffffff1a;
      border-radius: 24px 24px 24px 24px;
      bottom: -70px;
      display: flex;
      height: 193px;
      justify-content: center;
      left: 50%;
      position: absolute;
      transform: translate(-50%, -50%);
      width: 100%;

      >.photo {
        width: 64px;
        height: 64px;
        font-size: 18px;
        position: absolute;
        top: -20px;
        box-sizing: border-box;
        margin: 0;
        padding: 0;
        color: #fff;
        line-height: 1.5714285714285714;
        list-style: none;
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
        display: inline-flex;
        justify-content: center;
        align-items: center;
        overflow: hidden;
        white-space: nowrap;
        text-align: center;
        vertical-align: middle;
        background: rgba(0, 0, 0, 0.25);
        border: 1px solid transparent;
        border-radius: 50%;
      }

      >.info {
        padding-top: 50px;
        width: 80%;

        >.name {
          color: #fff;
          font-size: 22px;
          font-style: normal;
          font-weight: 700;
          line-height: 31px;
          text-align: center;
          text-transform: none;
        }

        >.tags {
          padding-bottom: 8px;
          text-align: center;

          >.tag {
            margin-right: 4px;
            background: #ffffff1a;
            border-radius: 4px 4px 4px 4px;
            color: #fff;
            font-size: 12px;
            font-weight: 500;
            line-height: 17px;
            border-color: transparent;
          }
        }

        >.infoContent {
          color: #fff;
          font-size: 16px;
          font-style: normal;
          font-weight: 500;
          height: 80px;
          line-height: 22px;
          overflow-y: auto;
          text-align: center;
          text-transform: none;
        }
      }
    }
  }

  >.chat-box {
    position: relative;

    // background: linear-gradient(rgba(255, 255, 255, 0) 75%, rgb(34, 34, 34));
    background-position: 50%;
    background-repeat: no-repeat;
    background-size: auto;
    // border: 1px solid #635677 !important;
    box-sizing: border-box;
    // color: #fff !important;
    display: flex;
    flex-direction: column;
    height: 100%;
    // margin: 0 auto;
    width: 100%;
    padding: 10px;
  }

  >.mask {
    background: rgba(0, 0, 0, 0.5);
  }
}

.messages {
  // height: calc(100% - 68px );
  overflow-y: auto;
}

.messages::-webkit-scrollbar {
  width: 0px;
}

.message {
  background: var(--bg-color3);
  // border: 1px solid #5b5b5e;
  max-width: calc(100% - 72px);
  // flex: 1;
  min-width: 80px;
  height: max-content;
}

.message2 {
  color: #000;
  background: rgba(200, 200, 200, 0.6);
  // border: 1px solid #5b5b5e;
  max-width: calc(100% - 72px);
  // flex: 1;
  min-width: 80px;
  height: max-content;
}

.photo {
  width: 56px;
}

.me {
  flex-direction: row-reverse;
}

.loadingMessage {
  position: relative;
  // display: flex;
  // justify-content: center;
  width: 60px;
  height: 32px;
}

.popup1 {
  .configForm {
    margin-bottom: 75px;
  }

  .bottom {
    position: absolute;
    bottom: 0;
    height: 75px;
    padding-bottom: 15px;
    background: var(--bg-color5);
    width: calc(100% - 30px);
    overflow-x: auto;

    .button {
      height: 100%;
      width: 80px;
      display: inline-flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      font-size: 11px;

      .icon {
        width: 34px;
        height: 34px;
        background: #6a6a6a;
        display: flex;
        justify-content: center;
        align-items: center;
        border-radius: 50%;
        font-size: 18px;
        margin-bottom: 10px;
      }
    }

    .button:not(:first-child) {
      margin-left: 20px;
    }

  }
}

.popup2 {
  height: 100%;
}
</style>
<style scoped>
.loadingMessage>>>.el-loading-parent--relative {
  width: 100%;
  height: 100%;

}

.loadingMessage>>>.el-loading-spinner {
  display: flex;
  justify-content: center;
}

.mButton {
  border: solid 0px;
}

.tm_button {
  width: 26px;
  height: 26px;
  font-size: 20px;
  padding: 0px;
}

.phoneBottomPopup>>>.el-dialog {
  margin-top: 0 !important;
  position: absolute;
  bottom: 0;
  min-height: 60%;
  background: rgba(255, 255, 255, 0);
}

.phoneBottomPopup>>>.el-dialog__header {
  padding: 0;
}

.phoneBottomPopup>>>.el-dialog__body {
  color: #fff;
  padding: 0;
  width: 100%;
  height: 100%;
  position: absolute;
  bottom: 0;
}

.phoneBottomPopup .popupContent {
  background: var(--bg-color5);
  color: #fff;
  width: 100%;
  height: 100%;
  padding: 10px 15px;
  position: relative;
}



.radio>>>.el-radio-button {
  margin-bottom: 5px;
  margin-right: 10px;

  /* border-left: solid 1px #DCDFE6; */
}

.radio>>>.el-radio-button__inner {
  border-left: solid 1px #DCDFE6;
  background-color: var(--bg-color5);
  border-radius: 4px;
  color: #fff;
}

.radio>>>.el-radio-button__orig-radio:checked+.el-radio-button__inner {
  border-left: solid 1px var(--bg-color1);
  background-color: var(--bg-color1);
  border-color: var(--bg-color1);
  -webkit-box-shadow: -1px 0 0 0 var(--bg-color1);
  box-shadow: -1px 0 0 0 var(--bg-color1);
}
</style>