Переглянути джерело

feat: 完善对话文件上传的限定条件

根据智能体的不同,所能上传的文件类型也不同
对此进行了限定
zhupei@smartai.com 1 рік тому
батько
коміт
dd1bab457a

+ 10 - 4
src/modules/conversation-chat/DialogInput.vue

@@ -20,7 +20,7 @@
         :enable_file_upload="enable_file_upload"
         :enable_frequent_question="enable_frequent_question"
         :enable_voice_recognition="enable_voice_recognition"
-        :file_upload_type="file_upload_type"
+        :file_accept="file_accept"
         :file_upload_limit="file_upload_limit"
         @fileUpload="handleFileUpload"
         @questionDefine="handleQuestionDefine"
@@ -98,9 +98,9 @@ const props = defineProps({
    * 对应html属性 accept
    * 对应 arco.design Upload accept 属性
    * @see https://arco.design/vue/component/upload#API
-   * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#htmlattrdefaccept
+   * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept
    */
-  file_upload_type: {
+  file_accept: {
     type: String,
     default: '*',
     required: false
@@ -202,7 +202,12 @@ const handleFileUpload = () => {
   /**
    * 选择文件的配置项
    */
-  const options = {};
+  const options = {
+    /**
+     * 所允许的文件类型
+     */
+    accept: props.file_accept
+  };
 
   /**
    * 选择文件
@@ -361,5 +366,6 @@ defineExpose({
 
 .file-upload-preview-container {
   margin-top: 5px;
+  padding: 5px;
 }
 </style>

+ 1 - 1
src/modules/conversation-chat/dialog-input/InputActions.vue

@@ -85,7 +85,7 @@ const props = defineProps({
    * @see https://arco.design/vue/component/upload#API
    * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#htmlattrdefaccept
    */
-  file_upload_type: {
+  file_accept: {
     type: String,
     default: '*',
     required: false

+ 33 - 0
src/modules/conversation-chat/use-file-select-v2.js

@@ -3,6 +3,30 @@ export default function useFileSelectedV2(options) {
 
   let ele_index = 0;
 
+  const default_opts = {
+    accept: '*'
+  };
+
+  function mergeOption(opts) {
+    if (!opts) {
+      return default_opts;
+    }
+
+    if (Object.keys(opts).length === 0) {
+      return default_opts;
+    }
+
+    const obj = {};
+    for (let key in default_opts) {
+      if (key in opts) {
+        obj[key] = opts[key];
+      } else {
+        obj[key] = default_opts[key];
+      }
+    }
+    return obj;
+  }
+
   return {
     /**
      * 文件选择的配置项
@@ -12,6 +36,11 @@ export default function useFileSelectedV2(options) {
      * @param {function} fn
      */
     select(options, fn) {
+      /**
+       * 合并参数
+       */
+      const opts = mergeOption(options);
+
       /**
        * https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input/file
        */
@@ -21,6 +50,10 @@ export default function useFileSelectedV2(options) {
       input.id = `9d75142a66eb4e23b7d403efe4584915-${cur}-${ele_index}`;
       input.setAttribute('multiple', true);
       input.setAttribute('style', 'display: none;');
+
+      // 设置允许上传的文件类型
+      input.setAttribute('accept', opts.accept);
+
       document.body.appendChild(input);
 
       ele_index = ele_index + 1;

+ 13 - 9
src/modules/file-preview/FileItemDocPreview.vue

@@ -26,8 +26,8 @@
         {{ file.name }}
       </template>
 
-      <ViewerPDFFromFile v-if="doc_type === 'pdf'" :file="file" :doc_width="DOC_WIDTH" :positions="positions" />
-      <ViewerDocxFromFile v-if="doc_type === 'doc'" :file="file" :doc_width="DOC_WIDTH" :positions="positions" />
+      <ViewerPDFFromFile v-if="doc_type === 'pdf'" :file="file" :doc_width="DOC_WIDTH" />
+      <ViewerDocxFromFile v-if="doc_type === 'doc'" :file="file" :doc_width="DOC_WIDTH" />
     </a-drawer>
   </div>
 </template>
@@ -41,6 +41,8 @@ import FileItemRemoveBtn from './FileItemRemoveBtn.vue';
 import ViewerPDFFromFile from '../viewer-pdf/ViewerPDFFromFile.vue';
 import ViewerDocxFromFile from '../viewer-docx/ViewerDocxFromFile.vue';
 
+import { getFileSuffix } from '../../utils/file-utils';
+
 const props = defineProps({
   file: Object,
   enable_remove: Boolean
@@ -59,9 +61,11 @@ const doc_type = computed(() => {
     return '';
   }
 
-  const arr = doc_name.split('.');
-  const len = arr.length;
-  const end_fix = arr[len - 1];
+  // const arr = doc_name.split('.');
+  // const len = arr.length;
+  // const end_fix = arr[len - 1];
+
+  const end_fix = getFileSuffix(doc_name);
 
   if (end_fix === 'pdf') {
     return 'pdf';
@@ -103,8 +107,10 @@ const file_end_fix = computed(() => {
 
   const file_name = file.name || '';
 
-  const name_info_arr = file_name.split('.');
-  const end_fix = name_info_arr[name_info_arr.length - 1];
+  // const name_info_arr = file_name.split('.');
+  // const end_fix = name_info_arr[name_info_arr.length - 1];
+
+  const end_fix = getFileSuffix(file_name);
 
   return end_fix;
 });
@@ -113,8 +119,6 @@ const file_end_fix = computed(() => {
  * 移除
  */
 const handleRemove = () => {
-  console.log('移除文件');
-
   emit('delete');
 };
 

+ 0 - 1
src/modules/viewer-docx/ViewerDocxFromFile.vue

@@ -53,7 +53,6 @@ onMounted(() => {
 
   renderDocxByBlob(box.value, props.file)
     .then((res) => {
-      console.log(res);
       // 所有页面都加载完毕,结束加载状态
       load_status.value = 3; // 加载成功
       load_msg.value = 'success';

+ 3 - 26
src/modules/viewer-docx/ViewerDocxFromUrl.vue

@@ -18,6 +18,7 @@
 <script setup>
 import { ref, useTemplateRef, onMounted } from 'vue';
 import { renderDocxByBlob } from '../../3rd-libs/docx-preview';
+import { url2Blob } from '../../utils/file-utils';
 
 const props = defineProps({
   /**
@@ -43,40 +44,16 @@ const box = useTemplateRef('box');
 const load_status = ref(1); // 1 默认值,未启动 2 加载中 3 成功 5 出错
 const load_msg = ref(''); // 加载消息
 
-/**
- * 将URL转换为blob数据
- * @param url
- */
-async function urlToBlob(url) {
-  try {
-    // 使用 fetch 获取资源
-    const response = await fetch(url);
-
-    // 检查响应是否成功(状态码在 200-299 之间)
-    if (!response.ok) {
-      throw new Error(`Network response was not ok: ${response.statusText}`);
-    }
-
-    // 将响应转换为 Blob 对象
-    const blob = await response.blob();
-
-    return blob;
-  } catch (error) {
-    console.error('There was a problem with the fetch operation:', error);
-    throw error;
-  }
-}
-
 onMounted(() => {
   load_status.value = 2; // 加载中
   load_msg.value = 'loading';
 
-  // 加载完成
-  urlToBlob(props.url)
+  url2Blob(props.url)
     .then((blob) => {
       renderDocxByBlob(box.value, blob)
         .then((res) => {
           console.log(res);
+
           // 所有页面都加载完毕,结束加载状态
           load_status.value = 3; // 加载成功
           load_msg.value = 'success';

+ 46 - 0
src/utils/file-utils.js

@@ -0,0 +1,46 @@
+import getSize from '../3rd-libs/filesize';
+
+/**
+ * 获取文件的尺寸
+ */
+export const getFileSize = getSize;
+
+/**
+ * 将URL转换为blob数据
+ * @param {string} url -  地址
+ */
+export async function url2Blob(url) {
+  try {
+    // 使用 fetch 获取资源
+    const response = await fetch(url);
+
+    // 检查响应是否成功(状态码在 200-299 之间)
+    if (!response.ok) {
+      throw new Error(`Network response was not ok: ${response.statusText}`);
+    }
+
+    // 将响应转换为 Blob 对象
+    const blob = await response.blob();
+
+    return blob;
+  } catch (error) {
+    console.error('There was a problem with the fetch operation:', error);
+    throw error;
+  }
+}
+
+/**
+ * 根据文件名获取文件后缀名
+ * @param {string} file_name
+ * @returns
+ */
+export const getFileSuffix = (file_name) => {
+  if (!file_name) {
+    return '';
+  }
+
+  const name_info_arr = file_name.split('.');
+  const end_fix = name_info_arr[name_info_arr.length - 1];
+
+  return end_fix;
+};

+ 43 - 5
src/views/conversation/ConversationChatContainer.vue

@@ -32,6 +32,7 @@
           :style="input_style"
           :disabled="input_disabled"
           :enable_file_upload="enable_file_upload"
+          :file_accept="file_accept"
           @sizeChange="handleInputSizeChange"
           @submit="handleInputSubmit"
         >
@@ -277,11 +278,11 @@ const enable_file_upload = computed(() => {
   const menu_id = current_menu_id.value;
 
   /**
-   * 1 报表合并:上传几个文档,进行合并
-   * 3 文档智能:上传文档,让智能体进行解析
-   * 5 智能数据:上传Excel,生成饼状图
-   * 6 小数绘图:上传图片,描述图片的内容
-   * 9 文档报告
+   * 1 报表合并:上传几个文档,进行合并  允许 .xlsx
+   * 3 文档智能:上传文档,让智能体进行解析 允许: .pdf/.docx
+   * 5 智能数据:上传Excel,生成饼状图 允许 .xlsx
+   * 6 小数绘图:上传图片,描述图片的内容 允许 .png/jpg/jpeg
+   * 9 文档报告: 允许 .docx
    */
   if (menu_id === 1 || menu_id === 3 || menu_id === 5 || menu_id === 6 || menu_id === 9) {
     return true;
@@ -289,6 +290,43 @@ const enable_file_upload = computed(() => {
 
   return false;
 });
+/**
+ * 表单区域:是否允许文件上传的类型
+ * 对应表单参数的 accept
+ */
+const file_accept = computed(() => {
+  const menu_id = current_menu_id.value;
+
+  /**
+   * 1 报表合并:上传几个文档,进行合并  允许 .xlsx
+   * 3 文档智能:上传文档,让智能体进行解析 允许: .pdf/.docx
+   * 5 智能数据:上传Excel,生成饼状图 允许 .xlsx
+   * 6 小数绘图:上传图片,描述图片的内容 允许 .png/jpg/jpeg
+   * 9 文档报告: 允许 .docx
+   */
+
+  if (menu_id === 1) {
+    return '.xlsx';
+  }
+
+  if (menu_id === 3) {
+    return '.pdf,.docx';
+  }
+
+  if (menu_id === 5) {
+    return '.xlsx';
+  }
+
+  if (menu_id === 6) {
+    return '.jpg,.jpeg,.png';
+  }
+
+  if (menu_id === 9) {
+    return '.docx';
+  }
+
+  return '*';
+});
 
 /**
  * 内容分享操作