copilot处理完成
This commit is contained in:
		@@ -16,16 +16,11 @@ export default {
 | 
			
		||||
      loading: false,
 | 
			
		||||
      prompt: "",
 | 
			
		||||
      history: [],
 | 
			
		||||
      apps: [
 | 
			
		||||
        {label: "日常助理", icon: "https://cdn.sinoecare.com/i/2024/07/04/66864da37fc2b.png"},
 | 
			
		||||
        {label: "文本助理", icon: "https://cdn.sinoecare.com/i/2024/07/04/66864da1684ad.png"},
 | 
			
		||||
      ],
 | 
			
		||||
      apps: [],
 | 
			
		||||
      filter: "",
 | 
			
		||||
      conversations: [
 | 
			
		||||
        {content: "请对“city不city”一词进行深入分析"},
 | 
			
		||||
        {content: "请对“city不city”一词进行深入分析"},
 | 
			
		||||
        {content: "请对“city不city”一词进行深入分析"},
 | 
			
		||||
      ]
 | 
			
		||||
      conversations: [],
 | 
			
		||||
      currentConversation: null,
 | 
			
		||||
      app: {}
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
@@ -38,19 +33,38 @@ export default {
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    ],
 | 
			
		||||
    rowBtns: () => [
 | 
			
		||||
      {icon: "https://cdn.sinoecare.com/i/2024/07/04/66866edc2910a.png", click: row => 0},
 | 
			
		||||
      {icon: "https://cdn.sinoecare.com/i/2024/07/04/66866ed734540.png", click: row => 0},
 | 
			
		||||
      {icon: "https://cdn.sinoecare.com/i/2024/07/04/66866eda99e4d.png", click: row => 0},
 | 
			
		||||
    rowBtns: v => [
 | 
			
		||||
      {icon: "https://cdn.sinoecare.com/i/2024/07/04/66866edc2910a.png", label: "置顶", click: row => 0},
 | 
			
		||||
      {icon: "https://cdn.sinoecare.com/i/2024/07/04/66866ed734540.png", label: "编辑", click: row => 0},
 | 
			
		||||
      {icon: "https://cdn.sinoecare.com/i/2024/07/04/66866eda99e4d.png", label: "删除", click: row => v.handleDeleteConversation(row.id)},
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  components: {ThinkingBar, ChatContent},
 | 
			
		||||
  methods: {
 | 
			
		||||
    getHistory(cb) {
 | 
			
		||||
      this.http.post("/app/appaicopilotinfo/list").then(res => {
 | 
			
		||||
    getHistory(params) {
 | 
			
		||||
      this.http.post("/app/appaicopilotinfo/list", null, {params}).then(res => {
 | 
			
		||||
        if (res?.data) {
 | 
			
		||||
          if (cb) cb(res.data.records)
 | 
			
		||||
          else this.history = res.data.records
 | 
			
		||||
          this.history = res.data.records
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    getApps() {
 | 
			
		||||
      return this.http.post("/app/appaiconfiginfo/list", null, {
 | 
			
		||||
        params: {
 | 
			
		||||
          status: 1, size: 999
 | 
			
		||||
        }
 | 
			
		||||
      }).then(res => {
 | 
			
		||||
        if (res?.data) {
 | 
			
		||||
          return this.apps = res.data.records
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    getConversations() {
 | 
			
		||||
      return this.http.post("/app/appaicopilotinfo/listHistory", null, {
 | 
			
		||||
        params: {content: this.filter}
 | 
			
		||||
      }).then(res => {
 | 
			
		||||
        if (res?.data) {
 | 
			
		||||
          return this.conversations = res.data.records || []
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
@@ -66,7 +80,8 @@ export default {
 | 
			
		||||
        if (++i < content.length) setTimeout(() => concatenateStr(content, i), 50)
 | 
			
		||||
      }
 | 
			
		||||
      this.$debounce(() => {
 | 
			
		||||
        const message = {appType: "2", userType: 0, content: this.prompt}
 | 
			
		||||
        const {currentConversation: conversationId, app, prompt: content} = this.$data
 | 
			
		||||
        const message = {appType: "2", userType: 0, content, conversationId, ...app}
 | 
			
		||||
        this.history.push(message)
 | 
			
		||||
        this.loading = true
 | 
			
		||||
        this.prompt = ""
 | 
			
		||||
@@ -80,11 +95,45 @@ export default {
 | 
			
		||||
          this.loading = false
 | 
			
		||||
        })
 | 
			
		||||
      }, 100)
 | 
			
		||||
    },
 | 
			
		||||
    handleDeleteConversation(conversationId) {
 | 
			
		||||
      this.$confirm("是否要删除该会话历史?").then(() => {
 | 
			
		||||
        this.http.post("/app/appaicopilotinfo/deleteConversation", null, {params: {conversationId}}).then(res => {
 | 
			
		||||
          if (res?.code == '0') {
 | 
			
		||||
            this.$message.success("删除成功!")
 | 
			
		||||
            this.getConversations()
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
      }).catch(() => 0)
 | 
			
		||||
    },
 | 
			
		||||
    handleChangeApp(item) {
 | 
			
		||||
      const {appId, id: aiConfigId} = item
 | 
			
		||||
      this.handleChangeConversation({appId, aiConfigId})
 | 
			
		||||
      this.history = [{userType: 2, content: `当前应用已切换至【${item.appName}】`}]
 | 
			
		||||
    },
 | 
			
		||||
    handleChangeConversation({conversationId, appId, aiConfigId} = {}) {
 | 
			
		||||
      this.currentConversation = conversationId
 | 
			
		||||
      this.app = {appId, aiConfigId}
 | 
			
		||||
    },
 | 
			
		||||
    getIcon(item = {}) {
 | 
			
		||||
      const icon = item.appIconUrl || "https://cdn.sinoecare.com/i/2024/07/04/66864da1684ad.png"
 | 
			
		||||
      return {
 | 
			
		||||
        backgroundImage: `url(${icon})`
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    currentConversation(v) {
 | 
			
		||||
      v && this.getHistory({conversationId: v})
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getHistory()
 | 
			
		||||
    Promise.all([this.getApps(), this.getConversations()]).then(() => {
 | 
			
		||||
      const {appId, id: aiConfigId} = this.apps.at(0)
 | 
			
		||||
      this.handleChangeConversation(this.conversations.at(0) || {appId, aiConfigId})
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
@@ -104,14 +153,14 @@ export default {
 | 
			
		||||
            <span v-text="profile.girdName"/>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="apps flex">
 | 
			
		||||
            <div v-for="(item,i) in apps" :key="i" class="app pointer" :style="{backgroundImage: `url(${item.icon})`}" v-text="item.label"/>
 | 
			
		||||
            <div v-for="(item,i) in apps" :key="i" class="app pointer" :style="getIcon(item)" v-text="item.appName" @click="handleChangeApp(item)"/>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="conversation">
 | 
			
		||||
            <el-input class="search" v-model="filter" placeholder="搜索历史对话记录" size="small" suffix-icon="el-icon-search" clearable/>
 | 
			
		||||
            <div class="item pointer" v-for="item in conversations" :key="item.id">
 | 
			
		||||
            <el-input class="search" v-model="filter" placeholder="搜索历史对话记录" size="small" suffix-icon="el-icon-search" clearable @change="getConversations"/>
 | 
			
		||||
            <div class="item pointer" v-for="item in conversations" :key="item.id" @click="currentConversation=item.id" :class="{current:item.conversationId==currentConversation}">
 | 
			
		||||
              {{ item.content }}
 | 
			
		||||
              <div class="operation flex">
 | 
			
		||||
                <div v-for="(btn,i) in rowBtns" :key="i" class="pointer" :style="{backgroundImage: `url(${btn.icon})`}"/>
 | 
			
		||||
                <div v-for="(btn,i) in rowBtns" :key="i" class="pointer" :style="{backgroundImage: `url(${btn.icon})`}" @click.stop="btn.click(item)"/>
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
@@ -123,7 +172,7 @@ export default {
 | 
			
		||||
              <div v-for="(btn,i) in btns" :key="i" class="btn pointer" :style="{backgroundImage: `url(${btn.icon})`}" v-text="btn.label" @click="btn.click"/>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="flex end">
 | 
			
		||||
              <el-input type="textarea" class="fill input" autosize resize="none" v-model="prompt" placeholder="请输入..." :rows="2"
 | 
			
		||||
              <el-input type="textarea" class="fill input" autosize resize="none" v-model="prompt" placeholder="请输入..." :rows="5"
 | 
			
		||||
                        @keydown.native="handleHotkey" :disabled="loading" :placeholder="loading?'正在思考中...':'请输入'"/>
 | 
			
		||||
              <div class="sendBtn" @click="handleSend"/>
 | 
			
		||||
            </div>
 | 
			
		||||
@@ -199,10 +248,11 @@ export default {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &.expand {
 | 
			
		||||
          width: 260px;
 | 
			
		||||
          width: 306px;
 | 
			
		||||
 | 
			
		||||
          & + .right {
 | 
			
		||||
            border-left-color: #ddd;
 | 
			
		||||
            width: 660px;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -210,7 +260,7 @@ export default {
 | 
			
		||||
          padding: 18px 14px;
 | 
			
		||||
          height: 88px;
 | 
			
		||||
          background: url("https://cdn.sinoecare.com/i/2024/06/04/665ed2bc580fa.png") no-repeat;
 | 
			
		||||
          background-size: 100%;
 | 
			
		||||
          background-size: 100% 100%;
 | 
			
		||||
          font-size: 14px;
 | 
			
		||||
          color: #222222;
 | 
			
		||||
          letter-spacing: 0;
 | 
			
		||||
@@ -304,7 +354,7 @@ export default {
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            &:hover {
 | 
			
		||||
            &:hover, &.current {
 | 
			
		||||
              background: #2b71fd24;
 | 
			
		||||
 | 
			
		||||
              .operation {
 | 
			
		||||
@@ -316,11 +366,12 @@ export default {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .right {
 | 
			
		||||
        width: 420px;
 | 
			
		||||
        width: 468px;
 | 
			
		||||
        height: 100%;
 | 
			
		||||
        padding: 14px 0 14px 14px;
 | 
			
		||||
        align-items: stretch;
 | 
			
		||||
        border-left: 1px solid transparent;
 | 
			
		||||
        transition: width 1s;
 | 
			
		||||
 | 
			
		||||
        .sendBtn {
 | 
			
		||||
          width: 36px;
 | 
			
		||||
@@ -346,9 +397,10 @@ export default {
 | 
			
		||||
 | 
			
		||||
        .topBar {
 | 
			
		||||
          width: 100%;
 | 
			
		||||
          height: 25px;
 | 
			
		||||
          height: 28px;
 | 
			
		||||
          border-bottom: 1px solid #E0E0E0;
 | 
			
		||||
          margin-bottom: 10px;
 | 
			
		||||
          align-items: flex-start;
 | 
			
		||||
 | 
			
		||||
          .btn {
 | 
			
		||||
            font-size: 12px;
 | 
			
		||||
@@ -371,6 +423,7 @@ export default {
 | 
			
		||||
          border: none;
 | 
			
		||||
          box-sizing: border-box;
 | 
			
		||||
          background: transparent;
 | 
			
		||||
          min-height: 73px !important;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <el-scrollbar class="chatContent">
 | 
			
		||||
    <div class="chat-wrapper" v-for="item in list" :key="item.id">
 | 
			
		||||
      <div class="chat-text" :class="{right:item.userType == '0'}">
 | 
			
		||||
        <img class="avatar" :src="avatar(item)" alt=""/>
 | 
			
		||||
      <div class="chat-text" :class="{right:item.userType == '0',system:item.userType == '2'}">
 | 
			
		||||
        <img v-if="item.userType!=2" class="avatar" :src="avatar(item)" alt=""/>
 | 
			
		||||
        <div class="content" v-text="item.content"/>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
@@ -11,6 +11,9 @@
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * userType: 0-用户 1-机器人 2-系统
 | 
			
		||||
 */
 | 
			
		||||
export default {
 | 
			
		||||
  name: "chatContent",
 | 
			
		||||
  props: {
 | 
			
		||||
@@ -58,7 +61,7 @@ export default {
 | 
			
		||||
 | 
			
		||||
    .content {
 | 
			
		||||
      position: relative;
 | 
			
		||||
      max-width: 220px;
 | 
			
		||||
      max-width: max(calc(100% - 140px), 220px);
 | 
			
		||||
      padding: 8px;
 | 
			
		||||
      border-radius: 4px;
 | 
			
		||||
      background: #F3F5F7;
 | 
			
		||||
@@ -91,6 +94,24 @@ export default {
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.system {
 | 
			
		||||
      padding-right: 0;
 | 
			
		||||
      justify-content: center;
 | 
			
		||||
 | 
			
		||||
      .content {
 | 
			
		||||
        font-size: 12px;
 | 
			
		||||
        background: #F0F0F0;
 | 
			
		||||
        border-radius: 4px;
 | 
			
		||||
        color: #888;
 | 
			
		||||
        padding: 3px 6px;
 | 
			
		||||
        width: fit-content;
 | 
			
		||||
 | 
			
		||||
        &:before {
 | 
			
		||||
          display: none;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .avatar {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user