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: 4 additions & 0 deletions ui/src/api/API_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,10 @@ API 对象和工作空间上下文,作为该抽屉的范围选择例外。Syst
- 知识库 Workflow API 记录为 `/<id>/action/<page>/<size>`,筛选 user_name、state;
详情和取消为 GET action/<actionId>、POST action/<actionId>/cancel。
- 智能体复制查询完整 ApplicationDetail,model 映射 model_id 后创建,不使用卡片摘要。
- Workspace 与 System 资源管理的 Application API 提供 `putApplicationPortal(applicationId, isPortal)` 和
`exportApplicationSkills(applicationId, applicationName)` 的本地 mock;前者返回 `{ id, is_portal }`,
后者返回 `{ application_id, name }`,均不发送请求或持久化,也不生成 Skills 文件。真实接口待接入,
不通过智能体配置保存接口模拟上下架。

### 智能体概览

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ const exportApplication = (applicationId: string, applicationName: string) => {
return getExportFile(`${applicationName}.mk`, `${prefix}/${applicationId}/export`)
}

/** 模拟 System 资源管理智能体 Skills 导出;TODO:接入真实下载接口。 */
const exportApplicationSkills = (applicationId: string, applicationName: string) =>
Promise.resolve({ application_id: applicationId, name: applicationName })

/** 模拟 System 资源管理智能体门户上下架;TODO:接入真实接口,当前不持久化。 */
const putApplicationPortal = (applicationId: string, isPortal: boolean) => Promise.resolve({ id: applicationId, is_portal: isPortal })

/** 获取 System 资源管理智能体详情。 */
const getApplicationDetail = (applicationId: string) => get<ApplicationDetail>(`${prefix}/${applicationId}`)

Expand Down Expand Up @@ -53,4 +60,6 @@ export default {
getApplicationPage,
deleteApplication,
exportApplication,
exportApplicationSkills,
putApplicationPortal,
}
9 changes: 9 additions & 0 deletions ui/src/api/admin/workspace/application/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ const exportApplication = (applicationId: string, applicationName: string) => {
return getExportFile(`${applicationName}.mk`, `${getPrefix()}/${applicationId}/export`)
}

/** 模拟导出工作空间智能体为 Skills;TODO:接入真实下载接口。 */
const exportApplicationSkills = (applicationId: string, applicationName: string) =>
Promise.resolve({ application_id: applicationId, name: applicationName })

/** 模拟工作空间智能体门户上下架;TODO:接入真实接口,当前不持久化。 */
const putApplicationPortal = (applicationId: string, isPortal: boolean) => Promise.resolve({ id: applicationId, is_portal: isPortal })

/** 导入智能体文件并创建工作空间智能体。 */
const postApplicationImport = (file: File, folderId: string) => {
const payload = new FormData()
Expand Down Expand Up @@ -89,6 +96,8 @@ export default {
putAccessToken,
deleteApplication,
exportApplication,
exportApplicationSkills,
putApplicationPortal,
postApplication,
postApplicationImport,
putApplication,
Expand Down
2 changes: 1 addition & 1 deletion ui/src/assets/iconfont.js

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions ui/src/components/COMPONENT_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,15 +246,17 @@ Element Plus 的 `v-infinite-scroll`。组件通过 `v-model` 管理已经加载

### MkStatusLabel

提供 `success`、`failure`、`loading`、`disabled` 四种图标类型,通过 `type + label` 展示业务状态。
组件不依赖 API 状态枚举或业务文案;业务方维护状态与 `{ type, label }` 的映射。
提供 `success`、`failure`、`loading`、`disabled`、`custom` 五种图标类型,通过 `type + label` 展示业务状态。
组件不依赖 API 状态枚举或业务文案;业务方维护状态与 `{ type, label, icon? }` 的映射。
`StatusLabelType`、`StatusLabelOptions` 从 `global/mk-status-label/types.ts` 导入。
传入 `type` 时使用该类型和外部 `label`,优先于布尔模式,不回退到启用/禁用文案。

未传 `type` 时保留 `active` 便捷模式,默认“已启用 / 已禁用”;
`activeText`、`inactiveText` 可修改文案,`inactiveIcon` 可覆盖未激活图标(默认 `icon_ban_filled`)。
成功图标固定为 `icon_succeed_colorful`,失败图标为 `icon_close_colorful`,加载类型使用 `LoadingIcon`,
禁用图标使用灰色样式。`inactiveIcon` 仅影响布尔模式。
`activeText`、`inactiveText` 可修改文案。
`icon` 接收完整 SVG Symbol ID,在两种模式下均优先替换图标,包括加载图标;不改变状态文案及禁用状态的灰色样式。
未传 `icon` 时,成功使用 `icon_succeed_colorful`,失败使用 `icon_close_colorful`,加载使用 `LoadingIcon`,
禁用使用 `icon_ban_filled`。仅替换未激活图标时,由调用方按 `active` 条件传入 `icon`。
`type="custom"` 使用外部 `label` 与 `icon`,不附加状态颜色,保留图标自带颜色或继承文字颜色;未传 `icon` 时仅显示文案。
接口使用 type/label,未知业务状态由调用方显示原始文案,不伪装成成功或禁用状态。

### MkTable
Expand Down
12 changes: 7 additions & 5 deletions ui/src/components/global/mk-status-label/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,26 @@ const props = withDefaults(
active?: boolean
activeText?: string
inactiveText?: string
inactiveIcon?: string
icon?: string
}>(),
{ activeText: '已启用', inactiveText: '已禁用', inactiveIcon: 'icon_ban_filled' },
{ activeText: '已启用', inactiveText: '已禁用' },
)

const displayType = computed(() => props.type ?? (props.active ? 'success' : 'disabled'))
const displayLabel = computed(() => (props.type !== undefined ? props.label : props.active ? props.activeText : props.inactiveText))
const iconName = computed(() => {
if (props.icon) return props.icon
if (displayType.value === 'custom') return undefined
if (displayType.value === 'success') return 'icon_succeed_colorful'
if (displayType.value === 'failure') return 'icon_close_colorful'
return props.type === undefined ? props.inactiveIcon : 'icon_ban_filled'
return 'icon_ban_filled'
})
</script>

<template>
<span class="flex-align-center gap-2">
<LoadingIcon v-if="displayType === 'loading'" :size="16" />
<MkIcon v-else :name="iconName" :class="{ 'text-N500!': displayType === 'disabled' }" />
<LoadingIcon v-if="displayType === 'loading' && !icon" :size="16" />
<MkIcon v-else-if="iconName" :name="iconName" :class="{ 'text-N500!': displayType === 'disabled' }" />
<span>{{ displayLabel }}</span>
</span>
</template>
3 changes: 2 additions & 1 deletion ui/src/components/global/mk-status-label/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export type StatusLabelType = 'success' | 'failure' | 'loading' | 'disabled'
export type StatusLabelType = 'success' | 'failure' | 'loading' | 'disabled' | 'custom'

export interface StatusLabelOptions {
type: StatusLabelType
label: string
icon?: string
}
2 changes: 1 addition & 1 deletion ui/src/layout/AppLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const mode = computed<LayoutMode>(() => route.meta.scope ?? 'workspace')
<LayoutHeader :mode="preview ? 'workspace' : mode" :preview="preview" />
<div class="flex">
<aside v-if="preview" class="h-layout-content w-sidebar"></aside>
<LayoutSidebar v-else-if="!route.meta.hideSidebar" :mode="mode" />
<LayoutSidebar v-else :mode="mode" />
<main class="mk-layout__main h-layout-content w-full overflow-hidden rounded-tl-xl bg-white transition-[margin] duration-200">
<RouterView v-if="!preview" />
</main>
Expand Down
19 changes: 13 additions & 6 deletions ui/src/layout/LayoutSidebar.vue
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
<script setup lang="ts">
import { ref, watch } from 'vue'
import { computed, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import SystemSidebar from './sidebar/SystemSidebar.vue'
import WorkspaceSidebar from './sidebar/WorkspaceSidebar.vue'
import { isSystem, isWorkspace } from './utils'
import type { LayoutMode } from './types'
import { useIsSmallScreen } from '@/utils/use-responsive'

defineProps<{ mode: LayoutMode }>()
const props = defineProps<{ mode: LayoutMode }>()

const route = useRoute()
const isSmallScreen = useIsSmallScreen()
const isSystemDetail = computed(() => isSystem(props.mode) && route.meta.resourceDetailRoot === true)
const collapsed = ref(false)

// 系统详情默认收起,离开详情恢复普通页面状态;小屏继续默认收起。
watch(
isSmallScreen,
(smallScreen) => {
collapsed.value = smallScreen
[isSmallScreen, isSystemDetail],
([smallScreen, systemDetail]) => {
collapsed.value = smallScreen || systemDetail
},
{ immediate: true },
)
</script>

<template>
<aside class="h-layout-content shrink-0 overflow-hidden transition-[width] duration-200" :class="isSystem(mode) && !collapsed ? 'w-sidebar-expanded' : 'w-sidebar'">
<aside
class="h-layout-content shrink-0 overflow-hidden transition-[width] duration-200"
:class="isSystem(mode) && !collapsed ? 'w-sidebar-expanded' : 'w-sidebar'"
>
<WorkspaceSidebar v-if="isWorkspace(mode)" />
<SystemSidebar v-if="isSystem(mode)" :collapsed="collapsed" @toggle="collapsed = !collapsed" />
</aside>
Expand Down
9 changes: 5 additions & 4 deletions ui/src/router/ROUTE_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ Workspace 根地址为 `/admin/workspace/:workspaceId`。`workspaceId` 只以当
### System

System 使用 `AppLayout`,左侧导航根据 `scope: 'system'` 对应路由的 `children` 自动生成。
系统侧栏在进入资源详情页(`resourceDetailRoot`)时默认收起,其他页面默认展开;小屏默认收起。
列表和详情页均保留系统侧栏,并支持手动切换;详情子页之间切换保留当前展开状态。

System 根地址为 `/admin/system`,默认进入首页 `/admin/system/home`。需要复用 Workspace 详情页面时使用独立路由名保留访问来源。System 知识库详情在 `system/index.ts` 的 children 注册,
继承 System 的 AppLayout,在主区展示详情目录和内容区。
Expand Down Expand Up @@ -144,7 +146,6 @@ Chat 导航守卫(`chat/index.ts`):
| `icon` | `string` | iconfont Symbol ID,子目录通常可以不配置 |
| `order` | `number` | 同级导航排序,数字越小越靠前 |
| `hidden` | `boolean` | 设置为 `true` 时不显示在导航中 |
| `hideSidebar` | `boolean` | 隐藏 AppLayout 应用侧栏,保留顶部栏和页面自身导航;子页继承 |
| `detailMenuVisible` | `(params) => boolean` | 按业务类型过滤详情菜单,不用于权限 |
| `canAccess` | `(params) => boolean` | 工作流返回详情时的访问判断 |
| `resource` | `ResourceAuthorizationType` | 系统资源授权页面当前管理的后端资源类型 |
Expand Down Expand Up @@ -233,8 +234,8 @@ Drawer、Dialog 通常不根据 path、路由名称或 Scope 自行维护 API
创建、卡片、设置及返回详情均传 knowledgeId 和字符串类型。全屏工作流不含 type,路径在各来源
知识库 ID 后追加 `/workflow`。System 地址不携带 workspaceId,shared 使用统一前缀,不保留 share 别名。

详情父页配置 hidden、resourceDetailRoot;System 另加 hideSidebar,在 AppLayout 内隐藏系统侧栏,
保留头部和详情目录。hidden 仅影响导航,不替代 hideSidebar;普通列表恢复系统侧栏。
详情父页配置 hidden、resourceDetailRoot;hidden 仅影响导航菜单,详情页仍保留 AppLayout 的
应用侧栏、头部和详情目录。
Workspace 共享覆盖 resourceScope,保留 Workspace scope 及知识库 activeMenu。

| 菜单 | 路径与条件 |
Expand All @@ -259,7 +260,7 @@ Workspace 详情父路由为 workspace-application-detail-layout,详情参数
System 资源管理详情为 `/system/resource/application/:applicationId/:type`,父路由名为
`system-resource-application-detail-layout`,默认进入 `system-resource-application-overview`。
配置集中在 `admin/system/modules/application-system-resource.ts`,由 System 路由汇总接入。
两种范围独立维护 children,复用 `application-detail` 页面;System 隐藏系统侧栏,不携带 workspaceId,
两种范围独立维护 children,复用 `application-detail` 页面;System 保留系统侧栏,不携带 workspaceId,
不提供 Workspace 共享或 System 共享的智能体详情。System 列表点击名称进入详情。
菜单为概览、设置、发布渠道、对话用户、对话日志;SIMPLE 的 setting 与高级 workflow-entry 互斥显示。
发布渠道使用 access 路径、workspace-application-access 路由名,对应 application-detail/access 页面。
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const systemResourceApplicationRoutes: RouteRecordRaw[] = [
name: 'system-resource-application-detail',
component: () => import('@/views/application-detail/index.vue'),
redirect: { name: 'system-resource-application-overview' },
meta: { title: '智能体详情', hidden: true, hideSidebar: true, resourceDetailRoot: true, scope: 'system', resourceScope: 'system-resource' },
meta: { title: '智能体详情', hidden: true, resourceDetailRoot: true, scope: 'system', resourceScope: 'system-resource' },
children: [
{
path: 'overview',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const systemResourceKnowledgeRoutes: RouteRecordRaw[] = [
name: 'system-resource-knowledge-detail',
component: () => import('@/views/knowledge-detail/index.vue'),
redirect: { name: 'system-resource-knowledge-document-list' },
meta: { title: '知识库详情', hidden: true, hideSidebar: true, resourceDetailRoot: true, scope: 'system', resourceScope: 'system-resource' },
meta: { title: '知识库详情', hidden: true, resourceDetailRoot: true, scope: 'system', resourceScope: 'system-resource' },
children: [
{
path: '',
Expand Down Expand Up @@ -149,6 +149,6 @@ export const systemResourceKnowledgeRoutes: RouteRecordRaw[] = [
path: '/system/resource/knowledge/:knowledgeId/:type/document/:documentId',
name: 'system-resource-knowledge-paragraph',
component: () => import('@/views/document-detail/index.vue'),
meta: { resourceScope: 'system-resource', scope: 'system', hideSidebar: true, title: '文档分段', hidden: true, resourceDetailRoot: true },
meta: { resourceScope: 'system-resource', scope: 'system', title: '文档分段', hidden: true, resourceDetailRoot: true },
},
]
4 changes: 2 additions & 2 deletions ui/src/router/admin/system/modules/knowledge-system-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const systemSharedKnowledgeRoutes: RouteRecordRaw[] = [
name: 'system-shared-knowledge-detail',
component: () => import('@/views/knowledge-detail/index.vue'),
redirect: { name: 'system-shared-knowledge-document-list' },
meta: { title: '共享知识库详情', hidden: true, hideSidebar: true, resourceDetailRoot: true, scope: 'system', resourceScope: 'system-shared' },
meta: { title: '共享知识库详情', hidden: true, resourceDetailRoot: true, scope: 'system', resourceScope: 'system-shared' },
children: [
{
path: '',
Expand Down Expand Up @@ -149,6 +149,6 @@ export const systemSharedKnowledgeRoutes: RouteRecordRaw[] = [
path: '/system/shared/knowledge/:knowledgeId/:type/document/:documentId',
name: 'system-shared-knowledge-paragraph',
component: () => import('@/views/document-detail/index.vue'),
meta: { resourceScope: 'system-shared', scope: 'system', hideSidebar: true, title: '文档分段', hidden: true, resourceDetailRoot: true },
meta: { resourceScope: 'system-shared', scope: 'system', title: '文档分段', hidden: true, resourceDetailRoot: true },
},
]
2 changes: 0 additions & 2 deletions ui/src/router/admin/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ declare module 'vue-router' {
icon?: string
order?: number
hidden?: boolean
/** 隐藏 AppLayout 的应用侧栏,保留顶部栏和页面自身导航。 */
hideSidebar?: boolean
/** 系统资源授权页面当前管理的资源类型。 */
resource?: ResourceAuthorizationType
/** 详情返回导航的可访问性判断,由业务路由配置。 */
Expand Down
10 changes: 7 additions & 3 deletions ui/src/views/VIEW_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@
- 工具表单按类型放在 `tool-form/`,共用参数及 Python 设置放在 `tool-form/component/`。
创建和编辑复用同一表单,不把不同类型字段合并成通用表单。
- `ToolCard` 点击工作流进入画布,其他类型调用编辑 Action 的同一表单实例;编辑、启停成功局部更新。
- 智能体的 Workspace 卡片与 System 资源列表复用门户上下架和导出 Action;门户入口按 `is_portal`
显示“上架到门户/从门户下架”,当前通过 mock 接口更新列表局部状态,刷新后恢复服务端状态。
导出使用二级菜单,包含“导出为 Skills”和“导出智能体”;Skills 当前调用 mock 接口并明确提示
尚未生成文件,智能体沿用现有文件导出。
商店列表由页面加载,卡片和版本更新按钮不重复查询。
- 工具头像由 `MkEditAvatar` 暂存文件,校验后先上传再保存;上传成功后清理暂存文件,避免保存失败后重复上传。
- Python 生成入口由 `CodeGenerate` 选择 Tool/Model API,复用 `GenerateContent`;全屏替换只修改草稿,确认后回写。
Expand Down Expand Up @@ -329,13 +333,13 @@ View 负责路由、资源与模式、图加载、保存/发布/调试编排
失败不伪装成零。快捷创建复用资源入口,`fitTriggerWidth` 仅显式开启时测量触发器。
- `HomeStatistics` 接收完整的 Workspace Homepage、System Homepage 或 Overview API。
智能体概览通过 `hideHeader: true` 隐藏详情布局标题栏,保留内容内的监控与排行标题。
基本信息由概览本地 `components/ApplicationBasicInfo.vue` 组织 Web 访问与后端 API 访问卡片;
基本信息直接在概览页 `application-detail/overview/index.vue` 中组织 Web 访问与后端 API 访问卡片;
Web 链接通过当前范围的 Application API 查询访问凭证,沿用 V2 的工作流 API 参数默认值与编码方式;
API 文档地址为 Chat 部署前缀下的 `/api-doc/`。两个地址使用只读输入框展示并支持复制;链接重置先确认,
成功后用返回的访问凭证更新链接,保留工作流参数,失败保留原链接。Web 访问开关查询后回填 `is_active`,
保存成功后按响应回显、失败保留原状态;开关保存与链接重置互斥,保存期间禁用开关、不显示 loading,链接重置保留按钮 loading。后端 API 访问开关仍待接入。
五个按钮流程分别放在 `chat/`、`embed-third-party/`、`access-restriction/`、`display-setting/`、
`api-key/`,入口和对应弹窗同目录维护。API Key 弹窗通过 `resourceApi.apiKey` 传入当前范围的完整 API 与智能体 ID,
“去对话”按钮直接在概览页维护;其余四个按钮流程分别放在 `embed-third-party/`、`access-restriction/`、
`display-setting/`、`api-key/`,入口和对应弹窗同目录维护。API Key 弹窗通过 `resourceApi.apiKey` 传入当前范围的完整 API 与智能体 ID,
复用 `business/api-key-list/`,Base URL 使用 Chat API 部署前缀加智能体 ID;
Workspace 与 System 资源管理共用智能体弹窗,分别使用各自接口,不回退或使用头像菜单的全局系统 API Key。
嵌入第三方弹窗接收概览已有的 Web 链接与访问凭证,不额外请求接口;按全屏、浮窗、移动端单选切换并复制代码,
Expand Down
13 changes: 0 additions & 13 deletions ui/src/views/application-detail/overview/chat/ButtonChat.vue

This file was deleted.

Loading
Loading