Browse Source

知识库管理接口联调完成(文件状态待定)

htc 4 days ago
parent
commit
7e29212b44

+ 58 - 1
src/api/agent/index.js

@@ -176,4 +176,61 @@ export function updateUserPwd(data) {
     data
   })
 }
-// ---end 教练管理
+// ---end 教练管理
+
+// ---start 知识库管理
+export function getKnowledgeList(query) {
+  return request({
+    url: '/core/knowledgebase/page',
+    method: 'get',
+    params: query
+  })
+}
+export function addKnowledge(data) {
+  return request({
+    url: '/core/knowledgebase',
+    method: 'post',
+    data
+  })
+}
+export function updateKnowledge(data) {
+  return request({
+    url: '/core/knowledgebase',
+    method: 'put',
+    data
+  })
+}
+export function getKnowledgeInfo(query) {
+  return request({
+    url: '/core/knowledgebase/'+query,
+    method: 'get'
+  })
+}
+export function deleteKnowledge(id) {
+  return request({
+    url: `/core/knowledgebase/delete/${id}`,
+    method: 'delete'
+  })
+}
+
+export function getKnowledgeFileList(query) {
+  return request({
+    url: '/core/knowledgedata/list',
+    method: 'get',
+    params: query
+  })
+}
+export function addKnowledgeFile(data) {
+  return request({
+    url: '/core/knowledgedata',
+    method: 'post',
+    data
+  })
+}
+export function deleteKnowledgeFile(id) {
+  return request({
+    url: `/core/knowledgedata/delete/${id}`,
+    method: 'delete'
+  })
+}
+// ---end 知识库管理

+ 1 - 1
src/assets/scss/common.scss

@@ -413,7 +413,7 @@ img {
     z-index: 1;
     width: 100%;
     // height: 100%;
-    height: calc(100vh - 260px);
+    height: calc(100vh - 170px);
     // overflow: hidden;
     overflow-y: auto;
     transition: width .3s;

+ 2 - 2
src/router/index.js

@@ -50,8 +50,8 @@ export const moduleRoutes = {
   children: [
     { path: '/home', component: () => import('@/views/modules/home'), name: 'home', meta: { title: '主页', isTab: false } },
     //创衡智能体
-    { path: '/agentDialog', component: () => import('@/views/modules/agent/dialog'), name: 'agentDialog', meta: { title: '创建新对话', isTab: false } },
-    { path: '/agentDialogResult', component: () => import('@/views/modules/agent/dialogResult'), name: 'agentDialogResult', meta: { title: '对话结果', isTab: false } },
+    // { path: '/agentDialog', component: () => import('@/views/modules/agent/dialog'), name: 'agentDialog', meta: { title: '创建新对话', isTab: false } },
+    // { path: '/agentDialogResult', component: () => import('@/views/modules/agent/dialogResult'), name: 'agentDialogResult', meta: { title: '对话结果', isTab: false } },
     { path: '/agentProgramAddTeam', component: () => import('@/views/modules/agent/program/addTeam'), name: 'agentProgramAddTeam', meta: { title: '添加团队', isTab: false } },
     { path: '/agentKnowledgeAdd', component: () => import('@/views/modules/agent/knowledge/add'), name: 'agentKnowledgeAdd', meta: { title: '创建知识库', isTab: false } },
     { path: '/agentKnowledgeDetail', component: () => import('@/views/modules/agent/knowledge/detail'), name: 'agentKnowledgeDetail', meta: { title: '知识库详情', isTab: false } },

+ 2 - 2
src/views/main-sidebar.vue

@@ -6,9 +6,9 @@
     <div class="logo">
       <img src="@/assets/images/agent/logo.png">
     </div>
-    <div class="create_dialog">
+    <!-- <div class="create_dialog">
       + 创建新对话
-    </div>
+    </div> -->
     <div class="aui-sidebar__inner" style="margin-top: 26px;">
       <el-menu
         :collapse="$store.state.sidebarFold"

+ 113 - 36
src/views/modules/agent/knowledge.vue

@@ -4,30 +4,25 @@
             <div class="left">知识库管理</div>
             <div class="right adfac">
                 <div class="r_query adfacjb queryInput">
-                    <el-input v-model="queryParams.name" placeholder="请输入知识库名称查询"></el-input>
+                    <el-input v-model="queryParams.baseName" placeholder="请输入知识库名称查询" @keyup.enter.native="getList"></el-input>
                     <img src="@/assets/images/agent/query_mini.png">
                 </div>
-                <!-- <div class="r_add" @click="handleAdd">+ 创建知识库</div> -->
                 <div class="r_add" @click="show=true">+ 创建知识库</div>
             </div>
         </div>
         <template v-if="list.length">
             <div class="list">
                 <div class="item" v-for="(item, index) in list" :key="index" @click.self="handleFileList(item)">
-                    <div class="i_top adfac">
+                    <div class="i_top adfac" @click.self="handleFileList(item)">
                         <img src="@/assets/images/agent/file_mini.png">
                         <div class="texts">
-                            <p>{{ '创衡 - 团队教练知识库' }}</p>
-                            <p><span>{{ 13 }}</span>文档·<span>{{ 22 }}</span>千字符·<span>{{ 0 }}</span>关联应用</p>
+                            <p>{{ item.baseName }}</p>
+                            <p>知识库<span>{{ item.dataNum||0 }}</span></p>
                         </div>
                     </div>
-                    <div class="i_txt" v-if="index===0">
-                    </div>
-                    <div class="i_txt" v-if="index===1">
-                        {{ 'useful for when you want to answer queries about the 一百个小故事_酒太白.txt' }}
-                    </div>
+                    <div class="i_txt" @click.self="handleFileList(item)">{{ item.description||'' }}</div>
                     <div class="i_bottom adfacjb">
-                        <div class="ib_l adfac" @click="handleTag">
+                        <div class="ib_l adfac" @click="handleTag(item)">
                             <img src="@/assets/images/agent/tag_mini.png">
                             <span>添加标签</span>
                         </div>
@@ -43,6 +38,18 @@
                     </div>
                 </div>
             </div>
+            <el-row style="display: flex;justify-content: center;">
+                <el-pagination
+                    @size-change="handleSizeChange"
+                    @current-change="handleCurrentChange"
+                    :current-page="queryParams.page"
+                    :page-sizes="[5, 10, 20, 50]"
+                    :page-size="10"
+                    layout="total, sizes, prev, pager, next, jumper"
+                    :total="total"
+                    v-show="total > 0">
+                </el-pagination>
+            </el-row>
         </template>
         <template v-else>
             <div class="empty adffcacjc">
@@ -82,11 +89,11 @@
         </el-dialog>
         <el-dialog width="579px" :visible.sync="setShow" title="知识库设置" @close="cancel3">
             <el-form ref="setRef" :model="zskForm" :rules="zskRules" label-width="120px" style="width: 90%;margin: 0 auto;" label-position="top">
-                <el-form-item label="知识库名称" prop="aaa">
-                    <el-input v-model="zskForm.aaa" placeholder="请输入知识库名称"></el-input>
+                <el-form-item label="知识库名称" prop="baseName">
+                    <el-input v-model="zskForm.baseName" placeholder="请输入知识库名称"></el-input>
                 </el-form-item>
-                <el-form-item label="知识库描述" prop="bbb">
-                    <el-input type="textarea" :rows="2" v-model="zskForm.bbb" placeholder="请输入知识库描述"></el-input>
+                <el-form-item label="知识库描述" prop="description">
+                    <el-input type="textarea" :rows="2" v-model="zskForm.description" placeholder="请输入知识库描述"></el-input>
                 </el-form-item>
             </el-form>
             <div class="demo-drawer__footer" style="display: flex;justify-content: end;">
@@ -98,12 +105,16 @@
 </template>
 
 <script setup name="">
-    import { ref, getCurrentInstance } from 'vue'
+    import { ref, getCurrentInstance, onMounted } from 'vue'
+    import {getKnowledgeList,addKnowledge,updateKnowledge,getKnowledgeInfo,deleteKnowledge} from '@/api/agent/index.js'
     const { proxy } = getCurrentInstance();
     
     const queryParams = ref({
-        name: ''
+        page:1,
+        limit:10,
+        baseName: ''
     })
+    const total = ref(0)
     const pvisibles = ref([false,false])
     const show = ref(false)
     const tagShow = ref(false)
@@ -112,10 +123,13 @@
     const buttonLoading3 = ref(false)
     const setShow = ref(false)
     const tagList = ref([])
-    const list = ref([1,1])
+    const list = ref([])
     const form = ref({
         id:'',
-        baseName: ''
+        coachId:proxy.$store.state.user.id,
+        baseName: '',
+        description: '',
+        labels:''
     })
     const rules = ref({
         baseName: [
@@ -125,14 +139,17 @@
     const zskRef = ref(null)
     const setRef = ref(null)
     const zskForm = ref({
-        aaa: '',
-        bbb: ''
+        id:'',
+        baseName: '',
+        coachId:proxy.$store.state.user.id,
+        description: '',
+        labels:''
     })
     const zskRules = ref({
-        aaa: [
+        baseName: [
             { required: true, message: '请输入知识库名称', trigger: 'blur' }
         ],
-        bbb: [
+        description: [
             { required: true, message: '请输入知识库描述', trigger: 'blur' }
         ]
     })
@@ -140,7 +157,12 @@
     const submitForm = () => {
         proxy.$refs.zskRef.validate((valid) => {
             if (valid) {
-                buttonLoading.value = true
+                addKnowledge(form.value).then(res => {
+                    if(res.code!==0) return proxy.$message.error(res.msg)
+                    proxy.$message.success('创建成功')
+                    show.value = false;
+                    getList()
+                })
                 
             } else {
                 return false;
@@ -148,12 +170,20 @@
         });
     }
     const cancel = () => {
-        show.value = false
-        proxy.$refs.zskRef.resetFields()
+        show.value = false;
+        form.value = {
+            id:'',
+            coachId:proxy.$store.state.user.id,
+            baseName: '',
+            description: '',
+            labels:''
+        }
+        proxy.$refs.zskRef.resetFields();
     }
 
     const handleFileList = (item) => {
-        proxy.$router.push({path: 'agentKnowledgeFile', query:{title: item.title||'知识库标题'}})
+        console.log(item)
+        proxy.$router.push({path: 'agentKnowledgeFile', query:{title: item.baseName,id:item.id}})
     }
 
     const handleShowPop = (index) => {
@@ -161,6 +191,7 @@
     }
 
     const handleSet = (item,index) => {
+        zskForm.value = {...zskForm.value, ...item}
         setShow.value = true;
         pvisibles.value[index] = false;
     }
@@ -172,11 +203,17 @@
             cancelButtonText: '取消',
             type: 'warning'
         }).then(() => {
-            
+            deleteKnowledge(item.id).then((res)=>{
+                if(res.code!==0) return proxy.$message.error(res.msg)
+                proxy.$message.success('删除成功')
+                getList()
+            })
         }).catch(() => {});
     }
 
-    const handleTag = () => {
+    const handleTag = (item) => {
+        form.value = {...form.value, ...item}
+        tagList.value = item.labels.split(',').map(l => ({name: l}));
         tagShow.value = true;
     }
     const handleDeleteTag = (item, index) => {
@@ -188,24 +225,40 @@
     }
 
     const submitForm2 = () => {
+        if(tagList.value.length === 0) return proxy.$message.error('请至少输入一条标签')
+        form.value.labels = tagList.value.map(item => item.name).join(',');
         buttonLoading2.value = true;
-        setTimeout(() => {
+        updateKnowledge(form.value).then((res)=>{
+            if(res.code!==0) return proxy.$message.error(res.msg)
+            proxy.$message.success('添加成功')
             tagShow.value = false;
             buttonLoading2.value = false;
-        }, 1000)
+            getList();
+        })
     }
     const cancel2 = () => {
         tagShow.value = false;
+        form.value = {
+            id:'',
+            coachId:proxy.$store.state.user.id,
+            baseName: '',
+            description: '',
+            labels:''
+        }
     }
 
     const submitForm3 = () => {
         proxy.$refs.setRef.validate((valid) => {
             if (valid) {
                 buttonLoading3.value = true;
-                setTimeout(() => {
+                updateKnowledge(zskForm.value).then((res)=>{
+                    if(res.code!==0) return proxy.$message.error(res.msg)
+                    proxy.$message.success('修改成功')
                     setShow.value = false;
                     buttonLoading3.value = false;
-                }, 1000)
+                    getList();
+                })
+
             } else {
                 return false;
             }
@@ -214,11 +267,35 @@
     const cancel3 = () => {
         setShow.value = false;
         zskForm.value = {
-            aaa: '',
-            bbb: ''
+            id:'',
+            coachId:proxy.$store.state.user.id,
+            baseName: '',
+            description: '',
+            labels:''
         }
         proxy.$refs.setRef.resetFields();
     }
+
+    const getList = () => {
+        getKnowledgeList(queryParams.value).then((res)=>{
+            if(res.code!==0) return proxy.$message.error(res.msg);
+            list.value = res.data.list;
+            total.value = res.data.total
+        })
+    }
+
+    const handleCurrentChange = (val) => {
+        queryParams.value.page = val;
+        getList()
+    }
+    const handleSizeChange = (val) => {
+        queryParams.value.limit = val;
+        getList()
+    }
+
+    onMounted(()=>{
+        getList();
+    })
 </script>
 
 <style scoped lang="scss">
@@ -312,7 +389,7 @@
                                 span{
                                     font-weight: bold;
                                     color: #6B7280;
-                                    margin: 0 2px;
+                                    margin-left: 5px;
                                 }
                             }
                         }

+ 112 - 71
src/views/modules/agent/knowledge/file.vue

@@ -11,7 +11,12 @@
             <div class="c_top adfacjb">
                 <div class="ct_l adfac">
                     <p>文件</p>
-                    <el-input placeholder="搜索" suffix-icon="el-icon-search" v-model="queryParams.filename"></el-input>
+                    <el-input placeholder="搜索" suffix-icon="el-icon-search" v-model="queryParams.fileName" style="width: 300px;" @keyup.enter.native="getList"></el-input>
+                    <el-select v-model="queryParams.status" placeholder="状态" style="width: 200px;margin-left: 20px;" @keyup.enter.native="getList">
+                        <el-option label="解析失败" :value="-1"></el-option>
+                        <el-option label="解析中" :value="0"></el-option>
+                        <el-option label="解析完成" :value="1"></el-option>
+                    </el-select>
                 </div>
                 <div class="ct_r">
                     <el-button type="primary" icon="el-icon-plus" @click="handleAddFile">添加文件</el-button>
@@ -24,18 +29,21 @@
                             {{ scope.$index + 1 }}
                         </template>
                     </el-table-column>
-                    <el-table-column label="文件名称" prop="aaa"></el-table-column>
-                    <el-table-column label="字符数" prop="bbb"></el-table-column>
-                    <el-table-column label="上传时间" prop="ccc"></el-table-column>
+                    <el-table-column label="文件名称" prop="fileName"></el-table-column>
+                    <el-table-column label="文件格式" prop="fileFormat"></el-table-column>
+                    <!-- <el-table-column label="字符数" prop="bbb"></el-table-column> -->
+                    <el-table-column label="上传时间" prop="createDate"></el-table-column>
                     <el-table-column label="状态" prop="ddd">
                         <template #default="scope">
-                            <el-switch v-model="value" active-color="#833478" inactive-color="#833478" active-text="可用" inactive-text="已禁用"></el-switch>
+                            <div class="sdiv adfac">
+                                <div class="sdian" :class="{'jxsb':scope.row.status===-1,'jxz':scope.row.status===0,'jxwc':scope.row.status===1}"></div>
+                                <div class="stext">{{ statuscfg[scope.row.status]||'' }}</div>
+                            </div>
                         </template>
                     </el-table-column>
-                    <el-table-column label="操作" width="200">
+                    <el-table-column label="操作" width="100">
                         <template #default="scope">
-                            <el-button link type="text" size="mini" @click="handleSetName(scope.row)">重命名</el-button>
-                            <el-button link type="text" size="mini" @click="handleDelete(scope.row)">删除</el-button>
+                            <el-button link type="text" size="mini" @click="handleDelete(scope.row)" v-hasPermi="['core:knowledgedata:delete']">删除</el-button>
                         </template>
                     </el-table-column>
                 </el-table>
@@ -66,8 +74,11 @@
                 <el-upload
                     class="upload-demo"
                     drag
-                    action=""
-                    multiple>
+                    :action="uploadUrl"
+                    :headers="uploadHeaders"
+                    :on-success="uploadFileSuccess"
+                    :before-upload="beforeAvatarUpload"
+                    :limit="1">
                     <i class="el-icon-upload"></i>
                     <div class="el-upload__text">点击或拖拽文件上传</div>
                     <div class="el-upload__text" style="font-size: 12px;color: #C1C7D2;line-height: 20px;margin-top: 8px;">
@@ -76,50 +87,73 @@
                 </el-upload>
             </div>
             <div class="demo-drawer__footer" style="display: flex;justify-content: end;">
-                <el-button :loading="buttonLoading" type="primary" @click="submitForm">确认</el-button>
+                <el-button :loading="buttonLoading" type="primary" @click="submitForm" v-hasPermi="['core:knowledgedata:save']">确认</el-button>
                 <el-button @click="cancel" style="margin-right: 5%;">取 消</el-button>
             </div>
         </el-dialog>
-        <el-dialog width="579px" :visible.sync="setShow" title="知识库设置" @close="cancel2">
-            <el-form ref="setRef" :model="zskForm" :rules="zskRules" label-width="120px" style="width: 90%;margin: 0 auto;" label-position="top">
-                <el-form-item label="知识库名称" prop="aaa">
-                    <el-input v-model="zskForm.aaa" placeholder="请输入知识库名称"></el-input>
-                </el-form-item>
-            </el-form>
-            <div class="demo-drawer__footer" style="display: flex;justify-content: end;">
-                <el-button :loading="buttonLoading2" type="primary" @click="submitForm2">保存</el-button>
-                <el-button @click="cancel2" style="margin-right: 5%;">取 消</el-button>
-            </div>
-        </el-dialog>
     </div>
 </template>
 
 <script setup name="">
-    import { ref, getCurrentInstance, onMounted } from 'vue'
+    import Cookies from "js-cookie";
+    import { ref, getCurrentInstance, onMounted, nextTick } from 'vue'
+    import {getKnowledgeFileList,addKnowledgeFile,deleteKnowledgeFile} from '@/api/agent/index.js'
     const { proxy } = getCurrentInstance();
+    const uploadUrl = `${window.SITE_CONFIG["apiURL"]}/sys/oss/uploadFile`
+    const uploadHeaders = {token:Cookies.get("token")}; 
     
+    const statuscfg = {
+        '-1':'解析失败',
+        '0':'解析中',
+        '1':'解析完成'
+    }
     const title = ref('')
     const list = ref([])
     const show = ref(false)
     const buttonLoading = ref(false)
     const queryParams = ref({
+        baseId:'',
         page: 1,
         limit: 10,
-        filename:''
+        fileName:'',
+        status:''
     })
     const total = ref(0)
     const loading = ref(false)
-    const setShow = ref(false)
-    const buttonLoading2 = ref(false)
-    const setRef = ref(null)
-    const zskForm = ref({
-        aaa: ''
-    })
-    const zskRules = ref({
-        aaa: [
-            { required: true, message: '请输入知识库名称', trigger: 'blur' }
-        ]
+    const fileDto = ref({
+        baseId:'',
+        fileData:'',
+        fileFormat:'',
+        fileName:''
     })
+    
+    const uploadFileSuccess = e =>{
+        fileDto.value.fileData = e.data;
+        proxy?.$modal.msgSuccess('上传成功');
+    }
+    const beforeAvatarUpload = (e) => {
+        let name = e.name.split('.')[0];
+        let type = e.name.split('.')[e.name.split('.').length-1];
+        let isTxt = e.type === 'text/plain';
+        let isPdf = e.type === 'application/pdf';
+        let isHtml = e.type === 'text/html';
+        let isExcel = e.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
+        let isDocx = e.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
+        if((type.toLowerCase() === 'xlsx' || type.toLowerCase() === 'xls' && isExcel) 
+            || (type.toLowerCase() === 'docx' && isDocx)
+            || (type.toLowerCase() === 'txt' && isTxt)
+            || (type.toLowerCase() === 'pdf' && isPdf)
+            || (type.toLowerCase() === 'html' && isHtml)
+            && e.size <= 1024*1024*15){
+            fileDto.value.fileName = name;
+            fileDto.value.fileFormat = type;
+        }else{
+            proxy?.$modal.msgError('请上传txt、pdf、html、xlsx、xls或docx格式的文件!且文件大小不超过15MB!');
+            fileDto.value.fileName = '';
+            fileDto.value.fileFormat = '';
+            return false;
+        }
+    }
 
     const handleBack = () => {
         proxy.$router.go(-1)
@@ -135,19 +169,22 @@
 
     const submitForm = () => {
         buttonLoading.value = true;
-        setTimeout(() => {
+        addKnowledgeFile(fileDto.value).then((res) => {
+            if(res.code!==0) return proxy?.$modal.msgError(res.msg);
+            proxy?.$modal.msgSuccess("上传成功");
             show.value = false;
             buttonLoading.value = false;
-            list.value = [...list.value, {id: 1}]
-        }, 2000)
+            getList();
+        })
     }
 
     const getList = () => {
         loading.value = true;
-        setTimeout(() => {
-            total.value = list.value.length
+        getKnowledgeFileList(queryParams.value).then((res) => {
             loading.value = false;
-        }, 1000)
+            list.value = res.data || [];
+            total.value = res.data.total;
+        })
     }
     const handleSizeChange = (val) => {
         queryParams.value.limit = val;
@@ -159,42 +196,21 @@
         getList()
     }
 
-    const handleSetName = (item) => {
-        setShow.value = true;
-    }
     async function handleDelete(row) {
-        await proxy?.$modal.confirm('确认删除文件【' + row.realName + '】吗?').finally(() => loading.value = false);
-        // let res = await deleteCoach([row.id]);
-        // if (res.code === 0) proxy?.$modal.msgSuccess("删除成功");
-        // else return proxy?.$modal.msgError(res.msg);
-        // await getList();
-    }
-
-    const submitForm2 = () => {
-        proxy.$refs.setRef.validate((valid) => {
-            if (valid) {
-                buttonLoading2.value = true;
-                setTimeout(() => {
-                    setShow.value = false;
-                    buttonLoading2.value = false;
-                }, 2000)
-            } else {
-                return false;
-            }
-        });
-    }
-
-    const cancel2 = () => {
-        setShow.value = false;
-        zskForm.value = {
-            aaa: ''
-        }
-        proxy.$refs.setRef.resetFields();
+        await proxy?.$modal.confirm('确认删除文件【' + row.fileName + '】吗?').finally(() => loading.value = false);
+        let res = await deleteKnowledgeFile([row.id]);
+        if (res.code === 0) proxy?.$modal.msgSuccess("删除成功");
+        else return proxy?.$modal.msgError(res.msg);
+        await getList();
     }
 
     onMounted(() => {
         title.value = proxy.$route.query.title;
-        getList()
+        queryParams.value.baseId = proxy.$route.query.id;
+        fileDto.value.baseId = proxy.$route.query.id;
+        nextTick(() => {
+            getList()
+        })
     })
 </script>
 
@@ -278,6 +294,31 @@
                 }
             }
         }
+
+        .sdiv{
+            .sdian{
+                width: 8px;
+                height: 8px;
+                border-radius: 50%;
+                &.jxsb{
+                    background: rgb(196, 33, 33);
+                }
+                &.jxz{
+                    background: #FFd750;
+                }
+                &.jxwc{
+                    background: #22C55D;
+                }
+            }
+            .stext{
+                font-family: PingFangSC, PingFang SC;
+                font-weight: 400;
+                font-size: 14px;
+                color: #393939;
+                line-height: 20px;
+                margin-left: 6px;
+            }
+        }
     }
     
     .cs_upload{

+ 1 - 1
src/views/modules/agent/program.vue

@@ -494,7 +494,7 @@
         getProgramTeamInfo,
         deleteProgramTeam 
     } from '@/api/agent/index.js'
-    const uploadUrl = `${window.SITE_CONFIG["apiURL"]}//sys/user/import`
+    const uploadUrl = `${window.SITE_CONFIG["apiURL"]}/sys/user/import`
     const uploadUrl2 = `${window.SITE_CONFIG["apiURL"]}/sys/oss/uploadFile`
     const uploadHeaders = {token:Cookies.get("token")};