Bladeren bron

Merge branch 'master' of http://gitlab.smartai.com/zhupei/smartai2dian0

zhupei@smartai.com 1 jaar geleden
bovenliggende
commit
401798875f

+ 8 - 0
src/apis/intelligent.js

@@ -51,6 +51,14 @@ export function getLabelList(keyword, labelType, objectId = undefined) {
     params
   });
 }
+//
+export function deleteDialog(id) {
+  return request({
+    url: `/api/dialog/delete?dialogId=${id}`,
+    method: 'get'
+  });
+}
+
 /**
  * 添加标签
  * @param {string} labelName 标签名称

+ 14 - 0
src/apis/knowledge.js

@@ -25,3 +25,17 @@ export function createOwnKnowledge(data) {
     data
   });
 }
+// 删除知识库
+export function deleteOwnKnowledge(id) {
+  return request({
+    url: `/api/knowledge/delete?knowledgeId=${id}`,
+    method: 'get'
+  });
+}
+// 知识库信息同步
+export function syncOwnKnowledge(id) {
+  return request({
+    url: `/api/knowledge/sync?knowledgeId=${id}`,
+    method: 'get'
+  });
+}

+ 2 - 1
src/apis/login.js

@@ -30,8 +30,9 @@ export function QueyrUserInfo() {
     method: 'get'
   });
 }
+
 // 获取用户路由
-export function generateRoutes() {
+export function QueyrRoutesList() {
   return request({
     url: '/api/user/user_routers',
     method: 'get'

+ 10 - 2
src/apis/rgflow-dify.js

@@ -32,6 +32,14 @@ export function createRgFlow(data) {
     data
   });
 }
+// 删除rgflow智能体
+export function deleteRgFlow(data) {
+  return request({
+    url: `/rgflow/v1/dialog/rm`,
+    method: 'post',
+    data
+  });
+}
 
 // 头像上传
 export function kbdocumentupload(data) {
@@ -174,11 +182,11 @@ export function achunkCreate(data) {
   });
 }
 //解析块列表接口
-export function queryChunkList(params) {
+export function queryChunkList(data) {
   return request({
     url: `/rgflow/v1/chunk/list`,
     method: 'post',
-    params
+    data
   });
 }
 

+ 3 - 1
src/base/storage.js

@@ -12,7 +12,9 @@ export const localST_Theme = new MyLocalStorage('theme'); // 主题
 export const localST_Locale = new MyLocalStorage('locale'); // 多语言
 export const localST_RecentAgent = new MyLocalStorage('recent_agent'); // 近期使用的agent
 export const localST_AllAgent = new MyLocalStorage('full_agent'); // 所有可用的agent
-export const localST_UserInfo = new MyLocalStorage('user_info'); // 所有可用的agent
+
+export const localST_UserInfo = new MyLocalStorage('user_info'); // 用户信息
+export const localST_RoutesList = new MyLocalStorage('routes_list'); // 用户身份token
 export const localST_RecentSearchType = new MyLocalStorage('recent_search_type'); // 最近的
 
 /**

+ 12 - 2
src/base/store/use-current-user.js

@@ -1,6 +1,6 @@
 import { defineStore } from 'pinia';
-import { login, QueyrUserInfo } from '../../apis/login';
-import { kuky_Authorization, localST_UserInfo } from '../storage';
+import { login, QueyrUserInfo, QueyrRoutesList } from '../../apis/login';
+import { kuky_Authorization, localST_UserInfo, localST_RoutesList } from '../storage';
 
 /**
  * 当前登录的用户信息
@@ -61,6 +61,16 @@ export const useCurrentUserStore = defineStore('current_user', {
       });
     },
 
+    // 获取并且存储用户路由列表
+    async getRoutesList() {
+      const {
+        code,
+        data: { routers }
+      } = await QueyrRoutesList();
+      if (code === 200) {
+        localST_RoutesList.setItem(JSON.stringify(routers));
+      }
+    },
     // 获取并且存储用户信息
     async getUserInfo() {
       const {

+ 9 - 2
src/modules/dify/MessageBody.vue

@@ -20,24 +20,31 @@ const BASE_URL = window.DIFY_BASE_URL;
 const token = kuky_Authorization.get();
 const defaultURL = ref('');
 
+//workflow  应用
+//configuration agent
 onMounted(async () => {
   defaultURL.value = BASE_URL + '/app/' + props.id + `/workflow?token=${token}`;
+  // console.log('defaultURL', BASE_URL + '/app/' + props.id + `/workflow`);
   const element = document.getElementById('dify');
   element.onload = function () {
     if (element && element.contentWindow) {
-      console.log('iframe loaded', element.contentWindow);
+      // console.log('iframe loaded', element.contentWindow);
       element.contentWindow.postMessage(
         JSON.stringify({
           type: 'insertStyle',
           value: `
-            .sticky{display:none;}`
+            .sticky{display:none;}
+            `
         }),
+
         defaultURL.value
       );
     }
     loading.value = false;
   };
 });
+// .style_app___hJq8 > div:first-of-type{display:none;}
+// .style_app___hJq8 .shrink-0{display:none;}
 </script>
 <style scoped lang="css">
 .body-container {

+ 20 - 11
src/modules/intelligent/MessageBody.vue

@@ -66,7 +66,7 @@
 
 <script setup>
 import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
-import { Modal } from '@arco-design/web-vue';
+import { Message, Modal } from '@arco-design/web-vue';
 import CardItem from '../../views/manage/CardItem.vue';
 import ManageTags from './ManageTags.vue';
 import { getIconIntelligent, getImageIntelligent } from '../common/icon-map.js';
@@ -74,8 +74,8 @@ import LabelSelected from './LabelSelected.vue';
 import { getDialogList } from '../../apis/intelligent';
 import { bus_intelligentSearch, bus_intelligentEdit } from '../../base/event-bus';
 import { dialogType } from '../../views/manage/common';
-import { getLabelList, addLabelToDialog, changeDialogStatus } from '../../apis/intelligent';
-import { deleteDify } from '../../apis/rgflow-dify';
+import { getLabelList, addLabelToDialog, changeDialogStatus, deleteDialog } from '../../apis/intelligent';
+import { deleteDify, deleteRgFlow } from '../../apis/rgflow-dify';
 
 const moke_data = ref([
   // {
@@ -131,8 +131,8 @@ const scrollHandler = (e) => {
     scroll_bottom.value = true;
     // 调用函数加载更多数据
     if (pages.current < total_pages.value) {
-      getDialog();
       pages.current += 1;
+      getDialog();
     } else {
     }
   }
@@ -152,23 +152,32 @@ const deleteIntelligent = (item) => {
     hideCancel: false,
     content: '确定删除该智能体吗?',
     async onOk(e) {
-      console.log('确定', item.agentType, dialogType.DIFY);
       // dify删除
       if (item.agentType == dialogType.DIFY) {
         await deleteDify(item.id);
+        const response = await deleteDialog(item.id);
+        if (response.code == 200) {
+          Message.success('删除成功');
+        }
         // TODO:刷新页面
-        bus_intelligentSearch.emit('');
+      } else if (item.agentType == dialogType.RAGFLOW) {
+        const data = {
+          dialog_ids: [item.id]
+        };
+        const res = await deleteRgFlow(data);
+        if (res.retcode == 0) {
+          const response = await deleteDialog(item.id);
+          if (response.code == 200) {
+            Message.success('删除成功');
+          }
+        }
       }
+      bus_intelligentSearch.emit('');
     },
     onCancel(e) {
       console.log('取消');
     }
   });
-  // if (item.agentType == dialogType.DIFY) {
-
-  //   deleteDify(item.id).then((res) => {});
-  // }
-  // console.log('deleteIntelligent');
 };
 
 // 获取标签列表

+ 8 - 4
src/modules/intelligent/ModelAddItem.vue

@@ -23,6 +23,7 @@ import { createDify } from '../../apis/rgflow-dify';
 import { createDialog } from '../../apis/intelligent';
 import { dialogType } from '../../views/manage/common';
 import { getIconIntelligent } from '../common/icon-map.js';
+import { Message } from '@arco-design/web-vue';
 const props = defineProps({
   show_model_item: {
     type: Boolean,
@@ -43,7 +44,7 @@ const formInit = {
 };
 const form = ref(Object.assign({}, formInit));
 
-const emit = defineEmits(['update:show_model_item', 'select_icon', 'updateIntelligentList']);
+const emit = defineEmits(['update:show_model_item', 'select_icon', 'updateIntelligentList', 'clearSelectIcon']);
 
 let show_modal = computed(() => props.show_model_item);
 
@@ -78,17 +79,20 @@ const createOwnDialog = async (data) => {
   try {
     const res = await createDialog(data);
     if (res.code == 200) {
-      form.value = Object.assign({}, formInit);
-      emit('update:show_model_item', false);
+      handleCancel();
       emit('updateIntelligentList');
+      Message.success('新建成功');
+    } else {
+      Message.error('新建失败');
     }
   } catch (err) {
-    console.log('创建对话失败', err);
+    console.log('创建失败', err);
   }
 };
 const handleCancel = () => {
   form.value = Object.assign({}, formInit);
   emit('update:show_model_item', false);
+  emit('clearSelectIcon');
 };
 const handleSelectIcon = () => {
   emit('select_icon');

+ 19 - 22
src/modules/intelligent/TopSetting.vue

@@ -29,6 +29,7 @@
     :target_intell_type="target_intell_type"
     @select_icon="selectIcon"
     @updateIntelligentList="updateIntelligentList"
+    @clearSelectIcon="clearSelectIcon"
   >
   </ModelAddItem>
   <ModelSelectIcon v-model:show_select_icon="show_select_icon" @sendIcon="sendIcon"></ModelSelectIcon>
@@ -38,8 +39,10 @@
     ref="editAgentKuai"
     :typeAngint="add_type"
     :formData="itemObj"
-    @queryList="queryList"
+    :target_icon="target_icon"
     @updateIntelligentList="updateIntelligentList"
+    @show_select_icon="showSelectIcon"
+    @clearSelectIcon="clearSelectIcon"
   ></AgentConfig>
 </template>
 
@@ -68,23 +71,6 @@ const show_rg_config = ref(false);
 const editAgentKuai = ref(null);
 let add_type = ref('add');
 let itemObj = reactive({});
-const queryList = async (params = {}) => {
-  // setLoading(true);
-  // try {
-  //   const { data } = await querydialogList(params);
-  //   console.log(data, 'data');
-  //   agentList.value = data.map((item) => {
-  //     return {
-  //       ...item,
-  //       off: true,
-  //     };
-  //   });
-  // } catch (err) {
-  //   // you can report use errorHandler or other
-  // } finally {
-  //   setLoading(false);
-  // }
-};
 
 // 搜索
 const handleSearch = funcDebounce(
@@ -120,9 +106,11 @@ const updateIntelligentList = () => {
   target_icon.value = '';
 };
 
-const getRagFlowDataFunc = async (id) => {
+// 该接口是rgflow编辑是获取智能体信息的接口,里面的图标需要字段icon需要替换成我们的数据
+const getRagFlowDataFunc = async (item) => {
+  target_icon.value = item.icon;
   try {
-    const res = await getRagFlowData(id);
+    const res = await getRagFlowData(item.id);
     Object.assign(itemObj, res.data);
     editAgentKuai.value.editClick();
   } catch (err) {
@@ -130,6 +118,14 @@ const getRagFlowDataFunc = async (id) => {
   } finally {
   }
 };
+
+const showSelectIcon = () => {
+  show_select_icon.value = true;
+};
+
+const clearSelectIcon = () => {
+  target_icon.value = '';
+};
 /**
  * 监听编辑智能体事件
  * @param {Object} item 编辑智能体对象
@@ -145,12 +141,13 @@ bus_intelligentEdit.on((item) => {
       // itemObj = item;
       show_rg_config.value = true;
       add_type = 'edit';
-      getRagFlowDataFunc(item.id);
+      getRagFlowDataFunc(item);
 
       break;
     case '4':
+      console.log(item);
       // TODO: 进入Dify智能体配置
-      router.push({ path: '/intelligent/detail', query: { id: item.id, name: item.name } });
+      router.push({ path: '/intelligent/detail', query: { id: item.id, name: item.name, mode: item.mode } });
       break;
     default:
       console.log('暂不支持该智能体类型');

+ 56 - 23
src/modules/intelligent/rgflow/AgentConfig.vue

@@ -26,16 +26,25 @@
                 <a-form-item field="name" label="智能体名称">
                   <a-input v-model="form.name" placeholder="请输入名称" />
                 </a-form-item>
-                <a-form-item label="智能体图标">
+                <a-form-item label="智能体图标" required>
                   <a-space direction="vertical" :style="{ width: '100%' }">
-                    <Upload
+                    <!-- <Upload
                       v-if="avatarShow"
                       :action="uploadAction"
                       :limit="1"
                       :url="form.icon ? httpUrl + form.icon : ''"
                       @update:fileList="updateFileList"
                       @success="handleSuccess"
-                    ></Upload>
+                    ></Upload> -->
+                    <div class="upload-empty" v-if="!props.target_icon.length" @click="handleUploadIcon">
+                      <icon-plus class="icon"></icon-plus>
+                    </div>
+                    <img
+                      class="upload-img"
+                      v-else
+                      :src="getIconIntelligent(props.target_icon)"
+                      @click="handleUploadIcon"
+                    />
                   </a-space>
                 </a-form-item>
                 <a-form-item label="空回复">
@@ -263,18 +272,26 @@
 </template>
 
 <script setup>
-import { onMounted, onBeforeMount, reactive, ref, nextTick, onUnmounted, onBeforeUnmount, computed } from 'vue';
+import { onMounted, reactive, ref, nextTick, onUnmounted, computed, onActivated } from 'vue';
+import { Message } from '@arco-design/web-vue';
+import { getIconIntelligent } from '../../common/icon-map.js';
 import { queryKbList, queryModelList, createRgFlow } from '../../../apis/rgflow-dify';
 import { createDialog } from '../../../apis/intelligent';
 import { getKnowledgeList } from '../../../apis/knowledge';
-import { dialogType } from '../../../views/manage/common';
+import { dialogType } from '../../../views/manage/common.js';
 import useLoading from './loading';
 import Upload from './Upload.vue';
-import { Message } from '@arco-design/web-vue';
+
 // import { dialogSet } from '@/api/Agent';
 
-const props = defineProps(['show_rg_config', 'typeAngint', 'formData']);
-const emit = defineEmits(['queryList', 'update:show_rg_config', 'updateIntelligentList']);
+const props = defineProps(['show_rg_config', 'typeAngint', 'formData', 'target_icon']);
+const emit = defineEmits([
+  'queryList',
+  'update:show_rg_config',
+  'updateIntelligentList',
+  'show_select_icon',
+  'clearSelectIcon'
+]);
 
 const { loading, setLoading } = useLoading(true);
 const visible = computed(() => props.show_rg_config);
@@ -360,7 +377,7 @@ const imageUrls = ref([]);
 
 const updateFileList = (newFileList) => {
   fileList.value = newFileList;
-  console.log(newFileList, 88);
+  // console.log(newFileList, 88);
 };
 
 const handleSuccess = (urls) => {
@@ -395,8 +412,12 @@ const rules = {
   ]
 };
 
+const handleUploadIcon = () => {
+  emit('show_select_icon');
+};
+
 const handleSubmit = ({ values, errors }) => {
-  console.log('values:', values, '\nerrors:', errors);
+  // console.log('values:', values, '\nerrors:', errors);
   if (!errors) {
   }
 };
@@ -408,6 +429,7 @@ const handleCancel = () => {
   form.name = '';
   emit('update:show_rg_config', false);
   emit('queryList');
+  emit('clearSelectIcon');
 };
 
 const handleOpened = (el) => {
@@ -437,7 +459,6 @@ const handleOpened = (el) => {
   });
 };
 const createOwnDialog = async (data, title) => {
-  console.log(data, 'data');
   const res = await createDialog(data);
   if (res.code == 200) {
     Message.success(title);
@@ -455,9 +476,6 @@ const handleBeforeOk = async (done) => {
   formRef2.value.validate().then((res) => {
     // console.log('res:', res)
   });
-  // TODO: 先写死知识库和模型
-  // form.kb_ids = ['5e96cc5aad3111ef93990242ac130006'];
-  form.llm_id = 'qwen-2.5-72b-instruct___OpenAI-API@OpenAI-API-Compatible';
   if (form.name && form.kb_ids.length > 0 && form.prompt_config.system && form.llm_id) {
     let title = '创建成功';
     let formNew = { ...form };
@@ -496,8 +514,8 @@ const handleBeforeOk = async (done) => {
           id: res.data.id,
           name: form.name,
           description: '',
-          icon: form.icon,
-          dialogType: dialogType.RAGFLOW_TYPE,
+          icon: props.target_icon,
+          dialogType: dialogType.RAGFLOW,
           mode: 'ragflow'
         };
         // TODO: 调用自己系统的新增
@@ -533,7 +551,7 @@ const editClick = (data) => {
       max_tokens.value = true;
     }
     Object.assign(form, props.formData);
-    console.log(form, '表单数据');
+    // console.log(form, '表单数据');
   });
 };
 
@@ -567,7 +585,10 @@ const queryModel = async () => {
     for (const key in data.data) {
       if (Object.hasOwnProperty.call(data.data, key)) {
         const element = data.data[key];
-        arrObj[key] = element.filter((item) => item.available === true && item.model_type === 'chat');
+        // console.log(element, 'element');
+        // arrObj[key] = element.filter((item) => item.available === true && item.model_type === 'chat');
+        // 先注释掉model_type过滤  加上暂无可用数据
+        arrObj[key] = element.filter((item) => item.available === true);
       }
     }
     modelList.value = arrObj;
@@ -603,20 +624,32 @@ const knowledgeData = async () => {
     setLoading(false);
   }
 };
-
-onBeforeMount(() => {
+onMounted(() => {
   queryModel();
   knowledgeData();
 });
-onMounted(() => {});
-
-onBeforeUnmount(() => {});
 
 defineExpose({
   editClick
 });
 </script>
 <style scoped>
+.upload-empty {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 44px;
+  height: 44px;
+  border-radius: 5px;
+  border: 1px dashed var(--color-neutral-6);
+  cursor: pointer;
+  .icon {
+    color: var(--color-neutral-6);
+  }
+}
+.upload-img {
+  cursor: pointer;
+}
 :deep .arco-tabs-nav-tab-list {
   width: 100%;
 

+ 37 - 19
src/modules/knowledge/MessageBody.vue

@@ -1,6 +1,12 @@
 <template>
   <div class="body-container" ref="body_container">
-    <CardItem v-for="item in moke_data" :key="item.id" :name="item.name" :img_src="item.img_src">
+    <CardItem
+      v-for="item in moke_data"
+      :key="item.id"
+      :name="item.name"
+      :img_src="item.img_src"
+      @click="handleToDetail(item)"
+    >
       <template #bottom>
         <div class="bottom">
           <div>{{ item.count }}{{ $t('management.document') }}</div>
@@ -12,7 +18,7 @@
         <a-dropdown trigger="hover" @select="handleSelect($event, item)">
           <icon-more :style="{ fontSize: '20px' }" />
           <template #content>
-            <a-doption :value="{ value: 'edit' }">{{ $t('management.edit') }}</a-doption>
+            <!-- <a-doption :value="{ value: 'edit' }">{{ $t('management.edit') }}</a-doption> -->
             <a-doption :value="{ value: 'delete' }">{{ $t('management.delete') }}</a-doption>
           </template>
         </a-dropdown>
@@ -33,7 +39,7 @@ import { Message, Modal } from '@arco-design/web-vue';
 import { useRouter } from 'vue-router';
 import CardItem from '../../views/manage/CardItem.vue';
 import { getImageKnowLedge } from '../common/icon-map.js';
-import { getKnowledgeList } from '../../apis/knowledge';
+import { getKnowledgeList, deleteOwnKnowledge } from '../../apis/knowledge';
 import { deleteKnow } from '../../apis/rgflow-dify.js';
 import { bus_knowledgeSearch } from '../../base/event-bus';
 
@@ -59,17 +65,17 @@ const scroll_bottom = ref(false);
 // 搜索文本
 const search_text = ref('');
 
+const handleToDetail = (item) => {
+  router.push({
+    path: '/knowledge/detail',
+    query: {
+      id: item.id,
+      name: item.name
+    }
+  });
+};
 const handleSelect = ({ value }, item) => {
-  if (value === 'edit') {
-    console.log('edit', item);
-    router.push({
-      path: '/knowledge/detail',
-      query: {
-        id: item.id,
-        name: item.name
-      }
-    });
-  } else {
+  if (value === 'delete') {
     toRemove(item);
   }
 };
@@ -84,15 +90,27 @@ const toRemove = (item) => {
         kb_id: item.id
       });
       if (data.retcode == 0) {
-        Message.success('删除成功');
-        pages.current = 1;
-        moke_data.value = [];
-        getKnowledge();
+        deleteOwnKnow(item.id);
       }
     },
     onCancel: () => {}
   });
 };
+const deleteOwnKnow = async (id) => {
+  try {
+    const res = await deleteOwnKnowledge(id);
+    if (res.code == 200) {
+      Message.success('删除成功');
+      pages.current = 1;
+      moke_data.value = [];
+      getKnowledge();
+    } else {
+      Message.error('删除失败');
+    }
+  } catch (err) {
+    console.log(err, 'flag');
+  }
+};
 const getKnowledge = async () => {
   if (pages.current == 1) {
     loading_data.value = true;
@@ -105,7 +123,7 @@ const getKnowledge = async () => {
           ...item,
           time: new Date(item.create_time).toLocaleString('zh-CN'),
           img_src: getImageKnowLedge(item.icon),
-          count: item.count ? item.count : 0
+          count: item.documents ? item.documents : 0
         };
       });
       moke_data.value.push(...data);
@@ -122,8 +140,8 @@ const scrollHandler = (e) => {
     scroll_bottom.value = true;
     // 调用函数加载更多数据
     if (pages.current < total_pages.value) {
-      getKnowledge();
       pages.current += 1;
+      getKnowledge();
     }
   }
 };

+ 5 - 1
src/modules/knowledge/rgflow/knowledgeLib/add.vue

@@ -36,9 +36,11 @@
 
 <script setup>
 import { onMounted, onBeforeMount, reactive, ref, computed } from 'vue';
+import { Message } from '@arco-design/web-vue';
 import axios from 'axios';
 import { kbdocumentupload } from '../../../../apis/rgflow-dify';
-import { Message } from '@arco-design/web-vue';
+import { toSyncOwnKnowledge } from './asyc.js';
+
 let CancelToken = axios.CancelToken;
 let source = null;
 const visible = ref(false);
@@ -74,6 +76,8 @@ const submitForm = async (done) => {
           emit('changeFetchData');
           Message.success('上传成功');
           handleCancel();
+          // 同步数据
+          toSyncOwnKnowledge(props.kbobj.id);
         }
       });
     });

+ 8 - 0
src/modules/knowledge/rgflow/knowledgeLib/asyc.js

@@ -0,0 +1,8 @@
+import { syncOwnKnowledge } from '../../../../apis/knowledge';
+export const toSyncOwnKnowledge = async (id) => {
+  try {
+    await syncOwnKnowledge(id);
+  } catch (error) {
+    console.log(error);
+  }
+};

+ 7 - 2
src/modules/knowledge/rgflow/knowledgeLib/config.vue

@@ -206,13 +206,15 @@ import { onMounted, onBeforeMount, reactive, ref, nextTick } from 'vue';
 import Upload from './components/Upload.vue';
 import { Message } from '@arco-design/web-vue';
 import { queryModelList, kbUpdate, getKnowledgeBaseModel } from '../../../../apis/rgflow-dify';
+import { toSyncOwnKnowledge } from './asyc.js';
 import message from '@arco-design/web-vue/es/message';
 import useLoading from './loading';
 import step1 from '../../../../assets/image/management/step1.png';
 import step2 from '../../../../assets/image/management/step2.png';
+
 const { loading, setLoading } = useLoading(true);
 const scrollContainer = ref();
-const props = defineProps(['kbtenantInfo']);
+const props = defineProps(['kbtenantInfo', 'kb_id']);
 const emit = defineEmits(['cancleConfig', 'saveConfig']);
 // 解析方法列表
 let parser_ids = props.kbtenantInfo.parser_ids.split(',').map((item) => {
@@ -328,6 +330,8 @@ const handleSubmit = async ({ values, errors }) => {
       Message.success('配置成功');
       // window.location.reload();
       emit('saveConfig');
+      //TODO 同步数据
+      toSyncOwnKnowledge(kbObj.id);
     }
     setLoading(false);
   } catch (err) {
@@ -449,7 +453,8 @@ export default {
   display: flex;
   justify-content: space-between;
   height: 100%;
-  overflow: hidden;
+  overflow-y: auto;
+  overflow-x: hidden;
   border-radius: 8px;
   background: var(--color-bg-2);
   padding-top: 80px;

+ 22 - 104
src/modules/knowledge/rgflow/knowledgeLib/index.vue

@@ -1,37 +1,6 @@
 <template>
   <div class="container">
-    <!-- <Breadcrumb :items="['dmx.list.index', 'dmx.list.kbm']" /> -->
     <div class="main-container">
-      <!-- <div class="lf-container">
-        <div class="lf-container-top">
-          <a-input-search placeholder="搜索" style="width: 130px" />
-          <addKnow @getknowledge="getknowledge" @getKbdetail="getKbdetail"></addKnow>
-        </div>
-        <a-spin :loading="listloading" class="lf-container-down">
-          <a-scrollbar style="height: calc(100vh - 300px); overflow: auto">
-            <div
-              class="tab"
-              v-for="(tab, index) in tabs"
-              :key="index"
-              @click="selectTab(index, tab)"
-              :class="{ active: selectedTab === index }"
-            >
-              {{ tab.name }}
-              <a-popover position="bl">
-                <icon-more v-hasPermi="'/kb/delete'" :style="{ position: 'absolute', top: '10px', right: '10px' }" />
-                <template #content>
-                  <span
-                    style="cursor: pointer; color: #4977ba; font-size: 12px"
-                    @click="deleteKnowledge(tab.id)"
-                    v-hasPermi="'/kb/delete'"
-                    ><icon-delete style="font-size: 14px" />删除</span
-                  >
-                </template>
-              </a-popover>
-            </div>
-          </a-scrollbar>
-        </a-spin>
-      </div> -->
       <div class="rt-container" v-if="tabs.length > 0">
         <a-tabs :active-key="activeKey" @change="handleTabChange">
           <a-tab-pane key="1" title="数据集">
@@ -60,13 +29,7 @@
                             </a-button>
                             <template #content>
                               <p>
-                                <a-button
-                                  type="text"
-                                  class="button"
-                                  style="color: #2a2a2b"
-                                  v-hasPermi="'/kb/data_status'"
-                                  @click="enableDisable(1)"
-                                >
+                                <a-button type="text" class="button" style="color: #2a2a2b" @click="enableDisable(1)">
                                   <template #icon>
                                     <icon-play-circle />
                                   </template>
@@ -74,13 +37,7 @@
                                 </a-button>
                               </p>
                               <p>
-                                <a-button
-                                  type="text"
-                                  class="button"
-                                  style="color: #2a2a2b"
-                                  v-hasPermi="'/kb/data_status'"
-                                  @click="enableDisable(0)"
-                                >
+                                <a-button type="text" class="button" style="color: #2a2a2b" @click="enableDisable(0)">
                                   <template #icon>
                                     <icon-record color="" />
                                   </template>
@@ -88,13 +45,7 @@
                                 </a-button>
                               </p>
                               <p>
-                                <a-button
-                                  type="text"
-                                  class="button"
-                                  style="color: #2a2a2b"
-                                  v-hasPermi="'/kb/data_analysis'"
-                                  @click="addBlock(1)"
-                                >
+                                <a-button type="text" class="button" style="color: #2a2a2b" @click="addBlock(1)">
                                   <template #icon>
                                     <icon-check-circle />
                                   </template>
@@ -102,13 +53,7 @@
                                 </a-button>
                               </p>
                               <p>
-                                <a-button
-                                  type="text"
-                                  class="button"
-                                  style="color: #2a2a2b"
-                                  v-hasPermi="'/kb/data_analysis'"
-                                  @click="addBlock(2)"
-                                >
+                                <a-button type="text" class="button" style="color: #2a2a2b" @click="addBlock(2)">
                                   <template #icon>
                                     <icon-close-circle />
                                   </template>
@@ -117,13 +62,7 @@
                               </p>
                               <a-divider style="margin: 10px 0" />
                               <p>
-                                <a-button
-                                  type="text"
-                                  class="button"
-                                  v-hasPermi="'/kb/data_delete'"
-                                  style="color: #2a2a2b"
-                                  @click="addBlock(3)"
-                                >
+                                <a-button type="text" class="button" style="color: #2a2a2b" @click="addBlock(3)">
                                   <template #icon>
                                     <icon-delete />
                                   </template>
@@ -197,23 +136,17 @@
                   @selection-change="selectTabChange"
                 >
                   <template #name="{ record }">
-                    <!--                    <icon-file style="color: #0960bd;margin-right: 4px;" />-->
-                    <icon-file style="margin-right: 4px" />
-                    <!--                    <span style="color: #0960bd;cursor: pointer" @click="fileClick">-->
-                    <!--                      {{record.name}}-->
-                    <!--                    </span>-->
-                    {{ record.name }}
+                    <a-link @click="handlePreview(record.id)">
+                      <icon-file style="margin-right: 4px" />
+                      {{ record.name }}
+                    </a-link>
                   </template>
                   <template #create_time="{ record }">
                     <span>{{ parseTime(record.create_time) }}</span>
                   </template>
-                  <!--                  <template #parser_id="{ record }">-->
-                  <!--                    <span>{{ parser_ids[record.parser_id]}}</span>-->
-                  <!--                  </template>-->
                   <template #status="{ record }">
                     <a-switch
                       v-model="record.status"
-                      :disabled="!getAut('/kb/data_status')"
                       size="small"
                       checked-value="1"
                       unchecked-value="0"
@@ -275,13 +208,7 @@
                         </a-popover>
                       </div>
                       <div>
-                        <a-button
-                          type="text"
-                          size="large"
-                          @click="run(record)"
-                          v-hasPermi="'/kb/data_analysis'"
-                          :loading="record.loading"
-                        >
+                        <a-button type="text" size="large" @click="run(record)" :loading="record.loading">
                           <template #icon>
                             <icon-sync v-if="record.run == '4'" />
                             <icon-sync v-if="record.run == '3'" />
@@ -303,10 +230,10 @@
                         </template>
                       </a-button>
                     </a-tooltip>
-                    <edit :item="record" v-hasPermi="'/kb/rename'" @upTabdateItem="upTabdateItem" />
+                    <edit :item="record" @upTabdateItem="upTabdateItem" />
                     <a-popconfirm :content="'确定删除吗'" type="warning" @ok="deleteItem(record)">
                       <a-tooltip content="删除">
-                        <a-button type="text" size="small" :disabled="record.run == '1'" v-hasPermi="'/kb/data_delete'">
+                        <a-button type="text" size="small" :disabled="record.run == '1'">
                           <template #icon>
                             <icon-delete />
                           </template>
@@ -317,7 +244,6 @@
                       <a-button
                         type="text"
                         size="small"
-                        v-hasPermi="'/kb/data_download'"
                         :disabled="record.run == '1'"
                         @click="onDownloadDocument(record)"
                       >
@@ -342,12 +268,12 @@
               </a-card>
             </a-scrollbar>
           </a-tab-pane>
-          <a-tab-pane key="2" title="测试" v-if="getAut('/kb/test')">
+          <a-tab-pane key="2" title="测试">
             <a-scrollbar class="rt-container-main" :style="{ height: documentHeight + 'px' }" style="overflow: hidden">
               <test ref="testForm"></test>
             </a-scrollbar>
           </a-tab-pane>
-          <a-tab-pane key="3" title="配置" v-if="getAut('/kb/update')">
+          <a-tab-pane key="3" title="配置">
             <a-scrollbar class="rt-container-main" :style="{ height: documentHeight + 'px' }" style="overflow: auto">
               <config
                 ref="configForm"
@@ -369,22 +295,6 @@
 import { computed, ref, reactive, watch, nextTick, onBeforeMount, onMounted, onBeforeUnmount } from 'vue';
 import { useI18n } from 'vue-i18n';
 import useLoading from './loading';
-// import {
-//   queryKbList,
-//   PolicyRecord,
-//   PolicyParams,
-//   queryKbDocumentList,
-//   deleteKnow,
-//   queryKbdetail,
-//   queryKbtenantInfo,
-//   kbdocumentrm,
-//   kbdocumentchangeparser,
-//   kbdocumentrun,
-//   kbdocumentchangeStatus,
-//   downloadFile,
-//   chunkSwitch,
-//   changeStatus
-// } from '@/api/kbList';
 import {
   queryKbList,
   queryKbDocumentList,
@@ -396,6 +306,7 @@ import {
   downloadFile,
   changeStatus
 } from '../../../../apis/rgflow-dify';
+import { toSyncOwnKnowledge } from './asyc.js';
 import cloneDeep from 'lodash/cloneDeep';
 // import Sortable from 'sortablejs';
 import add from './add.vue';
@@ -862,6 +773,8 @@ const addBlock = async (type) => {
         if (data.retcode == 0) {
           Message.success('删除成功');
           getKbList();
+          // 同步数据
+          toSyncOwnKnowledge(props.kb_id);
         }
       },
       onCancel: () => {}
@@ -1005,6 +918,11 @@ const changeFetchData = async (row) => {
     ...basePagination
   });
 };
+
+const handlePreview = (doc_id) => {
+  window.open(`${window.RGFLOW_BASE_URL}/document/${doc_id}?ext=docx&prefix=document`);
+};
+
 watch(
   () => columns.value,
   (val) => {

+ 2 - 0
src/modules/login/FormItem.vue

@@ -79,6 +79,8 @@ const handleSubmit = (data) => {
       .then((res) => {
         $message.success(res);
 
+        // 登录成功后,获取路由列表
+        userStore.getRoutesList()
         // 登录成功后,获取用户权限
         userStore.getUserInfo()
 

+ 5 - 1
src/modules/permission/TreeParts.vue

@@ -34,6 +34,10 @@ const props = defineProps({
     type: Array,
     default: () => [],
   },
+  permission: {
+    type: Object,
+    default: () => { },
+  },
   fieldNames: {
     type: Object,
     default: () => ({ label: 'label', key: 'id', children: 'children' }),
@@ -41,7 +45,7 @@ const props = defineProps({
 });
 
 const { treeData, title } = toRefs(props);
-
+const { permission: { add_permission, edit_permission, delete_permission } } = props;
 const emit = defineEmits(['nodeClick', 'onAddBtnClick', 'onDrop', 'onDeleteBtnClick']);
 const treeRef = ref(null);
 let is_lock = ref(false);

+ 5 - 3
src/modules/permission/group/index.vue

@@ -14,7 +14,7 @@
         <a-button v-hasPermi="'system:group:permissionConfig'" type="text"
           @click="handlePermissionConfig(record, true)">权限管理</a-button>
         <a-popconfirm content="确定删除该条数据吗?" type="warning" @ok="handleDelete(record.groupId)">
-          <a-button type="text" status="warning">删除</a-button>
+          <a-button v-hasPermi="'system:group:delete'" type="text" status="warning">删除</a-button>
         </a-popconfirm>
       </template>
     </DataTable>
@@ -47,7 +47,7 @@ import Modal from '../Modal.vue';
 import GroupForm from './GroupForm.vue';
 import MembertConfigModal from './MembertConfigModal.vue';
 import PermissionConfigModal from './PermissionConfigModal.vue';
-
+import { hasPermission } from '../../../utils/permission';
 import { QueryGroupList, QueryGroupUsers, SaveGroupUsers, ConfigGroupResource, GroupStatusSwitch, DeleteGroup, CreateGroup, UpdateGroup } from '../../../apis/permission/gruop';
 // TODO接口 模型tabs接口还没有
 import { QueryAllKnowledgeList, QueryAllDialogList } from '../../../apis/permission/common';
@@ -297,7 +297,9 @@ const getConfigList = async (tabsKey) => {
 }
 
 onMounted(() => {
-  getGroupList()
+  if (hasPermission('system:group:list')) {
+    getGroupList()
+  }
 })
 </script>
 

+ 11 - 5
src/modules/permission/org/index.vue

@@ -5,13 +5,14 @@
         key: 'deptId',
         title: 'deptName',
         children: 'children',
-      }" @nodeClick="onNodeClick" @addBtnClick="onAddBtnClick" @deleteBtnClick="onDeleteBtnClick" @drop="onNodeDrop" />
+      }" :permission="tree_permission_list" @nodeClick="onNodeClick" @addBtnClick="onAddBtnClick"
+        @deleteBtnClick="onDeleteBtnClick" @drop="onNodeDrop" />
     </div>
     <div class="right">
       <a-card title="详情" style="height: 100%">
         <OrgForm :org_form="org_form" @save="orgFromSave" @reset="orgFromReset">
           <template #actions>
-            <a-button @click="orgFromSave">保存</a-button>
+            <a-button v-hasPerm="'system:dept:edit'" @click="orgFromSave">保存</a-button>
             <a-button @click="orgFromReset">重置</a-button>
           </template>
         </OrgForm>
@@ -30,14 +31,17 @@ import { Message } from '@arco-design/web-vue';
 import TreeParts from '../TreeParts.vue';
 import OrgForm from './OrgForm.vue';
 import Modal from '../Modal.vue';
-
+import { hasPermission } from '../../../utils/permission';
 import { QueryDeptDetail, UpdateDept, UpdateDeptParent, CreateDept, DeleteDept } from '../../../apis/permission/org';
-
 import { QueryDeptTree } from '../../../apis/permission/common';
 
 const org_visible = ref(false);
 const is_edit_mode = ref(true);
 const org_tree_data = ref([]);
+const tree_permission_list = {
+  add_permission: 'system:dept:add',
+  delete_permission: 'system:dept:delete',
+}
 
 const org_form = reactive({
   parentName: '',
@@ -173,7 +177,9 @@ const onNodeDrop = async ({ dropNode, dragNode, dropPosition }) => {
   }
 };
 onMounted(() => {
-  getDeptTree();
+  if (hasPermission('system:dept:list')) {
+    getDeptTree();
+  }
 });
 </script>
 

+ 1 - 1
src/modules/permission/resource/ResourceForm.vue

@@ -70,7 +70,7 @@ const props = defineProps({
 const options = [
   {
     value: '3',
-    label: '目录',
+    label: '页面',
   },
   {
     value: '0',

+ 12 - 4
src/modules/permission/resource/index.vue

@@ -5,14 +5,15 @@
         key: 'menuId',
         title: 'menuName',
         children: 'children',
-      }" @nodeClick="onNodeClick" @addBtnClick="onAddBtnClick" @deleteBtnClick="onDeleteBtnClick" />
+      }" :permission="tree_permission_list" @nodeClick="onNodeClick" @addBtnClick="onAddBtnClick"
+        @deleteBtnClick="onDeleteBtnClick" />
     </div>
 
     <div class="right">
       <a-card title="详情" style="height: 100%;">
         <ResourceForm :resource_form="resource_form" @save="orgFromSave" @reset="orgFromReset">
           <template #actions>
-            <a-button @click="orgFromSave">保存</a-button>
+            <a-button v-hasPerm="'system:resource:edit'" @click="orgFromSave">保存</a-button>
             <a-button @click="orgFromReset">重置</a-button>
           </template>
         </ResourceForm>
@@ -31,7 +32,7 @@ import { Message } from '@arco-design/web-vue';
 import TreeParts from '../TreeParts.vue';
 import ResourceForm from './ResourceForm.vue';
 import Modal from '../Modal.vue';
-
+import { hasPermission } from '../../../utils/permission';
 import {
   QueryResourceTree, QueryResourceDetail, UpdateResource, CreateResource, DeleteResource
 } from '../../../apis/permission/resource';
@@ -39,6 +40,11 @@ import {
 const resourcevisible = ref(false);
 const is_edit_mode = ref(true);
 const resourcetree_data = ref([]);
+const tree_permission_list = {
+  add_permission: 'system:resource:add',
+  delete_permission: 'system:resource:delete',
+}
+
 
 const resource_form = reactive({
   parentName: '',
@@ -149,7 +155,9 @@ const orgFromCancel = () => {
   resourcevisible.value = false;
 }
 onMounted(() => {
-  getResourceTree();
+  if (hasPermission('system:resource:list')) {
+    getResourceTree();
+  }
 })
 </script>
 

+ 4 - 1
src/router.js

@@ -1,6 +1,9 @@
 import { createWebHashHistory, createRouter } from 'vue-router';
+import { localST_RoutesList } from './base/storage';
 
-import routes from './views/routes';
+import routes from './router/index.js';
+
+console.log('router', JSON.parse(localST_RoutesList.getItem()));
 
 /**
  * 配置路由方案

+ 53 - 0
src/router/index.js

@@ -0,0 +1,53 @@
+import Home from '../views/Home.vue';
+
+/**
+ * 路由表配置
+ */
+const routes = [
+  { path: '/', component: Home, redirect: '/chat/qa' },
+
+  // 登录与注册
+  { path: '/login', component: () => import('../views/Login.vue') },
+  { path: '/reg', component: () => import('../views/Register.vue') },
+
+  // 会话
+  { path: '/chat', component: () => import('../views/Conversation.vue') },
+  { path: '/chat/qa', component: () => import('../views/ConversationQA.vue') },
+  { path: '/chat/history', component: () => import('../views/ConversationHistory.vue') },
+  { path: '/chat/board', component: () => import('../views/ConversationBoard.vue') },
+
+  // 知识库
+  { path: '/knowledge', component: () => import('../views/Knowledge.vue') },
+  { path: '/knowledge/detail', component: () => import('../views/KnowledgeDetail.vue') },
+  // 模型
+  { path: '/model', component: () => import('../views/Model.vue') },
+  // Agent
+  { path: '/agent', component: () => import('../views/Agent.vue') },
+  // 智能体
+  { path: '/intelligent', component: () => import('../views/Intelligent.vue') },
+  // dify智能体详情
+  { path: '/intelligent/detail', component: () => import('../views/difyDetail.vue') },
+
+  // 权限管理
+  {
+    path: '/permission',
+    component: () => import('../views/layout/LayoutPermission.vue'),
+    children: [
+      { path: '/permission/account', component: () => import('../views/PermissionAccount.vue') },
+      { path: '/permission/org', component: () => import('../views/PermissionOrganization.vue') },
+      { path: '/permission/resource', component: () => import('../views/PermissionResource.vue') },
+      { path: '/permission/role', component: () => import('../views/PermissionRole.vue') },
+      { path: '/permission/group', component: () => import('../views/PermissionGroup.vue') }
+    ]
+  },
+
+  // 个人中心
+  { path: '/profile', component: () => import('../views/Profiles.vue') },
+  { path: '/setting', component: () => import('../views/Settings.vue') },
+
+  { path: '/xiaoshu', component: () => import('../views/Xiaoshu.vue') },
+
+  { path: '/about', component: () => import('../views/About.vue') }
+];
+
+export default routes;

+ 0 - 1
src/views/KnowledgeDetail.vue

@@ -17,5 +17,4 @@ import MessageDetail from '../modules/knowledge/rgflow/MessageDetail.vue';
 const route = useRoute();
 
 const { id, name } = route.query;
-console.log(id, name);
 </script>

+ 2 - 2
src/views/difyDetail.vue

@@ -2,7 +2,7 @@
   <LayoutExperience>
     <ContentContainer>
       <TopSetting :current_label="name"></TopSetting>
-      <MessageBody :id="id"></MessageBody>
+      <MessageBody :id="id" :mode="mode"></MessageBody>
     </ContentContainer>
   </LayoutExperience>
 </template>
@@ -16,5 +16,5 @@ import MessageBody from '../modules/dify/MessageBody.vue';
 
 const route = useRoute();
 
-const { id, name } = route.query;
+const { id, name, mode } = route.query;
 </script>

+ 0 - 53
src/views/routes.js

@@ -1,53 +0,0 @@
-import Home from './Home.vue';
-
-/**
- * 路由表配置
- */
-const routes = [
-  { path: '/', component: Home, redirect: '/chat/qa' },
-
-  // 登录与注册
-  { path: '/login', component: () => import('./Login.vue') },
-  { path: '/reg', component: () => import('./Register.vue') },
-
-  // 会话
-  { path: '/chat', component: () => import('./Conversation.vue') },
-  { path: '/chat/qa', component: () => import('./ConversationQA.vue') },
-  { path: '/chat/history', component: () => import('./ConversationHistory.vue') },
-  { path: '/chat/board', component: () => import('./ConversationBoard.vue') },
-
-  // 知识库
-  { path: '/knowledge', component: () => import('./Knowledge.vue') },
-  { path: '/knowledge/detail', component: () => import('./KnowledgeDetail.vue') },
-  // 模型
-  { path: '/model', component: () => import('./Model.vue') },
-  // Agent
-  { path: '/agent', component: () => import('./Agent.vue') },
-  // 智能体
-  { path: '/intelligent', component: () => import('./Intelligent.vue') },
-  // dify智能体详情
-  { path: '/intelligent/detail', component: () => import('./difyDetail.vue') },
-
-  // 权限管理
-  {
-    path: '/permission',
-    component: () => import('./layout/LayoutPermission.vue'),
-    children: [
-      { path: '/permission/account', component: () => import('./PermissionAccount.vue') },
-      { path: '/permission/org', component: () => import('./PermissionOrganization.vue') },
-      { path: '/permission/resource', component: () => import('./PermissionResource.vue') },
-      { path: '/permission/role', component: () => import('./PermissionRole.vue') },
-      { path: '/permission/group', component: () => import('./PermissionGroup.vue') }
-    ]
-  },
-
-  // 个人中心
-  { path: '/profile', component: () => import('./Profiles.vue') },
-  { path: '/setting', component: () => import('./Settings.vue') },
-
-  { path: '/xiaoshu', component: () => import('./Xiaoshu.vue') },
-
-  { path: '/about', component: () => import('./About.vue') }
-];
-
-export default routes;