Bladeren bron

feat:新增问题复制,编辑问答

hanyang 1 jaar geleden
bovenliggende
commit
355ad0a491

+ 7 - 3
src/modules/conversation-chat/DialogItem.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="dialog-item-container">
-    <DialogQuestion v-if="item_type === 'q'" :question="questionInfo" @select="handleSelectChat" />
+    <DialogQuestion v-if="item_type === 'q'" :question="questionInfo" @send="handleSend" @select="handleSelectChat" />
 
     <DialogAnswer
       v-if="item_type === 'a'"
@@ -35,7 +35,7 @@ const props = defineProps({
   answer_action_list: Array
 });
 
-const emit = defineEmits(['stop', 'retry', 'select', 'edit', 'download', 'toSearchPage', 'toShowMindMap']);
+const emit = defineEmits(['stop', 'retry', 'select', 'edit', 'download', 'toSearchPage', 'toShowMindMap', 'send']);
 
 /**
  * 当前这一项的类别,有两个值
@@ -56,7 +56,8 @@ const questionInfo = computed(() => {
     content: props.dialog.question,
     client_custom_icon: props.dialog.client_custom_icon,
     client_custom_upload_file_list: props.dialog.client_custom_upload_file_list,
-    client_custom_unique_id: props.dialog.client_custom_unique_id
+    client_custom_unique_id: props.dialog.client_custom_unique_id,
+    client_custom_knowledge_id: props.dialog.client_custom_knowledge_id
   };
 });
 
@@ -141,6 +142,9 @@ const handleDownload = () => {
 const handleSelectChat = () => {
   emit('select');
 };
+const handleSend = (question) => {
+  emit('send', question);
+};
 </script>
 
 <style lang="css" scoped>

+ 5 - 1
src/modules/conversation-chat/DialogList.vue

@@ -22,6 +22,7 @@
         @toSearchPage="toSearchPage(item)"
         @toShowMindMap="toShowMindMap(item)"
         @retry="handleRetryChat(item)"
+        @send="handleSend"
       />
 
       <DialogSuggestion v-if="suggestion.length !== 0" :suggestion="suggestion" />
@@ -72,7 +73,7 @@ const props = defineProps({
    * */
   is_show_right_page: Boolean
 });
-const emit = defineEmits(['edit', 'retry', 'toSearchPage', 'toShowMindMap']);
+const emit = defineEmits(['edit', 'retry', 'toSearchPage', 'toShowMindMap', 'send']);
 
 const scroll2Bottom = useScrollBottom('scroll_container');
 
@@ -113,6 +114,9 @@ const toSearchPage = (item) => {
 const toShowMindMap = (item) => {
   emit('toShowMindMap', item);
 };
+const handleSend = (question) => {
+  emit('send', question);
+};
 defineExpose({
   scroll2Bottom: () => {
     scroll2Bottom(1000000);

+ 51 - 4
src/modules/conversation-item/DialogQuestion.vue

@@ -5,8 +5,21 @@
     <div class="dialog-main question-main">
       <div class="dialog-content question-content">
         <div class="question-main-content">
-          <DialogContent :content="question.content" :show_think="false" class="question-content-core-text">
-          </DialogContent>
+          <div class="question-main-content-top">
+            <DialogQuestionActions
+              class="question-action"
+              @copy="handleCopy"
+              @edit="handleEdit"
+            ></DialogQuestionActions>
+            <DialogContent :content="question.content" :show_think="false" class="question-content-core-text">
+            </DialogContent>
+            <ReEditQuestion
+              v-if="show_edit_modal"
+              :content="question.content"
+              @close="handleClose"
+              @send="handleSend"
+            ></ReEditQuestion>
+          </div>
 
           <FileUploadPreviewV2
             v-if="question_attached_files.length !== 0"
@@ -24,12 +37,15 @@
 </template>
 
 <script setup>
-import { computed } from 'vue';
+import { computed, ref } from 'vue';
+import { Message } from '../../3rd-libs/arco-vue-libs';
 import BtnSelectItem from './BtnSelectItem.vue';
 import DialogContent from '../conversation-content/DialogContent.vue';
+import DialogQuestionActions from './DialogQuestionActions.vue';
+import ReEditQuestion from './ReEditQuestion.vue';
 
 import FileUploadPreviewV2 from '../file-preview/FileUploadPreviewV2.vue';
-
+import copyText from '../../3rd-libs/clipboard';
 const props = defineProps({
   show_select: true,
 
@@ -53,9 +69,29 @@ const question_attached_files = computed(() => {
 
 const emit = defineEmits(['select']);
 
+const show_edit_modal = ref(false);
 const handleSelectChange = () => {
   emit('select');
 };
+const handleCopy = () => {
+  copyText(props.question.content);
+  Message.success('已复制');
+};
+const handleEdit = () => {
+  show_edit_modal.value = true;
+};
+const handleClose = () => {
+  show_edit_modal.value = false;
+};
+const handleSend = (text) => {
+  console.log(props.question);
+  const question = {
+    ...props.question,
+    content: text
+  };
+  emit('send', question);
+  handleClose();
+};
 </script>
 
 <style src="./dialog-item-common.css" />
@@ -92,4 +128,15 @@ const handleSelectChange = () => {
   flex-direction: column;
   align-items: flex-end;
 }
+.question-main-content-top {
+  position: relative;
+  display: flex;
+  align-items: center;
+}
+.question-main-content-top:hover .question-action {
+  display: block;
+}
+.question-action {
+  display: none;
+}
 </style>

+ 57 - 0
src/modules/conversation-item/DialogQuestionActions.vue

@@ -0,0 +1,57 @@
+<template>
+  <div class="dialog-actions-container">
+    <div class="dialog-action-part dialog-action-left">
+      <div class="action-btn-item">
+        <a-tooltip :content="$t('conversation.copy')" position="top">
+          <icon-copy size="18" @click="handleCopy" />
+        </a-tooltip>
+      </div>
+
+      <div class="action-btn-item">
+        <a-tooltip :content="$t('conversation.edit')" position="top">
+          <icon-edit size="18" @click="handleEdit" />
+        </a-tooltip>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup>
+import { ref, computed } from 'vue';
+
+const emit = defineEmits(['copy', 'edit']);
+
+const handleCopy = () => {
+  emit('copy');
+};
+const handleEdit = () => {
+  emit('edit');
+};
+</script>
+<style lang="css" scoped>
+.dialog-actions-container {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+
+  /* height: 26px; */
+}
+
+.dialog-action-part {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.action-btn-item {
+  cursor: pointer;
+}
+
+.dialog-action-left .action-btn-item {
+  /* margin-left: 5px; */
+  margin-right: 10px;
+}
+.dialog-action-right .action-btn-item {
+  margin-left: 10px;
+  /* margin-right: 5px; */
+}
+</style>

+ 79 - 0
src/modules/conversation-item/ReEditQuestion.vue

@@ -0,0 +1,79 @@
+<template>
+  <div class="re-edit-question">
+    <a-textarea
+      v-model="text_input"
+      class="re-textarea-input"
+      :auto-size="textarea_size_config"
+      placeholder="Please enter something"
+      allow-clear
+    />
+    <div class="footer">
+      <a-button class="btn" @click="cancel">取消</a-button>
+      <a-button class="btn" type="primary" @click="send">发送</a-button>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { computed, ref } from 'vue';
+const props = defineProps({
+  content: String
+});
+const emit = defineEmits(['close', 'send']);
+
+const textarea_size_config = {
+  minRows: 3,
+  maxRows: 6
+};
+const text_input = ref(props.content);
+
+const cancel = () => {
+  emit('close');
+};
+const send = () => {
+  emit('send', text_input.value);
+};
+</script>
+<style scoped lang="css">
+.re-edit-question {
+  position: absolute;
+  top: 80px;
+  right: 0px;
+  width: 300px;
+  background-color: var(--color-bg-1);
+  padding: 20px;
+  z-index: 999;
+  box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.1);
+  border-radius: 12px;
+}
+
+.chat-textarea-input {
+  border-radius: 5px;
+}
+.chat-textarea-input:focus {
+  outline: none;
+}
+.footer {
+  text-align: right;
+  .btn {
+    border-radius: 18px;
+    margin-right: 5px;
+  }
+}
+</style>
+<style>
+.re-textarea-input.arco-textarea-wrapper {
+  border-color: var(--color-bg-1);
+}
+
+.re-textarea-input.arco-textarea-wrapper .arco-textarea {
+  background-color: var(--color-bg-1);
+  padding: 0;
+}
+
+.re-textarea-input.arco-textarea-wrapper:focus-within,
+.re-textarea-input.arco-textarea-wrapper.arco-textarea-focus {
+  /* border: none; */
+  border-color: var(--color-bg-1);
+}
+</style>

+ 37 - 0
src/views/conversation/ConversationChatContainer.vue

@@ -41,6 +41,7 @@
               @retry="handleRetryChat"
               @toSearchPage="toSearchPage"
               @toShowMindMap="toShowMindMap"
+              @send="handleSendChat"
               @submit="handleSuggestSubmit"
               :style="style_conversation_chat_list"
             >
@@ -666,6 +667,39 @@ const handleRetryChat = async (item) => {
     toSubmitNewChat(options);
   }
 };
+// 编辑问题重新问答
+const handleSendChat = async (item) => {
+  let chatMode = retry_action_option.value?.chatMode || 1;
+  let isDeep = retry_action_option.value?.isDeep || 1;
+  let parent_id = '';
+  const idx = chat_display_list.value.findIndex((it) => it.client_custom_unique_id === item.client_custom_unique_id);
+  if (idx !== -1 && idx > 0) {
+    parent_id = chat_display_list.value[idx - 1].parent_id || '';
+  }
+  if (item.client_custom_upload_file_list?.length) {
+    chatMode = 1;
+  }
+  if (item.client_custom_knowledge_id?.length) {
+    chatMode = 3;
+  }
+  if (item.client_custom_upload_file_list?.length) {
+    chatMode = 1;
+  }
+  if (item.client_custom_knowledge_id?.length) {
+    chatMode = 3;
+  }
+  const options = {
+    files: item.client_custom_upload_file_list || [],
+    text: item.content,
+    parent_id,
+    config: {
+      knowledgeId: item.client_custom_knowledge_id || [],
+      isDeep,
+      chatMode
+    }
+  };
+  toSubmitNewChat(options);
+};
 
 /**
  * 在聊天界面点击推荐项
@@ -1210,6 +1244,9 @@ const toSubmitNewChat = async (options) => {
       parent_id = lastItem.parent_id;
     }
   }
+  if (options.parent_id) {
+    parent_id = options.parent_id;
+  }
 
   mindMap_txt.value = options.text;
   // 用户选定的文件数量