Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ui/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,9 @@ Structural responsibilities:
internally to avoid circular access through the aggregate entry.
- Put functions shared by most pages or multiple business modules in `utils/`; detailed placement, file organization, and naming rules are maintained in `src/utils/UTILS_README.md`.
- Treat application, knowledge, model, and tool as the four special resource domains that can span
Workspace, System resource management, and System shared resources. Their route scope, API
Workspace resources, Workspace shared resources, System resource management, and System shared resources. Their route scope, API
selection, reusable cards, and context-specific Actions follow `ROUTE_README.md`,
`API_README.md`, and `VIEW_README.md`; do not extend this three-scope pattern to ordinary pages.
`API_README.md`, and `VIEW_README.md`; do not extend this resource-scope pattern to ordinary pages.
- Import source assets through `src/assets/`; use `public/` only when a file must retain its original filename and URL.

## Entry Points
Expand Down
34 changes: 31 additions & 3 deletions ui/src/api/API_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ src/api/
│ │ ├── conversation.ts # 调试对话、历史会话与语音接口
│ │ ├── application/ # 智能体接口
│ │ ├── knowledge/ # 知识库接口
│ │ ├── shared/ # 工作空间可用的共享模型、工具、知识库查询
│ │ ├── model.ts # 模型接口
│ │ ├── trigger/ # 触发器查询及维护接口
│ │ ├── tool/ # 工具、工具工作流及工具商店接口
Expand Down Expand Up @@ -101,7 +102,7 @@ FormData;保存返回完整配置,页面以该返回值作为唯一数据来
多套 API 时,以 `request` 为前缀加业务名区分,例如 `requestModelApi`、`requestToolApi`。
直接导入的 API 保持 PascalCase 命名;请求返回的 Promise 不属于此命名规则。

`application`、`knowledge`、`model`、`tool` 是需要同时考虑 Workspace、System 资源管理和
`application`、`knowledge`、`model`、`tool` 是需要同时考虑 Workspace 普通资源、Workspace 共享资源、System 资源管理和
System 共享资源的四类特殊资源。其接口按真实后端边界分别维护在 `admin/workspace/` 与
`admin/system/` 下,不把不同范围的 URL 合并为页面侧 API Map,也不让卡片或 Action 根据路由拼接
System 接口地址。
Expand Down Expand Up @@ -153,7 +154,7 @@ v3 编辑表单提交 `{ name, description }`,标题上限 64、更新说明
`workspace/tool/tool.ts` 的 `getAllTool(query)` 查询支持 `folder_id` 筛选的工作空间工具
非分页列表,用于文件夹菜单和工具选择弹窗。`getToolListWithShared(query)` 请求 `tool/tool_list`,
将响应的 `tools` 与 `shared_tools` 合并为 `ToolItem[]`,用于包含已授权共享工具的选项查询;
按工具类型筛选时使用 `tool_type`。`workspace/shared.ts` 的 `getAllTool(query)` 仅查询共享工具。
按工具类型筛选时使用 `tool_type`。`workspace/shared/tool.ts` 的 `getAllTool(query)` 仅查询共享工具。

### System 共享工具

Expand Down Expand Up @@ -200,7 +201,7 @@ MCP 入口加载配置后打开只读及复制弹窗;分词索引入口仅调
`/workspace/<workspaceId>/knowledge/import_knowledge`,响应为 `{ knowledge_id, type }`。
后端校验知识库导出包并创建资源;导入成功后的用户权限和列表刷新由调用页面负责。

`workspace/knowledge/knowledge.ts` 与 `workspace/shared.ts` 的 `getAllKnowledge(query)`
`workspace/knowledge/knowledge.ts` 与 `workspace/shared/knowledge/knowledge.ts` 的 `getAllKnowledge(query)`
分别查询工作空间及共享知识库的非分页列表,返回 `KnowledgeItem[]`,用于关联知识库选择等
需要全量选项的场景。原有 `getKnowledgePage` 继续用于分页列表。

Expand Down Expand Up @@ -492,3 +493,30 @@ System 接口由资源管理服务提供;本地开源后端没有对应扩展
版本和执行记录,前缀为 `/system/shared/tool`,调用只传资源 ID,不读取工作空间。
两种 System 工具 API 的 `getToolListWithShared` 查询各自 `/tool_list` 并合并 `tools`、`shared_tools`,
供画布的工具菜单及 MCP 选项使用。系统扩展接口需连接支持相应协议的部署进行联调。

### 知识库文档

`workspace/knowledge/document.ts` 仅维护文档分页查询,路径为
`/workspace/<workspaceId>/knowledge/<knowledgeId>/document/<currentPage>/<pageSize>`。
分页使用 `ParamsPage` / `ResponsePage<DocumentItem>`,支持 `name`、`create_user` 筛选;
文档页传 `resource_type: 'document'`,创建者选项复用 Workspace `common.ts` 的 `getAllUsers`。
类型从 `@/api/types` 导入,命中处理枚举从 `@/api/enums` 导入。API 不接收 loading,不重复包装响应。

### 工作空间共享资源查询

`workspace/shared/` 按最终资源文件拆分:`model.ts` 提供 `getModelList`,`tool.ts` 提供
`getToolPage`、`getAllTool`,`knowledge/knowledge.ts` 提供 `getKnowledgePage`、`getAllKnowledge`、`getKnowledgeDetail`。
上述资源查询沿用 `/system/shared/workspace/<workspaceId>/<resource>`,工作空间 ID 在调用时读取。
调用方直接导入对应资源文件,与普通工作空间 API 同时使用时分别命名为
`SharedModelApi`、`SharedToolApi`、`SharedKnowledgeApi`;目录不提供聚合入口。

`workspace/shared/knowledge/document.ts` 提供 `getDocumentPage(knowledgeId, page, query)`,
请求 `/system/shared/workspace/<workspaceId>/knowledge/<knowledgeId>/document/<currentPage>/<pageSize>`。
共享与普通知识库文档查询统一使用 `ParamsPage`、`ResponsePage<DocumentItem>` 和 `Dict<unknown>`,
不传 loading,不保留 v2 的 `Result` 或下划线分页参数。两个文件各自默认导出 API 对象。

共享知识库 `getKnowledgeDetail(knowledgeId)` 请求知识库资源 `/<knowledgeId>`,返回 `KnowledgeDetail`。

Workspace 共享知识库详情由 `resourceScope: 'workspace-shared'` 选择上述完整共享 API 对象;
普通详情继续使用 `workspace/knowledge/`。共享详情和文档查询不使用 System 共享资源管理 API,
也不回退到普通 Workspace 知识库接口。文档创建者选项沿用共享列表的 System `common.ts` 查询。
12 changes: 12 additions & 0 deletions ui/src/api/admin/workspace/knowledge/document.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { get } from '../../core/request'
import type { ParamsPage, ResponsePage } from '../../core/types'
import type { Dict, DocumentItem } from '@/api/types'
import { getWorkspaceId } from '@/utils/resource-context'

const getPrefix = (knowledgeId: string) => `/workspace/${getWorkspaceId()}/knowledge/${knowledgeId}/document`

/** 获取文档分页列表,支持名称和创建者筛选。 */
const getDocumentPage = (knowledgeId: string, page: ParamsPage, query?: Dict<unknown>) =>
get<ResponsePage<DocumentItem>>(`${getPrefix(knowledgeId)}/${page.currentPage}/${page.pageSize}`, query)

export default { getDocumentPage }
35 changes: 0 additions & 35 deletions ui/src/api/admin/workspace/shared.ts

This file was deleted.

12 changes: 12 additions & 0 deletions ui/src/api/admin/workspace/shared/knowledge/document.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { get } from '../../../core/request'
import type { ParamsPage, ResponsePage } from '../../../core/types'
import type { Dict, DocumentItem } from '@/api/types'
import { getWorkspaceId } from '@/utils/resource-context'

const getPrefix = (knowledgeId: string) => `/system/shared/workspace/${getWorkspaceId()}/knowledge/${knowledgeId}/document`

/** 获取工作空间共享知识库的文档分页列表。 */
const getDocumentPage = (knowledgeId: string, page: ParamsPage, query?: Dict<unknown>) =>
get<ResponsePage<DocumentItem>>(`${getPrefix(knowledgeId)}/${page.currentPage}/${page.pageSize}`, query)

export default { getDocumentPage }
18 changes: 18 additions & 0 deletions ui/src/api/admin/workspace/shared/knowledge/knowledge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { get } from '../../../core/request'
import type { ParamsPage, ResponsePage } from '../../../core/types'
import type { Dict, KnowledgeDetail, KnowledgeItem } from '@/api/types'
import { getWorkspaceId } from '@/utils/resource-context'

const getPrefix = () => `/system/shared/workspace/${getWorkspaceId()}/knowledge`

/** 获取工作空间共享的知识库分页列表。 */
const getKnowledgePage = (page: ParamsPage, query?: Dict<unknown>) =>
get<ResponsePage<KnowledgeItem>>(`${getPrefix()}/${page.currentPage}/${page.pageSize}`, query)

/** 获取工作空间共享的不分页知识库列表。 */
const getAllKnowledge = (query?: Dict<unknown>) => get<KnowledgeItem[]>(getPrefix(), query)

/** 获取工作空间共享的知识库详情。 */
const getKnowledgeDetail = (knowledgeId: string) => get<KnowledgeDetail>(`${getPrefix()}/${knowledgeId}`)

export default { getKnowledgePage, getAllKnowledge, getKnowledgeDetail }
12 changes: 12 additions & 0 deletions ui/src/api/admin/workspace/shared/model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { get } from '../../core/request'
import type { Dict, ModelItem } from '@/api/types'
import { getWorkspaceId } from '@/utils/resource-context'

const getPrefix = () => `/system/shared/workspace/${getWorkspaceId()}/model`

/** 获取工作空间共享的模型列表。 */
const getModelList = (query?: Dict<unknown>) => {
return get<ModelItem[]>(getPrefix(), query)
}

export default { getModelList }
18 changes: 18 additions & 0 deletions ui/src/api/admin/workspace/shared/tool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { get } from '../../core/request'
import type { ParamsPage, ResponsePage } from '../../core/types'
import type { Dict, ToolItem } from '@/api/types'
import { getWorkspaceId } from '@/utils/resource-context'

const getPrefix = () => `/system/shared/workspace/${getWorkspaceId()}/tool`

/** 获取工作空间共享的分页工具列表。 */
const getToolPage = (page: ParamsPage, query?: Dict<unknown>) => {
return get<ResponsePage<ToolItem>>(`${getPrefix()}/${page.currentPage}/${page.pageSize}`, query)
}

/** 获取工作空间共享的不分页工具列表。 */
const getAllTool = (query?: Dict<unknown>) => {
return get<ToolItem[]>(getPrefix(), query)
}

export default { getToolPage, getAllTool }
2 changes: 2 additions & 0 deletions ui/src/api/enums/document.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/** 文档命中处理方式。 */
export const DOCUMENT_HIT_HANDLING = { OPTIMIZATION: 'optimization', DIRECTLY_RETURN: 'directly_return' } as const
2 changes: 2 additions & 0 deletions ui/src/api/enums/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ export * from './knowledge'
export * from './trigger'
export * from './file'
export * from './state'

export * from './document'
23 changes: 23 additions & 0 deletions ui/src/api/types/document.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { DOCUMENT_HIT_HANDLING } from '@/api/enums'
import type { KnowledgeType } from './knowledge'
export type DocumentHitHandling = (typeof DOCUMENT_HIT_HANDLING)[keyof typeof DOCUMENT_HIT_HANDLING]
/** 文档分页列表数据。 */
export interface DocumentItem {
id: string
knowledge_id: string
name: string
type: KnowledgeType
is_active: boolean
status: string
status_meta?: Record<string, unknown>
paragraph_count: number
char_length: number
hit_num: number
hit_handling_method: DocumentHitHandling
directly_return_similarity: number
tags?: { id: string; key: string; value: string }[]
meta?: Record<string, unknown>
nick_name?: string | null
create_time: string
update_time: string
}
2 changes: 2 additions & 0 deletions ui/src/api/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ export type * from './homepage'
export type * from './file'
export type * from './state'
export type * from './portal'

export type * from './document'
2 changes: 1 addition & 1 deletion ui/src/assets/iconfont.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions ui/src/components/business/select-knowledge-dialog/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { computed, nextTick, ref, useTemplateRef } from 'vue'
import { cloneDeep } from 'lodash'
import KnowledgeApi from '@/api/admin/workspace/knowledge/knowledge'
import SharedApi from '@/api/admin/workspace/shared'
import SharedKnowledgeApi from '@/api/admin/workspace/shared/knowledge/knowledge'
import type { FolderItem, KnowledgeItem } from '@/api/types'
import { RESOURCE_TYPE } from '@/api/enums'
import { FOLDER_ENTRIES, FOLDER_ENTRY_ID } from '@/constants/folder'
Expand Down Expand Up @@ -44,7 +44,7 @@ function refreshKnowledge() {
knowledgeOptions.value = []
appliedSearchKeyword.value = searchKeyword.value.trim()
const shared = currentFolder.value.id === FOLDER_ENTRY_ID.SHARED
const requestApi = shared ? SharedApi : KnowledgeApi
const requestApi = shared ? SharedKnowledgeApi : KnowledgeApi
return requestApi
.getAllKnowledge({
...(shared ? {} : { folder_id: currentFolder.value.id }),
Expand Down
4 changes: 2 additions & 2 deletions ui/src/components/business/select-tool-dialog/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { computed, nextTick, ref, useTemplateRef } from 'vue'
import { cloneDeep } from 'lodash'
import ToolApi from '@/api/admin/workspace/tool/tool'
import SharedApi from '@/api/admin/workspace/shared'
import SharedToolApi from '@/api/admin/workspace/shared/tool'
import type { FolderItem, ToolItem, ToolType } from '@/api/types'
import { RESOURCE_TYPE, TOOL_TYPE } from '@/api/enums'
import { FOLDER_ENTRIES, FOLDER_ENTRY_ID } from '@/constants/folder'
Expand Down Expand Up @@ -42,7 +42,7 @@ function refreshTool() {
toolOptions.value = []
appliedSearchKeyword.value = searchKeyword.value.trim()
const shared = currentFolder.value.id === FOLDER_ENTRY_ID.SHARED
const requestApi = shared ? SharedApi : ToolApi
const requestApi = shared ? SharedToolApi : ToolApi
return requestApi
.getAllTool({
tool_type_list: props.toolTypes,
Expand Down
22 changes: 19 additions & 3 deletions ui/src/layout/ResourceDetailLayout.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
<script lang="ts">
/** 资源详情布局直接传给当前子页面的标题栏属性。 */
export interface ResourceDetailPageProps {
headerTarget: HTMLElement | null
title: string
}
</script>

<script setup lang="ts">
import { computed } from 'vue'
import { computed, shallowRef } from 'vue'
import { RouterView, useRoute, useRouter } from 'vue-router'
import { getMatchedChildRouteList } from '@/router/admin/utils'
import type { LayoutMenuItem } from './types'
Expand All @@ -18,6 +26,11 @@ const router = useRouter()
const detailMenuItems = computed(() => getMatchedChildRouteList(route))
const activeDetailMenuName = computed(() => route.meta.detailActiveMenu ?? String(route.name ?? ''))

/* 提供整个标题栏的挂载位置和当前路由标题。 */
const headerTarget = shallowRef<HTMLElement | null>(null)
const title = computed(() => route.meta.title ?? '')
const detailPageRef = shallowRef<{ customHeader?: boolean } | null>(null)

function navigateBack() {
emit('back')
}
Expand Down Expand Up @@ -47,9 +60,12 @@ function navigateToDetailMenu(detailMenuItem: LayoutMenuItem) {

<template #default="{ Header }">
<component :is="Header">
<h4>{{ route.meta.title }}</h4>
<div v-show="detailPageRef?.customHeader" ref="headerTarget" class="w-full min-w-0" />
<h4 v-if="!detailPageRef?.customHeader">{{ title }}</h4>
</component>
<RouterView />
<RouterView v-slot="{ Component }">
<component :is="Component" ref="detailPageRef" :header-target="headerTarget" :title="title" />
</RouterView>
</template>
</MkViewLayout>
</template>
Loading
Loading