Parcourir la source

feat: 完善功能、修复bug

1.
小数绘图的上传图片组件增加前置检查,如果之前的图片已上传,但是未发消息,不允许继续传图
2. 修复点击历史记录后,再点击 新建对话 按钮后,出现 agent not found
   的错误的问题
3. 优化图片上传组件,解耦,增强可维护性
4. 调整部分组件的名称,将相同功能组件聚合在同位置
zhupei il y a 1 an
Parent
commit
f61902f398

+ 9 - 0
src/components/DialogWrap.vue

@@ -282,6 +282,8 @@ import formatDialogItem from './dialog-wrap/format-dialog-item';
 
 import DocRefItem from './dialog-wrap/DocRefItem.vue';
 
+import {useImageUploadStatus} from '../store/modules/xs-huitu-image-upload/index';
+
 export default defineComponent({
   components: {
     DialogFeedback,
@@ -306,6 +308,10 @@ export default defineComponent({
     'reference'
   ],
   setup(props, { emit }) {
+    // 图片上传的状态
+    const imageUploadStatus = useImageUploadStatus();
+
+
     const knowledgeList = ref([[{}]]);
     const DOCUMENT_RESULT = {};
 
@@ -859,6 +865,9 @@ export default defineComponent({
               }
 
               setTimeout(() => {
+                // 文字消息上传成功
+                imageUploadStatus.messageFinish();
+
                 // 记录此时页面中的问题记录
                 huituSetTempImageIndex(dialogList.length);
 

+ 5 - 4
src/components/PictureFooter.vue

@@ -1,15 +1,16 @@
 <template>
 <footer>
     <div class="btn-container">
-        <picture-cards :agentId="agentId"/>
+        <PictureUpload :agentId="agentId"/>
     </div>
     
-    <MessagePicUpload />
+    <PictureMessageInput />
 </footer>
 </template>
 <script setup>
-import PictureCards from './PictureCards.vue'
-import MessagePicUpload from './MessagePicUpload.vue'
+import {onMounted, watch} from 'vue'
+import PictureUpload from './PictureUpload.vue'
+import PictureMessageInput from './PictureMessageInput.vue'
 
 const props = defineProps({
     agentId: String,

+ 97 - 50
src/components/MessagePicUpload.vue → src/components/PictureMessageInput.vue

@@ -26,60 +26,107 @@
         </div>
     </div>
 </template>
-<script>
+<script setup>
 import { defineComponent, ref, inject, onMounted, onBeforeUnmount } from "vue";
 
-export default defineComponent({
-    components: {},
-    props: ["readonly", "eventName"],
-    setup(props) {
-        const { helper } = inject("$global");
-        const value = ref("");
-        const ask_times = ref(0);
-        const maxLength = ref(6000);
-        const sendMessage = () => {
-            const msg_str = value.value;
-
-            if (msg_str.length > 0 && !props.readonly) {
-                if(ask_times.value === 0){
-                    helper.$bus.emit('open-dialog', msg_str);
-                }else{
-                    helper.$bus.emit('send-message', msg_str);
-                }
-
-                value.value = "";
-                ask_times.value = ask_times.value + 1;
-            }
-        };
-        const clearMessage = () => {
-            if (!props.readonly) {
-                helper.$bus.emit("clear-message");
-            }
-        };
-        const handleEnter = (e) => {
-            if (!e.shiftKey) {
-                e.preventDefault();
-                sendMessage();
-            }
-        };
-        onMounted(() => {
-            helper.$bus.on("set-input", (data) => {
-                value.value = data;
-            });
-        });
-        onBeforeUnmount(() => {
-            helper.$bus.off("set-input");
-        });
-        return {
-            value,
-            maxLength,
-            readonly: props.readonly,
-            sendMessage,
-            clearMessage,
-            handleEnter
-        };
+const props = defineProps({
+    readonly: Boolean,
+    eventName: String
+});
+
+const { helper } = inject("$global");
+const value = ref("");
+const ask_times = ref(0);
+const maxLength = ref(6000);
+const sendMessage = () => {
+    const msg_str = value.value;
+
+    if (msg_str.length > 0 && !props.readonly) {
+        if(ask_times.value === 0){
+            helper.$bus.emit('open-dialog', msg_str);
+        }else{
+            helper.$bus.emit('send-message', msg_str);
+        }
+
+        value.value = "";
+        ask_times.value = ask_times.value + 1;
+    }
+};
+
+const clearMessage = () => {
+    if (!props.readonly) {
+        helper.$bus.emit("clear-message");
     }
+};
+
+const handleEnter = (e) => {
+    if (!e.shiftKey) {
+        e.preventDefault();
+        sendMessage();
+    }
+};
+
+onMounted(() => {
+    helper.$bus.on("set-input", (data) => {
+        value.value = data;
+    });
+});
+
+onBeforeUnmount(() => {
+    helper.$bus.off("set-input");
 });
+
+// export default defineComponent({
+//     components: {},
+//     props: ["readonly", "eventName"],
+//     setup(props) {
+//         const { helper } = inject("$global");
+//         const value = ref("");
+//         const ask_times = ref(0);
+//         const maxLength = ref(6000);
+//         const sendMessage = () => {
+//             const msg_str = value.value;
+
+//             if (msg_str.length > 0 && !props.readonly) {
+//                 if(ask_times.value === 0){
+//                     helper.$bus.emit('open-dialog', msg_str);
+//                 }else{
+//                     helper.$bus.emit('send-message', msg_str);
+//                 }
+
+//                 value.value = "";
+//                 ask_times.value = ask_times.value + 1;
+//             }
+//         };
+//         const clearMessage = () => {
+//             if (!props.readonly) {
+//                 helper.$bus.emit("clear-message");
+//             }
+//         };
+//         const handleEnter = (e) => {
+//             if (!e.shiftKey) {
+//                 e.preventDefault();
+//                 sendMessage();
+//             }
+//         };
+//         onMounted(() => {
+//             helper.$bus.on("set-input", (data) => {
+//                 value.value = data;
+//             });
+//         });
+//         onBeforeUnmount(() => {
+//             helper.$bus.off("set-input");
+//         });
+//         return {
+//             value,
+//             maxLength,
+//             readonly: props.readonly,
+//             sendMessage,
+//             clearMessage,
+//             handleEnter
+//         };
+//     }
+// });
 </script>
 <style scoped>
 .message-input-border {

+ 114 - 93
src/components/PictureCards.vue → src/components/PictureUpload.vue

@@ -1,58 +1,40 @@
 <template>
-  
-    <!-- <section class="xiaoshuhuitu-sections">
-      <div v-for="(item, key) in data" :key="key" :style="{ background: item.background }">
-        <img :src="getAssetURL(item.img)" />
-        <div :style="{ color: item.color }">
-          {{ item.title }}
-          <span>{{ item.content }}</span>
-        </div>
-      </div>
-    </section> -->
-
 <footer class="picture-upload-footer">
-  <a-popover :popup-visible="showUpload" position="tl" @popup-visible-change="() => {
-    showDeleteTooltip = false;
-  }">
+  <a-popover :popup-visible="showUpload" position="tl" @popup-visible-change="handlePopupChange">
     <div class="text-hide">
-      <div class="upload-img-container" @click="() => {
-        showUpload = true;
-      }
-        ">
+      <div class="upload-img-container" @click="handleUploadClick">
         <img src="@/assets/document/6.svg" class="img-normal" v-if="!showUpload" />
         <img src="@/assets/document/7.svg" class="img-hover" v-if="!showUpload" />
         <img src="@/assets/document/8.svg" class="img-active" v-if="showUpload" />
       </div>
 
-      <p>已选择 {{ fileList.length }} 个图片</p>
+      <p>{{ file_status_label_tips }}</p>
     </div>
 
     <template #content>
       <div :class="{ 'upload-wrap': true, 'upload-wrap-narrow': uploadFile }">
         <header>
           <p>{{ uploadFile ? "上传图片" : "上传图片" }}</p>
-          <div @click="() => {
-            showUpload = false;
-          }
-            ">
+
+          <div @click="handleUploadClose">
             <icon-close size="large" />
           </div>
         </header>
 
         <div class="xiaoshuhuitu-image-upload">
-          <section>
+          <section v-if="tableData.length === 0">
             <a-upload 
-              draggable 
+              :draggable="true"
               list-type="picture"
               :multiple="false" 
               :limit="1" 
               :show-file-list="false"
-              @before-upload="onBeforeUpload" 
-              @exceed-limit="onExceedLimit" 
-              @before-remove="onBeforeRemove"
               :custom-request="customRequest" 
               :show-upload-button="{ showOnExceedLimit: false }"
               accept=".png,.jpg"
+              @before-upload="onBeforeUpload" 
+              @exceed-limit="onExceedLimit" 
+              @before-remove="onBeforeRemove"
             >
               <template #upload-button>
                 <div class="upload-main">
@@ -65,57 +47,45 @@
             </a-upload>
           </section>
 
-          <div v-if="tableData.length > 0">
+          <!-- <div v-if="tableData.length > 0">
             <p>
               <span>已选择图片列表</span>
               <span>共{{ tableData.length }}个</span>
             </p>
             <div>
-              <a-table :pagination="false" row-key="name" :columns="columns" :data="tableData"
-                :row-selection="rowSelection" v-model:selectedKeys="selectedKeys">
+              <a-table 
+                :pagination="false" 
+                row-key="name" 
+                :columns="columns" 
+                :data="tableData"
+                v-model:selectedKeys="selectedKeys"
+              >
                 <template #methods="{ record }">
-                  <a-tooltip content="下载">
-                    <div class="method-button" @click="downloadDocument(record)">
-                      <icon-cloud-download />
-                    </div>
-                  </a-tooltip>
-                  <a-popover :popup-visible="showDeleteTooltip && deleteId === record.key">
-                    <a-tooltip content="删除">
-                      <div class="method-button" @click="handleDeleteButton(record.key)">
-                        <icon-delete />
-                      </div>
-                    </a-tooltip>
-                    <template #content>
-                      <div>
-                        <p>删除后无法恢复,您是否删除?</p>
-                        <div class="delete-buttons">
-                          <div>
-                            <a-button size="mini" type="primary" style="margin-right: 10px"
-                              @click="deleteDocument">确认</a-button>
-                            <a-button size="mini" type="outline" @click="() => {
-                              showDeleteTooltip = false;
-                            }
-                              ">取消</a-button>
-                          </div>
-                        </div>
-                      </div>
-                    </template>
-                  </a-popover>
+                  <BtnImgDownload @download="downloadDocument(record)"/>
+                  <BtnImgDelete @delete="deleteDocument"/>
                 </template>
               </a-table>
             </div>
-          </div>
+          </div> -->
+
+          <FileListTable  
+            v-if="tableData.length > 0" 
+            :tableData="tableData" 
+            :columns="columns" 
+            :selectedKeys="selectedKeys"
+            @download="downloadDocument"
+            @delete="deleteDocument"
+          />
         </div>
       </div>
 
       <div class="bottom-buttons">
         <div>
-          <a-button type="outline" style="margin-right: 10px" @click="selectFiles(false)">取消</a-button>
-          <a-button :loading="buttonLoading" type="primary" @click="selectFiles(true, 'paper')">去{{
-            uploadFile ? '提问'
-              : '提问'
-          }}({{ fileList.length
-            }})</a-button>
+          <a-button type="outline" style="margin-right: 10px" @click="handleUploadClose">取消</a-button>
+
+          <a-button :loading="buttonLoading" type="primary" @click="selectFiles(true, 'paper')">
+            去{{ uploadFile ? '提问' : '提问' }} ({{ fileList.length}})
+          </a-button>
         </div>
       </div>
     </template>
@@ -127,7 +97,7 @@
 </template>
 <script>
 import dayjs from "dayjs";
-import { defineComponent, ref, inject, reactive } from "vue";
+import { defineComponent, ref, inject, reactive, onBeforeUnmount, computed } from "vue";
 
 import { Message } from '@arco-design/web-vue';
 
@@ -135,20 +105,34 @@ import BtnIframeComfyui from './btn-iframe-comfyui/BtnIframeComfyui.vue';
 
 import ImgEditBtn from './image-editor/ImgEditBtn.vue';
 
+import BtnImgDownload from './picture-upload/BtnImgDownload.vue';
+import BtnImgDelete from './picture-upload/BtnImgDelete.vue';
+
+import FileListTable from './picture-upload/FileListTable.vue';
+
 import {huituSetTempImageFile} from './dialog-wrap/temp-image'
 
+import {useImageUploadStatus} from '../store/modules/xs-huitu-image-upload/index';
+
 export default defineComponent({
   props: ["data", "uploadFile", "isQuestion", "agentId", "agengtName"],
   components: {
+    BtnImgDownload,
+    BtnImgDelete,
+    FileListTable,
+
     BtnIframeComfyui,
 
     ImgEditBtn
   },
   setup(props) {
-    const showUpload = ref(false);
     const { helper, ajax } = inject("$global");
 
+    const imageUploadStatus = useImageUploadStatus();
+    
     const maxSize = 30 * 1024 * 1024;
+
+    const showUpload = ref(false);
     let fileList = ref([]);
     const tableData = reactive([]);
     let formData = new FormData();
@@ -156,6 +140,42 @@ export default defineComponent({
     const showDeleteTooltip = ref(false);
     const deleteId = ref("");
     const buttonLoading = ref(false);
+
+    const file_status_label_tips = computed(() => {
+      const can_upload = imageUploadStatus.canUploadContinue;
+
+      if(!can_upload){
+        // 不允许上传
+        return `已保存 1 个图片`
+      }else{
+        return `已选择 ${fileList.value.length} 个图片`
+      }
+    });
+
+    const handlePopupChange = () => {
+      showDeleteTooltip.value = false;
+    };
+    const handleUploadClick = () => {
+      // 检查上一次传图后有没有发布文字,如果没有发布文字,则不允许再次上传图片
+      const can_upload = imageUploadStatus.canUploadContinue;
+      if(can_upload){
+        // console.log('允许继续上传图片', can_upload);
+      }else{
+        Message.warning('图片已保存,请输入文字进行提问');
+        return;
+      }
+
+      showUpload.value = true;
+    }
+
+    const handleUploadClose = () => {
+      showUpload.value = false;
+    }
+    const handleCancelDelete = () => {
+      showDeleteTooltip.value = false;
+    };
+
+
     const selectFiles = async (isSelect, type) => {
       if (isSelect) {
         if (props.uploadFile) {
@@ -202,6 +222,10 @@ export default defineComponent({
             helper.write('sendData', sendData);
           }
         } else {
+          // 图片上传的状态
+
+
+
           let temp_file = null;
           fileList.value.forEach(file => {
             formData.append('file', file)
@@ -220,6 +244,7 @@ export default defineComponent({
            * 此方案在用户刷新页面后就会失效
            */
           huituSetTempImageFile(temp_file, props.agentId, data.chat_id);
+          imageUploadStatus.uploadFinish(); // 记录图片的数据
 
           // 保存小数绘图数据
           helper.write('sendData', {
@@ -240,25 +265,11 @@ export default defineComponent({
           Message.info('图片已保存,请输入文字进行提问');
 
           // 文件清空
+          tableData.length = 0;
           fileList.value = [];
-
-          // created_at: 1732531229
-          // created_by: "069e660f-ffc1-4b02-bfed-0cfef46c928d"
-          // extension: "png"
-          // id: "0e15a523-d029-4ffd-b0b4-3ca4a99f65a4"
-          // mime_type: "image/png"
-          // name: "下载.png"
-          // size: 67593
-
-          /**
-          {
-              "message":"图片描述了什么",
-              "upload_file_id":"a1c91dda-2752-474f-8d90-ce0f072ee0a2"
-          }
-           */
-
-          // helper.$bus.emit("open-dialog", '合并Excel');
         }
+      }else{
+
       }
     };
 
@@ -337,21 +348,24 @@ export default defineComponent({
       }
     ];
 
-    const downloadDocument = (record) => { };
+    const downloadDocument = (record) => {
+      console.log('下载图片');
+    };
 
     const deleteDocument = () => {
-      const index = tableData.findIndex(item => item.key === deleteId.value);
-      tableData.splice(index, 1);
-      fileList.value = fileList.value.filter(item => item.uid !== deleteId.value);
+      // const index = tableData.findIndex(item => item.key === deleteId.value);
+      // tableData.splice(index, 1);
+      // fileList.value = fileList.value.filter(item => item.uid !== deleteId.value);
+
+      tableData.length = 0;
+      fileList.value = [];
     };
 
 
-    // const image_list = [
-    //   'https://s3.harix.iamidata.com/sd-txt2img-ningbo/20241121_4173677d-b021-4b3a-9535-b7e4de17cded?AWSAccessKeyId=mjf0vn4dlj76z7ph&Expires=2147483647&Signature=kBHLFhQKRUd%2F%2B1hnw0k5DZ8VuA4%3D',
-    //   'https://s3.harix.iamidata.com/sd-txt2img-ningbo/20241121_f0c4a724-ed43-4950-ade0-60190aa8eda4?AWSAccessKeyId=mjf0vn4dlj76z7ph&Expires=2147483647&Signature=Vd8Ja5X3W8qJFZl30NE8d%2B5GW40%3D',
-    //   'https://s3.harix.iamidata.com/sd-txt2img-ningbo/20241121_a969df4c-5b6f-4577-827d-f7459e1a1c69?AWSAccessKeyId=mjf0vn4dlj76z7ph&Expires=2147483647&Signature=CHVinI9kJWnToLXWZ5BHdj54nLM%3D'
-    // ]
+    // 组件卸载
+    onBeforeUnmount(() => {
 
+    });
 
     return {
       agengtName: props.agengtName,
@@ -375,6 +389,13 @@ export default defineComponent({
       selectFiles,
 
       // image_list
+
+      handlePopupChange,
+      handleCancelDelete,
+      handleUploadClick,
+      handleUploadClose,
+
+      file_status_label_tips,
     };
   }
 });

+ 337 - 0
src/components/picture-upload/BtnImgDelete.vue

@@ -0,0 +1,337 @@
+<template>
+<a-popover :popup-visible="showDeleteTooltip">
+    <a-tooltip content="删除">
+        <div class="method-button" @click="handleDeleteButton">
+            <icon-delete />
+        </div>
+    </a-tooltip>
+    
+    <template #content>
+        <div>
+        <p>删除后无法恢复,您是否删除?</p>
+        <div class="delete-buttons">
+            <div>
+            <a-button size="mini" type="primary" style="margin-right: 10px"
+                @click="deleteDocument">确认</a-button>
+            <a-button size="mini" type="outline" @click="handleCancelDelete">取消</a-button>
+            </div>
+        </div>
+        </div>
+    </template>
+</a-popover>
+</template>
+<script setup>
+import { defineComponent, ref, inject, reactive } from "vue";
+
+const emit = defineEmits(['delete']);
+
+const showDeleteTooltip = ref(false);
+
+const handleCancelDelete = () => {
+    showDeleteTooltip.value = false;
+};
+
+const handleDeleteButton = () => {
+    showDeleteTooltip.value = true;
+};
+
+/**
+ * 确认删除
+ */
+const deleteDocument = () => {
+    emit('delete');
+};
+</script>
+
+<style lang="scss" scoped>
+.bottom-buttons {
+  display: flex;
+  justify-content: right;
+
+  >div {
+    display: flex;
+  }
+}
+
+.delete-buttons {
+  margin-top: 10px;
+  display: flex;
+  justify-content: center;
+}
+
+.method-button {
+  display: inline-block;
+  padding: 4px 8px;
+  border-radius: 5px;
+  cursor: pointer;
+
+  &:hover {
+    background: rgba(150, 171, 185, 0.2);
+  }
+}
+
+/**宽度占位 */
+.placeholder-width-5px{
+  display: inline-block;
+  width: 10px;
+}
+.pictures-upload-info{
+  display: flex;
+  align-items: center;
+  justify-content: flex-start;
+}
+
+.upload-main {
+  width: 800px;
+  height: 109px;
+  background: url("@/assets/document/upload.svg");
+  margin: 0 auto;
+  padding: 24px 0px 24px 277px;
+  background-size: 100%;
+
+  >p {
+    color: #000;
+    font-weight: bold;
+    margin-bottom: 5px;
+    margin-top: 10px;
+
+    >span {
+      color: #00aea3;
+      text-decoration: underline;
+    }
+  }
+
+  >span {
+    font-size: 13px;
+    color: #7f7f7f;
+  }
+}
+
+footer.picture-upload-footer{
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+
+  .text-hide {
+    // width: 110px;
+    overflow: hidden;
+    display: flex;
+    align-items: center;
+  }
+
+  .upload-img-container{
+    cursor: pointer;
+    // width: 110px;
+    height: 32px;
+
+    .img-normal {
+      display: block;
+    }
+
+    .img-hover {
+      display: none;
+    }
+
+    &:hover {
+      .img-normal {
+        display: none;
+      }
+
+      .img-hover {
+        display: block;
+      }
+    }
+
+    >img {
+      width: 110px;
+      height: 32px;
+    }
+  }
+}
+
+main {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+
+  // >section {
+  //   overflow-y: auto;
+  //   display: flex;
+  //   flex-wrap: wrap;
+  //   gap: 20px;
+
+  //   &.section-full {
+  //     flex: 1;
+  //   }
+
+  //   >div {
+  //     width: 382px;
+  //     height: 120px;
+  //     padding: 20px 24px;
+  //     border-radius: 8px;
+  //     display: flex;
+
+  //     >img {
+  //       width: 38px;
+  //       height: 38px;
+  //       margin-right: 12px;
+  //     }
+
+  //     >div {
+  //       font-size: 18px;
+  //       font-weight: bold;
+
+  //       >span {
+  //         font-size: 15px;
+  //         font-weight: 400;
+  //         color: #797d7f;
+  //         margin-top: 8px;
+  //         overflow: hidden;
+  //         text-overflow: ellipsis;
+  //         display: -webkit-box;
+  //         -webkit-line-clamp: 2;
+  //         -webkit-box-orient: vertical;
+  //         line-height: 1.4;
+  //       }
+  //     }
+  //   }
+  // }
+
+
+  >footer {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-top: auto;
+
+    >div {
+      display: inline-flex;
+      align-items: center;
+      gap: 8px;
+      height: 32px;
+      border-radius: 21px;
+      border: 1px solid #e3e3e3;
+      white-space: nowrap;
+      overflow: hidden;
+      transition-duration: 0.3s;
+      width: 250px;
+
+      /**
+      &.text-hide {
+        width: 110px;
+        overflow: hidden;
+      }
+       */
+
+      &.text-narrow {
+        width: 100px;
+        overflow: hidden;
+
+        >div>img {
+          width: 100px;
+        }
+      }
+
+      >p {
+        overflow: hidden;
+        white-space: nowrap;
+      }
+
+      >div {
+        cursor: pointer;
+        width: 110px;
+        height: 32px;
+
+        .img-normal {
+          display: block;
+        }
+
+        .img-hover {
+          display: none;
+        }
+
+        &:hover {
+          .img-normal {
+            display: none;
+          }
+
+          .img-hover {
+            display: block;
+          }
+        }
+
+        >img {
+          width: 110px;
+          height: 32px;
+        }
+      }
+    }
+
+    >section {
+      display: flex;
+      align-items: center;
+      background: rgba(150, 171, 185, 0.2);
+      border-radius: 20px;
+      padding: 5px 10px;
+
+      >p {
+        margin-right: 5px;
+      }
+    }
+  }
+}
+
+.upload-wrap {
+  width: 800px;
+  height: 300px;
+  display: flex;
+  flex-direction: column;
+  padding-bottom: 30px;
+
+  &.upload-wrap-narrow {
+    height: auto;
+  }
+
+  >header {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin-bottom: 13px;
+
+    >p {
+      font-size: 18px;
+      font-weight: bold;
+    }
+
+    >div {
+      width: 38px;
+      height: 38px;
+      border-radius: 6px;
+      cursor: pointer;
+      justify-content: center;
+      align-items: center;
+      display: flex;
+
+      &:hover {
+        background: rgba(0, 0, 0, 0.05);
+      }
+    }
+  }
+
+  >div {
+    flex: 1;
+    overflow-y: auto;
+
+    >div {
+      >p {
+        margin: 20px 0;
+        color: #7f7f7f;
+        font-size: 13px;
+        display: flex;
+        justify-content: space-between;
+      }
+    }
+  }
+}
+</style>

+ 28 - 0
src/components/picture-upload/BtnImgDownload.vue

@@ -0,0 +1,28 @@
+<template>
+<a-tooltip content="下载">
+    <div class="method-button" @click="downloadDocument">
+        <icon-cloud-download />
+    </div>
+</a-tooltip>
+</template>
+<script setup>
+const emit = defineEmits(['download']);
+
+const downloadDocument = () => { 
+    emit('download');
+};
+
+</script>
+
+<style lang="scss" scoped>
+.method-button {
+  display: inline-block;
+  padding: 4px 8px;
+  border-radius: 5px;
+  cursor: pointer;
+
+  &:hover {
+    background: rgba(150, 171, 185, 0.2);
+  }
+}
+</style>

+ 45 - 0
src/components/picture-upload/FileListTable.vue

@@ -0,0 +1,45 @@
+<template>
+<div>
+    <p>
+        <span>已选择图片列表</span>
+        <span>共{{ tableData.length }}个</span>
+    </p>
+    <div>
+        <a-table 
+            :pagination="false" 
+            row-key="name" 
+            :columns="columns" 
+            :data="tableData"
+            :selectedKeys="selectedKeys"
+        >
+            <template #methods="{ record }">
+                <BtnImgDownload @download="downloadDocument(record)"/>
+                <BtnImgDelete @delete="deleteDocument"/>
+            </template>
+        </a-table>
+    </div>
+</div>
+</template>
+<script setup>
+import BtnImgDownload from './BtnImgDownload.vue';
+import BtnImgDelete from './BtnImgDelete.vue';
+
+const props = defineProps({
+    tableData: Array,
+    columns: Array,
+    selectedKeys: Array
+});
+
+const emit = defineEmits(['download', 'delete']);
+
+const downloadDocument = () => { 
+    emit('download');
+};
+
+const deleteDocument = () => {
+    emit('delete');
+}
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 58 - 0
src/store/modules/xs-huitu-image-upload/index.ts

@@ -0,0 +1,58 @@
+import { defineStore } from "pinia";
+
+/**
+ * 在小数绘图的图生文功能中
+ * 用户需要先上传一张图片,然后发布一段文字,询问上传的图片的一些信息
+ * 当用户上传一张图片后,如果不发布文字,继续上传图片,则会引起功能异常
+ * 为了避免用户连续上传图片,而不发布文字,特意做限制:
+ * 用户在上传一张图片后,必须发送一段文本,否则不能继续上传图片
+ * 此store的定义,就是为了处理该场景
+ * img_upload_status 表示图片上传的状态 0 表示图片未上传 1 表示图片已上传
+ * msg_send_status 表示文字发送的状态 0 表示文字未发送 1 表示文字已发送
+ *
+ * 当用户上传一张图片后,应将 img_upload_status 设置为 1,且将 msg_send_status 设置为0
+ * 当用户发送一段文字后,应将 msg_send_status 设置为 1,且将 img_upload_status 设置为 0
+ *
+ * 在上传图片的位置,应检查 img_upload_status 和 msg_send_status 的值,如果 img_upload_status === 1 但是 msg_send_status === 0,则图片上传功能不可用
+ */
+export const useImageUploadStatus = defineStore("imageUploadStatus", {
+  state: () => ({
+    img_upload_status: 0,
+    msg_send_status: 0
+  }),
+
+  getters: {
+    uploadStatus(state) {
+      return state.img_upload_status;
+    },
+    messageStatus(state) {
+      return state.msg_send_status;
+    },
+
+    /**
+     * 是否允许继续上传图片
+     * @param state
+     * @returns
+     */
+    canUploadContinue(state) {
+      return state.img_upload_status === 0;
+    }
+  },
+
+  actions: {
+    /**
+     * 图片已上传
+     */
+    uploadFinish() {
+      this.img_upload_status = 1;
+      this.msg_send_status = 0;
+    },
+    /**
+     * 文本消息已发送
+     */
+    messageFinish() {
+      this.msg_send_status = 1;
+      this.img_upload_status = 0;
+    }
+  }
+});

+ 7 - 7
src/views/Home.vue

@@ -157,8 +157,6 @@ import Slider from "../components/Slider.vue";
 import ProjectIntro from '../components/ProjectIntro.vue';
 import History from "../components/History.vue";
 import MessageInput from "../components/MessageInput.vue";
-// import PictureCards from '@/components/PictureCards.vue'
-// import MessagePicUpload from '../components/MessagePicUpload.vue'
 import PictureFooter from '../components/PictureFooter.vue';
 import DocumentDetail from "./DocumentDetail.vue";
 import DocumentCombine from "./DocumentCombine.vue";
@@ -189,8 +187,6 @@ export default defineComponent({
     Answer,
     MessageInput,
 
-    // PictureCards,
-    // MessagePicUpload,
     PictureFooter,
 
     DialogWrap,
@@ -238,9 +234,11 @@ export default defineComponent({
 
     const historyMode = ref(false);
     const dialogList = ref([]);
+
     const selectId = ref("");
+    const real_agent_id = ref(""); // 实际的agent_id,此值仅在 点击侧边栏具体功能时更改,例如点击 知识问答、文档智能按钮时更改
+    const agentIds = ref([]); // agent ID的列表
 
-    const agentIds = ref([]);
     const dialogId = ref("");
     const historyList = ref([]);
     const variables = ref([]);
@@ -294,6 +292,7 @@ export default defineComponent({
 
       // 获取当前选定的agent对应的ID
       selectId.value = (agents.find(agent => agent.name === node.title) || {}).id || null;
+      real_agent_id.value = selectId.value; // 记录agent_id值
 
       // 获取历史记录
       const data = await ajax.message.getDialogs(selectId.value);
@@ -496,13 +495,14 @@ export default defineComponent({
      * 点击新建对话按钮
      */
     const handelSetNewChat = () => {
+      selectId.value = real_agent_id.value;
+
       showDialog.value = false;
-      // selectId = selectId;
+
       historyMode.value = false;
       setReadonly(false);
 
       // 每次新建对话时,清空sendData数据
-      // helper.write('sendData', {}); 
       clearLocalStorageSendData();
     };
 

+ 1 - 4
src/views/PicArticle.vue

@@ -9,16 +9,13 @@
         </div>
       </div>
     </section>
-
-    <!-- <picture-cards :data="data" /> -->
 </main>
 </template>
 <script>
-import PictureCards from '@/components/PictureCards.vue'
 import { defineComponent, ref, inject, reactive } from "vue";
 export default defineComponent({
     components: {
-        PictureCards
+        
     },
     setup() {
         const { helper, ajax } = inject("$global");