Selaa lähdekoodia

feat: 新增文档报告生成功能

zhupei 1 vuosi sitten
vanhempi
sitoutus
9dbfb3e5eb
3 muutettua tiedostoa jossa 347 lisäystä ja 49 poistoa
  1. 32 1
      src/components/DialogWrap.vue
  2. 270 0
      src/components/DocumentReportFooter.vue
  3. 45 48
      src/views/Home.vue

+ 32 - 1
src/components/DialogWrap.vue

@@ -141,7 +141,7 @@
 
                         <section>
                             <DocRefItem v-for="(knowledge, knowledgeIndex) in item.reference" :key="knowledgeIndex"
-                                :knowledge="knowledge" :knowledgeIndex="knowledgeIndex" @go-document="goKnowledge"/>
+                                :knowledge="knowledge" :knowledgeIndex="knowledgeIndex" @go-document="goKnowledge(item.fullRefference)"/>
                         </section>
                     </div>
 
@@ -874,6 +874,37 @@ export default defineComponent({
                     }
                 }
 
+                if (chat_type === 'document_report') {
+                    const docReport = helper.read('sendData');
+
+                    if (docReport) {
+                        const upload_files = docReport.upload_files;
+
+                        sendData = {
+                            title: value,
+                            upload_files: docReport.upload_files,
+                            workflow: docReport.workflow
+                        }
+
+                        setTimeout(() => {
+                            // // 文字消息上传成功
+                            // imageUploadStatus.messageFinish();
+
+                            // // 记录此时页面中的问题记录
+                            // huituSetTempImageIndex(dialogList.length);
+
+                            helper.write('sendData', {});
+                        });
+                    } else {
+                        console.log('无数据信息');
+
+                        sendData = {
+                            message: value
+                        };
+                    }
+                }
+
+
                 const dt = JSON.stringify(sendData);
 
                 // 发送socket数据

+ 270 - 0
src/components/DocumentReportFooter.vue

@@ -0,0 +1,270 @@
+<template>
+    <footer class="upload-footer wendangbaogaoshengcheng-footer" v-if="start_status !== 3">
+        <!-- <template v-if="start_status === 1"> -->
+            <a-radio-group @change="handleTypeChange" v-model="act_type" :options="act_opts"></a-radio-group>
+
+            <div class="vertical-placeholder"></div>
+
+            <a-typography-text>
+                标题<span class="attention-requred">*</span>
+            </a-typography-text>
+            <a-input :style="{ flex: '1' }" v-model="textValue" :placeholder="`请输入标题`" allow-clear
+                @input="handleInputChange" />
+
+            <div class="vertical-placeholder"></div>
+
+            <a-typography-text>
+                请上传文件<span class="attention-requred">*</span>({{ file_total }}/{{ MAX_ACCEPT_FILE }})
+            </a-typography-text>
+            <a-upload :style="{ width: '300px' }" :file-list="file_list" :multiple="true" :limit="MAX_ACCEPT_FILE"
+                :auto-upload="false" :show-upload-button="{ showOnExceedLimit: false }" accept=".pdf,.docx"
+                @change="handleFileChange" />
+
+            <div class="vertical-placeholder"></div>
+
+            <a-button :style="{ width: '500px' }" type="primary" @click="handleStart" :disabled="start_status !== 1">开始</a-button>
+        <!-- </template>
+
+        <template v-if="start_status === 2">
+            <a-spin :size="32" />
+        </template>
+
+        <template v-if="start_status === 3">
+            <a-result status="success" title="文件已上传"></a-result>
+        </template>
+
+        <template v-if="start_status === 4">
+            <a-result status="warning" :title="start_message"></a-result>
+        </template>
+
+        <template v-if="start_status === 5">
+            <a-result status="error" :title="start_message"></a-result>
+        </template> -->
+    </footer>
+</template>
+<script setup>
+import { ref, inject, computed } from "vue";
+import { Message } from '@arco-design/web-vue';
+
+const props = defineProps({
+    agentId: String,
+});
+
+const { config, helper, ajax } = inject("$global");
+
+// 操作类型
+const act_type = ref(1);
+const act_opts = [
+    { label: '文档清洗', value: 1 },
+    { label: '报告生成', value: 2 },
+];
+
+// 标题
+const textValue = ref("");
+const maxLength = ref(120); // 允许输入的最大长度
+
+/**
+ * 文件处理
+ */
+const file_list = ref([]);
+const MAX_ACCEPT_FILE = 6;
+const file_total = computed(() => {
+    return file_list.value.length;
+});
+
+/**
+ * 网络请求状态
+ */
+const start_status = ref(1); // 状态值:1 初始 2 进行中 3 成功 4 出错 5 异常
+const start_message = ref('');
+
+/**
+ * 操作类型变化
+ * @param value
+ */
+const handleTypeChange = (value) => {
+    // console.log(value, '操作类型变化');
+}
+
+/**
+ * 标题数据变化
+ * @param value
+ */
+const handleInputChange = (value) => {
+    // console.log(value, '用戶輸入的内容');
+}
+
+/**
+ * 文件数据变化
+ * @param fileList
+ */
+const handleFileChange = (fileList) => {
+    file_list.value = fileList;
+
+    // console.log(fileList, '文件列表');
+}
+
+/**
+ * 文件上传操作
+ */
+const getFIleParams = () => {
+    const formData = new FormData();
+
+    const f_list = file_list.value;
+
+    f_list.forEach((item) => {
+        const file = item.file;
+
+        formData.append("file", file);
+    });
+
+    return formData;
+}
+
+/**
+ * 判断是否允许开始
+ */
+const canStart = () => {
+    const action_type = act_type.value; // 操作类型
+    const title = textValue.value; // 标题
+    const f_list = file_list.value;
+
+    if (!action_type || !title || f_list.length === 0) {
+        return false;
+    }
+
+    return true;
+}
+
+/**
+ * 点击开始按钮
+ * 1. 上传所有的文件,
+ * 2. 开始对话
+ */
+const handleStart = async () => {
+    const action_type = act_type.value; // 操作类型
+    const title = textValue.value; // 标题
+    const f_list = file_list.value;
+
+    if (!action_type) {
+        Message.error({content: '请选择类型', position: 'bottom'});
+        return;
+    }
+
+    if (!title) {
+        Message.error({content: '请填写标题', position: 'bottom'});
+        return;
+    }
+
+    if (f_list.length === 0) {
+        Message.error({content: '请选择文件', position: 'bottom'});
+        return;
+    }
+
+
+    const agent_id = props.agentId;
+
+    try {
+        // 进行中
+        start_status.value = 2;
+        start_message.value = 'loading';
+
+        // // 创建会话
+        // const dialog = await ajax.message.createDialog(agent_id);
+
+        // const chat_id = dialog.chat_id;
+
+        // 文件参数数据
+        const fm_data = getFIleParams();
+
+        const uploadResult1 = await ajax.file.uploadFiles(agent_id, fm_data);
+        // console.log(uploadResult1, '上传结果');
+
+        // const uploadResult2 = await ajax.file.uploadFile(agent_id, chat_id, fm_data);
+        // console.log(uploadResult2, '上传结果');
+
+        // if (uploadResult2.code !== 200) {
+        //     // 失败: 接口值不为 200,接口异常
+        //     start_status.value = 4;
+        //     start_message.value = uploadResult2.msg;
+        //     return;
+        // }
+
+        // console.log(uploadResult2, '文件上传结果');
+        const files_info = uploadResult1.files; // 数组
+        const file_id_list = files_info.map(item => item.id);
+        // console.log(file_id_list, '文件ID值');
+
+        // 保存小数绘图数据
+        helper.write('sendData', {
+            name: '文档报告生成',
+
+            agent_id: agent_id,
+            // chat_id: chat_id,
+
+            upload_files: file_id_list,
+            title: title,
+            workflow: action_type,
+        });
+
+        // helper.$bus.emit('send-message', {
+        //     upload_files: file_id_list,
+        //     title: title,
+        //     workflow: action_type,
+        // });
+
+        // helper.$bus.emit('send-message', title);
+        helper.$bus.emit('open-dialog', title);
+
+
+        // 上传成功
+        start_status.value = 3;
+        start_message.value = 'success';
+    } catch (err) {
+        console.log(err);
+
+        start_status.value = 5;
+        start_message.value = err.message;
+    }
+}
+
+const text_area_style = {
+    flex: 1,
+    borderRadius: '12px',
+    marginTop: '20px',
+    padding: '0px 30px 0 16px',
+    background: 'transparent',
+    border: '1px solid #e3e3e3',
+    minHeight: '120px',
+    paddingBottom: `${textValue.value.length > maxLength.value / 2 ? '20px' : ''}`
+};
+</script>
+<style lang="scss" scoped>
+.vertical-placeholder{
+    height: 10px;
+}
+
+.upload-footer {
+    margin-bottom: 50px;
+    padding: 20px;
+    width: 540px;
+    border: 1px solid #eee;
+}
+
+.attention-requred{
+    color: red;
+}
+
+.wendangbaogaoshengcheng-footer{
+    min-height: 240px;
+}
+</style>
+<style>
+.wendangbaogaoshengcheng-footer .arco-upload-icon.arco-upload-icon-start{
+    display: none;
+}
+
+.wendangbaogaoshengcheng-footer .arco-upload-progress{
+    display: none;
+}
+</style>

+ 45 - 48
src/views/Home.vue

@@ -2,15 +2,11 @@
     <div id="app">
         <Slider @select-nav="selectNav" :navId="navId" v-show="!closeOthers"></Slider>
 
-    <div class="main">
-      <div :class="{ 'history-wrap': true, 'history-wrap-open': !closeOthers && navId > -1 }">
-        <History
-          :list="historyList"
-          :selectId="selectId"
-          @handle-click="selectHistory"
-          @set-new="handelSetNewChat"
-        />
-      </div>
+        <div class="main">
+            <div :class="{ 'history-wrap': true, 'history-wrap-open': !closeOthers && navId > -1 }">
+                <History :list="historyList" :selectId="selectId" @handle-click="selectHistory"
+                    @set-new="handelSetNewChat" />
+            </div>
 
             <div class="wrap">
                 <Index v-if="navId === -1" :number="swiperNumber" @select-nav="selectNav" />
@@ -38,12 +34,12 @@
                             <!-- 文档出卷 -->
                             <DocumentQuestion v-if="navId === 7 && !showDialog" :agentId="selectId" />
 
-              <!-- 出题组卷 -->
-              <DocumentQuestion2 v-if="navId === 8 && !showDialog" :agentId="selectId" />
+                            <!-- 出题组卷 -->
+                            <DocumentQuestion2 v-if="navId === 8 && !showDialog" :agentId="selectId" />
 
                             <!-- 文库详情 -->
-                            <DocumentDetail v-if="navId === -2" :targetDocument="targetDocument" :dialogList="dialogList"
-                                @go-back="goBack" />
+                            <DocumentDetail v-if="navId === -2" :targetDocument="targetDocument"
+                                :dialogList="dialogList" @go-back="goBack" />
 
                             <dialog-wrap v-if="showDialog && initDialog" v-show="!hideDialog" :type="dialogType[navId]"
                                 :isSetting="false" :readonly="readonly" :agentId="selectId" :dialogId="dialogId"
@@ -52,7 +48,7 @@
                         </section>
 
                         <footer
-                            v-if="navId !== -2 && navId !== 0 && navId !== 3 && navId !== 6 && navId !== 1 && !historyMode">
+                            v-if="navId !== -2 && navId !== 0 && navId !== 3 && navId !== 6 && navId !== 1 && navId !== 9 && !historyMode">
                             <BtnIframeChujuan v-if="navId == 7" />
                             <message-input :readonly="readonly" eventName="open-dialog" />
                         </footer>
@@ -66,32 +62,21 @@
                                 </div>
 
                                 <div>
-                                    <a-input :style="{ flex: '1' }" :placeholder="`请输入${item.variable_name}`" allow-clear
-                                        @change="(event) => {
+                                    <a-input :style="{ flex: '1' }" :placeholder="`请输入${item.variable_name}`"
+                                        allow-clear @change="(event) => {
                                             customChange(event, item.node_id, item.variable_name);
-                                        }
-                                            " v-if="item.value_type === 1" />
+                                        }" v-if="item.value_type === 1" />
                                     <a-upload v-else :style="{ width: '300px' }" :multiple="false" :limit="1"
                                         :custom-request="(option) => {
                                             customRequest(option, item.node_id, item.variable_name);
-                                        }
-                                            " :show-upload-button="{ showOnExceedLimit: true }"
+                                        }" :show-upload-button="{ showOnExceedLimit: true }"
                                         accept=".pdf,.doc,.docx,.txt,.md,.ppt.pptx" />
                                 </div>
                             </section>
 
                             <a-textarea :max-length="maxLength" v-model="textValue"
                                 :show-word-limit="textValue.length > maxLength / 2" :auto-size="{ maxRows: 6 }"
-                                placeholder="输入您想了解的内容,Shift+Enter换行" :style="{
-                                    flex: 1,
-                                    borderRadius: '12px',
-                                    marginTop: '20px',
-                                    padding: '0px 30px 0 16px',
-                                    background: 'transparent',
-                                    border: '1px solid #e3e3e3',
-                                    minHeight: '120px',
-                                    paddingBottom: `${textValue.length > maxLength / 2 ? '20px' : ''}`
-                                }">
+                                placeholder="输入您想了解的内容,Shift+Enter换行" :style="text_area_style">
                             </a-textarea>
 
                             <a-button :style="{ width: '500px' }" type="primary" @click="beginCombine">开始</a-button>
@@ -104,17 +89,17 @@
                                         <span>{{ item.variable_name }}</span>
                                     </p>
                                 </div>
+
                                 <div>
-                                    <a-input :style="{ flex: '1' }" :placeholder="`请输入${item.variable_name}`" allow-clear
-                                        @change="(event) => {
+                                    <a-input :style="{ flex: '1' }" :placeholder="`请输入${item.variable_name}`"
+                                        allow-clear @change="(event) => {
                                             customChange(event, item.node_id, item.variable_name);
-                                        }
-                                            " v-if="item.value_type === 1" />
+                                        }" v-if="item.value_type === 1" />
+
                                     <a-upload v-else :style="{ width: '300px' }" :multiple="false" :limit="1"
                                         :custom-request="(option) => {
                                             customRequest(option, item.node_id, item.variable_name);
-                                        }
-                                            " :show-upload-button="{ showOnExceedLimit: true }"
+                                        }" :show-upload-button="{ showOnExceedLimit: true }"
                                         accept=".pdf,.doc,.docx,.txt,.md,.ppt.pptx" />
                                 </div>
                             </section>
@@ -124,16 +109,7 @@
                         <footer v-if="navId === 3 && showDialog && !historyMode" class="upload-footer">
                             <a-textarea :max-length="maxLength" v-model="textValue" :disabled="parseStatus"
                                 :show-word-limit="textValue.length > maxLength / 2" :auto-size="{ maxRows: 6 }"
-                                placeholder="输入您想了解的内容,Shift+Enter换行" :style="{
-                                    flex: 1,
-                                    borderRadius: '12px',
-                                    marginTop: '20px',
-                                    padding: '0px 30px 0 16px',
-                                    background: 'transparent',
-                                    border: '1px solid #e3e3e3',
-                                    minHeight: '120px',
-                                    paddingBottom: `${textValue.length > maxLength / 2 ? '20px' : ''}`
-                                }">
+                                placeholder="输入您想了解的内容,Shift+Enter换行" :style="text_area_style">
                             </a-textarea>
                             <a-button :style="{ width: '500px' }" type="primary" @click="continueCombine">开始</a-button>
                         </footer>
@@ -141,6 +117,8 @@
                         <!-- 小数绘图底部输入栏 -->
                         <PictureFooter v-if="navId === 6 && !historyMode" :agentId="selectId" />
 
+                        <DocumentReportFooter v-if="navId === 9 && !showDialog" :agentId="selectId" />
+
                         <!-- 侧边栏切换按钮 -->
                         <ToggleBtn v-if="navId !== -2" :closeOthers="closeOthers" @toggle="openAll" />
                     </div>
@@ -173,6 +151,8 @@ import Analysis from "./Analysis.vue";
 
 import ToggleBtn from '../components/ToggleBtn.vue';
 
+import DocumentReportFooter from '../components/DocumentReportFooter.vue'
+
 import BtnIframeChujuan from '../components/btn-iframe-chujuan/BtnIframeChujuan.vue'
 
 import { defineComponent, ref, onMounted, inject, onBeforeUnmount } from "vue";
@@ -203,6 +183,8 @@ export default defineComponent({
 
         ToggleBtn,
         BtnIframeChujuan, // 文档出卷按钮
+
+        DocumentReportFooter
     },
     setup() {
         // NOTE: 先把4文库问答的类型改成report类型,后续再改回来
@@ -215,7 +197,9 @@ export default defineComponent({
             "smartData",
             "huitu",  // 小数绘图
             "question",
-            "question"
+
+            "question",
+            'document_report', // 文档报告生成
         ];
 
         const { config, helper, ajax } = inject("$global");
@@ -522,6 +506,17 @@ export default defineComponent({
             // helper.write('sendData', {});
         }
 
+        const text_area_style = {
+            flex: 1,
+            borderRadius: '12px',
+            marginTop: '20px',
+            padding: '0px 30px 0 16px',
+            background: 'transparent',
+            border: '1px solid #e3e3e3',
+            minHeight: '120px',
+            paddingBottom: `${textValue.value.length > maxLength.value / 2 ? '20px' : ''}`
+        };
+
         return {
             SYSTEM_NAME,
             customChange,
@@ -556,7 +551,9 @@ export default defineComponent({
             maxLength,
 
             handelSetNewChat,
-            targetDocument
+            targetDocument,
+
+            text_area_style
         };
     }
 });