From 595975d31436d56d2c9348896d2ddefec61bf21d Mon Sep 17 00:00:00 2001 From: "xinxin.wu" Date: Wed, 21 Oct 2026 15:11:03 +0800 Subject: [PATCH] feat: api key --- ui/src/api/API_README.md | 19 ++ ui/src/api/admin/system/api-key.ts | 26 +++ .../application/api-key.ts | 27 +++ .../application/application.ts | 11 +- .../admin/workspace/application/api-key.ts | 28 +++ .../workspace/application/application.ts | 11 +- ui/src/api/types/api-key.ts | 22 ++ ui/src/api/types/application.ts | 13 ++ ui/src/api/types/index.ts | 1 + ui/src/components/COMPONENT_README.md | 14 ++ .../api-key-list/EditApiKeyDrawer.vue | 181 +++++++++++++++ .../business/api-key-list/expiration.ts | 38 ++++ .../business/api-key-list/index.vue | 206 ++++++++++++++++++ .../layout/avatar-dropdown/ApiKeyDialog.vue | 37 ++++ ui/src/layout/avatar-dropdown/index.vue | 14 +- ui/src/views/VIEW_README.md | 15 +- ui/src/views/application-detail/context.ts | 8 + .../AccessRestrictionDialog.vue | 20 ++ .../ButtonAccessRestriction.vue | 21 ++ .../overview/api-key/ApiKeyDialog.vue | 39 ++++ .../overview/api-key/ButtonApiKey.vue | 23 ++ .../overview/chat/ButtonChat.vue | 13 ++ .../components/ApplicationBasicInfo.vue | 157 +++++++++++++ .../display-setting/ButtonDisplaySetting.vue | 21 ++ .../display-setting/DisplaySettingDialog.vue | 20 ++ .../ButtonEmbedThirdParty.vue | 21 ++ .../EmbedThirdPartyDialog.vue | 20 ++ .../application-detail/overview/index.vue | 2 + .../resource-management/application/index.vue | 4 +- 29 files changed, 1025 insertions(+), 7 deletions(-) create mode 100644 ui/src/api/admin/system/api-key.ts create mode 100644 ui/src/api/admin/system/resource-management/application/api-key.ts create mode 100644 ui/src/api/admin/workspace/application/api-key.ts create mode 100644 ui/src/api/types/api-key.ts create mode 100644 ui/src/components/business/api-key-list/EditApiKeyDrawer.vue create mode 100644 ui/src/components/business/api-key-list/expiration.ts create mode 100644 ui/src/components/business/api-key-list/index.vue create mode 100644 ui/src/layout/avatar-dropdown/ApiKeyDialog.vue create mode 100644 ui/src/views/application-detail/overview/access-restriction/AccessRestrictionDialog.vue create mode 100644 ui/src/views/application-detail/overview/access-restriction/ButtonAccessRestriction.vue create mode 100644 ui/src/views/application-detail/overview/api-key/ApiKeyDialog.vue create mode 100644 ui/src/views/application-detail/overview/api-key/ButtonApiKey.vue create mode 100644 ui/src/views/application-detail/overview/chat/ButtonChat.vue create mode 100644 ui/src/views/application-detail/overview/components/ApplicationBasicInfo.vue create mode 100644 ui/src/views/application-detail/overview/display-setting/ButtonDisplaySetting.vue create mode 100644 ui/src/views/application-detail/overview/display-setting/DisplaySettingDialog.vue create mode 100644 ui/src/views/application-detail/overview/embed-third-party/ButtonEmbedThirdParty.vue create mode 100644 ui/src/views/application-detail/overview/embed-third-party/EmbedThirdPartyDialog.vue diff --git a/ui/src/api/API_README.md b/ui/src/api/API_README.md index fd40b9a8663..91a5ce879d0 100644 --- a/ui/src/api/API_README.md +++ b/ui/src/api/API_README.md @@ -369,6 +369,25 @@ API 对象和工作空间上下文,作为该抽屉的范围选择例外。Syst ### 智能体概览 +Workspace 与 System 资源管理的 `application/application.ts` 提供 `getAccessToken(applicationId)`, +沿用 V2 的 `//access_token` GET 接口,返回公开访问凭证 `ApplicationAccessToken`。 +概览使用 `access_token` 拼接 Web 链接,不使用智能体 ID 或 API Key 替代;API 文档地址使用 Chat 部署前缀。 +两范围的 `putAccessToken` 向同一路径提交 `{ access_token_reset: true }` 重置链接,或 `{ is_active: boolean }` 修改 Web 访问状态; +载荷复用 `ApplicationAccessTokenPayload`,使用返回的访问凭证与启用状态回显,不二次查询。 + +API Key 按三个入口分别维护: + +- `admin/workspace/application/api-key.ts`:`/workspace//application//application_key`。 +- `admin/system/resource-management/application/api-key.ts`:`/system/resource/application//application_key`。 +- `admin/system/api-key.ts`:`/system/api_key`,仅用于头像菜单。 + +三套均提供 `getApiKeyPage`、`postApiKey`、`putApiKey`、`deleteApiKey`; +两套智能体方法以 `applicationId` 为首参,仅 Workspace 接口在内部读取工作空间 ID;头像菜单接口不接收资源 ID。 +分页使用 `ParamsPage` 和 `ResponsePage`;创建 POST 空对象,由后端生成密钥; +修改只提交需要更新的配置,启停仅提交 `is_active`。Workspace 智能体删除返回空数据,其他两套沿用 V2 布尔类型;调用方不依赖返回值判断成功。 +共用业务类型在 `types/api-key.ts`,`remark` 字段待后端补充返回与持久化; +两套系统接口沿用 V2 路径,仍需对应部署联调;头像菜单密钥与系统资源管理智能体密钥不能互相替代。 + `admin/workspace/application/overview.ts` 独立维护概览接口,沿用 v2 的应用统计协议,在 `/workspace//application/` 下提供三个 GET 接口,均传入 `start_time`、`end_time`,由调用方管理 loading: diff --git a/ui/src/api/admin/system/api-key.ts b/ui/src/api/admin/system/api-key.ts new file mode 100644 index 00000000000..6987fbe128d --- /dev/null +++ b/ui/src/api/admin/system/api-key.ts @@ -0,0 +1,26 @@ +/** 系统 API Key 接口。TODO:联调 /system/api_key 及 remark 字段。 */ +import { del, get, post, put } from '../core/request' +import type { ParamsPage, ResponsePage } from '../core/types' +import type { ApiKeyPayload, ApiKeyRecord, Dict } from '@/api/types' + +const prefix = '/system/api_key' + +/** 分页查询系统 API Key。 */ +const getApiKeyPage = (page: ParamsPage, query?: Dict) => + get>(`${prefix}/${page.currentPage}/${page.pageSize}`, query) + +/** 生成系统 API Key。 */ +const postApiKey = () => post, ApiKeyRecord>(prefix, {}) + +/** 修改系统 API Key 配置或启用状态。 */ +const putApiKey = (apiKeyId: string, payload: ApiKeyPayload) => put(`${prefix}/${apiKeyId}`, payload) + +/** 删除系统 API Key。 */ +const deleteApiKey = (apiKeyId: string) => del(`${prefix}/${apiKeyId}`) + +export default { + getApiKeyPage, + postApiKey, + putApiKey, + deleteApiKey, +} diff --git a/ui/src/api/admin/system/resource-management/application/api-key.ts b/ui/src/api/admin/system/resource-management/application/api-key.ts new file mode 100644 index 00000000000..e17f91b1371 --- /dev/null +++ b/ui/src/api/admin/system/resource-management/application/api-key.ts @@ -0,0 +1,27 @@ +/** System 资源管理智能体 API Key 接口。TODO:接口待联调。 */ +import { del, get, post, put } from '@/api/admin/core/request' +import type { ParamsPage, ResponsePage } from '@/api/admin/core/types' +import type { ApiKeyPayload, ApiKeyRecord, Dict } from '@/api/types' + +const getPrefix = (applicationId: string) => `/system/resource/application/${applicationId}/application_key` + +/** 分页查询智能体 API Key。 */ +const getApiKeyPage = (applicationId: string, page: ParamsPage, query?: Dict) => + get>(`${getPrefix(applicationId)}/${page.currentPage}/${page.pageSize}`, query) + +/** 生成智能体 API Key。 */ +const postApiKey = (applicationId: string) => post, ApiKeyRecord>(getPrefix(applicationId), {}) + +/** 修改智能体 API Key 配置或启用状态。 */ +const putApiKey = (applicationId: string, apiKeyId: string, payload: ApiKeyPayload) => + put(`${getPrefix(applicationId)}/${apiKeyId}`, payload) + +/** 删除智能体 API Key。 */ +const deleteApiKey = (applicationId: string, apiKeyId: string) => del(`${getPrefix(applicationId)}/${apiKeyId}`) + +export default { + getApiKeyPage, + postApiKey, + putApiKey, + deleteApiKey, +} 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 87b2a062909..8b9d87e3565 100644 --- a/ui/src/api/admin/system/resource-management/application/application.ts +++ b/ui/src/api/admin/system/resource-management/application/application.ts @@ -1,6 +1,6 @@ import { del, get, getExportFile, put } from '@/api/admin/core/request' import type { ParamsPage, ResponsePage } from '@/api/admin/core/types' -import type { ApplicationDetail, ApplicationFormPayload, Dict } from '@/api/types' +import type { ApplicationAccessToken, ApplicationAccessTokenPayload, ApplicationDetail, ApplicationFormPayload, Dict } from '@/api/types' const prefix = '/system/resource/application' @@ -25,6 +25,13 @@ const exportApplication = (applicationId: string, applicationName: string) => { /** 获取 System 资源管理智能体详情。 */ const getApplicationDetail = (applicationId: string) => get(`${prefix}/${applicationId}`) +/** 获取 System 资源管理智能体公开访问凭证。 */ +const getAccessToken = (applicationId: string) => get(`${prefix}/${applicationId}/access_token`) + +/** 修改 System 资源管理智能体公开访问状态或重置凭证,返回更新后的配置。 */ +const putAccessToken = (applicationId: string, payload: ApplicationAccessTokenPayload) => + put(`${prefix}/${applicationId}/access_token`, payload) + /** 保存 System 资源管理智能体配置。 */ const putApplication = (applicationId: string, data: ApplicationFormPayload) => put(`${prefix}/${applicationId}`, data) @@ -38,6 +45,8 @@ const putApplicationPublish = (applicationId: string, publishName: string, publi export default { getApplicationDetail, + getAccessToken, + putAccessToken, putApplication, putApplicationPublish, getAllApplication, diff --git a/ui/src/api/admin/workspace/application/api-key.ts b/ui/src/api/admin/workspace/application/api-key.ts new file mode 100644 index 00000000000..3e5423e6e1d --- /dev/null +++ b/ui/src/api/admin/workspace/application/api-key.ts @@ -0,0 +1,28 @@ +/** 工作空间智能体 API Key 接口。 */ +import { del, get, post, put } from '../../core/request' +import type { ParamsPage, ResponsePage } from '../../core/types' +import type { ApiKeyPayload, ApiKeyRecord, Dict } from '@/api/types' +import { getWorkspaceId } from '@/utils/resource-context' + +const getPrefix = (applicationId: string) => `/workspace/${getWorkspaceId()}/application/${applicationId}/application_key` + +/** 分页查询智能体 API Key。 */ +const getApiKeyPage = (applicationId: string, page: ParamsPage, query?: Dict) => + get>(`${getPrefix(applicationId)}/${page.currentPage}/${page.pageSize}`, query) + +/** 生成智能体 API Key。 */ +const postApiKey = (applicationId: string) => post, ApiKeyRecord>(getPrefix(applicationId), {}) + +/** 修改智能体 API Key 配置或启用状态。 */ +const putApiKey = (applicationId: string, apiKeyId: string, payload: ApiKeyPayload) => + put(`${getPrefix(applicationId)}/${apiKeyId}`, payload) + +/** 删除智能体 API Key。 */ +const deleteApiKey = (applicationId: string, apiKeyId: string) => del(`${getPrefix(applicationId)}/${apiKeyId}`) + +export default { + getApiKeyPage, + postApiKey, + putApiKey, + deleteApiKey, +} diff --git a/ui/src/api/admin/workspace/application/application.ts b/ui/src/api/admin/workspace/application/application.ts index 96f77f8b988..7f08ca5b16c 100644 --- a/ui/src/api/admin/workspace/application/application.ts +++ b/ui/src/api/admin/workspace/application/application.ts @@ -1,6 +1,6 @@ import { del, get, getExportFile, post, put } from '../../core/request' import type { ParamsPage, ResponsePage } from '../../core/types' -import type { ApplicationDetail, ApplicationFormPayload, Dict } from '@/api/types' +import type { ApplicationAccessToken, ApplicationAccessTokenPayload, ApplicationDetail, ApplicationFormPayload, Dict } from '@/api/types' import { getWorkspaceId } from '@/utils/resource-context' const getPrefix = () => { @@ -25,6 +25,13 @@ const getApplicationDetail = (applicationId: string) => { return get(`${getPrefix()}/${applicationId}`) } +/** 获取智能体公开访问凭证。 */ +const getAccessToken = (applicationId: string) => get(`${getPrefix()}/${applicationId}/access_token`) + +/** 修改智能体公开访问状态或重置凭证,返回更新后的配置。 */ +const putAccessToken = (applicationId: string, payload: ApplicationAccessTokenPayload) => + put(`${getPrefix()}/${applicationId}/access_token`, payload) + /** 删除工作空间智能体。 */ const deleteApplication = (applicationId: string) => { return del(`${getPrefix()}/${applicationId}`) @@ -78,6 +85,8 @@ const putApplicationPublish = (applicationId: string, publishName: string, publi export default { getApplicationPage, getApplicationDetail, + getAccessToken, + putAccessToken, deleteApplication, exportApplication, postApplication, diff --git a/ui/src/api/types/api-key.ts b/ui/src/api/types/api-key.ts new file mode 100644 index 00000000000..abd04259332 --- /dev/null +++ b/ui/src/api/types/api-key.ts @@ -0,0 +1,22 @@ +/** 智能体与系统 API Key 共用的记录和修改参数。 */ +export interface ApiKeyRecord { + id: string + secret_key: string + is_active: boolean + allow_cross_domain: boolean + cross_domain_list: string[] + is_permanent: boolean + expire_time: string | null + create_time?: string + // TODO:后端补充 remark 的返回与持久化。 + remark?: string | null +} + +export interface ApiKeyPayload { + is_active?: boolean + allow_cross_domain?: boolean + cross_domain_list?: string[] + is_permanent?: boolean + expire_time?: string | null + remark?: string +} diff --git a/ui/src/api/types/application.ts b/ui/src/api/types/application.ts index bbbb04e2f9c..0fb6740f9fc 100644 --- a/ui/src/api/types/application.ts +++ b/ui/src/api/types/application.ts @@ -24,6 +24,19 @@ export interface ApplicationAccessStatusPayload { status: boolean } +/** 智能体公开访问链接使用的凭证。 */ +export interface ApplicationAccessToken { + application_id: string + access_token: string + is_active: boolean +} + +/** 智能体公开访问状态修改或令牌重置参数。 */ +export interface ApplicationAccessTokenPayload { + is_active?: boolean + access_token_reset?: boolean +} + export interface ApplicationDetail extends Omit { /** 详情接口返回的主模型 ID。 */ model?: string | null diff --git a/ui/src/api/types/index.ts b/ui/src/api/types/index.ts index 2ad046801b5..01dffb04a9d 100644 --- a/ui/src/api/types/index.ts +++ b/ui/src/api/types/index.ts @@ -1,5 +1,6 @@ /** API 与 View 或 Component 跨层业务类型的唯一公共入口。 */ export type * from './application' +export type * from './api-key' export type * from './common' export type * from './chat-user' export type * from './chat-auth' diff --git a/ui/src/components/COMPONENT_README.md b/ui/src/components/COMPONENT_README.md index 38ce7251589..a8d80c41af1 100644 --- a/ui/src/components/COMPONENT_README.md +++ b/ui/src/components/COMPONENT_README.md @@ -697,6 +697,20 @@ Model 配置器的默认模型也使用 `SelectModel`,仅展示已选的可选 业务组件显式导入,可调用固定业务 API;页面保留自身的列表查询、路由和保存编排。 +### ApiKeyList + +手动导入 `business/api-key-list/index.vue`,接收完整的 `api` 对象。Workspace 与 System 资源管理的智能体 API +必须同时传入 `applicationId`;头像菜单的 System API 不传该参数。API 入参类型直接在各使用组件内声明。 +组件不读取路由或自行选择接口,智能体概览通过详情上下文的 `resourceApi.apiKey` 传入对应 API。 +在弹窗内容中挂载,首次挂载查询,关闭后由外层弹窗销毁,下次打开重新加载。 +列表默认每页 20 条,不提供排序、列宽拖拽或批量操作;创建直接生成密钥,删除前确认, +启停成功后刷新,失败保留原状态。查询与列表操作共用 loading,编辑抽屉单独管理保存状态。 +密钥默认隐藏,翻页或刷新恢复隐藏,复制始终使用完整值,隐藏状态不通过 Tooltip 暴露明文。 + +`EditApiKeyDrawer` 是本功能内部抽屉,按永不过期、预设有效期或自定义日期编辑,预设有效期 +从保存时起算;跨域地址逐行去空白后提交数组。保存失败保留草稿,成功刷新列表。 +备注按 `remark` 预留,当前后端尚未持久化。Base URL 或 API 文档地址由调用方在列表外展示。 + ### GenerateQuestionsDialog `business/generate-questions/index.vue` 共用关联问题配置, diff --git a/ui/src/components/business/api-key-list/EditApiKeyDrawer.vue b/ui/src/components/business/api-key-list/EditApiKeyDrawer.vue new file mode 100644 index 00000000000..7aa0ef7ce8e --- /dev/null +++ b/ui/src/components/business/api-key-list/EditApiKeyDrawer.vue @@ -0,0 +1,181 @@ + + + diff --git a/ui/src/components/business/api-key-list/expiration.ts b/ui/src/components/business/api-key-list/expiration.ts new file mode 100644 index 00000000000..57e5d1258f3 --- /dev/null +++ b/ui/src/components/business/api-key-list/expiration.ts @@ -0,0 +1,38 @@ +/** API Key 的到期状态与有效期选项,仅供本功能使用。 */ +import type { ApiKeyRecord } from '@/api/types' + +export const expirationOptions = [ + { label: '永不过期', value: 'never' }, + { label: '7 天有效', value: '7' }, + { label: '30 天有效', value: '30' }, + { label: '90 天有效', value: '90' }, + { label: '180 天有效', value: '180' }, + { label: '自定义', value: 'custom' }, +] as const + +export type ExpirationType = (typeof expirationOptions)[number]['value'] + +export function getApiKeyExpiration(record: Pick, now = Date.now()) { + if (record.is_permanent) return { label: '永不过期', status: 'normal' } as const + const timestamp = record.expire_time ? new Date(record.expire_time).getTime() : NaN + if (!Number.isFinite(timestamp)) return { label: '—', status: 'normal' } as const + + const remaining = timestamp - now + if (remaining <= 0) return { label: '已过期', status: 'expired' } as const + if (remaining <= 7 * 86400000) { + const minutes = Math.ceil(remaining / 60000) + const label = + minutes < 60 ? `${minutes}分钟后过期` : minutes < 1440 ? `${Math.ceil(minutes / 60)}小时后过期` : `${Math.ceil(minutes / 1440)}天后过期` + return { label, status: 'soon' } as const + } + return { label: '', status: 'normal' } as const +} + +/** 预设有效期从保存时起算;自定义日期保持用户选择。 */ +export function getApiKeyExpireTime(type: ExpirationType, customTime: string | null, now = new Date()) { + if (type === 'never') return null + if (type === 'custom') return customTime + const date = new Date(now) + date.setDate(date.getDate() + Number(type)) + return date.toISOString() +} diff --git a/ui/src/components/business/api-key-list/index.vue b/ui/src/components/business/api-key-list/index.vue new file mode 100644 index 00000000000..3645f60e1a0 --- /dev/null +++ b/ui/src/components/business/api-key-list/index.vue @@ -0,0 +1,206 @@ + + + diff --git a/ui/src/layout/avatar-dropdown/ApiKeyDialog.vue b/ui/src/layout/avatar-dropdown/ApiKeyDialog.vue new file mode 100644 index 00000000000..c65db827c6f --- /dev/null +++ b/ui/src/layout/avatar-dropdown/ApiKeyDialog.vue @@ -0,0 +1,37 @@ + + + diff --git a/ui/src/layout/avatar-dropdown/index.vue b/ui/src/layout/avatar-dropdown/index.vue index fbe1e72f743..4525643c82b 100644 --- a/ui/src/layout/avatar-dropdown/index.vue +++ b/ui/src/layout/avatar-dropdown/index.vue @@ -1,11 +1,12 @@ + + diff --git a/ui/src/views/application-detail/overview/access-restriction/ButtonAccessRestriction.vue b/ui/src/views/application-detail/overview/access-restriction/ButtonAccessRestriction.vue new file mode 100644 index 00000000000..081c45093ad --- /dev/null +++ b/ui/src/views/application-detail/overview/access-restriction/ButtonAccessRestriction.vue @@ -0,0 +1,21 @@ + + + diff --git a/ui/src/views/application-detail/overview/api-key/ApiKeyDialog.vue b/ui/src/views/application-detail/overview/api-key/ApiKeyDialog.vue new file mode 100644 index 00000000000..87a85dfcc82 --- /dev/null +++ b/ui/src/views/application-detail/overview/api-key/ApiKeyDialog.vue @@ -0,0 +1,39 @@ + + + diff --git a/ui/src/views/application-detail/overview/api-key/ButtonApiKey.vue b/ui/src/views/application-detail/overview/api-key/ButtonApiKey.vue new file mode 100644 index 00000000000..75d35be12d1 --- /dev/null +++ b/ui/src/views/application-detail/overview/api-key/ButtonApiKey.vue @@ -0,0 +1,23 @@ + + + diff --git a/ui/src/views/application-detail/overview/chat/ButtonChat.vue b/ui/src/views/application-detail/overview/chat/ButtonChat.vue new file mode 100644 index 00000000000..9a54b8e78ea --- /dev/null +++ b/ui/src/views/application-detail/overview/chat/ButtonChat.vue @@ -0,0 +1,13 @@ + + + diff --git a/ui/src/views/application-detail/overview/components/ApplicationBasicInfo.vue b/ui/src/views/application-detail/overview/components/ApplicationBasicInfo.vue new file mode 100644 index 00000000000..1227de71530 --- /dev/null +++ b/ui/src/views/application-detail/overview/components/ApplicationBasicInfo.vue @@ -0,0 +1,157 @@ + + + diff --git a/ui/src/views/application-detail/overview/display-setting/ButtonDisplaySetting.vue b/ui/src/views/application-detail/overview/display-setting/ButtonDisplaySetting.vue new file mode 100644 index 00000000000..e3839218776 --- /dev/null +++ b/ui/src/views/application-detail/overview/display-setting/ButtonDisplaySetting.vue @@ -0,0 +1,21 @@ + + + diff --git a/ui/src/views/application-detail/overview/display-setting/DisplaySettingDialog.vue b/ui/src/views/application-detail/overview/display-setting/DisplaySettingDialog.vue new file mode 100644 index 00000000000..ebba5375a11 --- /dev/null +++ b/ui/src/views/application-detail/overview/display-setting/DisplaySettingDialog.vue @@ -0,0 +1,20 @@ + + + diff --git a/ui/src/views/application-detail/overview/embed-third-party/ButtonEmbedThirdParty.vue b/ui/src/views/application-detail/overview/embed-third-party/ButtonEmbedThirdParty.vue new file mode 100644 index 00000000000..4f94d1dd624 --- /dev/null +++ b/ui/src/views/application-detail/overview/embed-third-party/ButtonEmbedThirdParty.vue @@ -0,0 +1,21 @@ + + + diff --git a/ui/src/views/application-detail/overview/embed-third-party/EmbedThirdPartyDialog.vue b/ui/src/views/application-detail/overview/embed-third-party/EmbedThirdPartyDialog.vue new file mode 100644 index 00000000000..e0141cdc4df --- /dev/null +++ b/ui/src/views/application-detail/overview/embed-third-party/EmbedThirdPartyDialog.vue @@ -0,0 +1,20 @@ + + + diff --git a/ui/src/views/application-detail/overview/index.vue b/ui/src/views/application-detail/overview/index.vue index 2e3d6018491..2209fce92c0 100644 --- a/ui/src/views/application-detail/overview/index.vue +++ b/ui/src/views/application-detail/overview/index.vue @@ -4,6 +4,7 @@ import { useRoute } from 'vue-router' import { useApplicationDetailContext } from '../context' import type { ResourceDetailPageProps } from '@/layout/ResourceDetailLayout.vue' import HomeStatistics from '@/views/home/components/HomeStatistics.vue' +import ApplicationBasicInfo from './components/ApplicationBasicInfo.vue' import ApplicationRanking from './components/ApplicationRanking.vue' defineOptions({ name: 'ApplicationOverviewView' }) @@ -17,6 +18,7 @@ const { applicationId, resourceApi } = useApplicationDetailContext() diff --git a/ui/src/views/system/resource-management/application/index.vue b/ui/src/views/system/resource-management/application/index.vue index 96f1bdb1905..10a66b7f4de 100644 --- a/ui/src/views/system/resource-management/application/index.vue +++ b/ui/src/views/system/resource-management/application/index.vue @@ -151,7 +151,9 @@ onMounted(() => {