Procházet zdrojové kódy

调整知识图谱构建的菜单

yangdr před 4 týdny
rodič
revize
01153794e4

+ 73 - 0
src/api/AgentApi.ts

@@ -21,6 +21,16 @@ interface RequestActionParams { // 定义Job接口
     name: string
     value: any
 }
+export interface GraphData {
+    id: string
+    category: string
+    name: string
+    graph_description: string
+    graph_id: number
+    created: string
+    updated: string
+    status: number
+}
 export interface SearchData {
     job_name: string,
     start_category: string,
@@ -72,6 +82,7 @@ export const JobCategory = {
 }
 export const JobSatus = [
     //primary success info warning danger
+    { "label": "全部", "value": 9999, "tag": "danger", "could_be_set": false },
     { "label": "无效", "value": -1, "tag": "danger", "could_be_set": false },
     { "label": "准备中", "value": 0, "tag": "primary", "could_be_set": true },
     { "label": "运行中", "value": 1, "tag": "success", "could_be_set": false },
@@ -375,4 +386,66 @@ export function setConfig(params: any): Promise<StandardResponse> {
         ]
     }
     return serverRequest(URL_GET_CONFIG, data)
+}
+
+export async function serverStreamRequest(url: string, body: RequestBody) {
+    // var instance = axios.create({baseURL: 'http://127.0.0.1:8000', timeout: 80000})
+    // const handleStream = (response:any) => {
+    //     console.log("Stream started")
+    //     const reader = response.data.getReader()
+    //     const decoder = new TextDecoder()
+    //     let done:boolean = false 
+    //     while (!done) {
+    //       reader.read().then(({ done, value }:any) => {
+    //         done = done
+    //         if (done) {
+    //           console.log("Stream finished")
+    //         } else {
+    //           const chunkValue = decoder.decode(value)
+    //           console.log(chunkValue)
+    //         }
+    //       })
+    //     }
+    // }
+
+    // instance.post(url, body, {responseType: 'stream'})
+    // .then(handleStream)
+    // .catch(error => {
+    // console.error("Error:", error) 
+    // })
+    try {
+        let response = await fetch('http://127.0.0.1:8000' + url, {
+            method: 'POST', body: JSON.stringify(body),
+            headers: {
+                'Content-Type': 'application/json',
+            }
+        });
+        console.log(response);
+        if (!response.ok) {
+            throw new Error('Network response was not ok');
+        }
+        if (response.body === null) {
+            throw new Error('Response body is null');
+        }
+        const reader = response.body.getReader();
+        const textDecoder = new TextDecoder();
+        let result = true;
+        let output = ''
+        while (result) {
+            const { done, value } = await reader.read();
+
+            if (done) {
+                console.log('Stream ended');
+                result = false;
+                break;
+            }
+            const chunkText = textDecoder.decode(value);
+            output += chunkText;
+            console.log('Received chunk:', chunkText);
+        }
+    } catch (e) {
+        console.log(e);
+    }
+
+
 }

+ 11 - 2
src/components/CreateKBFileDialog.vue

@@ -1,10 +1,10 @@
 <template>
   <div class="add-kb-file-dialog">
     <el-dialog v-model="dialogVisible" title="知识库" width="1000px" align-center :show-close="false"
-      @closed="() => { emit('update:modelValue', false) }">
+      @closed="handleClosed">
       <el-form ref="formRef" style="max-width: 100%" :model="formData" label-width="auto" class="demo-dynamic">
         <el-form-item prop="name" label="知识库名称:">
-          {{ formData.name }}
+          <span style="font-weight: bold;">{{ formData.name }}</span>
         </el-form-item>
         <el-form-item prop="description" label="知识库备注:">
           {{ formData.description }}
@@ -267,6 +267,15 @@ const beforeRemove = (uploadFile, uploadFiles) => {
   //   () => false
   // )
 }
+
+const handleClosed = () => {
+  emit('update:modelValue', false)
+  if (formData.value.fileTableData.length > 0) {
+    formData.value.fileTableData.slice(0, formData.value.fileTableData.length)
+    proxy.$refs['formRef'].resetFields()
+    proxy.$refs['fileUploadRef'].clearFiles()
+  }
+}
 </script>
 
 <style lang="less" scoped>

+ 7 - 6
src/components/SideMenu.vue

@@ -3,13 +3,13 @@
     <div class="nav-section">
       <el-menu :default-active="$route.path" router>
         <h3>工作台</h3>
-        <el-menu-item index="/" :route="{ name: 'home' }">
+        <el-menu-item index="/kmplatform/kgbuilder/home" :route="{ name: 'home' }">
           <template #title>
             <!-- <el-icon></el-icon> -->
             <span>工作台概览</span>
           </template>
         </el-menu-item>
-        <el-menu-item index="/workspace/config" :route="{ name: 'config' }">
+        <el-menu-item index="/kmplatform/kgbuilder/config" :route="{ name: 'config' }">
           <template #title>
             <!-- <el-icon></el-icon> -->
             <span>配置</span>
@@ -17,8 +17,8 @@
         </el-menu-item>
 
         <h3>文本抽取</h3>
-        <el-menu-item v-for="queue in queues" :key="queue.id" :index="'queue' + '_' + queue.id"
-          @click="queueClicked(queue)">
+        <el-menu-item v-for="queue in queues" :key="queue.id"
+          :index="'/kmplatform/kgbuilder/workspace/queue/' + queue.id" @click="queueClicked(queue)">
           <template #title>
             <span>{{ queue.name }}</span>
             <el-tag v-if="queue.type == 'input'" effect="light" round>START</el-tag>
@@ -26,10 +26,11 @@
         </el-menu-item>
 
         <h3>知识图谱</h3>
-        <el-menu-item @click="handleMenuClick('graph')">
+        <el-menu-item index="/kmplatform/kgbuilder/workspace/graph" @click="handleMenuClick('graph')">
           <span>全部图谱</span>
         </el-menu-item>
-        <el-menu-item @click="handleMenuClick('graph-std-schemas')">
+        <el-menu-item index="/kmplatform/kgbuilder/workspace/graph-std-schemas"
+          @click="handleMenuClick('graph-std-schemas')">
           <span>图谱标准</span>
         </el-menu-item>
       </el-menu>

+ 1 - 1
src/dialogs/OCRDialog.vue

@@ -301,7 +301,7 @@ async function handleAllImport() {
     })
     const { data, code } = res
     if (code === 200) {
-      handleImportFiles(data.list)
+      handleImportFiles(data.list.filter((it: any) => it.status))
     }
 
   } catch (e) {

+ 2 - 0
src/stores/menu.js

@@ -75,3 +75,5 @@ export const useMenuStore = defineStore('menu', () => {
   }
   return { routeList, updateRouteList, operationPermissions, isOP }
 })
+
+export default useMenuStore

+ 0 - 1
src/views/Framework.vue

@@ -1,5 +1,4 @@
 <template>
-
   <div class="main-container">
     <el-container>
       <el-aside class="main-aside">

+ 49 - 160
src/views/GraphView.vue

@@ -1,6 +1,4 @@
 <template>
-
-
     <el-row>
         <span style="text-align: right;">
             <h2>知识图谱</h2>
@@ -8,32 +6,25 @@
     </el-row>
     <el-row style="margin:15px;">
         <el-button @click="handleRefreshTable">刷新</el-button>
+        <el-button @click="handleStreamTest">Stream</el-button>
     </el-row>
 
     <el-row>
-        <el-table :data="pageData.records" highlight-current-row @current-change="handleCurrentChange">
-            <el-table-column prop="id" label="ID" width="50"></el-table-column>
-            <el-table-column prop="job_category" label="工作类型" width="200"></el-table-column>
-            <el-table-column prop="job_name" label="工作名称" width="200"></el-table-column>
-            <el-table-column prop="job_creator" label="创建人" width="100"></el-table-column>
-            <el-table-column prop="status" label="状态" width="100">
-                <template v-slot="scope">
-                    <el-tag :type="getJobStatusTag(scope.row.status)">{{ formatStatus(scope.row.status) }}</el-tag>
-                </template>
-            </el-table-column>
-            <el-table-column label="操作" width="500">
-                <template v-slot="scope">
-                    <el-menu mode="horizontal">
+        <template v-for="(index) in pageData.records" :key="index">
+            <el-card shadow="hover" style="width: 300px; margin: 10px;">
+                <div slot="header" style="border-bottom: 1px solid #EFEFEF; height: 50px;">
+                    <span>#{{ index.graph_id }}</span>
+                    <el-button @click="handleViewGraph(index)" style="float: right; width:75px; padding: 3px 0"
+                        type="">查看</el-button>
+                </div>
+                <div class="card-content">
+                    <div style="margin-top:15px;font-size:16px;">
+                        {{ index.name }}
+                    </div>
+                </div>
+            </el-card>
+        </template>
 
-                        <el-sub-menu index="1">
-                            <template #title>操作</template>
-                            <el-menu-item index="1-1" @click="handleViewJob(scope.row)">查看</el-menu-item>
-                        </el-sub-menu>
-
-                    </el-menu>
-                </template>
-            </el-table-column>
-        </el-table>
 
     </el-row>
     <el-row style="margin-top:30px;">
@@ -41,45 +32,6 @@
             @current-change="handleCurrentPageChange" :current-page.sync="pageData.page">
         </el-pagination>
     </el-row>
-    <el-drawer title="工作详情" v-model="showDrawer" :direction="showDrawerDirection">
-        <el-tabs type="border-card" v-model="jobDetailsActivateTab">
-            <el-tab-pane label="基本信息" name="basic_info">
-                <div class="prop_header">任务类型</div>
-                <div>{{ currentJob.job_category }}</div>
-                <div class="prop_header">任务名称</div>
-                <div>{{ currentJob.job_name }}</div>
-                <div class="prop_header">创建人</div>
-                <div>{{ currentJob.job_creator }}</div>
-                <div class="prop_header">创建时间</div>
-                <div>{{ formatDate(currentJob.created) }}</div>
-                <div class="prop_header">更新时间</div>
-                <div>{{ formatDate(currentJob.updated) }}</div>
-                <div class="prop_header">日志</div>
-                <div><el-input type="textarea" v-model="currentJob.job_logs" :rows="20"></el-input></div>
-            </el-tab-pane>
-            <el-tab-pane label="文件夹" name="file_browse">
-                <el-row>
-                    <el-col :span="4">
-                        <el-tree :data="jobFileData" :props="jobFileTree" @node-click="handleTreeNodeClick"></el-tree>
-                    </el-col>
-                    <el-col :span="20">
-                        <el-table v-if="jobFileInDir.length > 0" :data="jobFileInDir" highlight-current-row
-                            style="width: 100%;">
-                            <el-table-column prop="type" label="类型" width="75"></el-table-column>
-                            <el-table-column prop="name" label="名称" width="250"></el-table-column>
-                            <el-table-column prop="size" label="操作" width="100">
-                                <template v-slot="scope">
-                                    <a :href="'/api/file/download/' + currentJob?.id + '/' + scope.row.path">下载</a>
-                                </template>
-                            </el-table-column>
-                        </el-table>
-                    </el-col>
-                </el-row>
-            </el-tab-pane>
-        </el-tabs>
-
-
-    </el-drawer>
 
 </template>
 
@@ -98,127 +50,64 @@ import {
     JobSatus,
     deleteJob,
     updateJob,
-    updateJobStatus
+    updateJobStatus,
+    serverStreamRequest,
 } from '@/api/AgentApi'
-import type { JobData, } from '@/api/AgentApi'
-import OCRDialog from '@/dialogs/OCRDialog.vue'
-import QueueSelectDialog from '@/dialogs/QueueSelectDialog.vue'
-import { ElNotification, ElMessageBox } from 'element-plus'
-import { formatTime } from 'element-plus/es/components/countdown/src/utils.mjs'
-import { formatDate } from '@/utils/misc'
-import { getSessionVar, saveSessionVar } from '@/utils/session'
-//从路由参数中获取队列ID
+import type { JobData, RequestBody, GraphData } from '@/api/AgentApi'
+import { getGraphs } from '@/api/GraphApi'
 
-const sessionId = ref<string | undefined>("")
-const ocrDialog = ref()
-const queueSelectDialog = ref()
-const queueId = ref("")
-const queueData = ref({ id: "0", queue_category: "", queue_name: "", title: "" })
-const showDrawer = ref(false)
-const showDrawerDirection = ref('rtl')
-const jobDetailsActivateTab = ref('basic_info')
-const queueIdNameDict = ref([
-    { id: "0", name: "DEFAULT", category: 'SYSTEM', title: "缺省队列", dialog: ocrDialog },
-    { id: "1", name: "OCR", category: 'SYSTEM', title: "文档OCR", dialog: ocrDialog },
-    { id: "2", name: "OCR_RESULTS", title: "OCR结果校对", category: 'SYSTEM', dialog: null },
-    { id: "3", name: "CHUNKS", title: "文本切片队列", category: 'SYSTEM', dialog: null },
-    { id: "4", name: "KB_EXTRACT", title: "知识抽取", category: 'SYSTEM', dialog: null },
-    { id: "5", name: "KB_BUILD", title: "图谱数据构建", category: 'SYSTEM', dialog: null },
-    { id: "6", name: "WORD", title: "WORD文档抽取", category: 'SYSTEM', dialog: ocrDialog },
-])
-
-const jobStatusList = ref(JobSatus)
-const jobFileTree = ref({
-    children: 'children',
-    label: 'label'
-})
-const pageData = ref({ page: 1, pages: 1, page_size: 10, total: 0, records: [] })
-const jobFileData = ref([])
-const jobFileInDir = ref([])
-const currentJob = ref<any>({ id: 0, job_category: "USER", job_name: "", job_creator: "", job_logs: "", updated: "", created: null })
-const currentActionJob = ref({ id: 0, job_category: "USER", job_name: "" })
+import { getSessionVar } from '@/utils/session'
+//从路由参数中获取队列ID
 
+interface PageData {
+    page: number;
+    pages: number;
+    page_size: number;
+    total: number;
+    records: GraphData[];
+}
+const pageData = ref<PageData>({ page: 1, pages: 1, page_size: 10, total: 0, records: [] })
 const route = useRoute()
 const router = useRouter()
-watch(route, (newValue, oldValue) => {
-    let para = newValue.params.id as string | undefined
-    if (para == undefined) {
-        return
-    }
-    console.log('route changed')
-    queueId.value = para
-    queueData.value.id = "0"
-    loadQueueData()
-})
 
 const handleRefreshTable = () => {
-    loadQueueData()
+    pageData.value.page = 1
+    loadGraphs()
+}
+function handleStreamTest() {
+    var data: RequestBody = {
+        id: "1",
+        action: 'search_nodes',
+        params: [
+        ]
+    }
+    serverStreamRequest("/kb/stream", data)
 }
 function formatStatus(status: number) {
     return getJobStatus(status)
 }
-function loadQueueData() {
 
-    jobFileData.value = []
-    jobFileInDir.value = []
-    currentJob.value = { id: 0, job_category: "USER", job_name: "" }
-    currentActionJob.value = { id: 0, job_category: "USER", job_name: "" }
-    // 根据队列ID获取队列数据
-    let queue_data = queueIdNameDict.value.find((item) => item.id == queueId.value)
+function handleViewGraph(graph: GraphData) {
 
-    if (queue_data == undefined) {
-        queueData.value = { id: "999", queue_category: 'SYSTEM', queue_name: 'UNKNOWN', title: "未知队列" }
+    if (graph == null) {
         return
     }
-    getQueue(queue_data.category, queue_data.name).then((res) => {
-        if (res.records.length == 0) {
-            return
-        }
-        queueData.value.id = res.records[0].id
-        queueData.value.queue_category = res.records[0].queue_category
-        queueData.value.queue_name = res.records[0].queue_name
-        queueData.value.title = queue_data.title
-    })
-    getJobs(queue_data.category, queue_data.name, pageData.value.page, pageData.value.page_size).then((res) => {
-        pageData.value.page = res.meta.page
-        pageData.value.pages = res.meta.pages
-        pageData.value.total = res.meta.total
-        pageData.value.records = res.records
-
-    })
-}
-function handleTreeNodeClick(data: any) {
-    if (data.type == 'dir') {
-        browseJobFile({ job_id: currentJob.value.id, path: data.name }).then((res) => {
-            jobFileInDir.value = res.records
-        })
-    }
+    router.push({ name: `graph-mgr`, params: { id: graph.graph_id } })
 }
-function handleCurrentPageChange(page: number) {
-    getJobs(queueData.value.queue_category, queueData.value.queue_name, page).then((res) => {
+function loadGraphs() {
+    getGraphs({ page: pageData.value.page, page_size: pageData.value.page_size }).then((res: any) => {
         pageData.value.page = res.meta.page
         pageData.value.pages = res.meta.pages
         pageData.value.total = res.meta.total
         pageData.value.records = res.records
     })
 }
-function handleViewJob(job: JobData) {
-    if (job == null) {
-        return
-    }
-    router.push({ name: 'graph-mgr', params: { id: job.id } })
-}
-function handleCurrentChange(data: any) {
-    if (data == null) {
-        return
-    }
-
-    //currentJob.value = data
+function handleCurrentPageChange(page: number) {
+    pageData.value.page = page
+    loadGraphs()
 }
 onMounted(() => {
-    sessionId.value = getSessionVar("session_id") as string | undefined
-    queueId.value = "5"
-    loadQueueData()
+    loadGraphs()
 })
 </script>
 

+ 49 - 36
src/views/KMPlatform/Home/Home.vue

@@ -21,19 +21,24 @@
         </div>
       </div>
       <div class="modules">
-        <div v-for="item in modules" @click="handleModuleClick(item.path)">{{ item.name }}</div>
+        <div v-for="item in modules" @click="handleModuleClick(item.path)">{{ item.title }}</div>
       </div>
     </div>
   </div>
 </template>
 
 <script setup lang="ts">
-import { ref, watchEffect, onBeforeUnmount, onMounted } from 'vue'
+import { ref, watchEffect, onBeforeUnmount, onMounted, watch } from 'vue'
 import { useRouter } from 'vue-router'
+import { intersectionBy, assign } from 'lodash'
 import { knowledgeGraphAddr } from "@/utils/config"
 import { getSessionVar } from '@/utils/session'
-import { handleError } from 'vue'
-const router = useRouter()
+import useMenuStore from "@/stores/menu"
+
+import { storeToRefs } from 'pinia'
+const menuStore = useMenuStore();
+const { routeList } = storeToRefs(menuStore)
+const router: any = useRouter()
 let timer: any
 // console.log("getSessionVar('knowledageSystem') ", getSessionVar('knowledageSystem'))
 let process = ref<any>([
@@ -53,46 +58,54 @@ let process = ref<any>([
     description: "知识更新、维护",
   }
 ])
-let modules = ref<any>([
-  {
-    name: "知识库构建",
-    path: "/kmplatform/knowledgebase/kbm",
 
-
-  },
-  {
-    name: '知识图谱构建',
-    path: "/kmplatform/kgbuilder",
-
-  },
-  {
-    name: "知识图谱维护",
-    path: knowledgeGraphAddr,
-
-  }
-])
-watchEffect(() => {
-  if (getSessionVar('knowledageSystem') == '') {
-    modules.value = [
-      {
-        name: "知识库构建",
-        path: "/kmplatform/knowledgebase/kbm",
-      },
-      {
-        name: '知识图谱构建',
-        path: "/kmplatform/kgbuilder",
-      }
-    ]
-  }
+const initModules = () => {
+  return [
+    {
+      title: "知识库构建",
+      path: "/kmplatform/knowledgebase",
+    },
+    {
+      title: '知识图谱构建',
+      path: "/kmplatform/kgbuilder",
+
+    },
+    {
+      title: "知识图谱维护",
+      path: knowledgeGraphAddr,
+    }
+  ]
 }
-)
+let modules = ref<any>(initModules())
+watch(routeList, (newValue) => {
+  console.log("routeList", newValue)
+  modules.value = intersectionBy(initModules(), newValue, 'path')
+  // enableModules.forEach((it)=>it.path=)
+  // modules.value.forEach((it: any) => it.path = "")
+  // assign(modules.value,enableModules)
+}, { immediate: true })
+// watchEffect(() => {
+//   if (getSessionVar('knowledageSystem') == '') {
+//     modules.value = [
+//       {
+//         title: "知识库构建",
+//         path: "/kmplatform/knowledgebase",
+//       },
+//       {
+//         title: '知识图谱构建',
+//         path: "/kmplatform/kgbuilder",
+//       }
+//     ]
+//   }
+// }
+// )
 
 function handleModuleClick(path: string) {
   if (/^https?/g.test(path)) {
     // path = 'http://localhost:8081/home.html'
     const newWindow = window.open(path, '_blank');
     timer = setInterval(() => {
-      newWindow?.postMessage({ type: 'login', username: getSessionVar("full_name"), userId: getSessionVar("user_id") }, "*")
+      newWindow?.postMessage({ type: 'login', usertitle: getSessionVar("full_title"), userId: getSessionVar("user_id") }, "*")
     }, 1000)
   } else {
     router.push({ path: path })

+ 1 - 1
src/views/KMPlatform/KnowledgeBase/KBM/KnowledgeBaseManagement.vue

@@ -200,7 +200,7 @@ defineOptions({
 const formData = ref({
   name: "",
   description: "",
-  tags: ""
+  tags: []
 })
 const rules = {
   name: [

+ 1 - 1
src/views/KMPlatform/KnowledgeBase/KM/KnowledgeManagement.vue

@@ -183,7 +183,7 @@ const handleCloseViewer = () => {
 };
 // 修改状态
 const handleStatusChange = async (id, status) => {
-  console.log('handleStatusChange', status)
+  // console.log('handleStatusChange', status)
   try {
     await proxy.$http.get(api.files + `${id}/changeStatus`, {
       params: {

+ 1 - 1
src/views/QueueView.vue

@@ -290,7 +290,7 @@ function formatJobCategory(category: string) {
     queueIdNameDict.value.forEach((item) => {
         // console.log(category, 'category')
         if ((item.category + "_" + item.name) == category) {
-            console.log(item.title)
+            // console.log(item.title)
             title = item.title
 
         }