Forráskód Böngészése

fix: 生成报告修改

hanyang 1 éve
szülő
commit
e992ee8fbb

+ 58 - 39
src/components/DialogWrap.vue

@@ -52,17 +52,15 @@
                             <icon-check-circle-fill :size="18" v-else />
                             <span>{{ item.capacity.status === "loading" ? "小数正在检索" : "查看检索信息" }}</span>
                             <!-- <b>{{ item.capacity.text }}</b> -->
-                            <icon-caret-right size="18"
-                                v-if="item.capacity.status === 'loaded' && !menuList[key]?.open" />
-                            <icon-caret-down size="18"
-                                v-if="item.capacity.status === 'loaded' && menuList[key]?.open" />
+                            <icon-caret-right size="18" v-if="item.capacity.status === 'loaded' && !menuList[key]?.open" />
+                            <icon-caret-down size="18" v-if="item.capacity.status === 'loaded' && menuList[key]?.open" />
                         </div>
 
                         <div v-else v-show="item.capacity.status === 'loading'"
                             :class="[readonly || item.capacity.status === 'loading' ? 'disabled' : '']">
                             <a-spin :size="18" />
                             <span v-if="type !== 'document_report'">{{ type === 'excel' ? '正在为您合并...' : '正在为您搜索答案...'
-                                }}</span>
+                            }}</span>
                             <span v-if="type === 'document_report'">{{ document_report_system_message }}</span>
                         </div>
 
@@ -88,10 +86,9 @@
                                         <span>
                                             <em v-for="(item, documentIndex) in document.list" :key="documentIndex">{{
                                                 item.title
-                                                }}</em>
+                                            }}</em>
                                         </span>
-                                        <icon-caret-down size="12"
-                                            v-if="documentKey === menuList[key].documentOpenIndex" />
+                                        <icon-caret-down size="12" v-if="documentKey === menuList[key].documentOpenIndex" />
                                         <icon-caret-right size="12" v-else />
                                     </div>
 
@@ -102,7 +99,7 @@
                                                 :style="{ flex: 1, margin: '0' }">
                                                 <span style="color: rgba(153, 153, 153, 1); font-size: 12px">{{
                                                     item.content
-                                                    }}</span>
+                                                }}</span>
                                             </a-typography-paragraph>
                                         </p>
                                     </div>
@@ -131,9 +128,8 @@
                     </div>
 
                     <div class="dialog-footer" v-else>
-                        <Answer :answer="item.answer" :index="key" :chat_id="dialogId" :chat_type="type"
-                            :agentId="agentId" :special_4_refference="item.fullRefference"
-                            :special_4_image="item.fullImageUrls" />
+                        <Answer :answer="item.answer" :index="key" :chat_id="dialogId" :chat_type="type" :agentId="agentId"
+                            :special_4_refference="item.fullRefference" :special_4_image="item.fullImageUrls" />
                     </div>
 
                     <!-- 处理来源 -->
@@ -146,9 +142,9 @@
                         </header>
 
                         <section>
-                            <DocRefItem v-for="(knowledge, knowledgeIndex) in item.reference.slice(0,3)"
+                            <DocRefItem v-for="(knowledge, knowledgeIndex) in item.reference.slice(0, 3)"
                                 :key="knowledgeIndex" :knowledge="knowledge" :knowledgeIndex="knowledgeIndex"
-                                @go-document="goKnowledge($event,item)" />
+                                @go-document="goKnowledge($event, item)" />
                         </section>
                     </div>
 
@@ -195,13 +191,15 @@
                                 </p>
                             </a-tooltip>
                             <a-tooltip content="查看日志">
-                                <p @click="checkLogs(item)" :class="[readonly ? 'disabled' : '']">
-                                    <icon-calendar />
+                                <p :class="[readonly ? 'disabled' : '']">
+                                    <BtnShowLog :logs_info="item.workflow"></BtnShowLog>
                                 </p>
+
                             </a-tooltip>
                             <a-tooltip content="生成报告">
                                 <p @click="generateReport(item)" :class="[readonly ? 'disabled' : '']">
                                     <icon-bookmark />
+
                                 </p>
                             </a-tooltip>
 
@@ -235,8 +233,7 @@
         <!-- <div v-show="readonly" @click="stopWriting" class="dialog-writing-button">
             <icon-record-stop :size="20" style="margin-right: 4px" />停止生成
         </div> -->
-        <dialog-feedback :showFeedback="showFeedback" @handleCancel="handleCancel" @handleOk="handleOk"
-            v-if="!isSetting" />
+        <dialog-feedback :showFeedback="showFeedback" @handleCancel="handleCancel" @handleOk="handleOk" v-if="!isSetting" />
     </div>
 </template>
 <script>
@@ -244,6 +241,7 @@ import { computed } from 'vue';
 
 
 import DialogFeedback from "./DialogFeedback.vue";
+import  BtnShowLog from './doc-gen-logs/BtnShowLog.vue'
 import { defineComponent, ref, onBeforeUnmount, onMounted, reactive, nextTick, inject } from "vue";
 
 import formatAnwserString from './answer-effect/format-anwser-string';
@@ -289,7 +287,8 @@ export default defineComponent({
         DocRefItem,
         CodeDisplay,
 
-        TimeWaste
+        TimeWaste,
+        BtnShowLog
     },
     props: [
         "open",
@@ -367,7 +366,6 @@ export default defineComponent({
         let dialogIndex = dialogList.length;
         const dialogScroll = ref("");
         const dialogConfig = ref({});
-
         const scrollToEnd = async () => {
             await nextTick();
             if (dialogScroll.value) {
@@ -439,13 +437,14 @@ export default defineComponent({
                 }
             }
         };
-        const checkLogs = (item) => {
-            // TODO: 查看日志
+        const closeReportLog = () => {
+            show_report_log.value = false
         }
         const generateReport = (item) => {
             // TODO: 生成报告
-            // console.log(item)
-            // helper.write('generate-report',item)
+            console.log(item)
+            // helper.write('generate-report', item)
+            helper.$bus.emit('open-document-dialog', item)
         }
 
 
@@ -470,7 +469,7 @@ export default defineComponent({
         };
         const checkAllReference = (fullRef) => {
             const knowledge = fullRef.reference[0];
-            goKnowledge(knowledge,fullRef)
+            goKnowledge(knowledge, fullRef)
         }
         // // 点击文档,打开新页面
         // const openDocuementPage = (knowledge) => {
@@ -659,7 +658,6 @@ export default defineComponent({
              */
             function handleSocketMessage(evt_dt, cur_chat_id) {
                 let res_data = null;
-
                 try {
                     res_data = JSON.parse(evt_dt);
                 } catch (err) {
@@ -669,7 +667,7 @@ export default defineComponent({
                 if (!res_data) {
                     return;
                 }
-
+                console.log(res_data,77)
                 const { type, reference, step_message, files } = res_data;
                 const msg_type = type; // 返回的消息类型
                 const chat_type = props.type; // 对话的类型
@@ -858,15 +856,31 @@ export default defineComponent({
                     // 文档报告,记录结束时间
                     if (chat_type === 'document_report') {
 
-                        if (document_report_time_end.value === null) {
+                        // if (document_report_time_end.value === null) {
+
+                        //     document_report_time_end.value = Date.now();
+
+                        //     const the_last = dialogList.pop();
 
-                            document_report_time_end.value = Date.now();
+                        //     const final_item = {
+                        //         doc_report_time_start: document_report_time_start.value,
+                        //         doc_report_time_end: document_report_time_end.value
+                        //     };
 
+                        //     for (let key in the_last) {
+                        //         final_item[key] = the_last[key];
+                        //     }
+
+                        //     dialogList.push(final_item);
+                        //     // 时间已使用,重置为null
+                        //     document_report_time_start.value = null;
+                        //     document_report_time_end.value = null;
+                        // }
+                        if (res_data && res_data.workflow) {
                             const the_last = dialogList.pop();
 
                             const final_item = {
-                                doc_report_time_start: document_report_time_start.value,
-                                doc_report_time_end: document_report_time_end.value
+                                doc_report_workflow: res_data.workflow,
                             };
 
                             for (let key in the_last) {
@@ -874,10 +888,8 @@ export default defineComponent({
                             }
 
                             dialogList.push(final_item);
-                            // 时间已使用,重置为null
-                            document_report_time_start.value = null;
-                            document_report_time_end.value = null;
                         }
+
                     } else {
                         // console.log('非文档报告');
                     }
@@ -1035,7 +1047,7 @@ export default defineComponent({
 
                 if (chat_type === 'document_report') {
                     const docReport = helper.read('sendData');
-
+                    console.log(docReport, 'docReport');
                     if (docReport) {
                         const upload_files = docReport.upload_files;
 
@@ -1047,6 +1059,7 @@ export default defineComponent({
                                 title: value,
                                 upload_files: docReport.upload_files,
                             }
+
                         }
 
                         if (workflow === 2) {
@@ -1061,6 +1074,8 @@ export default defineComponent({
                                  * 当workflow值为2时,存在此参数
                                  */
                                 sub_titles: docReport.sub_titles,
+                                // 文件类型
+                                file_type: docReport.file_type,
                             }
                         }
 
@@ -1075,10 +1090,15 @@ export default defineComponent({
                                     title: value,
                                     upload_files: docReport.upload_files,
 
-                                    "title_number": docReport.title_number/1,
+                                    "title_number": docReport.title_number / 1,
                                     "title_style": docReport.title_style,
                                     "title_query": docReport.title_query,
+                                    "is_clean": docReport.is_clean,
+                                }
+                                if (docReport.maxToken) {
+                                    sendData.max_tokens = docReport.maxToken;
                                 }
+                                console.log(sendData, 'sendData');
                             } else {
                                 // 后续连续问答参数
                                 sendData = {
@@ -1161,7 +1181,7 @@ export default defineComponent({
 
             showFeedback,
             copyAnswer,
-            checkLogs,
+            closeReportLog,
             generateReport,
             dialogList,
             getHTML,
@@ -1861,10 +1881,9 @@ export default defineComponent({
 }
 
 
-.answer-action-btns-container{
+.answer-action-btns-container {
     align-items: center;
 }
-
 </style>
 <style>
 .circle {

+ 188 - 54
src/components/DocumentReportFooter.vue

@@ -1,7 +1,7 @@
 <template>
     <footer class="wendangbaogaoshengcheng-footer" v-if="show_doc_rpt_footer">
         <div class="upload-footer" v-show="doc_form_show">
-            <div v-if="act_type === 3 && init_status" class="form-fold-btn" @click="handleFormFold">
+            <div v-show="act_type === 3 && init_status" class="form-fold-btn" @click="handleFormFold">
                 <icon-menu-fold :size="20" />
             </div>
 
@@ -10,7 +10,7 @@
             <div class="vertical-placeholder"></div>
 
             <TextInputType1 v-if="act_type === 1" @change="handleTextChange" />
-            <TextInputType2 v-if="act_type === 2" @change="handleTextChange" />
+            <TextInputType2 v-if="act_type === 2" :report_text="report_text" @change="handleTextChange" />
             <TextInputType3 v-if="act_type === 3" @change="handleTextChange" />
 
             <div class="vertical-placeholder"></div>
@@ -23,15 +23,19 @@
                 <a-upload :file-list="file_list" :multiple="true" :limit="MAX_ACCEPT_FILE" :auto-upload="false"
                     :show-upload-button="{ showOnExceedLimit: false }" accept=".pdf,.docx" @change="handleFileChange">
                     <template #upload-button>
-                        <a-tooltip :content="upload_warning_text">
-                            <a-button class="upload-button">
-                                <template #icon>
-                                    <icon-upload />
-                                </template>
-
-                                <template #default>点击上传</template>
-                            </a-button>
-                        </a-tooltip>
+                        <a-space>
+                            <a-tooltip :content="upload_warning_text">
+                                <a-button class="upload-button">
+                                    <template #icon>
+                                        <icon-upload />
+                                    </template>
+
+                                    <template #default>点击上传</template>
+                                </a-button>
+                            </a-tooltip>
+                            <a-typography>{{ '(' + file_list.length + '/' + MAX_ACCEPT_FILE + ')' + "已上传/最大支持"
+                            }}</a-typography>
+                        </a-space>
                     </template>
 
                     <template #file-name="{ fileItem }">
@@ -50,16 +54,18 @@
 
 
             <template v-if="act_type === 2 || act_type === 1 || show_start_btn">
+                <!-- <template v-if="act_type === 2 || act_type === 1 || is_first_generate"> -->
                 <div class="vertical-placeholder"></div>
 
                 <a-button :style="{ width: '500px' }" type="primary" @click="handleStart"
                     :disabled="start_status !== 1">开始</a-button>
             </template>
         </div>
-
         <template v-if="act_type === 3 && show_chat_text_input">
+            <!-- <template v-if="act_type === 3 && !is_first_generate"> -->
             <div class="message-input-container">
-                <div v-show="!doc_form_show" class="form-fold-btn open" @click="handleFormOpen">
+                <!-- 按需求新修改为,小标题多轮对话中只允许问答不允许修改 先对该按钮做隐藏 -->
+                <div v-show="false && !doc_form_show" class="form-fold-btn open" @click="handleFormOpen">
                     <!-- <icon-menu-fold :size="20" /> -->
                     <a-space>
                         <icon-menu-unfold :size="20" />
@@ -75,7 +81,7 @@
     </footer>
 </template>
 <script setup>
-import { ref, inject, computed } from "vue";
+import { ref, inject, computed, watch } from "vue";
 import { Message } from '@arco-design/web-vue';
 
 import MessageInputV2 from "./MessageInputV2.vue";
@@ -85,6 +91,7 @@ import TextInputType1 from './document-report/TextInputType1.vue'
 import TextInputType2 from './document-report/TextInputType2.vue'
 import TextInputType3 from './document-report/TextInputType3.vue'
 
+
 /**
  * 与此组件有关的对话参数的文档可查看此文件同目录下的 DocumentReportFooter.md 文件
  */
@@ -116,6 +123,12 @@ const text_title = ref(""); // 单行文本:标题
 const text_description = ref(""); // 多行文本:描述
 const chat_message = ref(''); // 对话输入框的消息
 
+const is_clean = ref(1); // 是否是文档清洗
+const max_tokens = ref(0); // 默认最大tokens
+const tokens = ref(0); //上传文件的token数
+const report_text = ref(''); //生成报告回填的小标题及关键内容
+const file_type = ref(1); // 文件类型 1本地文件  2清洗后的连接文件
+
 /**
  * 是否是第一次 小标题生成
  */
@@ -160,15 +173,78 @@ const handleFormFold = () => {
 const handleFormOpen = () => {
     doc_form_show.value = true;
 }
+// 订阅打开用户生成报告弹框事件
+helper.$bus.on('open-document-dialog', (item) => {
+    text_description.value = item.answer
+    report_text.value = text_description.value
+    // console.log(report_text.value, 999)
+    // console.log(text_description.value, 999)
+    console.log(item, 999)
+    let file_urls
+    /**
+     * 如果有文件,则使用文件链接,否则使用文件列表
+     * 否则使用文件列表
+     * */
+    if (item.file && item.file.file_url) {
+        file_urls = [item.file.file_url]
+        report_file_list.value = processFileUrls(file_urls)
+        file_list.value = report_file_list.value
+        file_type.value = 2
+        console.log(file_list.value, 999)
+    } else {
+        report_file_list.value = sub_title_file_list.value
+        file_list.value = report_file_list.value
+        file_type.value = 1
+    }
+
+    // TODO:判断是否进行了文档清洗
+    // 1.可以根据是否返回URL地址来判断,同时也可以使用用户设置的最大tolens和文件总tokens进行判断
+    // file_Type:1 本地  file_Type:2 链接
+    // type1:
+
+    // type2:
+    // const file_urls = [
+    //     'http:192.168.0.1:8000/static/file/test1.docx',
+    //     'http:192.168.0.1:8000/static/file/test2.docx'
+    // ]
+
+    console.log(file_list.value, 999)
+    // const file_list = he
+    handleFormOpen()
+
+})
+/**
+ * 文件链接处理为文件列表
+ * */
+const processFileUrls = (urls) => {
+    return urls.map(url => {
+        // 提取文件名
+        const name = url.split('/').pop();
+
+        // 创建并返回对象
+        return {
+            name: name,
+            percent: 0,
+            status: "clean",
+            file_url: url
+        };
+    });
+}
 
 /**
  * 文件处理
  */
 const file_list = ref([]);
-const MAX_ACCEPT_FILE = 30;
+const MAX_ACCEPT_FILE = 80;
 const file_total = computed(() => {
     return file_list.value.length;
 });
+/**
+ * 不同类型文件列表
+ * */
+const clear_file_list = ref([])
+const sub_title_file_list = ref([])
+const report_file_list = ref([])
 
 /**
  * 网络请求状态
@@ -183,7 +259,8 @@ const handleDefineReset = () => {
     text_title.value = '';
     text_description.value = '';
     chat_message.value = '';
-    is_first_generate.value = true;
+    // is_first_generate.value = true;
+    // 切换radio时先不重置该项
     show_chat_text_input.value = false;
     show_start_btn.value = true;
     doc_form_show.value = true;
@@ -199,6 +276,11 @@ const handleDefineReset = () => {
 const handleTextChange = (textObj) => {
     text_title.value = textObj.title || '';
     text_description.value = textObj.description || '';
+    is_clean.value = textObj.is_clean
+    if (textObj.max_tokens) {
+        max_tokens.value = textObj.max_tokens * 1000;
+    }
+
 }
 
 /**
@@ -216,7 +298,28 @@ const handleRadioChange = (value) => {
  * @param fileList
  */
 const handleFileChange = (fileList) => {
-    file_list.value = fileList;
+    if (act_type.value == 1) {
+        clear_file_list.value = fileList
+        file_list.value = clear_file_list.value;
+    }
+    if (act_type.value == 2) {
+        // 如果上传文件时,文件列表中显示清洗后的链接文件,则清空文件列表后再添加
+        if (file_type.value == 2) {
+            report_file_list.value = fileList.filter(item => {
+                console.log(item, 999)
+                return (item.status != 'clean')
+            });
+        } else {
+            report_file_list.value = fileList
+        }
+        file_list.value = report_file_list.value;
+
+    }
+    if (act_type.value == 3) {
+        sub_title_file_list.value = fileList;
+        file_list.value = sub_title_file_list.value;
+    }
+
 }
 
 /**
@@ -236,7 +339,6 @@ const handleChatMessageUpdate = (msg) => {
  */
 const getFIleParams = () => {
     const formData = new FormData();
-
     const f_list = file_list.value;
 
     f_list.forEach((item) => {
@@ -261,7 +363,6 @@ const handleStart = async () => {
     const action_type = act_type.value; // 操作类型
     let title = text_title.value; // 标题
     const f_list = file_list.value;
-
     if (!action_type) {
         showMsg('请选择类型');
         return;
@@ -308,7 +409,7 @@ const handleStart = async () => {
         // }
         if (is_first_generate.value) {
             // 第一次
-            init_status.value = true; // 标记为已点击开始,显示收起按钮
+            // init_status.value = true; // 标记为已点击开始,显示收起按钮
         } else {
             // 非第一次
             if (!chat_message.value) {
@@ -336,43 +437,53 @@ const handleStart = async () => {
         // const dialog = await ajax.message.createDialog(agent_id);
 
         // const chat_id = dialog.chat_id;
+        // 报告生成中如果是没有被清洗的文件,则需要上传文件,如果是清洗后的文件,则只需要上传file_type:2即可
+        let fm_data, uploadResult1, files_info, file_id_list, file_token_list, tempLocalStoreData
+        if (file_type.value == 1) {
+            // 文件参数数据
+            fm_data = getFIleParams();
+
+            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, '文件上传结果');
+            files_info = uploadResult1.files; // 数组
+            file_id_list = files_info.map(item => item.id);
+            // console.log(file_id_list, '文件ID值');
+            file_token_list = files_info.map(item => item.tokens);
+            console.log(file_token_list, '文件信息');
+            tokens.value = file_token_list.reduce((acc, cur) => (Number(acc) + Number(cur)), 0)
+            console.log(tokens, 'tokens')
+            tempLocalStoreData = {
+                name: '文档报告生成',
 
-        // 文件参数数据
-        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值');
-
-        let tempLocalStoreData = {
-            name: '文档报告生成',
+                agent_id: agent_id,
+                // chat_id: chat_id,
 
-            agent_id: agent_id,
-            // chat_id: chat_id,
+                workflow: action_type,
 
-            workflow: action_type,
+                upload_files: file_id_list,
+                title: title,
+                /**
+                 * 当workflow值为2或者3时,存在sub_title参数值
+                 */
+                sub_titles: text_description.value,
+            };
+        }
+        if (file_type.value == 2) {
+            file_id_list = file_list.value.map(item => item.file_url);
+        }
 
-            upload_files: file_id_list,
-            title: title,
-            /**
-             * 当workflow值为2或者3时,存在sub_title参数值
-             */
-            sub_titles: text_description.value,
-        };
 
         if (action_type === 1) {
             // 文档清洗
@@ -405,6 +516,7 @@ const handleStart = async () => {
                  * 当workflow值为2或者3时,存在sub_title参数值
                  */
                 sub_titles: text_description.value,
+                file_type: file_type.value,
             };
         }
 
@@ -426,7 +538,14 @@ const handleStart = async () => {
                 title_number: text_title.value || 8, // 小标题数量,默认值
                 title_style: text_description.value || '',
                 title_query: chat_message.value,
+                // 新增参数是否清洗,和文件token数
+                is_clean: is_clean.value,
+                tokens: tokens.value,
+
             };
+            if (!is_clean.value) {
+                tempLocalStoreData.max_tokens = max_tokens.value;
+            }
 
             if (is_first_generate.value) {
                 // 小标题生成
@@ -463,7 +582,21 @@ const handleStart = async () => {
         start_message.value = err.message;
     }
 }
-
+/**
+ * 根据act_type 值,切换文件列表
+ * */
+watch(() => act_type.value, (val) => {
+    console.log(val);
+    if (val == 1) {
+        file_list.value = clear_file_list.value
+    } else if (val == 2) {
+        file_list.value = report_file_list.value
+    } else if (val == 3) {
+        file_list.value = sub_title_file_list.value
+    }
+}, {
+    immediate: true
+})
 const upload_warning_text = `支持上传文件pdf、docx文档(最多${MAX_ACCEPT_FILE}个,每个大小不超过10MB)`;
 const radio_qingxi_text = "对上传的文档进行清洗,输出生成清洗后的文档";
 const radio_xiaobiaoti_text = "对上传文档进行内容总结和分类,生成小标题并提供相应的分类内容。"
@@ -554,6 +687,7 @@ const radio_shengcheng_text = "对上传的(经过清洗的)文档生成报告
     overflow-y: auto;
     padding-right: 5px;
 }
+
 .wendangbaogaoshengcheng-footer .arco-upload-list.arco-upload-list-type-text .arco-upload-list-item {
     margin-top: 10px;
 }

+ 190 - 148
src/components/History.vue

@@ -1,165 +1,188 @@
 <template>
-  <main>
-    <header>
-      <p>历史记录</p>
-      <div v-outside="() => {
-        openSearch = false;
-      }
-        ">
-        <div :class="{ close: openSearch }" @click="setNewDialog">
-          <img src="@/assets/history/plus.svg" width="20" />
-          <span v-show="!openSearch">新建对话</span>
-        </div>
-        <a-tooltip content="搜索">
-          <div @click="() => {
-            openSearch = true;
-          }
-            " :class="{ 'search-hide': openSearch }">
-            <img src="@/assets/history/search.svg" width="24" />
-          </div>
-        </a-tooltip>
-        <a-input :style="{ flex: 1, borderRadius: '19px', height: '38px' }" placeholder="搜索历史记录" allow-clear
-          v-show="openSearch">
-          <template #prefix>
-            <icon-search />
-          </template>
-        </a-input>
-      </div>
-    </header>
-    <p>置顶对话</p>
-    <div class="no-history" v-if="list.length === 0">
-      <div>
-        <img src="@/assets/history/full.svg" width="58" />
-        <p>暂无会话记录</p>
-        <p>点击新建对话即可开始</p>
-      </div>
-    </div>
-    <div v-else>
-      <section v-show="list.filter((v) => v.isTop).length > 0">
-        <div v-for="(item, key) in list.filter((v) => v.isTop)" :key="key"
-          :class="{ 'div-padding': openDeletes, active: selectId === item.id }" @click="handleClick(item.id)">
-          <em v-if="openDeletes" @click="setSelect(item.id)" :class="{ 'select-icon': true, active: item.isSelected }">
-            <img src="@/assets/history/ok.svg" width="10" />
-          </em>
-          <div v-if="false">
-            <p :id="`history-${item.id}`">{{ item.content }}</p>
-            <p>
-              <span>{{ item.time }}</span>
-              <span>
-                <a-tooltip content="取消置顶">
-                  <em @click="setTop(false, item.id)"><icon-to-bottom /></em>
-                </a-tooltip>
-                <a-tooltip content="重命名">
-                  <em><icon-edit @click="editItem(item.id)" /></em>
-                </a-tooltip>
-                <a-popover :popup-visible="showDeleteTooltip && deleteId === item.id">
-                  <a-tooltip content="删除">
-                    <em @click="handleDeleteButton(item.id)"><icon-delete /></em>
-                  </a-tooltip>
-                  <template #content>
-                    <p>删除后无法恢复,您是否删除?</p>
-                    <div class="delete-buttons">
-                      <div>
-                        <a-button size="mini" type="primary" style="margin-right: 10px"
-                          @click="deleteItem(item.id)">确认</a-button>
-                        <a-button size="mini" type="outline" @click="() => {
-                          showDeleteTooltip = false;
-                        }
-                          ">取消</a-button>
-                      </div>
+    <main>
+        <header>
+            <p>历史记录</p>
+            <div v-outside="() => {
+                    openSearch = false;
+                }
+            ">
+                <div :class="{ close: openSearch }" @click="setNewDialog">
+                    <img src="@/assets/history/plus.svg" width="20" />
+                    <span v-show="!openSearch">新建对话</span>
+                </div>
+                <a-tooltip content="搜索">
+                    <div @click="() => {
+                        openSearch = true;
+                    }
+                    " :class="{ 'search-hide': openSearch }">
+                        <img src="@/assets/history/search.svg" width="24" />
                     </div>
-                  </template>
-                </a-popover>
-              </span>
-            </p>
-          </div>
-        </div>
-      </section>
-      <section>
-        <div v-for="(item, key) in list.filter((v) => !v.isTop)" :key="key"
-          :class="{ 'div-padding': openDeletes, active: selectId === item.id }" @click="handleClick(item.id)">
-          <em v-if="openDeletes" @click="setSelect(item.id)" :class="{ 'select-icon': true, active: item.isSelected }">
-            <img src="@/assets/history/ok.svg" width="10" />
-          </em>
-          <div>
-            <p :id="`history-${item.id}`">{{ item.content }}</p>
-            <p>
-              <span>{{ item.time }}</span>
-              <span v-if="false">
-                <a-tooltip content="置顶">
-                  <em @click="setTop(true, item.id)"><icon-to-top /></em>
                 </a-tooltip>
-                <a-tooltip content="重命名">
-                  <em><icon-edit @click="editItem(item.id)" /></em>
-                </a-tooltip>
-                <a-popover :popup-visible="showDeleteTooltip && deleteId === item.id">
-                  <a-tooltip content="删除">
-                    <em @click="handleDeleteButton(item.id)"><icon-delete /></em>
-                  </a-tooltip>
-                  <template #content>
-                    <p>删除后无法恢复,您是否删除?</p>
-                    <div class="delete-buttons">
-                      <div>
-                        <a-button size="mini" type="primary" style="margin-right: 10px"
-                          @click="deleteItem(item.id)">确认</a-button>
-                        <a-button size="mini" type="outline" @click="() => {
+                <a-input :style="{ flex: 1, borderRadius: '19px', height: '38px' }" placeholder="搜索历史记录" allow-clear
+                    v-show="openSearch">
+                    <template #prefix>
+                        <icon-search />
+                    </template>
+                </a-input>
+            </div>
+        </header>
+        <p>置顶对话</p>
+        <div class="no-history" v-if="list.length === 0">
+            <div>
+                <img src="@/assets/history/full.svg" width="58" />
+                <p>暂无会话记录</p>
+                <p>点击新建对话即可开始</p>
+            </div>
+        </div>
+        <div v-else>
+            <section v-show="list_in_top.length > 0">
+                <div v-for="(item, key) in list_in_top" :key="key"
+                    :class="{ 'div-padding': openDeletes, active: selectId === item.id }" @click="handleClick(item.id)">
+                    <em v-if="openDeletes" @click="setSelect(item.id)"
+                        :class="{ 'select-icon': true, active: item.isSelected }">
+                        <img src="@/assets/history/ok.svg" width="10" />
+                    </em>
+
+                    <div v-if="false">
+                        <p :id="`history-${item.id}`" class="history-name-content">
+                            {{ item.content }}
+
+                            <HistoryType :type="item.workflow/1" />
+                        </p>
+
+                        <p>
+                            <span>{{ item.time }}</span>
+                            <span>
+                                <a-tooltip content="取消置顶">
+                                    <em @click="setTop(false, item.id)"><icon-to-bottom /></em>
+                                </a-tooltip>
+                                <a-tooltip content="重命名">
+                                    <em><icon-edit @click="editItem(item.id)" /></em>
+                                </a-tooltip>
+                                <a-popover :popup-visible="showDeleteTooltip && deleteId === item.id">
+                                    <a-tooltip content="删除">
+                                        <em @click="handleDeleteButton(item.id)"><icon-delete /></em>
+                                    </a-tooltip>
+                                    <template #content>
+                                        <p>删除后无法恢复,您是否删除?</p>
+                                        <div class="delete-buttons">
+                                            <div>
+                                                <a-button size="mini" type="primary" style="margin-right: 10px"
+                                                    @click="deleteItem(item.id)">确认</a-button>
+                                                <a-button size="mini" type="outline" @click="() => {
+                                                    showDeleteTooltip = false;
+                                                }
+                                                ">取消</a-button>
+                                            </div>
+                                        </div>
+                                    </template>
+                                </a-popover>
+                            </span>
+                        </p>
+                    </div>
+                </div>
+            </section>
+
+            <section>
+                <div v-for="(item, key) in list_in_normal" :key="key"
+                    :class="{ 'div-padding': openDeletes, active: selectId === item.id }" @click="handleClick(item.id)">
+                    <em v-if="openDeletes" @click="setSelect(item.id)"
+                        :class="{ 'select-icon': true, active: item.isSelected }">
+                        <img src="@/assets/history/ok.svg" width="10" />
+                    </em>
+                    <div>
+                        <p :id="`history-${item.id}`" class="history-name-content">
+                            {{ item.content }}
+
+                            <HistoryType :type="item.workflow / 1" />
+                        </p>
+
+                        <p>
+                            <span>{{ item.time }}</span>
+
+                            <span v-if="false">
+                                <a-tooltip content="置顶">
+                                    <em @click="setTop(true, item.id)"><icon-to-top /></em>
+                                </a-tooltip>
+                                <a-tooltip content="重命名">
+                                    <em><icon-edit @click="editItem(item.id)" /></em>
+                                </a-tooltip>
+                                <a-popover :popup-visible="showDeleteTooltip && deleteId === item.id">
+                                    <a-tooltip content="删除">
+                                        <em @click="handleDeleteButton(item.id)"><icon-delete /></em>
+                                    </a-tooltip>
+                                    <template #content>
+                                        <p>删除后无法恢复,您是否删除?</p>
+                                        <div class="delete-buttons">
+                                            <div>
+                                                <a-button size="mini" type="primary" style="margin-right: 10px"
+                                                    @click="deleteItem(item.id)">确认</a-button>
+                                                <a-button size="mini" type="outline" @click="() => {
                           showDeleteTooltip = false;
                         }
                           ">取消</a-button>
-                      </div>
+                                            </div>
+                                        </div>
+                                    </template>
+                                </a-popover>
+                            </span>
+                        </p>
                     </div>
-                  </template>
-                </a-popover>
-              </span>
-            </p>
-          </div>
+                </div>
+            </section>
         </div>
-      </section>
-    </div>
-    <footer v-if="list.length > 0 && false">
-      <div @click="() => {
+
+        <footer v-if="list.length > 0 && false">
+            <div @click="() => {
         openDeletes = true;
       }
         " v-if="!openDeletes">
-        <icon-delete />
-        <span>批量删除</span>
-      </div>
-      <section v-else>
-        <div @click="setAllSelect">
-          <em :class="{ 'select-icon': true, active: isAllSelected }">
-            <img src="@/assets/history/ok.svg" width="10" />
-          </em>
-          <span>全选</span>
-        </div>
-        <div>
-          <a-popover :popup-visible="showDeleteTooltip">
-            <a-button size="mini" type="primary" status="danger" style="margin-right: 10px"
-              @click="handleDeleteButton">删除</a-button>
-            <template #content>
-              <div>
-                <p>删除后无法恢复,您是否删除?</p>
-                <div class="delete-buttons">
-                  <div>
-                    <a-button size="mini" type="primary" style="margin-right: 10px" @click="deleteItems">确认</a-button>
-                    <a-button size="mini" type="outline" @click="() => {
-                      showDeleteTooltip = false;
-                    }
-                      ">取消</a-button>
-                  </div>
+                <icon-delete />
+                <span>批量删除</span>
+            </div>
+            <section v-else>
+                <div @click="setAllSelect">
+                    <em :class="{ 'select-icon': true, active: isAllSelected }">
+                        <img src="@/assets/history/ok.svg" width="10" />
+                    </em>
+                    <span>全选</span>
                 </div>
-              </div>
-            </template>
-          </a-popover>
-          <a-button size="mini" type="outline" @click="exitSelects">退出</a-button>
-        </div>
-      </section>
-    </footer>
-  </main>
+                <div>
+                    <a-popover :popup-visible="showDeleteTooltip">
+                        <a-button size="mini" type="primary" status="danger" style="margin-right: 10px"
+                            @click="handleDeleteButton">删除</a-button>
+                        <template #content>
+                            <div>
+                                <p>删除后无法恢复,您是否删除?</p>
+                                <div class="delete-buttons">
+                                    <div>
+                                        <a-button size="mini" type="primary" style="margin-right: 10px"
+                                            @click="deleteItems">确认</a-button>
+                                        <a-button size="mini" type="outline" @click="() => {
+                                            showDeleteTooltip = false;
+                                        }
+                                        ">取消</a-button>
+                                    </div>
+                                </div>
+                            </div>
+                        </template>
+                    </a-popover>
+
+                    <a-button size="mini" type="outline" @click="exitSelects">退出</a-button>
+                </div>
+            </section>
+        </footer>
+    </main>
 </template>
 <script>
-import { defineComponent, inject, onMounted, ref } from "vue";
+import { defineComponent, inject, onMounted, computed, ref } from "vue";
+import HistoryType from './history/HistoryType.vue'
+
 export default defineComponent({
-  props: ["selectId", "list"],
+    props: ["selectId", "list"],
+    components: {
+        HistoryType
+  },
   setup(props, { emit }) {
     const { helper } = inject("$global");
     const openSearch = ref(false);
@@ -233,6 +256,17 @@ export default defineComponent({
     const handleClick = (id) => {
       emit("handle-click", id);
     };
+
+
+    // 置顶的记录列表
+    const list_in_top = computed(() => {
+        return props.list.filter((v) => v.isTop)
+    });
+    //   非置顶的记录列表
+    const list_in_normal = computed(() => {
+        return props.list.filter((v) => !v.isTop)
+    });
+
     return {
       openSearch,
       handleDeleteButton,
@@ -248,7 +282,10 @@ export default defineComponent({
       deleteItems,
       deleteId,
       setNewDialog,
-      handleClick
+        handleClick,
+
+        list_in_top,
+        list_in_normal
     };
   }
 });
@@ -260,6 +297,11 @@ export default defineComponent({
   justify-content: center;
 }
 
+.history-name-content{
+    display: flex;
+    justify-content: space-between;
+}
+
 main {
   height: 100%;
   display: flex;

+ 20 - 5
src/components/doc-gen-logs/BtnShowLog.vue

@@ -1,24 +1,39 @@
 <template>
-    <div>
-        <a-button type="primary" @click="handleClick">查看日志</a-button>
+    <!-- <div> -->
+        <p type="primary" @click="handleClick">
+          <icon-calendar />
+          <!-- 查看日志 -->
+        </p>
 
         <a-drawer :width="340" :visible="visible" @ok="handleOk" @cancel="handleCancel" unmountOnClose>
-            <DocumentGenerateLogs :logs_info="example_res" />
+            <DocumentGenerateLogs :logs_info="logs_info" />
         </a-drawer>
-    </div>
+    <!-- </div> -->
 </template>
 <script setup>
 import { ref, inject, computed, nextTick } from "vue";
 
 import DocumentGenerateLogs from './DocumentGenerateLogs.vue'
 
-const visible = ref(false);
+const props = defineProps({
+    logs_info: {
+        type: Object,
+        default: () => {
+            return {}
+        }
+    },
+
+})
+const emit = defineEmits(['closeReportLog'])
+
+const visible = ref(false)
 
 const handleClick = () => {
     visible.value = true;
 };
 const handleOk = () => {
     visible.value = false;
+
 };
 const handleCancel = () => {
     visible.value = false;

+ 11 - 1
src/components/doc-gen-logs/LogsBaseInfo.vue

@@ -8,7 +8,7 @@
 
             <div>
                 <div class="st-field-label">运行时间</div>
-                <div class="st-field-value">{{ time_display }}</div>
+                <div class="st-field-value">{{ time_display_v2 }}</div>
             </div>
 
             <div>
@@ -63,6 +63,16 @@ const time_display = computed(() => {
     return `${str}s`;
 });
 
+const time_display_v2 = computed(() => {
+     const info = props.info || {};
+
+    const dis = info.elapsed_time;
+
+    const str = Number(dis / 1000).toFixed(3);
+
+    return `${str}s`;
+})
+
 const container_klass = computed(() => {
     const info = props.info || {};
 

+ 8 - 1
src/components/doc-gen-logs/WorkFlowTimeWaste.vue

@@ -1,6 +1,6 @@
 <template>
     <div class="work-flow-time-waste">
-        {{ time_display }}
+        {{ time_display_v2 }}
     </div>
 </template>
 <script setup>
@@ -27,6 +27,13 @@ const time_display = computed(() => {
 
     return `${str} ms`;
 });
+const time_display_v2 = computed(() => {
+    const dis = props.elapsed_time;
+
+    const str = Number(dis).toFixed(3);
+
+    return `${str} ms`;
+});
 
 </script>
 <style lang="scss" scoped>

+ 6 - 1
src/components/document-report/ActionTypeRadio.vue

@@ -14,9 +14,10 @@
     </a-space>
 </template>
 <script setup>
-import { ref } from "vue";
+import { ref , inject } from "vue";
 
 const emit = defineEmits(['change']);
+const { helper } = inject("$global");
 
 /**
  * 操作类型
@@ -30,6 +31,10 @@ const handleRadioClick = (value) => {
 
     emit('change', act_type.value);
 }
+// 订阅打开生成报告弹窗
+helper.$bus.on('open-document-dialog', () => {
+   handleRadioClick(2)
+})
 
 const radio_qingxi_text = "对上传的文档进行清洗,输出生成清洗后的文档";
 const radio_xiaobiaoti_text = "对上传文档进行内容总结和分类,生成小标题并提供相应的分类内容。"

+ 22 - 2
src/components/document-report/TextInputType2.vue

@@ -20,8 +20,17 @@
 <script setup>
 import { ref, inject, computed, nextTick } from "vue";
 
+const props = defineProps({
+    report_text: {
+        type:String,
+        default: ''
+    }
+})
+
 const emit = defineEmits(['change']);
 
+const { helper } = inject("$global");
+
 // : auto - size="{ minRows: 4, maxRows: 10 }"
 
 const placeholder_str = `
@@ -32,13 +41,16 @@ const placeholder_str = `
 
 // 标题
 const text_title = ref(""); // 单行文本:标题
-const text_description = ref(""); // 多行文本:描述
+const text_description = props.report_text.length ? ref(props.report_text) : ref(""); // 多行文本:描述
+
 
 const maxLength = ref(4080); // 允许输入的最大长度
 
 const parseStatus = ref(false);
 
-const wendangzhineng_text_input = ref('');
+const wendangzhineng_text_input = props.report_text.length ? ref(props.report_text) : ref("");
+console.log('props.report_text', text_description.value);
+console.log('props.report_text', wendangzhineng_text_input.value);
 const text_area_style = {
     // flex: 1,
     // // borderRadius: '12px',
@@ -90,6 +102,14 @@ const handleTextKeyUp = (e) => {
         // 文本更改
     }
 };
+/**
+ * 订阅生成报告数据
+ * */
+// const report_data = helper.read('generate-report')
+// console.log('report_data', report_data);
+// wendangzhineng_text_input.value = report_data.answer;
+// handleDescriptionChange(report_data.answer);
+
 </script>
 
 <style lang="scss" scoped>

+ 6 - 5
src/components/document-report/TextInputType3.vue

@@ -40,7 +40,7 @@
                 <a-typography-text class="label-class">
                     最大TOKEN数<span class="attention-requred">*</span>
                 </a-typography-text>
-                <a-input-number v-model="token_count" placeholder="请输入" class="input-demo" :min="0" :max="100"
+                <a-input-number v-model="token_count" placeholder="请输入" class="input-demo" :min="1" :max="100"
                     @change="handleTokenCountChange" />
             </a-space>
         </a-tooltip>
@@ -96,15 +96,16 @@ const handleChange = () => {
     const data = {
         title: text_title.value,
         description: text_description.value,
-        document_clear_status: document_clear_status.value,
+        is_clean: document_clear_status.value? 1 : 0,
     }
     if (!document_clear_status.value) {
-        data.token_count = token_count.value;
+        data.max_tokens = token_count.value;
     }
     nextTick(() => {
         emit('change', {
-            title: text_title.value,
-            description: text_description.value
+            // title: text_title.value,
+            // description: text_description.value
+            ...data
         });
     });
 }

+ 61 - 0
src/components/history/HistoryType.vue

@@ -0,0 +1,61 @@
+<template>
+    <a-tag v-if="show_tag" checkable size="small" color="arcoblue">{{ type_text }}</a-tag>
+</template>
+
+<script setup>
+import { defineComponent, inject, onMounted, computed, ref } from "vue";
+
+const props = defineProps({
+    /**
+     * 历史记录
+     * 文档报告历史记录有一个字段workflow用来描述历史记录的类型
+     * 0 默认不显示
+     * 1 清洗
+     * 2 报告
+     * 3 小标题
+     */
+    type: Number
+});
+
+/**
+ * 是否显示历史记录标签
+ */
+const show_tag = computed(() => {
+    const type = props.type / 1;
+
+    if (!type) {
+        return false;
+    }
+
+    if (isNaN(type)) {
+        return false;
+    }
+
+    if (type === 0) {
+        return false;
+    }
+
+    return true;
+});
+
+const type_text = computed(() => {
+    const type = props.type / 1;
+
+    switch (type) {
+        case 1:
+            return '清洗'
+        case 2:
+            return '报告';
+        case 3:
+            return '小标题';
+        default:
+            return '';
+    }
+});
+
+</script>
+<style scoped>
+.history-type{
+
+}
+</style>

+ 2 - 1
src/views/Home.vue

@@ -345,7 +345,8 @@ const selectNav = async (node) => {
             return {
                 content: value.name,
                 id: value.id,
-                time: value.update_date
+                time: value.update_date,
+                workflow: value.workflow
             };
         });
     }