Kaynağa Gözat

修改聊天应用

yangg 8 ay önce
ebeveyn
işleme
d4172a1672

+ 5 - 0
src/components/webAi/css/ChatBox.css

@@ -459,4 +459,9 @@ textarea {
 }
 ::v-deep .el-collapse-item__wrap{
   border-bottom: none;
+}
+
+.header_btn{
+  display: flex;
+  justify-content: flex-end;
 }

+ 156 - 125
src/components/webAi/index.vue

@@ -1,21 +1,27 @@
 <template>
   <div class="chat-container">
-    <el-collapse v-model="activeNames" v-if="$route.name !== 'ai'">
-      <el-collapse-item title="应用配置" name="1">
-        <div class="header" style="margin-top: 15px">
-          <el-form
-            :inline="true"
-            :model="AIform"
-            :rules="rules"
-            ref="AIformRef"
-            class="demo-form-inline"
-            style="margin-top: 15px"
-            label-position="right"
-            label-width="90px"
-          >
-            <el-row :gutter="24">
-              <el-col :span="8">
-                <!--  <el-form-item label="模型库:" prop="modelLibrary">
+    <el-dialog
+      title="应用配置"
+      :visible.sync="applicationDialogVisible"
+      width="80%"
+      :before-close="handleCloseApplicationDialog"
+      :close-on-click-modal="false"
+      :append-to-body="true"
+    >
+      <div class="header" style="margin-top: 15px">
+        <el-form
+          :inline="true"
+          :model="AIform"
+          :rules="rules"
+          ref="AIformRef"
+          class="demo-form-inline"
+          style="margin-top: 15px"
+          label-position="right"
+          label-width="90px"
+        >
+          <el-row :gutter="24">
+            <el-col :span="8">
+              <!--  <el-form-item label="模型库:" prop="modelLibrary">
               <el-select
                 v-model="AIform.modelLibrary"
                 placeholder="ollama"
@@ -24,15 +30,15 @@
                 <el-option label="ollama" value="ollama"></el-option>
               </el-select>
             </el-form-item> -->
-                <el-form-item label="应用名称:" prop="chat_name">
-                  <el-input
-                    v-model="AIform.chat_name"
-                    placeholder="请输入应用名称"
-                  ></el-input>
-                </el-form-item>
-              </el-col>
-              <el-col :span="8">
-                <!-- <el-form-item label="模型类型:" prop="model_type">
+              <el-form-item label="应用名称:" prop="chat_name">
+                <el-input
+                  v-model="AIform.chat_name"
+                  placeholder="请输入应用名称"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <!-- <el-form-item label="模型类型:" prop="model_type">
               <el-select
                 v-model="AIform.model_type"
                 placeholder="请输入选择"
@@ -41,108 +47,124 @@
                 <el-option label="chat" value="chat"></el-option>
               </el-select>
             </el-form-item> -->
-                <el-form-item label="模型名称:" prop="model_name">
-                  <el-select
-                    v-model="AIform.model_name"
-                    placeholder="请输入选择"
-                    style="width: 100%"
-                  >
-                    <el-option
-                      v-for="(item, index) in modelNameList"
-                      :label="item.name"
-                      :value="item.name"
-                      :key="index"
-                    ></el-option>
-                  </el-select>
-                </el-form-item>
-              </el-col>
-              <el-col :span="8">
-                <el-form-item label="知识库:" prop="knowledge_base_names">
-                  <el-select
-                    v-model="AIform.knowledge_base_names"
-                    multiple
-                    placeholder="请选择知识库"
-                    style="width: 100%"
-                    @change="handleKnowledgeBaseChange"
-                  >
-                    <el-option
-                      v-for="(item, index) in kneList"
-                      :label="item.name"
-                      :value="item.id"
-                      :key="index"
-                    ></el-option>
-                  </el-select> </el-form-item
-              ></el-col>
-            </el-row>
-            <el-row :gutter="24">
-              <el-col :span="8">
-                <el-form-item label="文档目录:" prop="document_directories">
-                  <el-select
-                    v-model="AIform.document_directories"
-                    placeholder="请选择文档目录"
-                    style="width: 100%"
-                    :disabled="!AIform.knowledge_base_names.length"
-                    @change="handleDirectoryChange"
-                  >
-                    <el-option
-                      v-for="(dir, index) in directoryList"
-                      :label="dir.name"
-                      :value="dir.id"
-                      :key="index"
-                    ></el-option>
-                  </el-select> </el-form-item
-              ></el-col>
-              <el-col :span="8">
-                <el-form-item label="文  档:" prop="documents">
-                  <el-select
-                    v-model="AIform.documents"
-                    multiple
-                    placeholder="请选择文档"
-                    style="width: 100%"
-                    :disabled="!AIform.document_directories"
-                  >
-                    <el-option
-                      v-for="(doc, index) in documentList"
-                      :label="doc.name"
-                      :value="doc.id"
-                      :key="index"
-                    ></el-option>
-                  </el-select>
-                </el-form-item>
-              </el-col>
-              <el-col :span="8">
-                <el-form-item label="描 述:">
-                  <el-input
-                    v-model="AIform.role_description"
-                    type="textarea"
-                    style="width: 350px"
-                  ></el-input>
-                </el-form-item>
-              </el-col>
-            </el-row>
-          </el-form>
-          <div class="selection-summary">
-            <div class="summary-content">
-              <span class="summary-label">当前选择了:</span>
-              <p class="summary-text">
-                模型库: OLLAMA 模型类型: CHAT 模型名称:
-                <span>{{ AIform.model_name }}</span>
-              </p>
-              <p class="summary-text">
-                知识库:<span>{{ getKnowledgeBaseNames }}</span> 文档:
-                <span>{{ getDocumentNames }}</span>
-              </p>
-            </div>
-            <el-button
+              <el-form-item label="模型名称:" prop="model_name">
+                <el-select
+                  v-model="AIform.model_name"
+                  placeholder="请输入选择"
+                  style="width: 100%"
+                  clearable
+                >
+                  <el-option
+                    v-for="(item, index) in modelNameList"
+                    :label="item.name"
+                    :value="item.name"
+                    :key="index"
+                  ></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="知识库:" prop="knowledge_base_names">
+                <el-select
+                  v-model="AIform.knowledge_base_names"
+                  multiple
+                  placeholder="请选择知识库"
+                  style="width: 100%"
+                  @change="handleKnowledgeBaseChange"
+                  clearable
+                  filterable
+                >
+                  <el-option
+                    v-for="(item, index) in kneList"
+                    :label="item.name"
+                    :value="item.id"
+                    :key="index"
+                  ></el-option>
+                </el-select> </el-form-item
+            ></el-col>
+          </el-row>
+          <el-row :gutter="24">
+            <el-col :span="8">
+              <el-form-item label="文档目录:" prop="document_directories">
+                <el-select
+                  v-model="AIform.document_directories"
+                  placeholder="请选择文档目录"
+                  style="width: 100%"
+                  :disabled="!AIform.knowledge_base_names.length"
+                  @change="handleDirectoryChange"
+                  clearable
+                  filterable
+                >
+                  <el-option
+                    v-for="(dir, index) in directoryList"
+                    :label="dir.name"
+                    :value="dir.id"
+                    :key="index"
+                  ></el-option>
+                </el-select> </el-form-item
+            ></el-col>
+            <el-col :span="8">
+              <el-form-item label="文  档:" prop="documents">
+                <el-select
+                  v-model="AIform.documents"
+                  multiple
+                  placeholder="请选择文档"
+                  style="width: 100%"
+                  :disabled="isDocumentSelectDisabled"
+                  clearable
+                  filterable
+                >
+                  <el-option
+                    v-for="(doc, index) in documentList"
+                    :label="doc.name"
+                    :value="doc.id"
+                    :key="index"
+                  ></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="描 述:">
+                <el-input
+                  v-model="AIform.role_description"
+                  type="textarea"
+                  style="width: 350px"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </el-form>
+        <div class="selection-summary">
+          <div class="summary-content">
+            <span class="summary-label">当前选择了:</span>
+            <p class="summary-text">
+              模型库: OLLAMA 模型类型: CHAT 模型名称:
+              <span>{{ AIform.model_name }}</span>
+            </p>
+            <p class="summary-text">
+              知识库:<span>{{ getKnowledgeBaseNames }}</span> 文档:
+              <span>{{ getDocumentNames }}</span>
+            </p>
+          </div>
+          <!-- <el-button
               type="primary"
               class="generate-button"
               @click="generateApplication"
               >生成应用</el-button
-            >
-          </div>
+            > -->
         </div>
-      </el-collapse-item></el-collapse
-    >
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="cancelApplication">取 消</el-button>
+        <el-button type="primary" @click="generateApplication"
+          >生成应用</el-button
+        >
+      </span>
+    </el-dialog>
+    <div class="header_btn">
+      <el-button type="primary" @click="addApplication">新增应用</el-button>
+    </div>
+
     <div class="title" v-if="$route.name !== 'ai'">
       <h1>聊天应用列表</h1>
       <!-- <span class="title_info">选择其他应用</span> -->
@@ -158,7 +180,9 @@
                 <i class="el-icon-more"></i>
               </span>
               <el-dropdown-menu slot="dropdown">
-                <el-dropdown-item @click.native="viewApplication(card)">查看</el-dropdown-item>
+                <el-dropdown-item @click.native="viewApplication(card)"
+                  >查看</el-dropdown-item
+                >
                 <el-dropdown-item @click.native="editApplication(card)"
                   >编辑</el-dropdown-item
                 >
@@ -297,6 +321,7 @@
                 v-model="editForm.model_name"
                 placeholder="请输入选择"
                 style="width: 100%"
+                clearable
               >
                 <el-option
                   v-for="(item, index) in modelNameList"
@@ -324,6 +349,8 @@
                 placeholder="请选择知识库"
                 style="width: 100%"
                 @change="handleEditKnowledgeBaseChange"
+                clearable
+                filterable
               >
                 <el-option
                   v-for="(item, index) in kneList"
@@ -349,6 +376,8 @@
                   )
                 "
                 @change="handleEditDirectoryChange"
+                clearable
+                  filterable
               >
                 <el-option
                   v-for="(dir, index) in editDirectoryList"
@@ -366,7 +395,9 @@
                 multiple
                 placeholder="请选择文档"
                 style="width: 100%"
-                :disabled="!editForm.document_directories"
+                :disabled="editForm.document_directories==''"
+                clearable
+                  filterable
               >
                 <el-option
                   v-for="(doc, index) in editDocumentList"
@@ -400,7 +431,7 @@
       width="80%"
       :append-to-body="true"
     >
-      <div v-if="viewForm" style="padding:0 20px;">
+      <div v-if="viewForm" style="padding: 0 20px">
         <p><strong>应用名称:</strong> {{ viewForm.chat_name }}</p>
         <p><strong>模型名称:</strong> {{ viewForm.model_name }}</p>
         <p>

+ 62 - 7
src/components/webAi/js/ChatBox.js

@@ -11,7 +11,7 @@ export default {
   },
   data() {
     return {
-      activeNames: ['0'],
+      applicationDialogVisible: false,
       isThinking: false,
       thinkingDots: '',
       messages: [
@@ -167,9 +167,64 @@ export default {
       } else {
         return `${names[0]}, ${names[1]} 等${names.length}个`;
       }
+    },
+    isDocumentSelectDisabled() {
+      return !this.AIform.knowledge_base_names.length ||this.AIform.document_directories=='';
     }
   },
   methods: {
+    /* 重置表单 */
+    resetForm() {
+      if (this.$refs.AIformRef) {
+        this.$refs.AIformRef.resetFields();
+      }
+      this.AIform = {
+        chat_name: '',
+        modelLibrary: 'ollama',
+        model_type: 'chat',
+        model_name: '',
+        knowledge_base_names: [],
+        document_directories: [],
+        documents: [],
+        temperature: 0.7,
+        max_tokens: 150,
+        top_p: 1.0,
+        frequency_penalty: 0.0,
+        presence_penalty: 0.0,
+        response_format: "text",
+        context_window: 2048,
+        user_id: "user123",
+        session_id: "session456",
+        language: "en",
+        timeout: 30,
+        role_name: "Admin",
+        role_description: "",
+        role_permissions: ["read", "write", "delete"]
+      };
+    },
+    /* 新增聊天应用 */
+    addApplication() {
+      this.resetForm();
+      this.applicationDialogVisible = true;
+    },
+
+    handleCloseApplicationDialog(done) {
+      this.$confirm('确认关闭?未保存的更改将会丢失。')
+        .then(_ => {
+          this.resetForm();
+          done();
+        })
+        .catch(_ => {});
+    },
+
+    cancelApplication() {
+      this.$confirm('确认取消?未保存的更改将会丢失。')
+        .then(_ => {
+          this.resetForm();
+          this.applicationDialogVisible = false;
+        })
+        .catch(_ => {});
+    },
     /* 查看 */
     viewApplication(card) {
       this.viewForm = { ...card };
@@ -296,7 +351,7 @@ export default {
     loadEditDocumentList(val) {
       // 找到选中目录的名称
       const selectedDirectoryName = val[0];
-    
+      const id= this.directoryList.find(el=>el.id==val)
       // 从 kneList 中找到对应的知识库
       const selectedKnowledgeBase = this.kneList.find(kb => 
         kb.name === this.editForm.knowledge_base_names[0]
@@ -310,12 +365,11 @@ export default {
       let queryForm = {
         page: 1,
         pageSize: 9999,
-        bucket_id: this.editForm.knowledge_base_names[0],
+        bucket_id:selectedDirectoryName === '全部' ? this.editForm.knowledge_base_names[0]:id.kb_id,
         doc_type_id: selectedDirectoryName === '全部' ? 0 : this.getDirectoryIdByName(selectedDirectoryName),
       };
     
       getBucketContents(queryForm).then(res => {
-        console.log(res);
         this.editDocumentList = res.data.documents;
       });
     },
@@ -462,8 +516,9 @@ export default {
 
             if (response.status === 200) {
               this.$message.success('应用生成成功');
-              this.AIform={}
+              this.resetForm();
               this.fetchApplicationList();
+              this.applicationDialogVisible = false; // 关闭弹窗
               // 可选:重定向到新应用或更新 UI
             } else {
               this.$message.error(response.data.message || '应用生成失败');
@@ -554,11 +609,11 @@ export default {
       });
     },
     loadDocumentList(val) {
-      console.log(val);
+     const id= this.directoryList.find(el=>el.id==val)
       let queryForm={
         page: 1,
         pageSize: 9999,
-        bucket_id: this.bucket_id,
+        bucket_id:val=='001'?this.bucket_id : id.kb_id,//this.bucket_id,
         doc_type_id: val=='001'?0 :val,
       }
       getBucketContents(queryForm).then(res=>{

+ 5 - 1
src/views/document/create.scss

@@ -92,13 +92,17 @@
                width:90%;
                margin:auto;
                .el-collapse-item {
+                .el-collapse-item__header{
+                  height: 30px;
+                }
                    .el-collapse-item__content{
+                    padding-bottom: 5px;
                      .sub-menus{
                        margin-left:15px;
                        font-size:12px;
                        height:20px;
                        line-height: 20px;
-                       cursor:pointer;
+                       /* cursor:move; */
                      }
                    }
                }

+ 7 - 7
src/views/document/create.vue

@@ -130,7 +130,7 @@
                     data-type="article"
                     class="sub-menus"
                   >
-                    <div @click="onTemplateInfo(it.id)">{{ it.title }}</div>
+                    <div @click="onTemplateInfo(it.id)" style="cursor:pointer">{{ it.title }}</div>
                   </div>
                 </el-collapse-item>
               </el-collapse>
@@ -297,7 +297,7 @@
                                         ) in fiveChild.dataList"
                                         :key="fiveIndex"
                                       >
-                                        <div>{{ fiveIts.name }}</div>
+                                        <div style="cursor:move;">{{ fiveIts.name }}</div>
                                       </div>
                                     </transition-group>
                                   </draggable>
@@ -319,7 +319,7 @@
                                     ) in greatGrandChild.dataList"
                                     :key="index"
                                   >
-                                    <div>{{ its.name }}</div>
+                                    <div style="cursor:move;">{{ its.name }}</div>
                                   </div>
                                 </transition-group>
                               </draggable>
@@ -339,7 +339,7 @@
                                 v-for="(it, index) in grandChild.dataList"
                                 :key="index"
                               >
-                                <div>{{ it.name }}</div>
+                                <div style="cursor:move;">{{ it.name }}</div>
                               </div>
                             </transition-group>
                           </draggable>
@@ -359,7 +359,7 @@
                             v-for="(it, index) in child.dataList"
                             :key="index"
                           >
-                            <div>{{ it.name }}</div>
+                            <div style="cursor:move;">{{ it.name }}</div>
                           </div>
                         </transition-group>
                       </draggable>
@@ -379,7 +379,7 @@
                         v-for="(it, index) in item.dataList"
                         :key="index"
                       >
-                        <div>{{ it.name }}</div>
+                        <div style="cursor:move;">{{ it.name }}</div>
                       </div>
                     </transition-group>
                   </draggable>
@@ -1430,7 +1430,7 @@ export default {
             const contentItems = (content.match(/{{([^}]+)}}/g) || []).map(
               (match) => match.slice(2, -2)
             );
-            console.log('contentItems',contentItems);
+            console.log("contentItems", contentItems);
             // 确保 content 中引用的所有 Directory 项都存在于 attrs 中
             contentItems.forEach((itemId) => {
               if (