From a7ce7040261ff599c579823cc9f7e4346a11e37f Mon Sep 17 00:00:00 2001 From: wangdan-fit2cloud Date: Thu, 22 Oct 2026 11:20:42 +0800 Subject: [PATCH] fix: overview --- ui/src/api/API_README.md | 5 + .../application/application.ts | 4 + .../workspace/application/application.ts | 4 + ui/src/api/types/application.ts | 27 +- ui/src/views/VIEW_README.md | 15 +- .../display-setting/DisplaySettingDialog.vue | 341 +++++++++++++++++- .../application-detail/overview/index.vue | 65 ++-- .../resource-management/application/index.vue | 14 +- .../resource-management/knowledge/index.vue | 6 +- 9 files changed, 425 insertions(+), 56 deletions(-) diff --git a/ui/src/api/API_README.md b/ui/src/api/API_README.md index f0075551ad2..28119a94ad4 100644 --- a/ui/src/api/API_README.md +++ b/ui/src/api/API_README.md @@ -379,6 +379,11 @@ Workspace 与 System 资源管理的 `application/application.ts` 提供 `getAcc 两范围的 `putAccessToken` 向同一路径提交 `{ access_token_reset: true }` 重置链接,或 `{ is_active: boolean }` 修改 Web 访问状态; 载荷复用 `ApplicationAccessTokenPayload`,使用返回的访问凭证与启用状态回显,不二次查询。 +展示设置共用 `ApplicationDisplaySetting`;`ApplicationAccessToken` 兼容可选展示字段,缺失字段由弹窗补齐默认值。 +两范围的 `putDisplaySetting` 沿用 V2 的 `//setting` PUT 接口,提交 FormData: +`custom_theme`、`float_location` 序列化为 JSON,图片字段提交本次文件,`_url` 保留已有地址; +恢复默认时图片文件与地址均提交空字符串。当前社区版后端未提供该路由,完整保存依赖支持此接口的部署。 + API Key 按三个入口分别维护: - `admin/workspace/application/api-key.ts`:`/workspace//application//application_key`。 diff --git a/ui/src/api/admin/system/resource-management/application/application.ts b/ui/src/api/admin/system/resource-management/application/application.ts index df45a84ec1b..9febd2ebc94 100644 --- a/ui/src/api/admin/system/resource-management/application/application.ts +++ b/ui/src/api/admin/system/resource-management/application/application.ts @@ -39,6 +39,9 @@ const getAccessToken = (applicationId: string) => get(`$ const putAccessToken = (applicationId: string, payload: ApplicationAccessTokenPayload) => put(`${prefix}/${applicationId}/access_token`, payload) +/** 保存智能体展示设置,沿用 V2 图片与配置的 multipart 协议。 */ +const putDisplaySetting = (applicationId: string, payload: FormData) => put(`${prefix}/${applicationId}/setting`, payload) + /** 保存 System 资源管理智能体配置。 */ const putApplication = (applicationId: string, data: ApplicationFormPayload) => put(`${prefix}/${applicationId}`, data) @@ -54,6 +57,7 @@ export default { getApplicationDetail, getAccessToken, putAccessToken, + putDisplaySetting, putApplication, putApplicationPublish, getAllApplication, diff --git a/ui/src/api/admin/workspace/application/application.ts b/ui/src/api/admin/workspace/application/application.ts index ced90312b9c..0ff7057e732 100644 --- a/ui/src/api/admin/workspace/application/application.ts +++ b/ui/src/api/admin/workspace/application/application.ts @@ -32,6 +32,9 @@ const getAccessToken = (applicationId: string) => get(`$ const putAccessToken = (applicationId: string, payload: ApplicationAccessTokenPayload) => put(`${getPrefix()}/${applicationId}/access_token`, payload) +/** 保存智能体展示设置,沿用 V2 图片与配置的 multipart 协议。 */ +const putDisplaySetting = (applicationId: string, payload: FormData) => put(`${getPrefix()}/${applicationId}/setting`, payload) + /** 删除工作空间智能体。 */ const deleteApplication = (applicationId: string) => { return del(`${getPrefix()}/${applicationId}`) @@ -94,6 +97,7 @@ export default { getApplicationDetail, getAccessToken, putAccessToken, + putDisplaySetting, deleteApplication, exportApplication, exportApplicationSkills, diff --git a/ui/src/api/types/application.ts b/ui/src/api/types/application.ts index 0fb6740f9fc..3c1956971a4 100644 --- a/ui/src/api/types/application.ts +++ b/ui/src/api/types/application.ts @@ -24,8 +24,33 @@ export interface ApplicationAccessStatusPayload { status: boolean } +/** 智能体展示设置;图片响应为 URL,保存时通过 FormData 分别提交文件及原 URL。 */ +export interface ApplicationDisplaySetting { + show_source: boolean + show_exec: boolean + language: string + show_history: boolean + draggable: boolean + show_guide: boolean + show_share: boolean + icon: string + chat_background: string + avatar: string + float_icon: string + user_avatar: string + disclaimer: boolean + disclaimer_value: string + custom_theme: { theme_color: string; header_font_color: string } + float_location: { + x: { type: 'left' | 'right'; value: number } + y: { type: 'top' | 'bottom'; value: number } + } + show_avatar: boolean + show_user_avatar: boolean +} + /** 智能体公开访问链接使用的凭证。 */ -export interface ApplicationAccessToken { +export interface ApplicationAccessToken extends Partial { application_id: string access_token: string is_active: boolean diff --git a/ui/src/views/VIEW_README.md b/ui/src/views/VIEW_README.md index 49111b215ec..d4bd2b4eb71 100644 --- a/ui/src/views/VIEW_README.md +++ b/ui/src/views/VIEW_README.md @@ -334,18 +334,21 @@ View 负责路由、资源与模式、图加载、保存/发布/调试编排 - `HomeStatistics` 接收完整的 Workspace Homepage、System Homepage 或 Overview API。 智能体概览通过 `hideHeader: true` 隐藏详情布局标题栏,保留内容内的监控与排行标题。 基本信息直接在概览页 `application-detail/overview/index.vue` 中组织 Web 访问与后端 API 访问卡片; - Web 链接通过当前范围的 Application API 查询访问凭证,沿用 V2 的工作流 API 参数默认值与编码方式; + Web 链接通过当前范围的 Application API 查询访问凭证,使用当前域名、Chat 部署前缀与访问凭证生成,不追加工作流输入参数; API 文档地址为 Chat 部署前缀下的 `/api-doc/`。两个地址使用只读输入框展示并支持复制;链接重置先确认, - 成功后用返回的访问凭证更新链接,保留工作流参数,失败保留原链接。Web 访问开关查询后回填 `is_active`, - 保存成功后按响应回显、失败保留原状态;开关保存与链接重置互斥,保存期间禁用开关、不显示 loading,链接重置保留按钮 loading。后端 API 访问开关仍待接入。 + 成功后用返回的访问凭证更新链接,失败保留原链接。Web 访问开关查询后回填 `is_active`, + 保存成功后按响应回显、失败保留原状态;开关保存与链接重置共用 loading,操作期间禁用开关,重置按钮显示 loading。后端 API 访问开关仍待接入。 “去对话”按钮直接在概览页维护;其余四个按钮流程分别放在 `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 链接与访问凭证,不额外请求接口;按全屏、浮窗、移动端单选切换并复制代码, - 关闭后恢复全屏模式。iframe 沿用 Web 链接及工作流参数,移动端增加 `mode=mobile`;浮窗使用 Chat API 前缀下的 - `/embed`,携带协议、主机、访问凭证及工作流参数,生成 HTML 时转义属性值。无访问凭证时禁用入口。 - 其他访问配置及弹窗业务尚待接入,不模拟保存。 + 关闭后恢复全屏模式。iframe 沿用 Web 链接,移动端增加 `mode=mobile`;浮窗使用 Chat API 前缀下的 + `/embed`,携带协议、主机和访问凭证,生成 HTML 时转义属性值。无访问凭证时禁用入口。 + 显示设置每次打开通过当前范围的 Application API 查询访问配置,支持主题色、语言、五类图片、 + 头像与对话展示开关、浮窗位置及免责声明,本地草稿实时预览。恢复默认仅改草稿,保存成功关闭, + 失败保留输入;图片限 JPG/PNG/GIF、10 MB,替换、恢复默认、关闭及卸载时释放临时 URL。 + 展示配置保存协议及后端支持情况见 API 文档。访问限制弹窗业务尚待接入,不模拟保存。 三类场景统一调用 `getMonitoring(workspaceId, range, applicationId)`;全部智能体使用空 ID, 两类首页不提交智能体筛选,概览传当前智能体 ID。页面直接传入完整 API,不包装接口。 排行由概览本地 `components/ApplicationRanking.vue` 调用 Overview API,展示用户 Tokens 消耗与提问次数两类 TOP5。 diff --git a/ui/src/views/application-detail/overview/display-setting/DisplaySettingDialog.vue b/ui/src/views/application-detail/overview/display-setting/DisplaySettingDialog.vue index ebba5375a11..d42eaf77689 100644 --- a/ui/src/views/application-detail/overview/display-setting/DisplaySettingDialog.vue +++ b/ui/src/views/application-detail/overview/display-setting/DisplaySettingDialog.vue @@ -1,20 +1,353 @@ diff --git a/ui/src/views/application-detail/overview/index.vue b/ui/src/views/application-detail/overview/index.vue index b6756984d66..e6a7ee006d3 100644 --- a/ui/src/views/application-detail/overview/index.vue +++ b/ui/src/views/application-detail/overview/index.vue @@ -4,7 +4,6 @@ import { useRoute } from 'vue-router' import { CHAT_API_BASE_PATH } from '@/api/constants' import { copyText } from '@/utils/clipboard' import { MsgConfirm, MsgSuccess } from '@/utils/message' -import type { ApiInputField } from '@/workflow-canvas/nodes/base-node/types' import { useApplicationDetailContext } from '../context' import type { ResourceDetailPageProps } from '@/layout/ResourceDetailLayout.vue' import HomeStatistics from '@/views/home/components/HomeStatistics.vue' @@ -25,30 +24,19 @@ const { application, applicationId, resourceApi } = useApplicationDetailContext( /* 基本信息:Web 访问链接与开关 */ const accessToken = ref('') -const webAccessActive = ref() -const savingWebAccess = ref(false) -const resettingAccessToken = ref(false) +const webAccessActive = ref(false) +const loading = ref(false) + const chatBasePath = CHAT_API_BASE_PATH.replace(/\/api$/, '') + const apiDocUrl = new URL(`${CHAT_API_BASE_PATH}-doc/`, window.location.origin).href -const shareUrl = computed(() => { - if (!accessToken.value) return '' - const url = new URL(`${chatBasePath}/${accessToken.value}`, window.location.origin) - const baseProperties = application.value?.work_flow?.nodes?.find((node) => node.id === 'base-node')?.properties as - | { api_input_field_list?: ApiInputField[]; input_field_list?: ApiInputField[] } - | undefined - const inputFields = - baseProperties?.api_input_field_list ?? baseProperties?.input_field_list?.filter((field) => field.assignment_method === 'api_input') ?? [] - // 沿用 V2 访问链接的参数编码方式,兼容旧版工作流输入配置。 - inputFields.forEach((field) => { - url.searchParams.append(encodeURIComponent(field.variable), encodeURIComponent(field.default_value ?? '')) - }) - return url.href -}) +// TODO:分享链接还有问题 +const shareUrl = computed(() => (accessToken.value ? `${window.location.origin}${chatBasePath}/${accessToken.value}` : '')) function handleChangeWebAccess() { - if (webAccessActive.value === undefined || savingWebAccess.value || resettingAccessToken.value) return false - savingWebAccess.value = true + if (loading.value) return false + loading.value = true return resourceApi.application .putAccessToken(applicationId.value, { is_active: !webAccessActive.value }) .then((config) => { @@ -58,19 +46,19 @@ function handleChangeWebAccess() { return true }) .finally(() => { - savingWebAccess.value = false + loading.value = false }) } function handleResetAccessToken() { - if (!accessToken.value || resettingAccessToken.value || savingWebAccess.value) return + if (!accessToken.value || loading.value) return return MsgConfirm('是否重新生成公开访问链接?', '重新生成后旧链接将失效,嵌入第三方的脚本也需要更新,请谨慎操作!', { confirmButtonText: '确认', confirmButtonType: 'primary', }).then( () => { - if (resettingAccessToken.value || savingWebAccess.value) return - resettingAccessToken.value = true + if (loading.value) return + loading.value = true return resourceApi.application .putAccessToken(applicationId.value, { access_token_reset: true }) .then((config) => { @@ -79,7 +67,7 @@ function handleResetAccessToken() { MsgSuccess('刷新成功') }) .finally(() => { - resettingAccessToken.value = false + loading.value = false }) }, () => undefined, @@ -110,27 +98,22 @@ onMounted(() => {
Web 访问
- +
链接
- +
@@ -142,23 +125,21 @@ onMounted(() => { - +
后端 API 访问
- - - - + +
API 文档
diff --git a/ui/src/views/system/resource-management/application/index.vue b/ui/src/views/system/resource-management/application/index.vue index 7afbf1dda50..12d6ff07ea8 100644 --- a/ui/src/views/system/resource-management/application/index.vue +++ b/ui/src/views/system/resource-management/application/index.vue @@ -159,9 +159,19 @@ onMounted(() => {