Browse Source

功能优化

songxy 4 months ago
parent
commit
fe35692bf3

+ 3 - 3
ais_knowledge/knowledge/src/main/resources/application.yaml

@@ -57,9 +57,9 @@ spring:
           #          url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.master.name} # PostgreSQL 连接的示例
           #          url: jdbc:oracle:thin:@10.10.10.8:1521:ORCL # Oracle 连接的示例
           #          url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例
-          url: jdbc:postgresql://60.191.110.205:15432/knowledge
-          username: postgres
-          password: zdww1402!
+          url: jdbc:postgresql://10.249.168.231:54321/zjugis_ai?currentSchema=knowledge
+          username: zjugis
+          password: zjugis1402!
 
 server:
   port: 9999

+ 3 - 3
ais_search/web/public/config.js

@@ -15,13 +15,13 @@
       '2': 15,
     },
 
-    // server: 'https://natureai.zjugis.com/server',
+    // server: 'https://zdzy.zrzyt.zj.gov.cn/aisKnowledge',
     server: '/server',
     managerServer: 'https://natureai.zjugis.com/manager/server',
     chatServer: '/chat',
     knowledgeServer: 'https://zdzy.zrzyt.zj.gov.cn/aiServer',
-    knowledgeDocUrl: 'http://127.0.0.1:8511/knowledge_base/download_doc?knowledge_base_name=policy&file_name=',
-    knowledgeDocUrlProxy: 'https://natureai.zjugis.com/doc/portal/knowledge_base/download_doc/',
+    knowledgeDocUrl: 'http://127.0.0.1:20331/knowledge_base/download_doc?knowledge_base_name=policy&file_name=',
+    knowledgeDocUrlProxy: 'https://zdzy.zrzyt.zj.gov.cn/aiServer/knowledge_base/download_doc?knowledge_base_name=policy&file_name=',
     landMarketUrl: 'https://natureai.zjugis.com/subscribe/',
     // 外链
     links: {

+ 1 - 0
ais_search/web/src/assets/base.css

@@ -4,6 +4,7 @@ html,body, #app {
   margin: 0;
   padding: 0;
   background: #f1f0f0;
+  background: #FFF;
 }
 
 html a:-webkit-any-link  {

+ 1 - 0
ais_search/web/src/components/markdown-toc/MarkdownToc.vue

@@ -35,6 +35,7 @@ watch(() => props.toc, val => {
 const tocTo = ref(null)
 
 const clickToc = top => {
+  console.log("top value:", top)
   window.scroll({
     top: top - 290 - 190,
     behavior: 'smooth'

+ 2 - 2
ais_search/web/src/components/pdf/PdfCanvas.vue

@@ -38,7 +38,7 @@ watch(
 const title = computed(() => {
   ;
   return decodeURI(decodeURI(props.src))
-    .replace(window.AppGlobalConfig.knowledgeDocUrlProxy + (decodeURI(props.src).indexOf("compose_paper_material_total") > 0 ? 'compose_paper_material_total/' : 'policy/'), '')
+    .replace(window.AppGlobalConfig.knowledgeDocUrlProxy, '')
     .replace('+', ' ');
   // return `/lib/pdfjs/web/viewer.html?file=http://121.40.148.47:8530/doc/knowledge_base/download_doc/国土资源部 国家发展和改革委员会+财政部+住房和城乡建设部农业部+中国人民银行+国家林业局+中国银行业监督管理委员会关于扩大国有土地有偿使用范围的意见%28279-283%29.pdf`
 });
@@ -79,7 +79,7 @@ async function init() {
 }
 
 const fullScreen = () => {
-
+  console.log(props.src)
   window.open(`/lib/pdfjs/web/viewer.html?file=${decodeURI(props.src)}&t=`+ new Date().getTime(), '_blank')
 }
 

+ 1 - 1
ais_search/web/src/components/pdf/TxtViewer.vue

@@ -44,7 +44,7 @@ const fullScreen = () => {
 
 const title = computed(() => {
   return decodeURI(decodeURI(props.src))
-    .replace(window.AppGlobalConfig.knowledgeDocUrlProxy + (decodeURI(props.src).indexOf("compose_paper_material_total") > 0 ? 'compose_paper_material_total/' : 'policy/'), '')
+    .replace(window.AppGlobalConfig.knowledgeDocUrlProxy, '')
     .replace('+', ' ');
   // return `/lib/pdfjs/web/viewer.html?file=http://121.40.148.47:8530/doc/knowledge_base/download_doc/国土资源部 国家发展和改革委员会+财政部+住房和城乡建设部农业部+中国人民银行+国家林业局+中国银行业监督管理委员会关于扩大国有土地有偿使用范围的意见%28279-283%29.pdf`
 });

+ 1 - 1
ais_search/web/src/components/pdf/WordViewer.vue

@@ -61,7 +61,7 @@ watch(
 );
 const title = computed(() => {
   return decodeURI(decodeURI(props.src))
-    .replace(window.AppGlobalConfig.knowledgeDocUrlProxy + (decodeURI(props.src).indexOf("compose_paper_material_total") > 0 ? 'compose_paper_material_total/' : 'policy/'), '')
+    .replace(window.AppGlobalConfig.knowledgeDocUrlProxy, '')
     .replace('+', ' ');
   // return `/lib/pdfjs/web/viewer.html?file=http://121.40.148.47:8530/doc/knowledge_base/download_doc/国土资源部 国家发展和改革委员会+财政部+住房和城乡建设部农业部+中国人民银行+国家林业局+中国银行业监督管理委员会关于扩大国有土地有偿使用范围的意见%28279-283%29.pdf`
 });

+ 33 - 36
ais_search/web/src/views/ai-search/ai-search.vue

@@ -665,9 +665,9 @@ const streamToAnswer = () => {
 };
 
 const tabs = [
-  { key: 'knowledge', name: '知识库' },
-  { key: 'paper', name: '学术' },
-  { key: 'net', name: '全网' }
+  { key: 'knowledge', name: '知识库' }
+  // { key: 'paper', name: '学术' },
+  // { key: 'net', name: '全网' }
 ];
 
 const steps = ref([
@@ -1115,7 +1115,7 @@ const quest = async (isFllow) => {
     docs: []
   };
   activeIndex.value = 0;
-  // await getQuestionKeyWords();
+  getQuestionKeyWords();
 
   if (activeTab.value === 'net') {
     questionUrl = '/chat/bing_chat';
@@ -1452,8 +1452,10 @@ const openDoc = (doc, i) => {
       '=policy&',
       activeTab.value === 'paper' ? '=compose_paper_material_total&' : '=policy&'
     ),
-    window.AppGlobalConfig.knowledgeDocUrlProxy +
-      (activeTab.value === 'paper' ? 'compose_paper_material_total/' : 'policy/')
+    window.AppGlobalConfig.knowledgeDocUrlProxy.replace(
+      '=policy&',
+      activeTab.value === 'paper' ? '=compose_paper_material_total&' : '=policy&'
+    )
   );
   showDoc.value = true;
   fileType.value = type;
@@ -1504,10 +1506,11 @@ const openDocByIndex = (ind, id) => {
       '=policy&',
       activeTab.value === 'paper' ? '=compose_paper_material_total&' : '=policy&'
     ),
-    window.AppGlobalConfig.knowledgeDocUrlProxy +
-      (activeTab.value === 'paper' ? 'compose_paper_material_total/' : 'policy/')
+    window.AppGlobalConfig.knowledgeDocUrlProxy.replace(
+      '=policy&',
+      activeTab.value === 'paper' ? '=compose_paper_material_total&' : '=policy&'
+    )
   );
-
   showDoc.value = true;
 };
 window.openDocByIndex = openDocByIndex;
@@ -1590,8 +1593,10 @@ for example:
     redirect: 'follow'
   };
 
-  fetch(window.AppGlobalConfig.knowledgeServer + '/chat/chat/completions', requestOptions)
-    .then((response) => response.json())
+  fetch(window.AppGlobalConfig.knowledgeServer + '/chat/chat', requestOptions)
+    .then((response) => {
+      return response.json()
+    })
     .then((msg) => {
       const str = msg.choices[0]?.message?.content;
       if (str) {
@@ -1608,7 +1613,7 @@ const changeRecommendedQuestions = () => {
     questions.value = recommendedQuestions.slice(0, 5);
   } else {
     questions.value = recommendedQuestions.slice(5);
-    // getRecommendedQuestion(true)
+    getRecommendedQuestion(true)
   }
 };
 
@@ -1618,19 +1623,7 @@ const getQuestionKeyWords = async () => {
   myHeaders.append('Content-Type', 'application/json');
   questions.value = [];
   const raw = JSON.stringify({
-    messages: [
-      {
-        // 精确关键词提取叙述
-        content: `
-        请从以下文本中提取核心关键词,确保关键词简洁明了且准确反映文本的主要内容。
-        请按照以下格式输出:
-        关键词:关键词1,关键词2。
-        文本如下:“${question}”`,
-        role: 'user'
-      }
-    ],
-    // model: 'qwen1.5-chat',
-    model: 'qwen2.5-instruct',
+    query: `请从以下文本中提取核心关键词,确保关键词简洁明了且准确反映文本的主要内容。 请按照以下格式输出:关键词:关键词1,关键词2。文本如下:“${question}”`,
     stream: false
   });
 
@@ -1641,17 +1634,16 @@ const getQuestionKeyWords = async () => {
     redirect: 'follow'
   };
 
-  return fetch(window.AppGlobalConfig.knowledgeServer + '/chat/chat/completions', requestOptions)
+  return fetch(window.AppGlobalConfig.knowledgeServer + '/chat/chat', requestOptions)
     .then((response) => response.json())
-    .then((msg) => {
+    .then((msgStr) => {
+      const msg = JSON.parse(msgStr)
       activeIndex.value = 1;
       const str = msg.choices[0]?.message?.content;
       if (str) {
-        // steps.value[0].tags = str.split('\n\n').replaceAll('核心词为:', '').replaceAll("。", "").map(q => {
-        //
-        //   return q.substring(q.indexOf('.') + 1, q.length)
-        // }).splice(0,3);
-        const keywords = splitWords(str).slice(0, 3);
+        const str1 = str.slice(str.indexOf("</think>")+7)
+        console.log(str1)
+        const keywords = splitWords(str1).slice(0, 3);
         setActiveIndexTags(0, keywords);
         currentResponse.value.keywords = keywords;
       }
@@ -1664,6 +1656,7 @@ const splitWords = (word) => {
     word = word
       .replaceAll('核心词为:', '')
       .replaceAll('问题核心词:', '')
+      .replaceAll('>', '')
       .replaceAll('。', '')
       .trim();
 
@@ -1773,7 +1766,14 @@ const generateToc = () => {
     // });
     return;
   }
-  const markdowns = document.getElementById('resMarkdown').children;
+  const resMarkdownDom = document.getElementById("resMarkdown");
+  let thinkDoms = resMarkdownDom.getElementsByTagName("think");
+  let markdowns = null;
+  if (!thinkDoms || thinkDoms.length === 0) {
+    markdowns = resMarkdownDom.children;
+  } else {
+    markdowns = thinkDoms[0].children
+  }
   let index = 1;
   let children = [];
   let toc = [];
@@ -1857,12 +1857,10 @@ defineExpose({ search, changeActiveTab, stopAI });
 </script>
 <style scoped lang="scss">
 @import 'src/assets/scss/variables';
-
 .ai-search-detail {
   width: 100%;
   background: $background_color;
   height: 100%;
-  overflow: hidden;
   .header {
     width: 100%;
     height: 60px;
@@ -1876,7 +1874,6 @@ defineExpose({ search, changeActiveTab, stopAI });
     display: flex;
     margin-top: 50px;
     padding-bottom: 50px;
-    overflow-y: auto;
     .markdown-toc-tdsc {
       :deep(.toc-list) {
         margin: 30px 0;

+ 78 - 55
ais_search/web/src/views/document/FileDetail.vue

@@ -1,39 +1,22 @@
 <template>
   <div class="file-detail">
+    <div class="bg"></div>
     <div class="center-box">
       <div class="center-top">
-        <div
-          class="tool-btn"
-          style="color: #ff9900"
-          v-if="fileDetail.isCollected"
-          @click="cancelStarThisFile"
-        >
-          <StarFilled />
-          <span class="star-file-text">取消收藏</span>
-        </div>
-        <div class="tool-btn" @click="starThisFile" v-else>
-          <StarOutlined />
-          <span>收藏文档</span>
-        </div>
-        <div
-          class="tool-btn"
-          @click="
-            downloadFile({
-              ...fileDetail,
-              fileStorepath: pdfSrc,
-            })
-          "
-        >
-          <DownloadOutlined />
-          <span>下载</span>
-        </div>
+        <div class="title">{{ fileDetail?.name }}</div>
+        <div class="close" @click="closeHandle">X</div>
       </div>
       <div class="pdf-box" id="scrollArea1">
-        <PDFReader
-          v-if="fileDetail"
-          ref="pdfViewer"
-          :src="getRealFilePath(fileDetail.fileStorepath)"
-        />
+          <p-d-f-viewer
+            v-if="['pdf'].includes(fileType)"
+            :src="fileDetail['viewerUrl']"
+          />
+          <word-viewer
+            v-if="['docx','doc'].includes(fileType)"
+            :src="fileDetail['viewerUrl']"
+            :num="1"
+          >
+          </word-viewer>
       </div>
     </div>
   </div>
@@ -48,53 +31,84 @@ import {
   DownloadOutlined,
   StarFilled,
 } from "@ant-design/icons-vue";
-import PDFReader from "../components/PDFReader.vue";
-import { getRealFilePath } from '@/utils/common.js';
+import PDFViewer from '@/components/pdf/PdfCanvas.vue';
+import WordViewer from '@/components/pdf/WordViewer.vue';
 
-const pdfViewer = ref<any>(null);
 
 const props = defineProps({
   // 文件详情
   fileDetail: {
     type: Object,
     default: {},
+  },
+  fileType: {
+    type: String,
+    default: ''
   }
 });
-const { fileDetail } = toRefs(props);
-const pdfSrc = ref("");
-onMounted(() => {
-  getDocDetail();
-});
-watch(
-  () => fileDetail.value,
-  () => {
-    getDocDetail();
-  }
-);
-const getDocDetail = () => {
-  const src = fileDetail.value.fileStorepath;
-  pdfSrc.value = getRealFilePath(src);
-
-};
-
 const downloadFile = () => {
 
+}
+const emits = defineEmits(['close'])
+const closeHandle = () => {
+  emits('close')
 }
 </script>
 <style scoped lang="scss">
 .file-detail {
   width: 100%;
-  height: calc(100% - 60px);
-  display: flex;
+  height: 100%;
+  position: fixed;
+  left: 0px;
+  right: 0px;
+  top: 0px;
+  bottom: 0px;
+  margin: auto;
+  z-index: 9999999999;
+  overflow-y: hidden;
+  >.bg {
+    position: absolute;
+    left: 0px;
+    right: 0px;
+    top: 0px;
+    bottom: 0px;
+    margin: auto;
+    z-index: 9999999999;
+    overflow-y: hidden;
+    background: rgba(0,0,0,0.4);
+  }
   .center-box {
-    flex: 1;
+    width: 80%;
+    border: 1px solid #f00;
+    height: calc(100% - 60px);
+    margin: auto;
+    position: absolute;
+    left: 0px;
+    right: 0px;
+    top: 0px;
+    bottom: 0px;
+    margin: auto;
+    box-shadow: 0px 10px 10px rgba(0, 0, 0, 0.2);  
+    background: #Fff;
+    border: 1px solid #cecece;
+    z-index: 9999999999;
     .center-top {
       width: 100%;
       height: 50px;
       display: flex;
-      justify-content: flex-end;
+      justify-content: space-between;
       align-items: center;
-      padding-right: 20px;
+      >div {
+        &.title {
+          font-weight: bold;
+          font-size: 18px;
+          margin-left: 20px;
+        }
+        &.close {
+          margin-right: 20px;
+          cursor: pointer;
+        }
+      }
       .tool-btn {
         font-weight: 500;
         font-size: 14px;
@@ -117,6 +131,15 @@ const downloadFile = () => {
       height: calc(100% - 55px);
       background: white;
       overflow-y: auto;
+      position: relative;
+      ::v-deep {
+        .pdf-container,
+        .word-container {
+          .header {
+            display: none !important;
+          }
+        }
+      }
     }
   }
 }

+ 43 - 32
ais_search/web/src/views/document/index.vue

@@ -3,14 +3,16 @@
     <div class="header">
       <home-header @login="emits('login')" sub-title="知识库管理" />
     </div>
+    <FileDetail
+      v-if="fileViewerVisabled"
+      :fileDetail="currentFile"
+      :fileType="fileType"
+      :changeFile="showFileDetail"
+      @close="closeViewerHandle"
+    />
     <div class="my-doc-container">
       <TitleHeader :items="menuList"  @tabClick="tabClickHandle" />
-      <FileDetail
-        v-if="clickFileDetail && clickFileDetail.sign == 'file'"
-        :fileDetail="clickFileDetail"
-        :changeFile="showFileDetail"
-      />
-      <div class="page-content" v-else>
+      <div class="page-content">
         <div class="content-top">
           <div class="left">
             <a-button
@@ -33,7 +35,7 @@
               >下载</a-button
             >
             <a-button
-              v-if="clickFileDetail"
+              v-if="false"
               :icon="h(DeliveredProcedureOutlined)"
               @click="moveFiles(state.selectedRowKeys)"
               style="margin-left: 15px; height: 36px"
@@ -59,12 +61,14 @@
         </div>
         <div class="content-table">
           <a-table
-            :rowSelection="{
+            :row-selection="{
               selectedRowKeys: state.selectedRowKeys,
               onChange: onSelectChange,
             }"
+            rowKey="id"
+            :loading="loading"
             :columns="columns"
-            :dataSource="dataSource"
+            :data-source="dataSource"
             :pagination="false"
           >
             <template #bodyCell="{ column, record }">
@@ -99,6 +103,7 @@
                   type="text"
                   :icon="h(DownloadOutlined)"
                   style="margin-right: 15px"
+                  v-if="record.type"
                   @click="
                     record.type
                       ? downloadFile(record)
@@ -125,6 +130,7 @@
                       <a-menu-item>
                         <a-button
                           type="link"
+                          v-if="false"
                           :icon="h(DeliveredProcedureOutlined)"
                           style="color: #000"
                           @click="moveFiles([record.id])"
@@ -194,9 +200,6 @@ import {
 import HomeHeader from '@/views/home/components/HomeHeader.vue';
 import { message } from "ant-design-vue";
 import MyIcon from "@/components/myIcon/index.vue";
-import {
-  downloadDocs,
-} from "./http";
 import MoveFileModel from "./MoveFiles.vue";
 import FileUpload from "./FileUpload.vue";
 import FileDetail from "./FileDetail.vue";
@@ -293,18 +296,23 @@ const columns = [
 ];
 const searchValue = ref("");
 const dataSource = ref<any[]>([]);
+const loading = ref(false)
 const getDataSource = () => {
   // 重置选中的文件
   state.selectedRowKeys = [];
   const urlStr = `/ai/knowledge/file/list`
+  loading.value = true;
   // 获取文档列表
   http.get(urlStr, {
     name: searchValue.value,
     parentId: currentTabId.value
   }).then((result) => {
+    loading.value = false;
     if (result.data) {
       dataSource.value = result.data;
     }
+  }).catch((err) => {
+    loading.value = false;
   });
 };
 
@@ -316,8 +324,8 @@ const state = reactive<{
   loading: false,
 });
 
-const onSelectChange = (selectedRowKeys: any[]) => {
-  state.selectedRowKeys = selectedRowKeys;
+const onSelectChange = (selectedRowKeys1) => {
+  state.selectedRowKeys = selectedRowKeys1;
 };
 const searchHandle = () => {
   getDataSource()
@@ -354,16 +362,13 @@ const createFolder = async () => {
 
 // 下载(单文件下载)
 const downloadFile = async (data: any) => {
-  if (!data.fileStorepath) {
-    message.error("下载失败,未找到文件下载地址!");
-    return;
-  }
-  return;
+  const downloadUrl = `${window.AppGlobalConfig.knowledgeDocUrlProxy}${data.name}`
+  const response = await fetch(downloadUrl);
   const blob = await response.blob();
   const url = window.URL.createObjectURL(blob);
   const a = document.createElement("a");
   a.href = url;
-  a.download = data.fileName ?? "download.pdf"; // 强制下载并指定文件名
+  a.download = data.name ?? "download.pdf"; // 强制下载并指定文件名
   document.body.appendChild(a);
   a.click();
   document.body.removeChild(a);
@@ -380,11 +385,12 @@ const closeHandle = () => {
 // 多文件打包下载
 const downloadFiles = async (ids: any[] = []) => {
   message.success("正在为你下载文件,请稍等 ...");
-  try {
-    await downloadDocs(ids);
-  } catch {
-    message.error("下载失败,请稍后重试!");
-  }
+  const selectedArrs = dataSource.value.filter((item) => {
+    return ids.includes(item['id']);
+  })
+  selectedArrs.forEach((item) => {
+    downloadFile(item['name'])
+  })
 };
 //文件夹编辑
 const editableData = reactive({});
@@ -460,16 +466,21 @@ const refreshList = () => {
     changeMenu();
   }
 };
-
 // 跳到文件详情页面
+const fileViewerVisabled = ref(false)
+const fileType = ref('')
+const currentFile = ref()
 const showFileDetail = (data: any) => {
-  clickFileDetail.value = {
-    ...data,
-    id: data.fileId,
-  };
-  // 触发目录切换的回调
-  changeMenu(data.fileName);
+  console.log(data)
+  fileViewerVisabled.value = true;
+  data['viewerUrl'] = `${window.AppGlobalConfig.knowledgeDocUrlProxy}${data.name}`
+  currentFile.value = data;
+  const name = data.name;
+  fileType.value = name.slice(name.indexOf(".") + 1)
 };
+const closeViewerHandle = () => {
+  fileViewerVisabled.value = false;
+}
 </script>
 <style scoped lang="scss">
 @import "./index.scss";

+ 3 - 3
ais_search/web/src/views/home/home.vue

@@ -39,7 +39,7 @@
               @keydown.enter.native="search"
               :placeholder="placeholder"
             />
-            <a-select v-model:value="scope.name" class="select" v-if="typeIndex == 0">
+            <a-select v-model:value="scope.name" class="select" v-if="false">
               <a-select-option value="knowledge">知识库</a-select-option>
               <a-select-option value="paper">学术</a-select-option>
               <a-select-option value="net">全网</a-select-option>
@@ -50,7 +50,7 @@
             <a-select v-model:value="scopeQt.name" class="select" v-if="typeIndex == 2">
               <a-select-option value="title">关键词</a-select-option>
             </a-select>
-            <div class="line"></div>
+            <div class="line" v-if="false"></div>
             <button class="search-btn" @click="search" v-login-required>搜索</button>
           </div>
           <div class="scopes">
@@ -299,7 +299,7 @@ const dsChange = (type) => {
             background: #ffffff;
             border-radius: 8px 8px 8px 8px;
             border: 2px solid #0E83F8;
-            padding: 0 21px 0px 116px;
+            padding: 0 21px 0px 21px;
             font-family: PingFang SC, PingFang SC;
 
             &:hover,

+ 1 - 1
ais_search/web/vite.config.js

@@ -42,7 +42,7 @@ export default defineConfig({
     proxy: {
       '/server': {
           // target: 'http://121.40.148.47:8531/server',
-          target: 'http://localhost:9999/',
+          target: 'https://zdzy.zrzyt.zj.gov.cn/aisKnowledge',
           changeOrigin: true,
           rewrite: function (path) { return path.replace(/^\/server/, ''); }
       },