Browse Source

提交全部代码(功能基本实现,样式有瑕疵)

ligao 7 months ago
parent
commit
3776613cf2

+ 120 - 0
src/api/system/knowledgeInfo/index.ts

@@ -1,6 +1,7 @@
 import request from '@/utils/request';
 import { AxiosPromise } from 'axios';
 import { KnowledgeInfoVO, KnowledgeInfoForm, KnowledgeInfoQuery } from '@/api/system/knowledgeInfo/types';
+import {KnowledgeAttachForm, KnowledgeAttachQuery, KnowledgeAttachVO} from "@/api/system/knowledgeAttach/types";
 
 /**
  * 查询知识库列表
@@ -61,3 +62,122 @@ export const delKnowledgeInfo = (id: string | number | Array<string | number>) =
     method: 'delete'
   });
 };
+/**
+ * 查询知识片段列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listKnowledgeFragment = (query?: KnowledgeFragmentQuery): AxiosPromise<KnowledgeFragmentVO[]> => {
+  return request({
+    url: '/system/knowledgeFragment/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询知识片段详细
+ * @param id
+ */
+export const getKnowledgeFragment = (id: string | number): AxiosPromise<KnowledgeFragmentVO> => {
+  return request({
+    url: '/system/knowledgeFragment/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增知识片段
+ * @param data
+ */
+export const addKnowledgeFragment = (data: KnowledgeFragmentForm) => {
+  return request({
+    url: '/system/knowledgeFragment',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改知识片段
+ * @param data
+ */
+export const updateKnowledgeFragment = (data: KnowledgeFragmentForm) => {
+  return request({
+    url: '/system/knowledgeFragment',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除知识片段
+ * @param id
+ */
+export const delKnowledgeFragment = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/system/knowledgeFragment/' + id,
+    method: 'delete'
+  });
+};
+
+/**
+ * 查询知识库附件列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listKnowledgeAttach = (query?: KnowledgeAttachQuery): AxiosPromise<KnowledgeAttachVO[]> => {
+  return request({
+    url: '/system/knowledgeAttach/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询知识库附件详细
+ * @param id
+ */
+export const getKnowledgeAttach = (id: string | number): AxiosPromise<KnowledgeAttachVO> => {
+  return request({
+    url: '/system/knowledgeAttach/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增知识库附件
+ * @param data
+ */
+export const addKnowledgeAttach = (data: KnowledgeAttachForm) => {
+  return request({
+    url: '/system/knowledgeAttach',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改知识库附件
+ * @param data
+ */
+export const updateKnowledgeAttach = (data: KnowledgeAttachForm) => {
+  return request({
+    url: '/system/knowledgeAttach',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除知识库附件
+ * @param id
+ */
+export const delKnowledgeAttach = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/system/knowledgeAttach/' + id,
+    method: 'delete'
+  });
+};

+ 312 - 0
src/api/system/knowledgeInfo/types.ts

@@ -229,3 +229,315 @@ export interface KnowledgeInfoQuery extends PageQuery {
 
 
 
+export interface KnowledgeFragmentVO {
+  /**
+   *
+   */
+  id: string | number;
+
+  /**
+   * 知识库ID
+   */
+  knowledgeCode: string;
+
+  /**
+   * 文档ID
+   */
+  docCode: string;
+
+  /**
+   * 知识片段ID
+   */
+  fragmentCode: string;
+
+  /**
+   * 片段索引下标
+   */
+  idx: string | number;
+
+  /**
+   * 文档内容
+   */
+  content: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+
+}
+
+export interface KnowledgeFragmentForm extends BaseEntity {
+  /**
+   *
+   */
+  id?: string | number;
+
+  /**
+   * 知识库ID
+   */
+  knowledgeCode?: string;
+
+  /**
+   * 文档ID
+   */
+  docCode?: string;
+
+  /**
+   * 知识片段ID
+   */
+  fragmentCode?: string;
+
+  /**
+   * 片段索引下标
+   */
+  idx?: string | number;
+
+  /**
+   * 文档内容
+   */
+  content?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+
+}
+
+export interface KnowledgeFragmentQuery extends PageQuery {
+
+  /**
+   * 知识库ID
+   */
+  knowledgeCode?: string;
+
+  /**
+   * 文档ID
+   */
+  docCode?: string;
+
+  /**
+   * 知识片段ID
+   */
+  fragmentCode?: string;
+
+  /**
+   * 片段索引下标
+   */
+  idx?: string | number;
+
+  /**
+   * 文档内容
+   */
+  content?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}
+export interface KnowledgeAttachVO {
+  /**
+   *
+   */
+  id: string | number;
+
+  /**
+   * 知识库ID
+   */
+  knowledgeCode: string;
+
+  /**
+   * 文档编码
+   */
+  docCode: string;
+
+  /**
+   * 文档名称
+   */
+  docName: string;
+
+  /**
+   * 文档类型
+   */
+  docType: string;
+
+  /**
+   * 对象存储ID
+   */
+  ossId: string | number;
+
+  /**
+   * 拆解图片状态10未开始,20进行中,30已完成
+   */
+  picStatus: number;
+
+  /**
+   * 分析图片状态10未开始,20进行中,30已完成
+   */
+  picAnysStatus: number;
+
+  /**
+   * 写入向量数据库状态10未开始,20进行中,30已完成
+   */
+  vectorStatus: number;
+
+  /**
+   * 文档内容
+   */
+  content: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+
+  /**
+   * 文件本地存储路径,如:D:/knowledge/files/abc123xyz_报告.pdf
+   */
+  filePath: string;
+
+  /**
+   * 可访问的HTTP下载链接,如:http://xxx/api/file/download?docId=abc123
+   */
+  publicUrl: string;
+
+}
+
+export interface KnowledgeAttachForm extends BaseEntity {
+  /**
+   *
+   */
+  id?: string | number;
+
+  /**
+   * 知识库ID
+   */
+  knowledgeCode?: string;
+
+  /**
+   * 文档编码
+   */
+  docCode?: string;
+
+  /**
+   * 文档名称
+   */
+  docName?: string;
+
+  /**
+   * 文档类型
+   */
+  docType?: string;
+
+  /**
+   * 对象存储ID
+   */
+  ossId?: string | number;
+
+  /**
+   * 拆解图片状态10未开始,20进行中,30已完成
+   */
+  picStatus?: number;
+
+  /**
+   * 分析图片状态10未开始,20进行中,30已完成
+   */
+  picAnysStatus?: number;
+
+  /**
+   * 写入向量数据库状态10未开始,20进行中,30已完成
+   */
+  vectorStatus?: number;
+
+  /**
+   * 文档内容
+   */
+  content?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+
+  /**
+   * 文件本地存储路径,如:D:/knowledge/files/abc123xyz_报告.pdf
+   */
+  filePath?: string;
+
+  /**
+   * 可访问的HTTP下载链接,如:http://xxx/api/file/download?docId=abc123
+   */
+  publicUrl?: string;
+
+}
+
+export interface KnowledgeAttachQuery extends PageQuery {
+
+  /**
+   * 知识库ID
+   */
+  knowledgeCode?: string;
+
+  /**
+   * 文档编码
+   */
+  docCode?: string;
+
+  /**
+   * 文档名称
+   */
+  docName?: string;
+
+  /**
+   * 文档类型
+   */
+  docType?: string;
+
+  /**
+   * 对象存储ID
+   */
+  ossId?: string | number;
+
+  /**
+   * 拆解图片状态10未开始,20进行中,30已完成
+   */
+  picStatus?: number;
+
+  /**
+   * 分析图片状态10未开始,20进行中,30已完成
+   */
+  picAnysStatus?: number;
+
+  /**
+   * 写入向量数据库状态10未开始,20进行中,30已完成
+   */
+  vectorStatus?: number;
+
+  /**
+   * 文档内容
+   */
+  content?: string;
+
+  /**
+   * 文件本地存储路径,如:D:/knowledge/files/abc123xyz_报告.pdf
+   */
+  filePath?: string;
+
+  /**
+   * 可访问的HTTP下载链接,如:http://xxx/api/file/download?docId=abc123
+   */
+  publicUrl?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}
+
+
+
+
+
+

+ 40 - 2
src/api/system/project/index.ts

@@ -1,7 +1,6 @@
 import request from '@/utils/request';
 import { AxiosPromise } from 'axios';
-import { ProjectVO, ProjectForm, ProjectQuery } from '@/api/system/project/types';
-
+import { ProjectVO, ProjectForm, ProjectQuery,ModelVO,ModelQuery,AgentQuery ,AgentVO, KnowledgeInfoVO,KnowledgeInfoQuery } from '@/api/system/project/types';
 /**
  * 查询项目列表
  * @param query
@@ -61,3 +60,42 @@ export const delProject = (id: string | number | Array<string | number>) => {
     method: 'delete'
   });
 };
+/**
+ * 查询模型列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listModel = (query?: ModelQuery): AxiosPromise<ModelVO[]> => {
+  return request({
+    url: '/system/model/list',
+    method: 'get',
+    params: query
+  });
+};
+/**
+ * 查询智能体列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listAgent = (query?: AgentQuery): AxiosPromise<AgentVO[]> => {
+  return request({
+    url: '/system/agent/list',
+    method: 'get',
+    params: query
+  });
+};
+/**
+ * 查询知识库列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listKnowledgeInfo = (query?: KnowledgeInfoQuery): AxiosPromise<KnowledgeInfoVO[]> => {
+  return request({
+    url: '/system/knowledgeInfo/list',
+    method: 'get',
+    params: query
+  });
+};

+ 275 - 0
src/api/system/project/types.ts

@@ -144,3 +144,278 @@ export interface ProjectQuery extends PageQuery {
 
 
 
+export interface ModelVO {
+  /**
+   * 主键
+   */
+  id: string | number;
+
+  /**
+   * 模型名称
+   */
+  modelName: string;
+
+  /**
+   *
+   */
+  network: number;
+
+  /**
+   * 公司
+   */
+  company: string;
+
+  /**
+   * 简介
+   */
+  introduce: string;
+
+  /**
+   * 0-启用;1-禁用
+   */
+  status: number;
+
+  /**
+   * 排序权重
+   */
+  sort: number;
+
+  /**
+   *
+   */
+  remark: string;
+
+}
+
+export interface ModelQuery extends PageQuery {
+
+  /**
+   * 模型名称
+   */
+  modelName?: string;
+
+  /**
+   *
+   */
+  network?: number;
+
+  /**
+   * 公司
+   */
+  company?: string;
+
+  /**
+   * 简介
+   */
+  introduce?: string;
+
+  /**
+   * 0-启用;1-禁用
+   */
+  status?: number;
+
+  /**
+   * 排序权重
+   */
+  sort?: number;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}
+
+export interface AgentVO {
+  /**
+   *
+   */
+  id: string | number;
+
+  /**
+   * 智能体名称
+   */
+  name: string;
+
+  /**
+   * 描述
+   */
+  description: string;
+
+  /**
+   *
+   */
+  remark: string;
+
+}
+
+export interface AgentQuery extends PageQuery {
+
+  /**
+   * 智能体名称
+   */
+  name?: string;
+
+  /**
+   * 描述
+   */
+  description?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}
+
+export interface KnowledgeInfoVO {
+  /**
+   *
+   */
+  id: string | number;
+
+  /**
+   * 知识库ID
+   */
+  knowledgeCode: string;
+
+  /**
+   * 知识库名称
+   */
+  knowledgeName: string;
+
+  /**
+   * 描述
+   */
+  description: string;
+
+  /**
+   * 用户ID
+   */
+  userId: string | number;
+
+  /**
+   * 是否公开知识库(0 否 1是)
+   */
+  share: number;
+
+  /**
+   * 知识分隔符
+   */
+  knowledgeSeparator: string;
+
+  /**
+   * 提问分隔符
+   */
+  questionSeparator: string;
+
+  /**
+   * 重叠字符数
+   */
+  overlapChar: number;
+
+  /**
+   * 知识库中检索的条数
+   */
+  retrieveLimit: number;
+
+  /**
+   * 文本块大小
+   */
+  textBlockSize: number;
+
+  /**
+   * 向量库
+   */
+  vectorModelName: string;
+
+  /**
+   * 向量模型
+   */
+  embeddingModelName: string;
+
+  /**
+   * 系统提示词
+   */
+  systemPrompt: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+
+}
+
+export interface KnowledgeInfoQuery extends PageQuery {
+
+  /**
+   * 知识库ID
+   */
+  knowledgeCode?: string;
+
+  /**
+   * 知识库名称
+   */
+  knowledgeName?: string;
+
+  /**
+   * 描述
+   */
+  description?: string;
+
+  /**
+   * 用户ID
+   */
+  userId?: string | number;
+
+  /**
+   * 是否公开知识库(0 否 1是)
+   */
+  share?: number;
+
+  /**
+   * 知识分隔符
+   */
+  knowledgeSeparator?: string;
+
+  /**
+   * 提问分隔符
+   */
+  questionSeparator?: string;
+
+  /**
+   * 重叠字符数
+   */
+  overlapChar?: number;
+
+  /**
+   * 知识库中检索的条数
+   */
+  retrieveLimit?: number;
+
+  /**
+   * 文本块大小
+   */
+  textBlockSize?: number;
+
+  /**
+   * 向量库
+   */
+  vectorModelName?: string;
+
+  /**
+   * 向量模型
+   */
+  embeddingModelName?: string;
+
+  /**
+   * 系统提示词
+   */
+  systemPrompt?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}
+
+
+

+ 5 - 0
src/types/components.d.ts

@@ -20,10 +20,13 @@ declare module 'vue' {
     ElButton: typeof import('element-plus/es')['ElButton']
     ElCard: typeof import('element-plus/es')['ElCard']
     ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
+    ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
+    ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
+    ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDivider: typeof import('element-plus/es')['ElDivider']
     ElDrawer: typeof import('element-plus/es')['ElDrawer']
@@ -34,6 +37,7 @@ declare module 'vue' {
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
     ElIcon: typeof import('element-plus/es')['ElIcon']
+    ElImage: typeof import('element-plus/es')['ElImage']
     ElInput: typeof import('element-plus/es')['ElInput']
     ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
     ElLink: typeof import('element-plus/es')['ElLink']
@@ -54,6 +58,7 @@ declare module 'vue' {
     ElTabPane: typeof import('element-plus/es')['ElTabPane']
     ElTabs: typeof import('element-plus/es')['ElTabs']
     ElTag: typeof import('element-plus/es')['ElTag']
+    ElText: typeof import('element-plus/es')['ElText']
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElTree: typeof import('element-plus/es')['ElTree']
     ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']

+ 535 - 120
src/views/system/knowledgeInfo/index.vue

@@ -1,124 +1,106 @@
 <template>
-  <div class="p-2">
+  <div style="width: 100%; height: auto;">
     <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
       <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
+        <div class="p-4 bg-white rounded">
           <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="知识库ID" prop="knowledgeCode">
-              <el-input v-model="queryParams.knowledgeCode" placeholder="请输入知识库ID" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
             <el-form-item label="知识库名称" prop="knowledgeName">
               <el-input v-model="queryParams.knowledgeName" placeholder="请输入知识库名称" clearable @keyup.enter="handleQuery" />
             </el-form-item>
             <el-form-item label="描述" prop="description">
               <el-input v-model="queryParams.description" placeholder="请输入描述" clearable @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="用户ID" prop="userId">
-              <el-input v-model="queryParams.userId" placeholder="请输入用户ID" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="是否公开知识库" prop="share">
-              <el-input v-model="queryParams.share" placeholder="请输入是否公开知识库" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="知识分隔符" prop="knowledgeSeparator">
-              <el-input v-model="queryParams.knowledgeSeparator" placeholder="请输入知识分隔符" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="提问分隔符" prop="questionSeparator">
-              <el-input v-model="queryParams.questionSeparator" placeholder="请输入提问分隔符" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="重叠字符数" prop="overlapChar">
-              <el-input v-model="queryParams.overlapChar" placeholder="请输入重叠字符数" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="知识库中检索的条数" prop="retrieveLimit">
-              <el-input v-model="queryParams.retrieveLimit" placeholder="请输入知识库中检索的条数" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="文本块大小" prop="textBlockSize">
-              <el-input v-model="queryParams.textBlockSize" placeholder="请输入文本块大小" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="向量库" prop="vectorModelName">
-              <el-input v-model="queryParams.vectorModelName" placeholder="请输入向量库" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="向量模型" prop="embeddingModelName">
-              <el-input v-model="queryParams.embeddingModelName" placeholder="请输入向量模型" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="系统提示词" prop="systemPrompt">
-              <el-input v-model="queryParams.systemPrompt" placeholder="请输入系统提示词" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
             <el-form-item>
               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
               <el-button icon="Refresh" @click="resetQuery">重置</el-button>
             </el-form-item>
           </el-form>
-        </el-card>
+        </div>
       </div>
     </transition>
 
-    <el-card shadow="never">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:knowledgeInfo:add']">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:knowledgeInfo:edit']">修改</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:knowledgeInfo:remove']">删除</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:knowledgeInfo:export']">导出</el-button>
-          </el-col>
+    <div class="bg-white p-4 rounded">
+      <div class="flex justify-between items-center mb-4">
+        <h2 class="text-xl font-bold">知识库列表</h2>
+        <div class="flex space-x-2">
+          <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:knowledgeInfo:add']">新增</el-button>
+          <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:knowledgeInfo:remove']">删除</el-button>
+          <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:knowledgeInfo:export']">导出</el-button>
           <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-        </el-row>
-      </template>
+        </div>
+      </div>
 
-      <el-table v-loading="loading" border :data="knowledgeInfoList" @selection-change="handleSelectionChange">
+      <el-table
+          v-loading="loading"
+          :data="knowledgeInfoList"
+          @selection-change="handleSelectionChange"
+          class="compact-table"
+      >
         <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="" align="center" prop="id" v-if="true" />
-        <el-table-column label="知识库ID" align="center" prop="knowledgeCode" />
+        <el-table-column label="知识库编号" align="center" prop="knowledgeCode" />
         <el-table-column label="知识库名称" align="center" prop="knowledgeName" />
-        <el-table-column label="描述" align="center" prop="description" />
-        <el-table-column label="用户ID" align="center" prop="userId" />
-        <el-table-column label="是否公开知识库" align="center" prop="share" />
-        <el-table-column label="知识分隔符" align="center" prop="knowledgeSeparator" />
-        <el-table-column label="提问分隔符" align="center" prop="questionSeparator" />
-        <el-table-column label="重叠字符数" align="center" prop="overlapChar" />
-        <el-table-column label="知识库中检索的条数" align="center" prop="retrieveLimit" />
-        <el-table-column label="文本块大小" align="center" prop="textBlockSize" />
-        <el-table-column label="向量库" align="center" prop="vectorModelName" />
-        <el-table-column label="向量模型" align="center" prop="embeddingModelName" />
-        <el-table-column label="系统提示词" align="center" prop="systemPrompt" />
-        <el-table-column label="备注" align="center" prop="remark" />
+        <el-table-column label="描述" align="center" prop="description" width="600" ellipsis />
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
           <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:knowledgeInfo:edit']"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:knowledgeInfo:remove']"></el-button>
-            </el-tooltip>
+            <div class="flex space-x-2 items-center">
+              <el-tooltip content="上传文件" placement="top">
+                <el-upload
+                    :action="uploadUrl"
+                    :headers="headers"
+                    :show-file-list="false"
+                    accept=".txt,.pdf,.docx,.pptx,.xlsx,.xls,.csv,.json"
+                    :data="{ knowledgeCode: scope.row.knowledgeCode }"
+                    :before-upload="beforeUpload"
+                    :on-success="handleUploadSuccess"
+                    :on-error="handleUploadError"
+                >
+                  <el-button link type="primary" icon="Upload"></el-button>
+                </el-upload>
+              </el-tooltip>
+              <el-tooltip content="查看附件" placement="top">
+                <el-button link type="primary" icon="Folder" @click="handleAttachment(scope.row)"></el-button>
+              </el-tooltip>
+              <el-tooltip content="删除" placement="top">
+                <el-button
+                    link
+                    type="danger"
+                    icon="Delete"
+                    @click="handleDelete(scope.row)"
+                    v-hasPermi="['system:knowledgeInfo:remove']"
+                ></el-button>
+              </el-tooltip>
+            </div>
           </template>
         </el-table-column>
       </el-table>
 
-      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
-    </el-card>
+      <div class="flex justify-center mt-4">
+        <el-pagination
+            v-show="total > 0"
+            :total="total"
+            v-model:current-page="queryParams.pageNum"
+            v-model:page-size="queryParams.pageSize"
+            @current-change="getList"
+            layout="prev, pager, next"
+        />
+      </div>
+
+    </div>
+
     <!-- 添加或修改知识库对话框 -->
     <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
-      <el-form ref="knowledgeInfoFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="知识库ID" prop="knowledgeCode">
-          <el-input v-model="form.knowledgeCode" placeholder="请输入知识库ID" />
-        </el-form-item>
+      <el-form ref="knowledgeInfoFormRef" :model="form" :rules="rules" label-width="100px">
         <el-form-item label="知识库名称" prop="knowledgeName">
           <el-input v-model="form.knowledgeName" placeholder="请输入知识库名称" />
         </el-form-item>
         <el-form-item label="描述" prop="description">
           <el-input v-model="form.description" placeholder="请输入描述" />
         </el-form-item>
-        <el-form-item label="用户ID" prop="userId">
-          <el-input v-model="form.userId" placeholder="请输入用户ID" />
-        </el-form-item>
-        <el-form-item label="是否公开知识库" prop="share">
-          <el-input v-model="form.share" placeholder="请输入是否公开知识库" />
+        <el-form-item label="是否公开" prop="share">
+          <el-radio-group v-model="form.share">
+            <el-radio :label="1">是</el-radio>
+            <el-radio :label="0">否</el-radio>
+          </el-radio-group>
         </el-form-item>
         <el-form-item label="知识分隔符" prop="knowledgeSeparator">
           <el-input v-model="form.knowledgeSeparator" placeholder="请输入知识分隔符" />
@@ -127,25 +109,26 @@
           <el-input v-model="form.questionSeparator" placeholder="请输入提问分隔符" />
         </el-form-item>
         <el-form-item label="重叠字符数" prop="overlapChar">
-          <el-input v-model="form.overlapChar" placeholder="请输入重叠字符数" />
+          <el-input-number v-model="form.overlapChar" placeholder="请输入重叠字符数" style="width: 100%" />
         </el-form-item>
-        <el-form-item label="知识库中检索条数" prop="retrieveLimit">
-          <el-input v-model="form.retrieveLimit" placeholder="请输入知识库中检索的条数" />
+        <el-form-item label="检索条数" prop="retrieveLimit">
+          <el-input-number v-model="form.retrieveLimit" placeholder="请输入知识库中检索的条数" style="width: 100%" />
         </el-form-item>
         <el-form-item label="文本块大小" prop="textBlockSize">
-          <el-input v-model="form.textBlockSize" placeholder="请输入文本块大小" />
+          <el-input-number v-model="form.textBlockSize" placeholder="请输入文本块大小" style="width: 100%" />
         </el-form-item>
         <el-form-item label="向量库" prop="vectorModelName">
-          <el-input v-model="form.vectorModelName" placeholder="请输入向量库" />
+          <el-select v-model="form.vectorModelName" placeholder="请选择向量库" style="width: 100%">
+            <el-option label="weaviate" value="weaviate" />
+            <el-option label="milvus" value="milvus" />
+          </el-select>
         </el-form-item>
         <el-form-item label="向量模型" prop="embeddingModelName">
-          <el-input v-model="form.embeddingModelName" placeholder="请输入向量模型" />
-        </el-form-item>
-        <el-form-item label="系统提示词" prop="systemPrompt">
-          <el-input v-model="form.systemPrompt" placeholder="请输入系统提示词" />
-        </el-form-item>
-        <el-form-item label="备注" prop="remark">
-            <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
+          <el-select v-model="form.embeddingModelName" placeholder="请选择向量模型" style="width: 100%">
+            <el-option label="text-embedding-3-small" value="text-embedding-3-small" />
+            <el-option label="quentinz/bge-large-zh-v1.5" value="quentinz/bge-large-zh-v1.5" />
+            <el-option label="baai/bge-m3" value="baai/bge-m3" />
+          </el-select>
         </el-form-item>
       </el-form>
       <template #footer>
@@ -155,14 +138,131 @@
         </div>
       </template>
     </el-dialog>
+
+    <!-- 附件管理对话框 -->
+    <el-dialog
+        title="知识库附件"
+        v-model="fileVisible"
+        width="80%"
+        append-to-body
+    >
+      <div class="flex justify-between items-center mb-4">
+        <div class="text-lg font-semibold">知识库: {{ currentKnowledgeName }}</div>
+        <div>
+          <el-upload
+              :action="uploadUrl"
+              :headers="headers"
+              :show-file-list="false"
+              accept=".txt,.pdf,.docx,.pptx,.xlsx,.xls,.csv,.json"
+              multiple
+              :data="{ knowledgeCode: currentKnowledgeCode }"
+              :on-success="handleUploadSuccess"
+              :before-upload="beforeUpload"
+              :on-error="handleUploadError"
+          >
+            <el-button type="primary" icon="Upload">文件上传</el-button>
+          </el-upload>
+        </div>
+      </div>
+
+      <el-table :data="fileData" v-loading="fileLoading" class="attachment-table">
+        <el-table-column prop="docName" label="文档名称" width="250" />
+        <el-table-column prop="docType" label="文档类型" width="120" />
+        <el-table-column label="状态" width="150">
+          <template #default="scope">
+            <el-tag :type="getStatusTagType(scope.row.vectorStatus)">
+              {{ getStatusText(scope.row.vectorStatus) }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="大小" width="120">
+          <template #default="scope">
+            {{ formatFileSize(scope.row.fileSize) }}
+          </template>
+        </el-table-column>
+        <el-table-column label="上传时间" width="180">
+          <template #default="scope">
+            {{ formatDateTime(scope.row.createTime) }}
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" width="200">
+          <template #default="scope">
+            <el-button
+                type="danger"
+                size="small"
+                icon="Delete"
+                @click="handleDeleteFile(scope.row)"
+            >删除</el-button>
+            <el-button
+                type="primary"
+                size="small"
+                icon="Document"
+                @click="handleFragment(scope.row)"
+            >片段</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <div class="mt-4 text-sm text-gray-500">
+        <div class="flex items-center mb-2">
+          <div class="w-3 h-3 bg-blue-500 rounded-full mr-2"></div>
+          <span>支持的文件类型: .txt, .pdf, .docx, .pptx, .xlsx, .xls, .csv, .json</span>
+        </div>
+        <div class="flex items-center">
+          <div class="w-3 h-3 bg-blue-500 rounded-full mr-2"></div>
+          <span>最大文件大小: 10MB</span>
+        </div>
+      </div>
+    </el-dialog>
+
+    <!-- 知识片段对话框 -->
+    <el-dialog
+        title="知识片段"
+        v-model="fragmentVisible"
+        width="80%"
+        append-to-body
+    >
+      <div class="mb-4">
+        <div class="text-lg font-semibold">{{ currentDocumentName }}</div>
+        <div class="text-sm text-gray-500">共 {{ fragmentData.length }} 个片段</div>
+      </div>
+
+      <el-table :data="fragmentData" class="fragment-table">
+        <el-table-column label="序号" width="80">
+          <template #default="scope">
+            <div class="text-center">{{ scope.$index + 1 }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="content" label="片段内容">
+          <template #default="scope">
+            <div class="fragment-content">
+              {{ scope.row.content }}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" width="120">
+          <template #default="scope">
+            <el-button
+                type="danger"
+                size="small"
+                icon="Delete"
+                @click="handleDeleteFragment(scope.row)"
+            >删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-dialog>
   </div>
 </template>
 
 <script setup name="KnowledgeInfo" lang="ts">
-import { listKnowledgeInfo, getKnowledgeInfo, delKnowledgeInfo, addKnowledgeInfo, updateKnowledgeInfo } from '@/api/system/knowledgeInfo';
-import { KnowledgeInfoVO, KnowledgeInfoQuery, KnowledgeInfoForm } from '@/api/system/knowledgeInfo/types';
+import { listKnowledgeInfo, getKnowledgeInfo, delKnowledgeInfo, addKnowledgeInfo, updateKnowledgeInfo,listKnowledgeAttach, delKnowledgeAttach, listKnowledgeFragment, delKnowledgeFragment } from '@/api/system/knowledgeInfo';
+import { KnowledgeInfoVO, KnowledgeInfoQuery, KnowledgeInfoForm, KnowledgeFragmentVO, KnowledgeAttachVO } from '@/api/system/knowledgeInfo/types';
+import { getCurrentInstance, ComponentInternalInstance } from 'vue';
+import { useUserStore } from '@/store/modules/user';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const userStore = useUserStore();
 
 const knowledgeInfoList = ref<KnowledgeInfoVO[]>([]);
 const buttonLoading = ref(false);
@@ -173,6 +273,21 @@ const single = ref(true);
 const multiple = ref(true);
 const total = ref(0);
 
+// 附件相关状态
+const fileVisible = ref(false);
+const fragmentVisible = ref(false);
+const fileLoading = ref(false);
+const fileData = ref<KnowledgeAttachVO[]>([]);
+const fragmentData = ref<KnowledgeFragmentVO[]>([]);
+const currentKnowledgeCode = ref('');
+const currentKnowledgeName = ref('');
+const currentDocumentName = ref('');
+const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + '/system/knowledgeAttach/upload');
+const headers = ref({
+  Authorization: 'Bearer ' + userStore.token,
+  clientId: import.meta.env.VITE_APP_CLIENT_ID
+});
+
 const queryFormRef = ref<ElFormInstance>();
 const knowledgeInfoFormRef = ref<ElFormInstance>();
 
@@ -220,6 +335,12 @@ const data = reactive<PageData<KnowledgeInfoForm, KnowledgeInfoQuery>>({
     }
   },
   rules: {
+    knowledgeName: [{ required: true, message: "知识库名称不能为空", trigger: "blur" }],
+    retrieveLimit: [{ required: true, message: "检索条数不能为空", trigger: "blur" }],
+    textBlockSize: [{ required: true, message: "文本块大小不能为空", trigger: "blur" }],
+    vectorModelName: [{ required: true, message: "向量库不能为空", trigger: "change" }],
+    embeddingModelName: [{ required: true, message: "向量模型不能为空", trigger: "change" }],
+    share: [{ required: true, message: "是否公开不能为空", trigger: "change" }]
   }
 });
 
@@ -228,10 +349,16 @@ const { queryParams, form, rules } = toRefs(data);
 /** 查询知识库列表 */
 const getList = async () => {
   loading.value = true;
-  const res = await listKnowledgeInfo(queryParams.value);
-  knowledgeInfoList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
+  try {
+    const res = await listKnowledgeInfo(queryParams.value);
+    knowledgeInfoList.value = res.rows;
+    total.value = res.total;
+  } catch (error) {
+    console.error('获取知识库列表失败:', error);
+    proxy?.$modal.msgError("获取知识库列表失败");
+  } finally {
+    loading.value = false;
+  }
 }
 
 /** 取消按钮 */
@@ -268,6 +395,16 @@ const handleSelectionChange = (selection: KnowledgeInfoVO[]) => {
 /** 新增按钮操作 */
 const handleAdd = () => {
   reset();
+  form.value = {
+    ...initFormData,
+    share: 0,        // 默认选"否"
+    overlapChar: 30,  // 默认重叠字符数为30
+    knowledgeCode: generateRandomString(), //随机编号
+    textBlockSize: 300,
+    retrieveLimit: 5,
+    vectorModelName: "weaviate",
+    embeddingModelName: "quentinz/bge-large-zh-v1.5",
+  };
   dialog.visible = true;
   dialog.title = "添加知识库";
 }
@@ -276,10 +413,15 @@ const handleAdd = () => {
 const handleUpdate = async (row?: KnowledgeInfoVO) => {
   reset();
   const _id = row?.id || ids.value[0]
-  const res = await getKnowledgeInfo(_id);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = "修改知识库";
+  try {
+    const res = await getKnowledgeInfo(_id);
+    Object.assign(form.value, res.data);
+    dialog.visible = true;
+    dialog.title = "修改知识库";
+  } catch (error) {
+    console.error('获取知识库详情失败:', error);
+    proxy?.$modal.msgError("获取知识库详情失败");
+  }
 }
 
 /** 提交按钮 */
@@ -287,25 +429,48 @@ const submitForm = () => {
   knowledgeInfoFormRef.value?.validate(async (valid: boolean) => {
     if (valid) {
       buttonLoading.value = true;
-      if (form.value.id) {
-        await updateKnowledgeInfo(form.value).finally(() =>  buttonLoading.value = false);
-      } else {
-        await addKnowledgeInfo(form.value).finally(() =>  buttonLoading.value = false);
+      try {
+        if (form.value.id) {
+          await updateKnowledgeInfo(form.value);
+        } else {
+          await addKnowledgeInfo(form.value);
+        }
+        proxy?.$modal.msgSuccess("操作成功");
+        dialog.visible = false;
+        await getList();
+      } catch (error) {
+        console.error('操作失败:', error);
+        proxy?.$modal.msgError("操作失败");
+      } finally {
+        buttonLoading.value = false;
       }
-      proxy?.$modal.msgSuccess("操作成功");
-      dialog.visible = false;
-      await getList();
     }
   });
 }
 
-/** 删除按钮操作 */
 const handleDelete = async (row?: KnowledgeInfoVO) => {
-  const _ids = row?.id || ids.value;
-  await proxy?.$modal.confirm('是否确认删除知识库编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
-  await delKnowledgeInfo(_ids);
-  proxy?.$modal.msgSuccess("删除成功");
-  await getList();
+  // 获取要删除的ID数组 - 使用主键id而不是knowledgeCode
+  const deleteIds = row ? [row.id] : ids.value;
+
+  // 确认删除提示
+  const message = row
+      ? `是否确认删除知识库名称为"${row.knowledgeName}"的数据项?`
+      : `是否确认删除选中的${deleteIds.length}项数据?`;
+
+  try {
+    await proxy?.$modal.confirm(message);
+
+    // 调用删除API,传递ID数组
+    await delKnowledgeInfo(deleteIds);
+
+    proxy?.$modal.msgSuccess("删除成功");
+    await getList();
+  } catch (error) {
+    if (error !== 'cancel') {
+      console.error('删除失败:', error);
+      proxy?.$modal.msgError("删除失败");
+    }
+  }
 }
 
 /** 导出按钮操作 */
@@ -315,7 +480,257 @@ const handleExport = () => {
   }, `knowledgeInfo_${new Date().getTime()}.xlsx`)
 }
 
+/** 查看附件 */
+const handleAttachment = async (row: KnowledgeInfoVO) => {
+  currentKnowledgeCode.value = row.knowledgeCode;
+  currentKnowledgeName.value = row.knowledgeName;
+  fileLoading.value = true;
+  try {
+    const res = await listKnowledgeAttach({ knowledgeCode: row.knowledgeCode });
+    fileData.value = res.rows;
+    fileVisible.value = true;
+  } catch (error) {
+    console.error('获取附件列表失败:', error);
+    proxy?.$modal.msgError("获取附件列表失败");
+  } finally {
+    fileLoading.value = false;
+  }
+}
+
+/** 删除附件 */
+const handleDeleteFile = async (row: KnowledgeAttachVO) => {
+  try {
+    await proxy?.$modal.confirm('是否确认删除文档"' + row.docName + '"?');
+    // 使用主键id而不是docCode
+    await delKnowledgeAttach(row.id);
+    proxy?.$modal.msgSuccess("删除成功");
+    // 刷新附件列表
+    await handleAttachment({ knowledgeCode: currentKnowledgeCode.value } as KnowledgeInfoVO);
+  } catch (error) {
+    console.error('删除失败:', error);
+    proxy?.$modal.msgError("删除失败");
+  }
+}
+/** 查看知识片段 */
+const handleFragment = async (row: KnowledgeAttachVO) => {
+  currentDocumentName.value = row.docName;
+  try {
+    const res = await listKnowledgeFragment({ docCode: row.docCode });
+    fragmentData.value = res.rows;
+    fragmentVisible.value = true;
+  } catch (error) {
+    console.error('获取知识片段失败:', error);
+    proxy?.$modal.msgError("获取知识片段失败");
+  }
+}
+
+/** 删除知识片段 */
+const handleDeleteFragment = async (row: KnowledgeFragmentVO) => {
+  try {
+    await proxy?.$modal.confirm('是否确认删除该知识片段?');
+    // 使用主键id而不是fragmentCode
+    await delKnowledgeFragment(row.id);
+    proxy?.$modal.msgSuccess("删除成功");
+    // 刷新片段列表
+    await handleFragment({ docCode: row.docCode } as KnowledgeAttachVO);
+  } catch (error) {
+    console.error('删除失败:', error);
+    proxy?.$modal.msgError("删除失败");
+  }
+}
+
+/** 文件上传成功处理 */
+const handleUploadSuccess = (response: any) => {
+  if (response.code === 200) {
+    proxy?.$modal.msgSuccess("上传成功");
+    // 刷新附件列表
+    if (fileVisible.value) {
+      handleAttachment({ knowledgeCode: currentKnowledgeCode.value } as KnowledgeInfoVO);
+    }
+  } else {
+    proxy?.$modal.msgError(response.msg || "上传失败");
+  }
+}
+
+/** 文件上传失败处理 */
+const handleUploadError = (error: any) => {
+  let errMsg = '上传失败';
+  if (error.response) {
+    const res = error.response;
+    errMsg = res.data.msg || `请求错误:${res.status} ${res.statusText}`;
+  } else if (error.message) {
+    errMsg = error.message;
+  }
+  proxy?.$modal.msgError(errMsg);
+}
+
+/** 文件上传前校验 */
+const beforeUpload = (file: File) => {
+  const allowedExtensions = ['.txt', '.pdf', '.docx', '.pptx', '.xlsx', '.xls', '.csv', '.json'];
+  const fileExtension = file.name.substring(file.name.lastIndexOf('.')).toLowerCase();
+
+  if (!allowedExtensions.includes(fileExtension)) {
+    proxy?.$modal.msgError('上传文件格式不支持! 仅支持以下格式:' + allowedExtensions.join(', '));
+    return false;
+  }
+
+  const isLt10M = file.size / 1024 / 1024 < 10;
+  if (!isLt10M) {
+    proxy?.$modal.msgError('上传文件大小不能超过 10MB!');
+    return false;
+  }
+
+  return true;
+}
+
+/** 获取状态标签类型 */
+const getStatusTagType = (status: number) => {
+  switch (status) {
+    case 10: return 'info';   // 未开始
+    case 20: return 'warning'; // 进行中
+    case 30: return 'success'; // 已完成
+    default: return 'info';
+  }
+}
+
+/** 获取状态文本 */
+const getStatusText = (status: number) => {
+  switch (status) {
+    case 10: return '未开始';
+    case 20: return '处理中';
+    case 30: return '已完成';
+    default: return '未知状态';
+  }
+}
+
+/** 格式化文件大小 */
+const formatFileSize = (bytes: number) => {
+  if (bytes === 0) return '0 Bytes';
+  const k = 1024;
+  const sizes = ['Bytes', 'KB', 'MB', 'GB'];
+  const i = Math.floor(Math.log(bytes) / Math.log(k));
+  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
+}
+
+/** 格式化日期时间 */
+const formatDateTime = (dateString: string) => {
+  if (!dateString) return '';
+  const date = new Date(dateString);
+  return date.toLocaleString();
+}
+
+//随机生成16位字符串
+function generateRandomString() {
+  // 可选字符集合
+  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+  let result = '';
+
+  // 生成16位随机字符
+  for (let i = 0; i < 10; i++) {
+    result += chars.charAt(Math.floor(Math.random() * chars.length));
+  }
+
+  return result;
+}
+
 onMounted(() => {
   getList();
 });
+
+
 </script>
+
+<style>
+/* 全局生效 */
+#app, body, html {
+  width: 100%;
+  height: auto !important;
+}
+
+/* 紧凑表格行间距 */
+.el-table.compact-table .el-table__body tr td {
+  padding-top: 12px !important;
+  padding-bottom: 12px !important;
+}
+
+/* 紧凑操作按钮间距 */
+.el-button--text {
+  margin-top: -2px !important;
+  margin-bottom: -2px !important;
+}
+
+/* 紧凑分页控件上下间距 */
+.flex.justify-center.mt-4 {
+  margin-top: 10px !important;
+}
+
+/* 紧凑表格行高 */
+.el-table__row {
+  line-height: 1.2 !important;
+}
+
+/* 按钮悬停效果 */
+.el-button--primary:hover {
+  background-color: transparent !important;
+  color: #006BE6 !important;
+  border-color: #006BE6 !important;
+}
+
+.el-button--danger:hover {
+  background-color: transparent !important;
+  color: #e74c3c !important;
+  border-color: #c0392b !important;
+}
+
+.el-button--success:hover {
+  background-color: transparent !important;
+  color: #9b59b6 !important;
+  border-color: #8e44ad !important;
+}
+
+/* 标题栏样式 */
+.text-xl.font-bold {
+  font-size: 18px;
+  font-weight: 600;
+  color: #333;
+}
+
+/* 表单卡片样式 */
+.bg-white.rounded {
+  border-radius: 4px;
+  box-shadow: 0 1px 2px 0 rgba(0,0,0,0.05);
+}
+
+/* 附件表格样式 */
+.attachment-table .el-table__row {
+  height: 60px;
+}
+
+/* 片段表格样式 */
+.fragment-table .el-table__row {
+  height: auto;
+}
+
+.fragment-content {
+  padding: 10px;
+  background-color: #f9f9f9;
+  border-radius: 4px;
+  white-space: pre-wrap;
+  line-height: 1.5;
+  font-size: 14px;
+  color: #333;
+}
+
+/* 状态标签样式 */
+.el-tag {
+  padding: 0 8px;
+  height: 24px;
+  line-height: 24px;
+  font-size: 12px;
+}
+
+/* 上传按钮样式 */
+.upload-button {
+  margin-left: 10px;
+}
+</style>

+ 423 - 72
src/views/system/project/index.vue

@@ -4,9 +4,6 @@
       <div v-show="showSearch" class="mb-[10px]">
         <el-card shadow="hover">
           <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="部门id" prop="deptId">
-              <el-input v-model="queryParams.deptId" placeholder="请输入部门id" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
             <el-form-item label="组织名称" prop="organization">
               <el-input v-model="queryParams.organization" placeholder="请输入组织名称" clearable @keyup.enter="handleQuery" />
             </el-form-item>
@@ -19,15 +16,6 @@
             <el-form-item label="公钥" prop="publicKey">
               <el-input v-model="queryParams.publicKey" placeholder="请输入公钥" clearable @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="模型仓库" prop="modelIds">
-              <el-input v-model="queryParams.modelIds" placeholder="请输入模型仓库" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="知识库仓库" prop="ragIds">
-              <el-input v-model="queryParams.ragIds" placeholder="请输入知识库仓库" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="智能体权限" prop="agentIds">
-              <el-input v-model="queryParams.agentIds" placeholder="请输入智能体权限" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
             <el-form-item>
               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
               <el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -58,56 +46,106 @@
 
       <el-table v-loading="loading" border :data="projectList" @selection-change="handleSelectionChange">
         <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="主键索引" align="center" prop="id" v-if="true" />
-        <el-table-column label="部门id" align="center" prop="deptId" />
         <el-table-column label="组织名称" align="center" prop="organization" />
         <el-table-column label="项目名称" align="center" prop="project" />
         <el-table-column label="私钥" align="center" prop="privateKey" />
         <el-table-column label="公钥" align="center" prop="publicKey" />
-        <el-table-column label="模型仓库" align="center" prop="modelIds" />
-        <el-table-column label="知识库仓库" align="center" prop="ragIds" />
-        <el-table-column label="智能体权限" align="center" prop="agentIds" />
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
           <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:project:edit']"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:project:remove']"></el-button>
-            </el-tooltip>
+            <div class="flex space-x-2">
+              <el-tooltip content="修改" placement="top">
+                <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:project:edit']"></el-button>
+              </el-tooltip>
+              <el-tooltip content="删除" placement="top">
+                <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:project:remove']"></el-button>
+              </el-tooltip>
+              <div class="flex items-center">
+                <button
+                    @click="handleButtonClick('model', scope.row)"
+                    class="text-green-500 hover:text-green-600 border border-transparent hover:border-green-600 hover:border-1 py-1 px-2 rounded-md text-xs"
+                >
+                  配置模型
+                </button>
+
+                <div class="mx-1 text-gray-400 h-full">|</div>
+                <button
+                    @click="handleButtonClick('knowledge', scope.row)"
+                    class="text-green-500 hover:text-green-600 border border-transparent hover:border-green-600 hover:border-1 py-1 px-2 rounded-md text-xs"
+                >
+                  配置知识库
+                </button>
+                <div class="mx-1 text-gray-400 h-full">|</div>
+                <button
+                    @click="handleButtonClick('agent', scope.row)"
+                    class="text-green-500 hover:text-green-600 border border-transparent hover:border-green-600 hover:border-1 py-1 px-2 rounded-md text-xs"
+                >
+                  配置智能体
+                </button>
+              </div>
+            </div>
           </template>
         </el-table-column>
       </el-table>
+      <el-dialog
+          v-model="showModelDialog"
+          title="配置模型"
+          width="800px"
+          append-to-body
+      >
+        <el-card shadow="never" v-loading="modelLoading">
+          <el-checkbox-group v-model="selectedModelIds">
+            <el-row :gutter="16">
+              <el-col
+                  :span="8"
+                  v-for="model in modelList"
+                  :key="model.id"
+                  class="mb-4"
+              >
+                <el-checkbox
+                    :label="model.id"
+                    class="w-full flex items-center"
+                >
+                  <div class="ml-2">
+                    <div class="font-medium">{{ model.modelName }}</div>
+                    <div class="text-xs text-gray-500">
+                      {{ model.company }} · {{ model.introduce }}
+                    </div>
+                  </div>
+                </el-checkbox>
+              </el-col>
+            </el-row>
+          </el-checkbox-group>
+
+          <div v-if="modelList.length === 0" class="text-center py-8 text-gray-500">
+            暂无可用模型
+          </div>
+        </el-card>
+
+        <template #footer>
+          <div class="dialog-footer">
+            <el-button @click="showModelDialog = false">取消</el-button>
+            <el-button type="primary" @click="submitModelConfig">确定</el-button>
+          </div>
+        </template>
+      </el-dialog>
 
       <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
     </el-card>
     <!-- 添加或修改项目对话框 -->
     <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
       <el-form ref="projectFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="部门id" prop="deptId">
-          <el-input v-model="form.deptId" placeholder="请输入部门id" />
-        </el-form-item>
         <el-form-item label="组织名称" prop="organization">
-            <el-input v-model="form.organization" type="textarea" placeholder="请输入内容" />
+          <el-input v-model="form.organization" type="textarea" placeholder="请输入内容" />
         </el-form-item>
         <el-form-item label="项目名称" prop="project">
-            <el-input v-model="form.project" type="textarea" placeholder="请输入内容" />
+          <el-input v-model="form.project" type="textarea" placeholder="请输入内容" />
         </el-form-item>
         <el-form-item label="私钥" prop="privateKey">
-            <el-input v-model="form.privateKey" type="textarea" placeholder="请输入内容" />
+          <el-input v-model="form.privateKey" type="textarea" placeholder="请输入内容" />
         </el-form-item>
         <el-form-item label="公钥" prop="publicKey">
           <el-input v-model="form.publicKey" placeholder="请输入公钥" />
         </el-form-item>
-        <el-form-item label="模型仓库" prop="modelIds">
-            <el-input v-model="form.modelIds" type="textarea" placeholder="请输入内容" />
-        </el-form-item>
-        <el-form-item label="知识库仓库" prop="ragIds">
-            <el-input v-model="form.ragIds" type="textarea" placeholder="请输入内容" />
-        </el-form-item>
-        <el-form-item label="智能体权限" prop="agentIds">
-            <el-input v-model="form.agentIds" type="textarea" placeholder="请输入内容" />
-        </el-form-item>
       </el-form>
       <template #footer>
         <div class="dialog-footer">
@@ -116,12 +154,99 @@
         </div>
       </template>
     </el-dialog>
+    <!-- 智能体配置对话框 -->
+    <el-dialog
+        v-model="showAgentDialog"
+        title="配置智能体"
+        width="800px"
+        append-to-body
+    >
+      <el-card shadow="never" v-loading="agentLoading">
+        <el-checkbox-group v-model="selectedAgentIds">
+          <el-row :gutter="16">
+            <el-col
+                :span="8"
+                v-for="agent in agentList"
+                :key="agent.id"
+                class="mb-4"
+            >
+              <el-checkbox
+                  :label="agent.id"
+                  class="w-full flex items-center"
+              >
+                <div class="ml-2">
+                  <div class="font-medium">{{ agent.name }}</div>
+                  <div class="text-xs text-gray-500">
+                    {{ agent.description }}
+                  </div>
+                </div>
+              </el-checkbox>
+            </el-col>
+          </el-row>
+        </el-checkbox-group>
+
+        <div v-if="agentList.length === 0" class="text-center py-8 text-gray-500">
+          暂无可用智能体
+        </div>
+      </el-card>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="showAgentDialog = false">取消</el-button>
+          <el-button type="primary" @click="submitAgentConfig">确定</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 知识库配置对话框 -->
+    <el-dialog
+        v-model="showKnowledgeDialog"
+        title="配置知识库"
+        width="800px"
+        append-to-body
+    >
+      <el-card shadow="never" v-loading="knowledgeLoading">
+        <el-checkbox-group v-model="selectedKnowledgeIds">
+          <el-row :gutter="16">
+            <el-col
+                :span="8"
+                v-for="knowledge in knowledgeList"
+                :key="knowledge.id"
+                class="mb-4"
+            >
+              <el-checkbox
+                  :label="knowledge.id"
+                  class="w-full flex items-center"
+              >
+                <div class="ml-2">
+                  <div class="font-medium">{{ knowledge.knowledgeName }}</div>
+                  <div class="text-xs text-gray-500">
+                    {{ knowledge.description }}
+                  </div>
+                </div>
+              </el-checkbox>
+            </el-col>
+          </el-row>
+        </el-checkbox-group>
+
+        <div v-if="knowledgeList.length === 0" class="text-center py-8 text-gray-500">
+          暂无可用知识库
+        </div>
+      </el-card>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="showKnowledgeDialog = false">取消</el-button>
+          <el-button type="primary" @click="submitKnowledgeConfig">确定</el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup name="Project" lang="ts">
-import { listProject, getProject, delProject, addProject, updateProject } from '@/api/system/project';
-import { ProjectVO, ProjectQuery, ProjectForm } from '@/api/system/project/types';
+import { listProject, getProject, delProject, addProject, updateProject, listModel, listAgent, listKnowledgeInfo } from '@/api/system/project';
+import { ProjectVO, ProjectQuery, ProjectForm, ModelVO, AgentVO, KnowledgeInfoVO } from '@/api/system/project/types';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 
@@ -137,7 +262,7 @@ const total = ref(0);
 const queryFormRef = ref<ElFormInstance>();
 const projectFormRef = ref<ElFormInstance>();
 
-const dialog = reactive<DialogOption>({
+const dialog = reactive({
   visible: false,
   title: ''
 });
@@ -149,11 +274,12 @@ const initFormData: ProjectForm = {
   project: undefined,
   privateKey: undefined,
   publicKey: undefined,
-  modelIds: undefined,
-  ragIds: undefined,
-  agentIds: undefined,
+  modelIds: [],
+  ragIds: [],
+  agentIds: [],
 }
-const data = reactive<PageData<ProjectForm, ProjectQuery>>({
+
+const data = reactive({
   form: {...initFormData},
   queryParams: {
     pageNum: 1,
@@ -166,28 +292,55 @@ const data = reactive<PageData<ProjectForm, ProjectQuery>>({
     modelIds: undefined,
     ragIds: undefined,
     agentIds: undefined,
-    params: {
-    }
+    params: {}
   },
   rules: {
-    ragIds: [
-      { required: true, message: "知识库仓库不能为空", trigger: "blur" }
+    organization: [
+      { required: true, message: "组织名称不能为空", trigger: "blur" }
     ],
-    agentIds: [
-      { required: true, message: "智能体权限不能为空", trigger: "blur" }
+    project: [
+      { required: true, message: "项目名称不能为空", trigger: "blur" }
     ],
   }
 });
 
 const { queryParams, form, rules } = toRefs(data);
 
+// 对话框状态
+const showAgentDialog = ref(false);
+const agentLoading = ref(false);
+const agentList = ref<AgentVO[]>([]);
+const selectedAgentIds = ref<(string | number)[]>([]);
+
+const showKnowledgeDialog = ref(false);
+const knowledgeLoading = ref(false);
+const knowledgeList = ref<KnowledgeInfoVO[]>([]);
+const selectedKnowledgeIds = ref<(string | number)[]>([]);
+
+const showModelDialog = ref(false);
+const modelLoading = ref(false);
+const modelList = ref<ModelVO[]>([]);
+const selectedModelIds = ref<(string | number)[]>([]);
+const currentProject = ref<ProjectVO | null>(null);
+
 /** 查询项目列表 */
 const getList = async () => {
   loading.value = true;
-  const res = await listProject(queryParams.value);
-  projectList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
+  try {
+    const res = await listProject(queryParams.value);
+    projectList.value = res.rows.map(item => ({
+      ...item,
+      modelIds: item.modelIds || [],
+      ragIds: item.ragIds || [],
+      agentIds: item.agentIds || []
+    }));
+    total.value = res.total;
+  } catch (error) {
+    console.error('获取项目列表失败:', error);
+    proxy?.$modal.msgError("获取项目列表失败");
+  } finally {
+    loading.value = false;
+  }
 }
 
 /** 取消按钮 */
@@ -231,11 +384,16 @@ const handleAdd = () => {
 /** 修改按钮操作 */
 const handleUpdate = async (row?: ProjectVO) => {
   reset();
-  const _id = row?.id || ids.value[0]
-  const res = await getProject(_id);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = "修改项目";
+  const _id = row?.id || ids.value[0];
+  try {
+    const res = await getProject(_id);
+    Object.assign(form.value, res.data);
+    dialog.visible = true;
+    dialog.title = "修改项目";
+  } catch (error) {
+    console.error('获取项目详情失败:', error);
+    proxy?.$modal.msgError("获取项目详情失败");
+  }
 }
 
 /** 提交按钮 */
@@ -243,14 +401,21 @@ const submitForm = () => {
   projectFormRef.value?.validate(async (valid: boolean) => {
     if (valid) {
       buttonLoading.value = true;
-      if (form.value.id) {
-        await updateProject(form.value).finally(() =>  buttonLoading.value = false);
-      } else {
-        await addProject(form.value).finally(() =>  buttonLoading.value = false);
+      try {
+        if (form.value.id) {
+          await updateProject(form.value);
+        } else {
+          await addProject(form.value);
+        }
+        proxy?.$modal.msgSuccess("操作成功");
+        dialog.visible = false;
+        await getList();
+      } catch (error) {
+        console.error('操作失败:', error);
+        proxy?.$modal.msgError("操作失败");
+      } finally {
+        buttonLoading.value = false;
       }
-      proxy?.$modal.msgSuccess("操作成功");
-      dialog.visible = false;
-      await getList();
     }
   });
 }
@@ -258,10 +423,14 @@ const submitForm = () => {
 /** 删除按钮操作 */
 const handleDelete = async (row?: ProjectVO) => {
   const _ids = row?.id || ids.value;
-  await proxy?.$modal.confirm('是否确认删除项目编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
-  await delProject(_ids);
-  proxy?.$modal.msgSuccess("删除成功");
-  await getList();
+  try {
+    await proxy?.$modal.confirm('是否确认删除项目编号为"' + _ids + '"的数据项?');
+    await delProject(_ids);
+    proxy?.$modal.msgSuccess("删除成功");
+    await getList();
+  } catch (error) {
+    console.error('删除失败:', error);
+  }
 }
 
 /** 导出按钮操作 */
@@ -271,7 +440,189 @@ const handleExport = () => {
   }, `project_${new Date().getTime()}.xlsx`)
 }
 
+const fetchModelList = async () => {
+  try {
+    modelLoading.value = true;
+    const res = await listModel({
+      pageNum: 1,
+      pageSize: 1000,
+      status: 0
+    });
+    modelList.value = res.rows;
+  } catch (error) {
+    console.error('获取模型列表失败:', error);
+    proxy?.$modal.msgError("获取模型列表失败");
+  } finally {
+    modelLoading.value = false;
+  }
+};
+
+const fetchAgentList = async () => {
+  try {
+    agentLoading.value = true;
+    const res = await listAgent({
+      pageNum: 1,
+      pageSize: 1000,
+    });
+    agentList.value = res.rows;
+  } catch (error) {
+    console.error('获取智能体列表失败:', error);
+    proxy?.$modal.msgError("获取智能体列表失败");
+  } finally {
+    agentLoading.value = false;
+  }
+};
+
+const fetchKnowledgeList = async () => {
+  try {
+    knowledgeLoading.value = true;
+    const res = await listKnowledgeInfo({
+      pageNum: 1,
+      pageSize: 1000,
+      share: 1
+    });
+    knowledgeList.value = res.rows;
+  } catch (error) {
+    console.error('获取知识库列表失败:', error);
+    proxy?.$modal.msgError("获取知识库列表失败");
+  } finally {
+    knowledgeLoading.value = false;
+  }
+};
+
+const openModelConfig = async (row: ProjectVO) => {
+  currentProject.value = row;
+  selectedModelIds.value = row.modelIds ? [...row.modelIds] : [];
+  await fetchModelList();
+  showModelDialog.value = true;
+};
+
+const openAgentConfig = async (row: ProjectVO) => {
+  console.log(currentProject.value);
+  currentProject.value = row;
+  selectedAgentIds.value = row.agentIds ? [...row.agentIds] : [];
+  await fetchAgentList();
+  showAgentDialog.value = true;
+};
+
+const openKnowledgeConfig = async (row: ProjectVO) => {
+  currentProject.value = row;
+  selectedKnowledgeIds.value = row.ragIds ? [...row.ragIds] : [];
+  await fetchKnowledgeList();
+  showKnowledgeDialog.value = true;
+};
+
+const submitModelConfig = async () => {
+  if (!currentProject.value) return;
+
+  try {
+    modelLoading.value = true;
+    const modelIdsArray = Array.isArray(selectedModelIds.value)
+        ? selectedModelIds.value
+        : [selectedModelIds.value];
+
+    // 先获取当前项目的完整数据
+    const currentProjectData = await getProject(currentProject.value.id);
+
+    // 只更新 modelIds,保留其他字段
+    const payload = {
+      ...currentProjectData.data, // 保留原有数据
+      modelIds: modelIdsArray,
+      model_ids: modelIdsArray // 如果需要兼容旧字段
+    };
+
+    await updateProject(payload);
+    proxy?.$modal.msgSuccess("模型配置成功");
+    showModelDialog.value = false;
+    await getList();
+  } catch (error) {
+    console.error('模型配置失败:', error);
+    proxy?.$modal.msgError("模型配置失败");
+  } finally {
+    modelLoading.value = false;
+  }
+};
+
+const submitAgentConfig = async () => {
+  if (!currentProject.value) return;
+
+  try {
+    agentLoading.value = true;
+    const agentIdsArray = Array.isArray(selectedAgentIds.value)
+        ? selectedAgentIds.value
+        : [selectedAgentIds.value];
+
+    // 先获取当前项目的完整数据
+    const currentProjectData = await getProject(currentProject.value.id);
+
+    // 只更新 agentIds,保留其他字段
+    const payload = {
+      ...currentProjectData.data, // 保留原有数据
+      agentIds: agentIdsArray,
+      agent_ids: agentIdsArray // 如果需要兼容旧字段
+    };
+
+    await updateProject(payload);
+    proxy?.$modal.msgSuccess("智能体配置成功");
+    showAgentDialog.value = false;
+    await getList();
+  } catch (error) {
+    console.error('智能体配置失败:', error);
+    proxy?.$modal.msgError("智能体配置失败");
+  } finally {
+    agentLoading.value = false;
+  }
+};
+
+const submitKnowledgeConfig = async () => {
+  if (!currentProject.value) return;
+
+  try {
+    knowledgeLoading.value = true;
+    const knowledgeIdsArray = Array.isArray(selectedKnowledgeIds.value)
+        ? selectedKnowledgeIds.value
+        : [selectedKnowledgeIds.value];
+
+    // 先获取当前项目的完整数据
+    const currentProjectData = await getProject(currentProject.value.id);
+
+    // 只更新 ragIds,保留其他字段
+    const payload = {
+      ...currentProjectData.data, // 保留原有数据
+      ragIds: knowledgeIdsArray,
+      rag_ids: knowledgeIdsArray // 如果需要兼容旧字段
+    };
+
+    await updateProject(payload);
+    proxy?.$modal.msgSuccess("知识库配置成功");
+    showKnowledgeDialog.value = false;
+    await getList();
+  } catch (error) {
+    console.error('知识库配置失败:', error);
+    proxy?.$modal.msgError("知识库配置失败");
+  } finally {
+    knowledgeLoading.value = false;
+  }
+};
+
+
+
+
+const handleButtonClick = (type: 'model' | 'knowledge' | 'agent', row: ProjectVO) => {
+  switch (type) {
+    case 'model':
+      openModelConfig(row);
+      break;
+    case 'knowledge':
+      openKnowledgeConfig(row);
+      break;
+    case 'agent':
+      openAgentConfig(row);
+      break;
+  }
+};
+
 onMounted(() => {
   getList();
 });
-</script>
+</script>