Selaa lähdekoodia

feat: 调整文档报告的功能

zhupei 1 vuosi sitten
vanhempi
sitoutus
18c5c1bfcc

+ 7 - 1
README.md

@@ -1,6 +1,10 @@
 # 小数
 
-大模型 AI 能力平台,为你的下一个创意助力
+大模型 AI 能力平台,为你的下一个创意助力。
+
+此分支专为`上海电科院`部署。
+
+内网测试环境为:`http://192.168.20.119:8105/`
 
 ## 环境参考
 
@@ -25,6 +29,8 @@ $ npm run dev # localhost:80
 $ npm run build
 ```
 
+
+
 ## 项目须知
 
 1. `dist`目录需要在`git`进行追踪,不必添加到`.gitignore`文件中。

+ 4 - 4
public/config.js

@@ -6,18 +6,18 @@ window.__IFRAME_URL_CHUJUAN = 'http://192.168.20.119:8501'
 /**
  * 对话 websocket 连接地址
  */
-window.WEBSOCKET_BASE_URL = 'ws://smartai.com:8401';
+window.WEBSOCKET_BASE_URL = 'ws://192.168.20.119:8105';
 
 /**
  * API调用地址
  */
-window.API_BASE_URL = 'http://smartai.com:8401';
+window.API_BASE_URL = 'http://192.168.20.119:8105';
 
 /**
  * 静态资源地址
  * 图片、文档等类型的地址
  */
-window.ASSETS_BASE_URL = 'http://smartai.com:8401';
+window.ASSETS_BASE_URL = 'http://192.168.20.119:8105';
 
 /**
  * 小数绘图 -> ComfyUI -> iframe弹窗地址
@@ -41,5 +41,5 @@ window.__REFFERENCE_ASSETS_FILE_URL = "http://192.168.20.119:11080"
 /**
  * 项目基本信息
  */
-window.__SITE_TITLE = '信通小数';
+window.__SITE_TITLE = '上海电科院';
 window.__SITE_INTRODUCE = '大模型AI能力平台,为你的下一个创意助力';

+ 2 - 2
src/ajax/api/agent.js

@@ -5,8 +5,8 @@ import request from "../request";
  * @returns {Promise<Object>}
  */
 const getAgents = () => {
-    // return request.get("/api/agent/list");
-    return request.get("/api/user/menus");
+    return request.get("/api/agent/list");
+    // return request.get("/api/user/menus");
 };
 
 /**

+ 2 - 2
src/ajax/api/user.js

@@ -15,8 +15,8 @@ const getInfo = () => {
  * @returns {Promise<Object>}
  */
 const login = (username, password) => {
-    // const url = "/api/auth/login";
-    const url = "/api/auth/v2/login";
+    const url = "/api/auth/login";
+    // const url = "/api/auth/v2/login";
 
     return request.post(url, {
         username,

+ 130 - 66
src/components/DocumentReportFooter.vue

@@ -1,84 +1,134 @@
 <template>
-    <footer class="upload-footer wendangbaogaoshengcheng-footer" v-if="start_status !== 3">
-        <a-space size="large">
-            <a-tooltip :content="radio_qingxi_text">
-                <a-radio :value="1" :model-value="act_type" @click="handleRadioClick(1)">文档清洗</a-radio>
-            </a-tooltip>
-
-            <a-tooltip :content="radio_shengcheng_text">
-                <a-radio :value="2" :model-value="act_type" @click="handleRadioClick(2)">报告生成</a-radio>
-            </a-tooltip>
-        </a-space>
-
-        <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>
-        </a-typography-text>
-
-
-        <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>
-            </template>
-
-            <template #file-name="{ fileItem }">
-                <a-tooltip :content="fileItem.name">
-                    <span>{{fileItem.name}}</span>
-                </a-tooltip>
-            </template>
-
-            <!-- <template #upload-item="{ fileItem, index }">
+    <footer class="wendangbaogaoshengcheng-footer" v-if="start_status !== 3">
+        <div class="upload-footer" v-show="doc_form_show">
+            <div v-if="act_type === 3" class="form-fold-btn" @click="handleFormFold">
+                <icon-menu-fold :size="20" />
+            </div>
+
+            <ActionTypeRadio @change="handleRadioChange"/>
+
+            <div class="vertical-placeholder"></div>
+
+            <TextInputType1 v-if="act_type === 1" @change="handleTextChange"/>
+            <TextInputType2 v-if="act_type === 2" @change="handleTextChange"/>
+            <TextInputType3 v-if="act_type === 3" @change="handleTextChange"/>
+
+            <div class="vertical-placeholder"></div>
+
+            <a-typography-text>
+                请上传文件<span class="attention-requred">*</span>
+            </a-typography-text>
+
+            <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>
+                </template>
+
+                <template #file-name="{ fileItem }">
+                    <a-tooltip :content="fileItem.name">
+                        <span>{{fileItem.name}}</span>
+                    </a-tooltip>
+                </template>
+
+                <!-- <template #upload-item="{ fileItem, index }">
                 <div>
                     <div>{{ fileItem.name }}</div>
                 </div>
             </template> -->
-        </a-upload>
+            </a-upload>
+
 
+            <template v-if="act_type === 2 || act_type === 1">
+                <div class="vertical-placeholder"></div>
 
-        <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">
+            <div class="message-input-container">
+                <div v-show="!doc_form_show" class="form-fold-btn open" @click="handleFormOpen">
+                    <icon-menu-fold :size="20" />
+                </div>
 
-        <a-button :style="{ width: '500px' }" type="primary" @click="handleStart"
-            :disabled="start_status !== 1">开始</a-button>
+                <message-input :readonly="readonly" eventName="open-dialog" />
+            </div>
+        </template>
     </footer>
 </template>
 <script setup>
 import { ref, inject, computed } from "vue";
 import { Message } from '@arco-design/web-vue';
 
+import MessageInput from "./MessageInput.vue";
+
+import ActionTypeRadio from './document-report/ActionTypeRadio.vue'
+import TextInputType1 from './document-report/TextInputType1.vue'
+import TextInputType2 from './document-report/TextInputType2.vue'
+import TextInputType3 from './document-report/TextInputType3.vue'
+
 const props = defineProps({
     agentId: String,
+
+    readonly: Boolean
 });
 
 const { config, helper, ajax } = inject("$global");
 
-// 操作类型
+/**
+ * 操作类型
+ * 1 文档清洗
+ * 2 报告生成
+ * 3 小标题生成
+ */
 const act_type = ref(1);
-const act_opts = [
-    { label: '文档清洗', value: 1 },
-    { label: '报告生成', value: 2 },
-];
+const text_title = ref(""); // 单行文本:标题
+const text_description = ref(""); // 多行文本:描述
+
+/**
+ * 文本输入区域变化事件
+ * @param textObj
+ */
+const handleTextChange = (textObj) => {
+    text_title.value = textObj.title || '';
+    text_description.value = textObj.description || '';
+}
+
+const handleTextClear = () => {
+    text_title.value =  '';
+    text_description.value =  '';
+}
+/**
+ * 操作类别变更
+ * @param value
+ */
+const handleRadioChange = (value) => {
+    act_type.value = value / 1;
+
+    handleTextClear();
+}
 
-// 标题
-const textValue = ref("");
-const maxLength = ref(120); // 允许输入的最大长度
+/**
+ * 控制表单区域的展开和折叠
+ * 当 使用 小标题生成 功能时,表单可以进行折叠或者展开,并且存在 对话输入区域,且必须输入文本才可以进行对话
+ */
+const doc_form_show = ref(true);
+const handleFormFold = () => {
+    doc_form_show.value = false;
+}
+const handleFormOpen = () => {
+    doc_form_show.value = true;
+}
 
 /**
  * 文件处理
@@ -95,10 +145,6 @@ const file_total = computed(() => {
 const start_status = ref(1); // 状态值:1 初始 2 进行中 3 成功 4 出错 5 异常
 const start_message = ref('');
 
-const handleRadioClick = (value) => {
-    act_type.value = value / 1;
-}
-
 /**
  * 标题数据变化
  * @param value
@@ -143,7 +189,7 @@ const showMsg = (msg) => {
  */
 const handleStart = async () => {
     const action_type = act_type.value; // 操作类型
-    const title = textValue.value; // 标题
+    const title = text_title.value; // 标题
     const f_list = file_list.value;
 
     if (!action_type) {
@@ -233,6 +279,7 @@ const handleStart = async () => {
 
 const upload_warning_text = `支持上传文件pdf、docx文档(最多${MAX_ACCEPT_FILE}个,每个大小不超过10MB)`;
 const radio_qingxi_text = "对上传的文档进行清洗,输出生成清洗后的文档";
+const radio_xiaobiaoti_text = "对上传文档进行内容总结和分类,生成小标题并提供相应的分类内容。"
 const radio_shengcheng_text = "对上传的(经过清洗的)文档生成报告,输出生成的报告文档"
 </script>
 <style lang="scss" scoped>
@@ -241,10 +288,23 @@ const radio_shengcheng_text = "对上传的(经过清洗的)文档生成报告
 }
 
 .upload-footer {
-    margin-bottom: 50px;
+    margin-bottom: 10px;
     padding: 20px;
     width: 540px;
+    // min-height: 240px;
     border: 1px solid #eee;
+
+    position: relative;
+}
+.form-fold-btn{
+    position: absolute;
+    right: 10px;
+    cursor: pointer;
+    z-index: 9;
+}
+.form-fold-btn.open{
+    left: 4px;
+    top: -4px;
 }
 
 .attention-requred {
@@ -252,7 +312,7 @@ const radio_shengcheng_text = "对上传的(经过清洗的)文档生成报告
 }
 
 .wendangbaogaoshengcheng-footer {
-    min-height: 240px;
+
 }
 
 .max-limit-warning {
@@ -268,6 +328,10 @@ const radio_shengcheng_text = "对上传的(经过清洗的)文档生成报告
     background-color: rgb(var(--primary-5));
     color: #fff;
 }
+
+.message-input-container{
+    position: relative;
+}
 </style>
 <style>
 .wendangbaogaoshengcheng-footer .arco-upload-icon.arco-upload-icon-start {

+ 37 - 0
src/components/document-report/ActionTypeRadio.vue

@@ -0,0 +1,37 @@
+<template>
+    <a-space size="large">
+        <a-tooltip :content="radio_qingxi_text">
+            <a-radio :value="1" :model-value="act_type" @click="handleRadioClick(1)">文档清洗</a-radio>
+        </a-tooltip>
+
+        <a-tooltip :content="radio_xiaobiaoti_text">
+            <a-radio :value="3" :model-value="act_type" @click="handleRadioClick(3)">小标题生成</a-radio>
+        </a-tooltip>
+
+        <a-tooltip :content="radio_shengcheng_text">
+            <a-radio :value="2" :model-value="act_type" @click="handleRadioClick(2)">报告生成</a-radio>
+        </a-tooltip>
+    </a-space>
+</template>
+<script setup>
+import { ref } from "vue";
+
+const emit = defineEmits(['change']);
+
+/**
+ * 操作类型
+ * 1 文档清洗
+ * 2 报告生成
+ * 3 小标题生成
+ */
+const act_type = ref(1);
+const handleRadioClick = (value) => {
+    act_type.value = value / 1;
+
+    emit('change', act_type.value);
+}
+
+const radio_qingxi_text = "对上传的文档进行清洗,输出生成清洗后的文档";
+const radio_xiaobiaoti_text = "对上传文档进行内容总结和分类,生成小标题并提供相应的分类内容。"
+const radio_shengcheng_text = "对上传的(经过清洗的)文档生成报告,输出生成的报告文档"
+</script>

+ 40 - 0
src/components/document-report/TextInputType1.vue

@@ -0,0 +1,40 @@
+<template>
+    <a-typography-text>
+        标题<span class="attention-requred">*</span>
+    </a-typography-text>
+
+    <a-input :style="{ flex: '1' }" v-model="text_title" :placeholder="`请输入标题`" allow-clear
+        @input="handleInputChange" />
+</template>
+<script setup>
+import { ref, inject, computed, nextTick } from "vue";
+
+const emit = defineEmits(['change']);
+
+// 标题
+const text_title = ref("");
+
+const handleChange = () => {
+    nextTick(() => {
+        emit('change', {
+            title: text_title.value,
+            description: ''
+        });
+    });
+}
+
+/**
+ * 标题数据变化
+ * @param value
+ */
+const handleInputChange = (value) => {
+    text_title.value = value;
+
+    handleChange();
+}
+</script>
+<style lang="scss" scoped>
+.attention-requred {
+    color: red;
+}
+</style>

+ 95 - 0
src/components/document-report/TextInputType2.vue

@@ -0,0 +1,95 @@
+<template>
+    <a-typography-text>
+        标题<span class="attention-requred">*</span>
+    </a-typography-text>
+    <a-input :style="{ flex: '1' }" v-model="text_title" :placeholder="`请输入标题`" allow-clear
+        @input="handleInputChange" />
+
+    <div class="vertical-placeholder"></div>
+
+    <a-typography-text>
+        小标题<span class="attention-requred">*</span>
+    </a-typography-text>
+    <a-textarea :max-length="maxLength" v-model="wendangzhineng_text_input" :disabled="parseStatus"
+        :show-word-limit="wendangzhineng_text_input.length > maxLength / 2" :auto-size="{ maxRows: 6 }"
+        placeholder="输入您想了解的内容,Shift+Enter换行" :style="text_area_style" @keyup="handleTextKeyUp"
+        @input="handleDescriptionChange">
+    </a-textarea>
+</template>
+
+<script setup>
+import { ref, inject, computed, nextTick } from "vue";
+
+const emit = defineEmits(['change']);
+
+// 标题
+const text_title = ref(""); // 单行文本:标题
+const text_description = ref(""); // 多行文本:描述
+
+const maxLength = ref(120); // 允许输入的最大长度
+
+const parseStatus = ref(false);
+
+const wendangzhineng_text_input = ref('');
+const text_area_style = {
+    flex: 1,
+    // borderRadius: '12px',
+    // marginTop: '20px',
+    padding: '0px 10px 0 3px',
+    background: 'transparent',
+    border: '1px solid #e3e3e3',
+    minHeight: '120px',
+    paddingBottom: `${text_title.value.length > maxLength.value / 2 ? '20px' : ''}`
+};
+
+const handleChange = () => {
+    nextTick(() => {
+        emit('change', {
+            title: text_title.value,
+            description: text_description.value
+        });
+    });
+}
+
+/**
+ * 标题数据变化
+ * @param value
+ */
+const handleInputChange = (value) => {
+    text_title.value = value;
+
+    handleChange();
+}
+
+/**
+ * 多行文本变化
+ * @param value
+ */
+const handleDescriptionChange = (value) => {
+    text_description.value = value;
+
+    handleChange();
+}
+
+/**
+ * 用户按键事件
+ * @param e
+ */
+const handleTextKeyUp = (e) => {
+    if (e.keyCode === 13) {
+        // enter
+    } else {
+        // 文本更改
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+.vertical-placeholder {
+    height: 10px;
+}
+
+.attention-requred {
+    color: red;
+}
+</style>

+ 95 - 0
src/components/document-report/TextInputType3.vue

@@ -0,0 +1,95 @@
+<template>
+    <a-typography-text>
+        标题<span class="attention-requred">*</span>
+    </a-typography-text>
+    <a-input :style="{ flex: '1' }" v-model="text_title" :placeholder="`请输入标题`" allow-clear
+        @input="handleInputChange" />
+
+    <div class="vertical-placeholder"></div>
+
+    <a-typography-text>
+        风格示例<span class="attention-requred">*</span>
+    </a-typography-text>
+    <a-textarea :max-length="maxLength" v-model="wendangzhineng_text_input" :disabled="parseStatus"
+        :show-word-limit="wendangzhineng_text_input.length > maxLength / 2" :auto-size="{ maxRows: 6 }"
+        placeholder="输入您想了解的内容,Shift+Enter换行" :style="text_area_style" @keyup="handleTextKeyUp"
+        @input="handleDescriptionChange">
+    </a-textarea>
+</template>
+
+<script setup>
+import { ref, inject, computed, nextTick } from "vue";
+
+const emit = defineEmits(['change']);
+
+// 标题
+const text_title = ref(""); // 单行文本:标题
+const text_description = ref(""); // 多行文本:描述
+
+const maxLength = ref(120); // 允许输入的最大长度
+
+const parseStatus = ref(false);
+
+const wendangzhineng_text_input = ref('');
+const text_area_style = {
+    flex: 1,
+
+    padding: '0px 10px 0 3px',
+    background: 'transparent',
+    border: '1px solid #e3e3e3',
+    minHeight: '120px',
+    paddingBottom: `${text_title.value.length > maxLength.value / 2 ? '20px' : ''}`
+};
+
+
+const handleChange = () => {
+    nextTick(() => {
+        emit('change', {
+            title: text_title.value,
+            description: text_description.value
+        });
+    });
+}
+
+/**
+ * 标题数据变化
+ * @param value
+ */
+const handleInputChange = (value) => {
+    text_title.value = value;
+
+    handleChange();
+}
+
+/**
+ * 多行文本变化
+ * @param value
+ */
+const handleDescriptionChange = (value) => {
+    text_description.value = value;
+
+    handleChange();
+}
+
+/**
+ * 用户按键事件
+ * @param e
+ */
+const handleTextKeyUp = (e) => {
+    if (e.keyCode === 13) {
+        // enter
+    } else {
+        // 文本更改
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+.vertical-placeholder {
+    height: 10px;
+}
+
+.attention-requred {
+    color: red;
+}
+</style>

+ 41 - 41
src/utils/config.js

@@ -30,50 +30,50 @@ export default {
             dialog: "我可以理解和学习人类的语言,具备多轮对话的能力,现在和我开始交流吧~"
         },
 
-        {
-            id: 5,
-            title: "智能数据",
-            icon: "8",
-            img: "/src/assets/index/8.png",
-            desc: "您可以上传文档或添加数据库地址,小数可针对你文档的数据进行分析,并生成指定的图表",
-            dialog: "您可以上传文档或添加数据库地址,小数可针对你文档的数据进行分析,并生成指定的图表"
-        },
-        {
-            id: 6,
-            title: "小数绘图",
-            icon: "7",
-            img: "/src/assets/index/7.png",
-            desc: "基于您上传的图片,生成对应的文字描述并基于图片内容实现问答。",
-            dialog: "基于您上传的图片,生成对应的文字描述并基于图片内容实现问答。"
-        },
-        {
-            id: 7,
-            title: "文档出卷",
-            icon: "6",
-            img: "/src/assets/index/6.png",
-            desc: "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。",
-            dialog: "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。"
-        },
-        {
-            id: 8,
-            title: "出题组卷",
-            icon: "6",
-            img: "/src/assets/index/6.png",
-            desc: "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。",
-            dialog: "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。"
-        },
-
         // {
-        //     id: 0,
-        //     title: "报告生成",
-        //     icon: "2",
-        //     img: "/src/assets/index/2.png",
-        //     // desc: "基于您创建的报告格式和内容,快速生成定制报告,并支持一键下载",
-        //     desc: "基于您创建的报告格式和知识库中的文档内容,快速生成定制报告,并支持一键下载。",
-        //     // dialog: "基于您创建的报告格式和内容,快速生成定制报告,并支持一键下载。",
-        //     dialog: "基于您创建的报告格式和知识库中的文档内容,快速生成定制报告,并支持一键下载。"
+        //     id: 5,
+        //     title: "智能数据",
+        //     icon: "8",
+        //     img: "/src/assets/index/8.png",
+        //     desc: "您可以上传文档或添加数据库地址,小数可针对你文档的数据进行分析,并生成指定的图表",
+        //     dialog: "您可以上传文档或添加数据库地址,小数可针对你文档的数据进行分析,并生成指定的图表"
+        // },
+        // {
+        //     id: 6,
+        //     title: "小数绘图",
+        //     icon: "7",
+        //     img: "/src/assets/index/7.png",
+        //     desc: "基于您上传的图片,生成对应的文字描述并基于图片内容实现问答。",
+        //     dialog: "基于您上传的图片,生成对应的文字描述并基于图片内容实现问答。"
+        // },
+        // {
+        //     id: 7,
+        //     title: "文档出卷",
+        //     icon: "6",
+        //     img: "/src/assets/index/6.png",
+        //     desc: "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。",
+        //     dialog: "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。"
+        // },
+        // {
+        //     id: 8,
+        //     title: "出题组卷",
+        //     icon: "6",
+        //     img: "/src/assets/index/6.png",
+        //     desc: "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。",
+        //     dialog: "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。"
         // },
 
+        {
+            id: 0,
+            title: "报告生成",
+            icon: "2",
+            img: "/src/assets/index/2.png",
+            // desc: "基于您创建的报告格式和内容,快速生成定制报告,并支持一键下载",
+            desc: "基于您创建的报告格式和知识库中的文档内容,快速生成定制报告,并支持一键下载。",
+            // dialog: "基于您创建的报告格式和内容,快速生成定制报告,并支持一键下载。",
+            dialog: "基于您创建的报告格式和知识库中的文档内容,快速生成定制报告,并支持一键下载。"
+        },
+
         {
             id: 9,
             title: "文档报告",

+ 1 - 0
src/views/Home.vue

@@ -137,6 +137,7 @@
                         <!-- 小数绘图底部输入栏 -->
                         <PictureFooter v-if="navId === 6 && !historyMode" :agentId="selectId" />
 
+                        <!-- 文档报告 -->
                         <DocumentReportFooter v-if="navId === 9 && !showDialog" :agentId="selectId" />
 
                         <!-- 侧边栏切换按钮 -->

+ 1 - 2
vite.config.js

@@ -20,8 +20,7 @@ export default defineConfig({
         host: "0.0.0.0", // IP配置,支持从IP启动
         proxy: {
             "/api": {
-                target: "http://smartai.com:8401",
-                // target: "http://192.168.20.119:9301",
+                target: 'http://192.168.20.119:8105',
                 changeOrigin: true,
                 secure: false,
                 ws: true,