feat: Rename 'application' to 'consumer' and optimize consumer module display

This commit is contained in:
maggieyyy
2024-10-23 16:49:09 +08:00
parent b74f4adfd8
commit 69f330737f
33 changed files with 320 additions and 223 deletions
@@ -253,7 +253,7 @@ const PUBLIC_ROUTES:RouteConfig[] = [
key:uuidv4(),
},
{
path:'tenantManagement',
path:'consumer',
component:<Outlet />,
provider:TenantManagementProvider,
key:uuidv4(),
@@ -48,8 +48,8 @@ const themeToken = {
const TOTAL_MENU_ITEMS:MenuProps['items'] = useMemo(() => [
getNavItem($t('工作空间'), 'workspace','/guide/page',<Icon icon="ic:baseline-space-dashboard" width="18" height="18"/>, [
getNavItem(<a>{$t('首页')}</a>, 'guide','/guide/page',<Icon icon="ic:baseline-home" width="18" height="18"/>,undefined,undefined,'all'),
getNavItem(<a>{$t('应用')}</a>, 'tenantManagement','/tenantManagement',<Icon icon="ic:baseline-apps" width="18" height="18"/>,undefined,undefined,'all'),
getNavItem(<a>{$t('服务')}</a>, 'service','/service',<Icon icon="ic:baseline-blinds-closed" width="18" height="18"/>,undefined,undefined,'all'),
getNavItem(<a>{$t('消费者')}</a>, 'consumer','/consumer',<Icon icon="ic:baseline-apps" width="18" height="18"/>,undefined,undefined,'all'),
getNavItem(<a>{$t('团队')}</a>, 'team','/team',<Icon icon="ic:baseline-people-alt" width="18" height="18"/>,undefined,undefined,'all'),
]),
getNavItem($t('API 市场'), 'serviceHub','/serviceHub',<Icon icon="ic:baseline-hub" width="18" height="18"/>,undefined,undefined,'system.workspace.api_market.view'),
@@ -17,8 +17,8 @@ export const TranslateWord = ()=>{
{$t('只读成员')}
{$t('服务管理员')}
{$t('服务开发者')}
{$t('应用开发者')}
{$t('应用管理员')}
{$t('消费者开发者')}
{$t('消费者管理员')}
{$t('驱动名称')}
{$t('请求失败数')}
{$t('转发失败数')}
@@ -53,8 +53,8 @@ export const TranslateWord = ()=>{
{$t('上传 OpenAPI 文档 (.json/.yaml)')}
{$t('替换 OpenAPI 文档 (.json/.yaml)')}
{$t('打开 OpenAPI YAML 编辑器')}
{$t('无需审核:允许任何应用调用该服务')}
{$t('人工审核:仅允许通过人工审核的应用调用该服务')}
{$t('无需审核:允许任何消费者调用该服务')}
{$t('人工审核:仅允许通过人工审核的消费者调用该服务')}
{$t('永久')}
{$t('否')}
{$t('是')}
@@ -72,7 +72,7 @@ export const TranslateWord = ()=>{
{$t('版本状态')}
{$t('创建人')}
{$t('审核时间')}
{$t('申请方-应用')}
{$t('申请方-消费者')}
{$t('审核状态')}
{$t('申请人')}
{$t('审核人')}
@@ -15,7 +15,7 @@ export const SUBSCRIBE_APPROVAL_TABLE_COLUMN : PageProColumns<ApprovalTableListI
},
},
{
title:('申请方-应用'),
title:('申请方-消费者'),
dataIndex: ['application','name'],
ellipsis:true
},
@@ -76,7 +76,7 @@ export const SUBSCRIBE_APPROVAL_INNER_TODO_TABLE_COLUMN : PageProColumns<Subscri
},
},
{
title:('申请方-应用'),
title:('申请方-消费者'),
dataIndex: ['application','name'],
ellipsis:true
},
@@ -111,7 +111,7 @@ export const SUBSCRIBE_APPROVAL_INNER_DONE_TABLE_COLUMN : PageProColumns<Subscri
},
},
{
title:('申请方-应用'),
title:('申请方-消费者'),
dataIndex: ['application','name'],
ellipsis:true
},
@@ -445,7 +445,7 @@ export const ChangeTypeEnum = {
export const SubscribeApprovalList = [
{
title:('申请方应用'),key:'application'
title:('申请方消费者'),key:'application'
},
{
title:('申请方所属团队'),key:'applyTeam'
+8 -3
View File
@@ -20,8 +20,8 @@ export const STATUS_COLOR = {
// avoid changing route within ths same category
export const routerKeyMap = new Map<string, string[]|string>([
['workspace',['tenantManagement','service','team','guide']],
['my',['tenantManagement','service','team']],
['workspace',['consumer','service','team','guide']],
['my',['consumer','service','team']],
['mainPage',['dashboard','systemrunning']],
['operationCenter',['member','user','role','common']],
['organization',['member','user','role']],
@@ -68,4 +68,9 @@ export const routerKeyMap = new Map<string, string[]|string>([
export const DELETE_TIPS = {
default:('该数据删除后将无法找回,请确认是否删除?')
}
}
export const DATA_SHOW_TYPE_OPTIONS = [
{label:'列表', value:'list'},
{label:'块', value:'block'},
]
@@ -1,7 +1,7 @@
{
"工作空间": "Kc0e5ef9f",
"首页": "K4de11e23",
"应用": "Kfe93ef35",
"消费者": "Kfe93ef35",
"服务": "Kb58e0c3f",
"团队": "Kc9e489f5",
"API 市场": "K61c89f5f",
@@ -95,8 +95,8 @@
"只读成员": "Ke41d7451",
"服务管理员": "Kf99e8b66",
"服务开发者": "Kda8db57a",
"应用开发者": "K216a1ac7",
"应用管理员": "K27924db",
"消费者开发者": "K216a1ac7",
"消费者管理员": "K27924db",
"驱动名称": "K8dc5c723",
"请求失败数": "Kda249fe8",
"转发失败数": "Kcf2df651",
@@ -131,8 +131,8 @@
"上传 OpenAPI 文档 (.json/.yaml)": "K6206e4ad",
"替换 OpenAPI 文档 (.json/.yaml)": "Kfba46e6d",
"打开 OpenAPI YAML 编辑器": "Kdac8ce7e",
"无需审核:允许任何应用调用该服务": "Kffd7e274",
"人工审核:仅允许通过人工审核的应用调用该服务": "K8a8b13e4",
"无需审核:允许任何消费者调用该服务": "Kffd7e274",
"人工审核:仅允许通过人工审核的消费者调用该服务": "K8a8b13e4",
"永久": "Kbfe02d7f",
"否": "K1e9c479e",
"是": "Kaddfcb6b",
@@ -150,7 +150,7 @@
"版本状态": "Kcbf39b82",
"创建人": "K339d15b5",
"审核时间": "K7194cea2",
"申请方-应用": "K831aa6c0",
"申请方-消费者": "K831aa6c0",
"审核状态": "K7ad449bc",
"审核人": "K3b3a98ce",
"来源": "K61b62ace",
@@ -369,7 +369,7 @@
"创建 AI 服务和 API": "Kc057704a",
"创建 AI 类型的服务,并且你可以将 Prompt 提示词设置为一个 API,简化使用 AI 的流程。": "K76bb4a09",
"创建调用 Token": "K71b2c70f",
"为了安全地调用 API,你需要创建一个应用以及Token。": "K9bdd8403",
"为了安全地调用 API,你需要创建一个消费者以及Token。": "K9bdd8403",
"调用": "Kc5738b6c",
"现在你可以通过 Token 来调用这些 API。": "Kd6d7ca1f",
"快速接入 REST API": "K86cf95f",
@@ -379,13 +379,13 @@
"核心功能": "K2cdbb773",
"账号与角色": "K3378c50d",
"邀请你的团队成员加入 APIPark,共同管理和调用 API。": "Kda5bb930",
"团队中包含了人员、应用和服务,不同团队之间的应用和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。": "Kc8239422",
"团队中包含了人员、消费者和服务,不同团队之间的消费者和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。": "Kc8239422",
"服务内包含一组 API,并且可以发布到 API 市场被其他团队使用。": "Kd5be0cd7",
"权限管理": "K62e89ee7",
"订阅服务": "K8f7808e6",
"如果需要调用某个服务的 API,需要先订阅该服务,并且等待提供服务的团队审核后才可发起 API 请求。": "Kf2410413",
"审核订阅申请": "K6c2e44b8",
"提供服务的团队可以审核来自其他团队的订阅申请,审核通过后的应用才可发起 API 请求。": "Ka0a8840a",
"提供服务的团队可以审核来自其他团队的订阅申请,审核通过后的消费者才可发起 API 请求。": "Ka0a8840a",
"APIPark 提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。": "K3453272",
"Hello!欢迎使用 APIPark": "Kd518ba3e",
"你能通过 APIPark 快速在企业内部构建 API 开放门户/市场,享受极致的转发性能、API 可观测、服务治理、多租户管理、订阅审核流程等诸多好处。": "K7e04ea16",
@@ -518,7 +518,7 @@
"添加成员": "Kec46a57f",
"输入姓名查找": "K48724410",
"搜索用户名、邮箱": "Kb9052305",
"设置团队和成员,然后你可以在团队内创建服务和应用、订阅API,成员只能看到所属团队内的服务和应用。": "K5ece3bac",
"设置团队和成员,然后你可以在团队内创建服务和消费者、订阅API,成员只能看到所属团队内的服务和消费者。": "K5ece3bac",
"添加团队": "K510cdd27",
"输入名称、ID、负责人查找团队": "K9244ae14",
"配置团队": "Kc7b24b4b",
@@ -538,8 +538,8 @@
"导出": "Ka2c794a2",
"退出全屏": "Kaf70c3b",
"(0)调用详情": "Kd22841a4",
"应用调用统计": "K1512e983",
"请选择应用": "Kb4d2007f",
"消费者调用统计": "K1512e983",
"请选择消费者": "Kb4d2007f",
"调用趋势": "K8c7f2d2e",
"(0)-(1)调用趋势": "K657c3452",
"调用量统计": "Kc04efb87",
@@ -562,7 +562,7 @@
"请选择服务": "Kffcfe375",
"调用详情": "Ka65f739c",
"API 请求量 Top10": "K89b7ac79",
"应用调用量 Top10": "Kc0915603",
"消费者调用量 Top10": "Kc0915603",
"服务被调用量 Top10": "Kf90b54",
"暂无请求统计数据": "Kfb26388",
"请求统计": "Kc8cbd8f8",
@@ -585,9 +585,9 @@
"万": "Ke6a935d",
"搜索分类或标签": "Kd59290a2",
"暂无API数据": "K6b75bdbc",
"搜索或选择应用": "Kd8a7a689",
"搜索或选择消费者": "Kd8a7a689",
"申请理由": "K4b15d6f5",
"应用管理": "Kb7e869a4",
"消费者管理": "Kb7e869a4",
"鉴权类型": "Kb71b5a13",
"Iss": "K4d1465ee",
"签名算法": "K5dcd7ed8",
@@ -600,9 +600,9 @@
"SK": "K31418470",
"Apikey": "Kbfeb5297",
"隐藏鉴权信息": "Ke64e43a",
"应用名称": "K5168eb63",
"应用 ID": "K546e46f",
"删除应用": "K95764d1d",
"消费者名称": "K5168eb63",
"消费者 ID": "K546e46f",
"删除消费者": "K95764d1d",
"鉴权详情": "K217cb125",
"添加鉴权": "K2bb63eca",
"编辑鉴权": "Kd74d69b7",
@@ -619,7 +619,7 @@
"请确认是否取消订阅申请?": "K1856c229",
"搜索服务": "K66ea2f0",
"审核中": "K8adf7f8b",
"添加应用": "K667bbbe7",
"添加消费者": "K667bbbe7",
"暂无服务描述": "Ka4b45550",
"订阅的服务数量:已通过 (0) 个,申请中 (1) 个": "K3c7b175f",
"退出测试": "Kbe3e9335",
@@ -630,14 +630,14 @@
"Base URL": "Kc29dabf2",
"申请": "K4aa9ed2c",
"服务信息": "K6c060779",
"接入应用": "K8723422e",
"接入消费者": "K8723422e",
"供应方": "Kb97544cb",
"分类": "Kb32f0afe",
"版本": "K81634069",
"更新时间": "Keefda53d",
"无标签": "K96a2f1c8",
"API 数量": "K72b0c0b3",
"接入应用数量": "K93d5a66e",
"接入消费者数量": "K93d5a66e",
"关联标签": "K96059c69",
"更新者": "K8b7c2592",
"添加 Open Api": "K32263abd",
@@ -1,7 +1,7 @@
{
"Kc0e5ef9f": "工作空间",
"K4de11e23": "首页",
"Kfe93ef35": "应用",
"Kfe93ef35": "消费者",
"Kb58e0c3f": "服务",
"Kc9e489f5": "团队",
"K61c89f5f": "API 门户",
@@ -91,8 +91,8 @@
"K6206e4ad": "上传 OpenAPI 文档 (.json/.yaml)",
"Kfba46e6d": "替换 OpenAPI 文档 (.json/.yaml)",
"Kdac8ce7e": "打开 OpenAPI YAML 编辑器",
"Kffd7e274": "无审核:允许所有应用订阅该服务",
"K8a8b13e4": "人工审核:仅允许审核通过的应用订阅该服务",
"Kffd7e274": "无审核:允许所有消费者订阅该服务",
"K8a8b13e4": "人工审核:仅允许审核通过的消费者订阅该服务",
"Kbfe02d7f": "永久",
"K1e9c479e": "否",
"Kaddfcb6b": "是",
@@ -259,7 +259,7 @@
"Kc057704a": "创建 AI 服务和 API",
"K76bb4a09": "创建 AI 类型的服务,并且你可以将 Prompt 提示词设置为一个 API,简化使用 AI 的流程。",
"K71b2c70f": "创建调用 Token",
"K9bdd8403": "为了安全地调用 API,你需要创建一个应用以及Token。",
"K9bdd8403": "为了安全地调用 API,你需要创建一个消费者以及Token。",
"Kc5738b6c": "调用",
"Kd6d7ca1f": "现在你可以通过 Token 来调用这些 API。",
"K86cf95f": "快速接入 REST API",
@@ -269,16 +269,16 @@
"K2cdbb773": "核心功能",
"K3378c50d": "账号与角色",
"Kda5bb930": "邀请你的团队成员加入 APIPark,共同管理和调用 API。",
"Kc8239422": "团队中包含了人员、应用和服务,不同团队之间的应用和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。",
"Kc8239422": "团队中包含了人员、消费者和服务,不同团队之间的消费者和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。",
"Kd5be0cd7": "服务内包含一组 API,并且可以发布到 API 市场被其他团队使用。",
"K62e89ee7": "权限管理",
"K8f7808e6": "订阅服务",
"Kf2410413": "如果需要调用某个服务的 API,需要先订阅该服务,并且等待提供服务的团队审核后才可发起 API 请求。",
"K6c2e44b8": "审核订阅",
"Ka0a8840a": "审核其他应用的订阅申请,审核通过后的才可发起 API 请求。",
"Ka0a8840a": "审核其他消费者的订阅申请,审核通过后的才可发起 API 请求。",
"K3453272": "APIPark 提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。",
"Kd518ba3e": "Hello!欢迎使用 APIPark",
"K7e04ea16": "🦄 APIPark 是开源的一站式 AI 网关和 API 开发者门户,帮助企业和开发者快速接入 100+ AI 模型,将 AI 模型和 Prompt 提示词组合成新的 API,并且统一所有 AI 的请求数据格式,避免切换 AI 模型或调整提示词时影响你的 APP 应用或者微服务。你还可以通过 APIPark 的开发者门户在团队内共享 API,管理调用的应用并保障你的 API 安全,通过清晰的图表来监控你的 AI API 使用情况。",
"K7e04ea16": "🦄 APIPark 是开源的一站式 AI 网关和 API 开发者门户,帮助企业和开发者快速接入 100+ AI 模型,将 AI 模型和 Prompt 提示词组合成新的 API,并且统一所有 AI 的请求数据格式,避免切换 AI 模型或调整提示词时影响你的 APP 消费者或者微服务。你还可以通过 APIPark 的开发者门户在团队内共享 API,管理调用的消费者并保障你的 API 安全,通过清晰的图表来监控你的 AI API 使用情况。",
"Kedd41c18": "✨ 如果你喜欢 APIPark,欢迎在 Github 为我们 Star 或提供产品反馈意见。",
"Kef02fd87": "快速入门",
"K43a3b38d": "我们提供了一些任务来帮你快速了解 APIPark",
@@ -405,7 +405,7 @@
"Kec46a57f": "添加成员",
"K48724410": "输入姓名查找",
"Kb9052305": "搜索用户名、邮箱",
"K5ece3bac": "设置团队和成员,然后你可以在团队内创建服务和应用、订阅API,成员只能看到所属团队内的服务和应用。",
"K5ece3bac": "设置团队和成员,然后你可以在团队内创建服务和消费者、订阅API,成员只能看到所属团队内的服务和消费者。",
"K510cdd27": "添加团队",
"K9244ae14": "输入名称、ID、负责人查找团队",
"Kc7b24b4b": "设置团队",
@@ -425,8 +425,8 @@
"Ka2c794a2": "导出",
"Kaf70c3b": "退出全屏",
"Kd22841a4": "(0)调用详情",
"K1512e983": "应用调用统计",
"Kb4d2007f": "请选择应用",
"K1512e983": "消费者调用统计",
"Kb4d2007f": "请选择消费者",
"K8c7f2d2e": "调用趋势",
"K657c3452": "(0)-(1)调用趋势",
"Kc04efb87": "调用量统计",
@@ -449,7 +449,7 @@
"Kffcfe375": "请选择服务",
"Ka65f739c": "调用详情",
"K89b7ac79": "API Top10",
"Kc0915603": "应用 Top10",
"Kc0915603": "消费者 Top10",
"Kf90b54": "服务 Top10",
"Kfb26388": "无请求数据",
"Kc8cbd8f8": "请求统计",
@@ -472,9 +472,9 @@
"Ke6a935d": "万",
"Kd59290a2": "搜索分类或标签",
"K6b75bdbc": "无API数据",
"Kd8a7a689": "搜索或选择应用",
"Kd8a7a689": "搜索或选择消费者",
"K4b15d6f5": "申请理由",
"Kb7e869a4": "应用管理",
"Kb7e869a4": "消费者管理",
"Kb71b5a13": "鉴权类型",
"K4d1465ee": "ISS",
"K5dcd7ed8": "签名算法",
@@ -488,9 +488,9 @@
"Kbfeb5297": "API Key",
"K1a78e6f0": "过期时间",
"Ke64e43a": "隐藏认证信息",
"K5168eb63": "应用名称",
"K546e46f": "应用 ID",
"K95764d1d": "删除应用",
"K5168eb63": "消费者名称",
"K546e46f": "消费者 ID",
"K95764d1d": "删除消费者",
"K217cb125": "鉴权详情",
"K2bb63eca": "添加鉴权",
"Kd74d69b7": "编辑鉴权",
@@ -507,7 +507,7 @@
"K1856c229": "是否取消订阅申请?",
"K66ea2f0": "搜索服务",
"K8adf7f8b": "审核中",
"K667bbbe7": "添加应用",
"K667bbbe7": "添加消费者",
"Ka4b45550": "无服务描述",
"K3c7b175f": "订阅服务:已通过 (0) ,审核中 (1)",
"Kbe3e9335": "退出测试",
@@ -517,14 +517,14 @@
"K59cdbec3": "服务介绍",
"K4aa9ed2c": "申请订阅",
"K6c060779": "服务信息",
"K8723422e": "接入应用",
"K8723422e": "接入消费者",
"Kb97544cb": "供应方",
"Kb32f0afe": "分类",
"K81634069": "版本",
"Keefda53d": "更新时间",
"K96a2f1c8": "无标签",
"K72b0c0b3": "API 数量",
"K93d5a66e": "接入应用数量",
"K93d5a66e": "接入消费者数量",
"K96059c69": "关联标签",
"K8b7c2592": "更新者",
"K32263abd": "添加 Open Api",
@@ -546,8 +546,8 @@
"Ke41d7451": "只读成员",
"Kf99e8b66": "服务管理员",
"Kda8db57a": "服务开发者",
"K216a1ac7": "应用开发者",
"K27924db": "应用管理员",
"K216a1ac7": "消费者开发者",
"K27924db": "消费者管理员",
"K8dc5c723": "驱动名称",
"Kda249fe8": "失败",
"Kcf2df651": "失败",
@@ -589,7 +589,7 @@
"Kcbf39b82": "版本状态",
"K339d15b5": "创建人",
"K7194cea2": "审核时间",
"K831aa6c0": "申请方-应用",
"K831aa6c0": "申请方-消费者",
"K7ad449bc": "审核状态",
"K3b3a98ce": "审核人",
"K61b62ace": "来源",
@@ -1,6 +1,6 @@
/**
* @description api )
* @description api )
* @param request
* @returns
*/
@@ -22,7 +22,7 @@ import { NodeData } from "@core/const/system-running/type"
import { TopologyProjectItem, TopologyServiceItem } from "@core/pages/systemRunning/SystemRunning"
/**
* @description api )
* @description api )
* @param request
* @returns
*/
@@ -366,7 +366,7 @@ const PUBLIC_ROUTES:RouteConfig[] = [
key:uuidv4(),
},
{
path:'tenantManagement',
path:'consumer',
component:<Outlet />,
provider:TenantManagementProvider,
key:uuidv4(),
@@ -1,7 +1,7 @@
export const BASE_GROUP_ORDER = JSON.stringify({})
/**
*
*
*/
export const RELATIVE_PICTURE_NODE_FONTSIZE = 14
@@ -49,14 +49,14 @@ export interface GetProjectGroupRelativeRequest {
}
/**
* ()
* ()
*/
export interface GetSpaceProjectGroupRelativeRequest {
spaceId: string
}
/**
*
*
*/
export interface GetSpaceProjectGroupRelativeResponse {
success: boolean
@@ -355,12 +355,12 @@ export const PROXY_HEADER_CONFIG:ConfigField<ProxyHeaderItem>[] = [
export const SERVICE_VISUALIZATION_OPTIONS = [
{label:('内部服务:可通过网关访问,但不展示在服务广场'),value:'inner'},
{label:('公开服务:可通过网关访问,展示在服务广场,可被其他应用订阅'),value:'public'}];
{label:('公开服务:可通过网关访问,展示在服务广场,可被其他消费者订阅'),value:'public'}];
export const SERVICE_APPROVAL_OPTIONS = [
{label:('无需审核:允许任何应用调用该服务'),value:'auto'},
{label:('人工审核:仅允许通过人工审核的应用调用该服务'),value:'manual'}];
{label:('无需审核:允许任何消费者调用该服务'),value:'auto'},
{label:('人工审核:仅允许通过人工审核的消费者调用该服务'),value:'manual'}];
export const SERVICE_KIND_OPTIONS = [
{label:('REST'),value:'rest'},
{label:('AI'),value:'ai'}];
+1 -1
View File
@@ -10,7 +10,7 @@ async function initializeApp() {
// 初始化行为
// await fetchInitialConfig(); // 示例:获取初始配置
// 异步操作完成后,渲染React应用
// 异步操作完成后,渲染React消费者
ReactDOM.createRoot(document.getElementById('root')!).render(
<StrictMode>
<GlobalProvider>
@@ -164,7 +164,10 @@ const AiSettingList = ()=>{
return (
<Card title={
<div className="flex items-center justify-between">
<div className="flex items-center h-[22px] ai-setting-svg-container" dangerouslySetInnerHTML={{ __html: provider.logo }} />
<div className="flex items-center gap-[4px]">
<span className=" flex items-center h-[22px] ai-setting-svg-container" dangerouslySetInnerHTML={{ __html: provider.logo }} ></span>
<span className="font-normal">{provider.name}</span>
</div>
<Tag bordered={false} color={provider.configured ? 'green' : undefined} className="h-[22px] px-[4px] text-center">
{provider.configured ? $t('已配置') : $t('未配置')}
</Tag>
@@ -30,7 +30,7 @@ export default function Guide(){
},
{
title: $t("创建调用 Token"),
description: $t('为了安全地调用 API,你需要创建一个应用以及Token。'),
description: $t('为了安全地调用 API,你需要创建一个消费者以及Token。'),
link: 'https://docs.apipark.com/docs/quick/suberscriber/application'
},
{
@@ -50,7 +50,7 @@ export default function Guide(){
},
{
title: $t("创建调用 Token"),
description: $t('为了安全地调用 API,你需要创建一个应用以及Token。'),
description: $t('为了安全地调用 API,你需要创建一个消费者以及Token。'),
link: 'https://docs.apipark.com/docs/quick/suberscriber/subscribe'
},
{
@@ -82,7 +82,7 @@ export default function Guide(){
},
{
title: $t("团队"),
description: $t('团队中包含了人员、应用和服务,不同团队之间的应用和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。'),
description: $t('团队中包含了人员、消费者和服务,不同团队之间的消费者和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。'),
link: 'https://docs.apipark.com/docs/quick/provider/service'
},
{
@@ -102,7 +102,7 @@ export default function Guide(){
},
{
title: $t("审核订阅申请"),
description: $t('提供服务的团队可以审核来自其他团队的订阅申请,审核通过后的应用才可发起 API 请求。'),
description: $t('提供服务的团队可以审核来自其他团队的订阅申请,审核通过后的消费者才可发起 API 请求。'),
link: 'https://docs.apipark.com/docs/quick/suberscriber/subscribe'
}
]
@@ -14,7 +14,6 @@ import { DrawerWithFooter } from "@common/components/aoplatform/DrawerWithFooter
import SystemConfig from "./SystemConfig.tsx";
import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx";
import { $t } from "@common/locales/index.ts";
import Joyride from "react-joyride";
import InsidePage from "@common/components/aoplatform/InsidePage.tsx";
const SystemList:FC = ()=>{
@@ -37,7 +36,7 @@ const SystemList:FC = ()=>{
getGlobalAccessData()?.then?.(()=>{
getSystemList()
})
return
return Promise.resolve({data:[], success:false})
}
if(!tableHttpReload){
setTableHttpReload(true)
@@ -165,7 +165,7 @@ const TeamList:FC = ()=>{
return (
<InsidePage
pageTitle={$t('团队')}
description={$t("设置团队和成员,然后你可以在团队内创建服务和应用、订阅API,成员只能看到所属团队内的服务和应用。")}
description={$t("设置团队和成员,然后你可以在团队内创建服务和消费者、订阅API,成员只能看到所属团队内的服务和消费者。")}
showBorder={false}
contentClassName=" pr-PAGE_INSIDE_X pb-PAGE_INSIDE_B"
>
@@ -99,7 +99,7 @@ export default function MonitorAppPage(props:MonitorAppPageProps){
fetchTableData(data).then((resp) => {
const {code,data,msg} = resp
if(code === STATUS_CODE.SUCCESS){
exportExcel($t('应用调用统计'), [query!.start!, query!.end!], $t('应用调用统计'), 'dashboard_application', APPLICATION_TABLE_GLOBAL_COLUMNS_CONFIG, data.statistics)
exportExcel($t('消费者调用统计'), [query!.start!, query!.end!], $t('消费者调用统计'), 'dashboard_application', APPLICATION_TABLE_GLOBAL_COLUMNS_CONFIG, data.statistics)
}else{
message.error(msg || $t(RESPONSE_TIPS.dataError))
}
@@ -144,13 +144,13 @@ export default function MonitorAppPage(props:MonitorAppPageProps){
onTimeRangeChange={handleTimeRangeChange}/>
<div className="flex flex-wrap items-center row-gap-[12px] pt-btnybase mr-btnybase">
<div>
<label className="inline-block whitespace-nowrap">{$t('应用')}</label>
<label className="inline-block whitespace-nowrap">{$t('消费者')}</label>
<Select
className="w-[346px]"
mode="multiple"
maxTagCount={1}
// maxTagPlaceholder={(selectedList) => `and ${selectedList.length} more selected`}
placeholder={$t("请选择应用")}
placeholder={$t("请选择消费者")}
value={queryData?.projects}
options={listOfApps}
onChange={(value)=>{setQueryData(prevData=>({...prevData || {}, projects:value}))}}
@@ -212,7 +212,7 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => {
children:<MonitorTable className="py-[10px]" ref={monitorApiTableRef} type='api' id="dashboard_top10_api" onRowClick={(record)=>{APP_MODE !== 'pro' ? null : getDetailData(record as MonitorApiData,'api')}} request={()=>getTablesData(queryData||{},'api')}/>
},
{
label:$t('应用调用量 Top10'),
label:$t('消费者调用量 Top10'),
key:'subscribers',
children:<MonitorTable className="py-[10px]" ref={monitorSubTableRef} type='subscribers' id="dashboard_top10_subscriber" onRowClick={(record)=>{APP_MODE !== 'pro' ? null : getDetailData(record as MonitorSubscriberData,'subscriber')}} request={()=>getTablesData(queryData||{},'subscriber')} />
},
@@ -181,8 +181,8 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(PageProColumns<MonitorData>&{eoTitle
export const APPLICATION_TABLE_GLOBAL_COLUMNS_CONFIG:(PageProColumns<MonitorApiData>&{eoTitle:string})[] = [
{
title:('应用名称'),
eoTitle:('应用名称'),
title:('消费者名称'),
eoTitle:('消费者名称'),
dataIndex: 'name',
width:160,
ellipsis:true,
@@ -190,8 +190,8 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(PageProColumns<MonitorData>&{eoTitle
disable:true
},
{
title:('应用 ID'),
eoTitle:('应用 ID'),
title:('消费者 ID'),
eoTitle:('消费者 ID'),
dataIndex: 'id',
width: 140,
ellipsis:true,
@@ -29,7 +29,7 @@ export default function DashboardTabPage(){
children:<Outlet />
},
{
label:$t('应用调用统计'),
label:$t('消费者调用统计'),
key:'provider',
children:<Outlet />
},
@@ -74,7 +74,7 @@ const PUBLIC_ROUTES:RouteConfig[] = [
]
},
{
path:'tenantManagement',
path:'consumer',
component:<Outlet />,
provider:TenantManagementProvider,
key:uuidv4(),
@@ -1,13 +1,12 @@
import { MenuProps } from "antd";
import { getItem } from "@common/utils/navigation";
import { ServiceHubTableListItem } from "./type";
import { PageProColumns } from "@common/components/aoplatform/PageList";
import { frontendTimeSorter } from "@common/utils/dataTransfer";
export const SERVICE_HUB_TABLE_COLUMNS: PageProColumns<ServiceHubTableListItem>[] = [
{
title:('服务名称'),
title:('消费者'),
dataIndex: 'name',
ellipsis:true,
width:160,
@@ -17,32 +16,39 @@ export const SERVICE_HUB_TABLE_COLUMNS: PageProColumns<ServiceHubTableListItem>[
},
},
{
title:('服务ID'),
title:('消费者 ID'),
dataIndex: 'id',
width: 140,
ellipsis:true
},
{
title:('服务标签'),
dataIndex: 'tags',
title:('团队'),
dataIndex: ['team','name'],
ellipsis:true,
renderText:(_,entity:ServiceHubTableListItem)=>entity.tags?.map(x=>x.name).join(',') || '-'
},
{
title:('所属系统'),
dataIndex: ['app','name'],
title:('订阅服务数量'),
dataIndex: 'subscribeNum',
ellipsis:true
},
{
title:('所属团队'),
dataIndex: ['team','name'],
title:('鉴权数量'),
dataIndex: 'authNum',
ellipsis:true
},
{
title:('服务分类'),
dataIndex: ['catalogue','name'],
title:('描述'),
dataIndex:'description',
ellipsis:true
}
},
{
title:('创建时间'),
dataIndex: 'createTime',
width:182,
ellipsis:true,
sorter: (a,b)=>frontendTimeSorter(a,b,'createTime')
},
];
@@ -57,11 +57,11 @@ export const ApplyServiceModal = forwardRef<ApplyServiceHandle,ApplyServiceProps
<Col span={18}>{entity.id}</Col>
</Row>
<Form.Item
label={$t("应用")}
label={$t("消费者")}
name="applications"
rules={[{ required: true }]}
>
<Select className="w-INPUT_NORMAL" disabled={reApply} placeholder={$t("搜索或选择应用")} mode="multiple" options={mySystemOptionList?.filter((x)=>x.value !== entity.id)}/>
<Select className="w-INPUT_NORMAL" disabled={reApply} placeholder={$t("搜索或选择消费者")} mode="multiple" options={mySystemOptionList?.filter((x)=>x.value !== entity.id)}/>
</Form.Item>
{ entity.approvalType === 'manual' &&
<Form.Item
@@ -172,7 +172,7 @@ const ServiceHubDetail = ()=>{
</section>
<section className="col-span-1 p-btnbase px-btnrbase">
<Descriptions title={$t("服务信息")} column={1} size={'small'}>
<Descriptions.Item label={$t("接入应用")}>{serviceBasicInfo?.appNum ?? '-'}</Descriptions.Item>
<Descriptions.Item label={$t("接入消费者")}>{serviceBasicInfo?.appNum ?? '-'}</Descriptions.Item>
<Descriptions.Item label={$t("供应方")}>{serviceBasicInfo?.team?.name || '-'}</Descriptions.Item>
<Descriptions.Item label={$t("审核")}>{serviceBasicInfo?.approvalType ? $t((approvalTypeTranslate[serviceBasicInfo?.approvalType] || '-' )): '-'}</Descriptions.Item>
<Descriptions.Item label={$t("分类")}>{serviceBasicInfo?.catalogue?.name || '-'}</Descriptions.Item>
@@ -127,46 +127,46 @@ const ServiceHubList:FC = ()=>{
return (
<ServiceHubGroup filterOption={filterOption} dispatch={dispatch}>
<div className="h-full padding-top-40">
<Spin className="h-full" wrapperClassName="h-full" indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />} spinning={filterOption.listLoading}>
{filterOption.showServicesList && filterOption.showServicesList.length > 0 ? <VirtuosoGrid
style={{ height: '100%'}}
data={filterOption.showServicesList}
totalCount={filterOption.showServicesList.length}
itemContent={(index) => {
const item = filterOption.showServicesList[index];
return (
<div className="pt-[20px]">
<Card title={CardTitle(item)} className="shadow-[0_5px_10px_0_rgba(0,0,0,0.05)] rounded-[10px] overflow-visible cursor-pointer h-[180px] m-0 transition duration-500 hover:shadow-[0_5px_20px_0_rgba(0,0,0,0.15)] hover:scale-[1.05]" classNames={{header:'border-b-[0px] p-[20px] ', body:"pt-0"}} onClick={()=>showDocumentDetail(item)}>
<span className="line-clamp-3 text-[12px] text-[#666] "
style={{'word-break':'auto-phrase'}}>{item.description || $t('暂无服务描述')}</span>
</Card>
</div>
);
}}
components={{
List: forwardRef(({ style, children, ...props }, ref) => (
<div
ref={ref}
{...props}
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))',
columnGap: '20px',
padding:'40px',
...style,
paddingBottom:'40px'
<Spin className="h-full" wrapperClassName="h-full" indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />} spinning={filterOption.listLoading}>
{filterOption.showServicesList && filterOption.showServicesList.length > 0 ? <VirtuosoGrid
style={{ height: '100%'}}
data={filterOption.showServicesList}
totalCount={filterOption.showServicesList.length}
itemContent={(index) => {
const item = filterOption.showServicesList[index];
return (
<div className="pt-[20px]">
<Card title={CardTitle(item)} className="shadow-[0_5px_10px_0_rgba(0,0,0,0.05)] rounded-[10px] overflow-visible cursor-pointer h-[180px] m-0 transition duration-500 hover:shadow-[0_5px_20px_0_rgba(0,0,0,0.15)] hover:scale-[1.05]" classNames={{header:'border-b-[0px] p-[20px] ', body:"pt-0"}} onClick={()=>showDocumentDetail(item)}>
<span className="line-clamp-3 text-[12px] text-[#666] "
style={{'word-break':'auto-phrase'}}>{item.description || $t('暂无服务描述')}</span>
</Card>
</div>
);
}}
>
{children}
</div>
)),
Item: ({ children, ...props }) => (
<>
{children}</>
)
}}
/>:<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>}
</Spin>
components={{
List: forwardRef(({ style, children, ...props }, ref) => (
<div
ref={ref}
{...props}
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))',
columnGap: '20px',
padding:'40px',
...style,
paddingBottom:'40px'
}}
>
{children}
</div>
)),
Item: ({ children, ...props }) => (
<>
{children}</>
)
}}
/>:<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>}
</Spin>
</div>
</ServiceHubGroup>
)
@@ -186,7 +186,7 @@ const CardTitle = (service:ServiceHubTableListItem)=>{
<Tooltip title={$t('API 数量')}>
<span className="mr-[12px] flex items-center"><ApiOutlined className="mr-[1px] text-[14px] h-[14px] w-[14px]"/><span className="font-normal text-[14px]">{service.apiNum ?? '-'}</span></span>
</Tooltip>
<Tooltip title={$t('接入应用数量')}>
<Tooltip title={$t('接入消费者数量')}>
<span className="mr-[12px] flex items-center"><span className="h-[14px] mr-[4px] flex items-center "><iconpark-icon size="14px" name="auto-generate-api"></iconpark-icon></span><span className="font-normal text-[14px]">{service.subscriberNum ?? '-'}</span></span>
</Tooltip>
</div>
@@ -8,7 +8,7 @@ export default function ManagementAppSetting(){
return (
<div className=" h-full pt-[32px]">
<div className="flex items-center justify-between w-full ml-[10px] text-[18px] leading-[25px] pb-[16px]" ><span className="font-bold">{$t('应用管理')}</span></div>
<div className="flex items-center justify-between w-full ml-[10px] text-[18px] leading-[25px] pb-[16px]" ><span className="font-bold">{$t('消费者管理')}</span></div>
<div className="h-[calc(100%-41px)] flex flex-col ">
<ManagementConfig type='edit' teamId={teamId!} appId={appId!}/>
</div>
@@ -96,7 +96,7 @@ const ManagementConfig = forwardRef<ManagementConfigHandle,ManagementConfigProps
const {code,msg} = response
if(code === STATUS_CODE.SUCCESS){
message.success(msg || $t(RESPONSE_TIPS.success))
navigate(`/tenantManagement/list`)
navigate(`/consumer/list`)
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
}
@@ -131,7 +131,7 @@ const ManagementConfig = forwardRef<ManagementConfigHandle,ManagementConfigProps
>
<div>
<Form.Item<ManagementConfigFieldType>
label={$t("应用名称")}
label={$t("消费者名称")}
name="name"
rules={[{ required: true,whitespace:true }]}
>
@@ -139,7 +139,7 @@ const ManagementConfig = forwardRef<ManagementConfigHandle,ManagementConfigProps
</Form.Item>
<Form.Item<ManagementConfigFieldType>
label={$t("应用 ID")}
label={$t("消费者 ID")}
name="id"
rules={[{ required: true ,whitespace:true }]}
>
@@ -167,10 +167,10 @@ const ManagementConfig = forwardRef<ManagementConfigHandle,ManagementConfigProps
<WithPermission access="team.application.application.delete" showDisabled={false}>
<div className="bg-[rgb(255_120_117_/_5%)] rounded-[10px] mt-[50px] p-btnrbase pb-0">
<p className="text-left"><span className="font-bold">{$t('删除应用')}</span>{$t('删除操作不可恢复,请谨慎操作!')}</p>
<p className="text-left"><span className="font-bold">{$t('删除消费者')}</span>{$t('删除操作不可恢复,请谨慎操作!')}</p>
<div className="text-left">
<WithPermission access="team.application.application.delete">
<Button className="m-auto mt-[16px] mb-[20px]" type="default" danger={true} onClick={deleteApplicationModal} loading={delBtnLoading}>{$t('删除应用')}</Button>
<Button className="m-auto mt-[16px] mb-[20px]" type="default" danger={true} onClick={deleteApplicationModal} loading={delBtnLoading}>{$t('删除消费者')}</Button>
</WithPermission>
</div>
</div>
@@ -32,7 +32,7 @@ export default function ManagementInsidePage(){
const TENANT_MANAGEMENT_APP_MENU: MenuProps['items'] = useMemo(()=>[
getItem($t('订阅的服务'), 'service'),
getItem($t('访问授权'), 'authorization'),
getItem($t('应用管理'), 'setting'),
getItem($t('消费者管理'), 'setting'),
],[state.language])
const menuData = useMemo(()=>{
@@ -45,7 +45,7 @@ export default function ManagementInsidePage(){
const onMenuClick: MenuProps['onClick'] = (node) => {
setActiveMenu(node.key)
navigateTo(`/tenantManagement/${teamId}/inside/${appId}/${node.key}`)
navigateTo(`/consumer/${teamId}/inside/${appId}/${node.key}`)
};
useEffect(()=>{
@@ -60,7 +60,7 @@ export default function ManagementInsidePage(){
}
setBreadcrumb(
[
{title:<Link to={`/tenantManagement/list/${teamId}`}>{$t('应用')}</Link>},
{title:<Link to={`/consumer/list/${teamId}`}>{$t('消费者')}</Link>},
...(_appName ? [{title:_appName}] : [])
]
)
@@ -84,7 +84,7 @@ useEffect(()=>{
<div className="flex flex-1 h-full">
<div className="w-[220px] border-0 border-solid border-r-[1px] border-r-BORDER">
<div className="text-[18px] leading-[25px] pl-[12px] py-[12px]">
<Button type="text" onClick={()=>navigateTo(`/tenantManagement/list/${teamId}`)}><ArrowLeftOutlined className="max-h-[14px]" />{$t('返回')}</Button>
<Button type="text" onClick={()=>navigateTo(`/consumer/list/${teamId}`)}><ArrowLeftOutlined className="max-h-[14px]" />{$t('返回')}</Button>
</div>
<Menu
onClick={onMenuClick}
@@ -1,7 +1,7 @@
import { MenuProps, Menu, App, Avatar, Card, Tooltip, Empty } from "antd";
import { useState, forwardRef, useEffect, useRef } from "react";
import { MenuProps, Menu, App, Avatar, Card, Tooltip, Empty, Button, Radio } from "antd";
import { useState, forwardRef, useEffect, useRef, useMemo, memo } from "react";
import { VirtuosoGrid } from "react-virtuoso";
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const";
import { BasicResponse, DATA_SHOW_TYPE_OPTIONS, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const";
import { ServiceHubAppListItem } from "../../../const/serviceHub/type";
import { useFetch } from "@common/hooks/http";
import { useBreadcrumb } from "@common/contexts/BreadcrumbContext";
@@ -14,6 +14,9 @@ import { Icon } from "@iconify/react/dist/iconify.js";
import { useGlobalContext } from "@common/contexts/GlobalStateContext";
import { $t } from "@common/locales";
import WithPermission from "@common/components/aoplatform/WithPermission";
import InsidePage from "@common/components/aoplatform/InsidePage";
import PageList from "@common/components/aoplatform/PageList";
import { SERVICE_HUB_TABLE_COLUMNS } from "@market/const/serviceHub/const";
export default function ServiceHubManagement() {
const { message ,modal} = App.useApp()
@@ -27,30 +30,48 @@ export default function ServiceHubManagement() {
const [teamList, setTeamList] = useState<MenuItem[]>([])
const {setAppName} = useTenantManagementContext()
const navigateTo = useNavigate()
const {getTeamAccessData,cleanTeamAccessData,checkPermission,getGlobalAccessData,accessInit} = useGlobalContext()
const {getTeamAccessData,cleanTeamAccessData,checkPermission,getGlobalAccessData,accessInit,state} = useGlobalContext()
type MenuItem = Required<MenuProps>['items'][number];
const [dataShowType, setDataShowType] = useState<'block'|'list'>('list')
const [tableHttpReload, setTableHttpReload] = useState(true);
const [tableListDataSource, setTableListDataSource] = useState<ServiceHubAppListItem[]>([]);
const [tableSearchWord, setTableSearchWord] = useState<string>('')
const getServiceList = ()=>{
if(!accessInit){
getGlobalAccessData()?.then?.(()=>{getServiceList()})
return
return Promise.resolve({data:[], success:false})
}
if(dataShowType === 'list' && !tableHttpReload){
setTableHttpReload(true)
return Promise.resolve({
data: tableListDataSource,
success: true,
});
}
setServiceLoading(true)
return fetchData<BasicResponse<{apps:ServiceHubAppListItem}>>(!checkPermission('system.workspace.application.view_all') ? 'my_apps':'apps',{method:'GET',eoParams:{ team:teamId,keyword:''},eoTransformKeys:['api_num','subscribe_num','subscribe_verify_num']}).then(response=>{
return fetchData<BasicResponse<{apps:ServiceHubAppListItem}>>(!checkPermission('system.workspace.application.view_all') ? 'my_apps':'apps',{method:'GET',eoParams:{ team:teamId,keyword:tableSearchWord},eoTransformKeys:['api_num','subscribe_num','subscribe_verify_num']}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
setServiceList([...data.apps,{type:'addNewItem'}])
setTableListDataSource(data.apps)
setTableHttpReload(false)
return {data:data.apps, success: true}
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
return {data:[], success:false}
}
}).catch(() => {
return {data:[], success:false}
}).finally(()=>{
setServiceLoading(false)
})
}
const onClick: MenuProps['onClick'] = (e) => {
navigateTo(`/tenantManagement/list/${e.key}`)
navigateTo(`/consumer/list/${e.key}`)
};
@@ -82,7 +103,7 @@ const getServiceList = ()=>{
let content:string|React.ReactNode = ''
switch (type){
case 'add':
title=$t('添加应用')
title=$t('添加消费者')
content=<ManagementConfig ref={addManagementRef} type={type} teamId={teamId!} />
break;
// case 'edit':{
@@ -124,10 +145,14 @@ const getServiceList = ()=>{
})
}
const dataShowTypeOptions = useMemo(()=>DATA_SHOW_TYPE_OPTIONS.map((x)=>({label:$t(x.label),value:x.value})),[
state.language
])
useEffect(()=>{
if(teamId ){
getTeamAccessData(teamId)
getServiceList()
if(dataShowType === 'block'){getServiceList()}
}
return ()=>{
cleanTeamAccessData()
@@ -137,70 +162,94 @@ useEffect(()=>{
useEffect(() => {
setBreadcrumb(
[
{title:$t('应用')}
{title:$t('消费者')}
]
)
getTeamsList()
setAppName('')
}, []);
const BlockArea = ()=>(
<div className="flex flex-1 h-full">
<div className="w-[220px] border-0 border-solid border-r-[1px] border-r-BORDER h-full overflow-hidden">
<div className="text-[18px] leading-[25px] pl-[20px] pt-[20px] pb-[10px] font-bold">{$t('团队')}</div>
<Menu
onClick={onClick}
style={{ width: 220}}
className="overflow-auto h-[calc(100%-55px)]"
mode="inline"
items={teamList}
selectedKeys={teamId?[teamId]:[]}
/>
</div>
<div className="w-[calc(100%-220px)] padding-top-20">
<div className="mt-[20px] ml-[40px] text-[18px] leading-[25px] font-bold">{$t('消费者')}</div>
<VirtuosoGrid
style={{ height: 'calc(100% - 45px)'}}
data={serviceList}
totalCount={serviceList.length}
itemContent={(index) => {
const item = serviceList[index];
return (
<div className="pt-[20px]">{
item.type === 'addNewItem' ?<WithPermission access="team.application.application.add" showDisabled={false}><Card className="shadow-[0_5px_10px_0_rgba(0,0,0,0.05)] rounded-[10px] overflow-visible cursor-pointer h-[180px] transition duration-500 hover:shadow-[0_5px_20px_0_rgba(0,0,0,0.15)] hover:scale-[1.05]" classNames={{body:'h-[180px] flex items-center justify-center cursor-pointer'}} onClick={()=>{openModal('add')}}>
<div className="flex items-center"><Icon icon="ic:baseline-add" width="18" height="18"/><span>{$t('添加消费者')}</span></div>
</Card></WithPermission> : <Card title={CardTitle(item)} className="shadow-[0_5px_10px_0_rgba(0,0,0,0.05)] rounded-[10px] overflow-visible cursor-pointer h-[180px] transition duration-500 hover:shadow-[0_5px_20px_0_rgba(0,0,0,0.15)] hover:scale-[1.05]" classNames={{header:'border-b-[0px] p-[20px] ', body:"pt-0"}} onClick={()=>{setAppName(item.name);navigateTo(`/consumer/${teamId}/inside/${item.id}/service`)}}>
<span className="line-clamp-3 break-all">{item.description || $t('暂无服务描述')}</span>
</Card>}</div>
);
}}
components={{
List: forwardRef(({ style, children, ...props }, ref) => (
<div
ref={ref}
{...props}
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))',
columnGap: '20px',
padding:'40px',
...style,
paddingBottom:'40px'
}}
>
{children}
</div>
)),
Item: ({ children, ...props }) => (
<>
{children}</>
)
}}
/>
</div>
</div>
)
return (<>{
teamList && teamList.length > 0 ?
<div className="flex flex-1 h-full">
<div className="w-[220px] border-0 border-solid border-r-[1px] border-r-BORDER h-full overflow-hidden">
<div className="text-[18px] leading-[25px] pl-[20px] pt-[20px] pb-[10px] font-bold">{$t('团队')}</div>
<Menu
onClick={onClick}
style={{ width: 220}}
className="overflow-auto h-[calc(100%-55px)]"
mode="inline"
items={teamList}
selectedKeys={teamId?[teamId]:[]}
/>
</div>
<div className="w-[calc(100%-220px)] padding-top-20">
<div className="mt-[20px] ml-[40px] text-[18px] leading-[25px] font-bold">{$t('应用')}</div>
<VirtuosoGrid
style={{ height: 'calc(100% - 45px)'}}
data={serviceList}
totalCount={serviceList.length}
itemContent={(index) => {
const item = serviceList[index];
return (
<div className="pt-[20px]">{
item.type === 'addNewItem' ?<WithPermission access="team.application.application.add" showDisabled={false}><Card className="shadow-[0_5px_10px_0_rgba(0,0,0,0.05)] rounded-[10px] overflow-visible cursor-pointer h-[180px] transition duration-500 hover:shadow-[0_5px_20px_0_rgba(0,0,0,0.15)] hover:scale-[1.05]" classNames={{body:'h-[180px] flex items-center justify-center cursor-pointer'}} onClick={()=>{openModal('add')}}>
<div className="flex items-center"><Icon icon="ic:baseline-add" width="18" height="18"/><span>{$t('添加应用')}</span></div>
</Card></WithPermission> : <Card title={CardTitle(item)} className="shadow-[0_5px_10px_0_rgba(0,0,0,0.05)] rounded-[10px] overflow-visible cursor-pointer h-[180px] transition duration-500 hover:shadow-[0_5px_20px_0_rgba(0,0,0,0.15)] hover:scale-[1.05]" classNames={{header:'border-b-[0px] p-[20px] ', body:"pt-0"}} onClick={()=>{setAppName(item.name);navigateTo(`/tenantManagement/${teamId}/inside/${item.id}/service`)}}>
<span className="line-clamp-3 break-all">{item.description || $t('暂无服务描述')}</span>
</Card>}</div>
);
}}
components={{
List: forwardRef(({ style, children, ...props }, ref) => (
<div
ref={ref}
{...props}
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))',
columnGap: '20px',
padding:'40px',
...style,
paddingBottom:'40px'
}}
>
{children}
</div>
)),
Item: ({ children, ...props }) => (
<>
{children}</>
)
}}
/>
</div>
</div> :
<InsidePage
className="overflow-y-auto pb-PAGE_INSIDE_B"
pageTitle={$t('消费者')}
description={$t('创建并管理自己的消费者实体,每个消费者可以订阅多个API服务,确保在调用之前已获得相应权限。你可以为消费者生成 API 密钥等鉴权方式,用于安全地调用 API 服务')}
showBorder={false}
scrollPage={false}
contentClassName={dataShowType === 'list' ? 'pr-PAGE_INSIDE_X pb-PAGE_INSIDE_B' :''}
customBtn={
<Radio.Group
options={dataShowTypeOptions}
onChange={(e)=>setDataShowType(e.target.value)}
value={dataShowType}
optionType="button"
buttonStyle="solid"
/>}
>{
dataShowType === 'block' ? <BlockArea /> : <TableArea language={state.language} getServiceList={getServiceList} addNewApp={()=>openModal('add')} setTableHttpReload={setTableHttpReload} setTableSearchWord={setTableSearchWord} editApp={(row:ServiceHubAppListItem)=>{setAppName(row.name);navigateTo(`/consumer/${row.team.id}/inside/${row.id}/service`)}}/>
}
</InsidePage> :
<Empty className="mt-[100px]" image={Empty.PRESENTED_IMAGE_SIMPLE} />
}
</>)
@@ -220,4 +269,39 @@ const CardTitle = (service:ServiceHubAppListItem)=>{
</div>
</div>
)
}
}
type TableAreaProps = {
language:string
getServiceList:()=>Promise<{data:ServiceHubAppListItem[], success:boolean}>
addNewApp:()=>Promise<void>
setTableHttpReload:(b:boolean)=>void
setTableSearchWord:(s:string)=>void
editApp:(item:ServiceHubAppListItem)=>void
}
const TableArea = memo(({language, getServiceList, addNewApp, setTableHttpReload, setTableSearchWord, editApp}:TableAreaProps)=>{
const columns = useMemo(()=>{
const res = SERVICE_HUB_TABLE_COLUMNS.map(x=>{
return {...x,title:typeof x.title === 'string' ? $t(x.title as string) : x.title}})
return res
},[language])
return (
<PageList
id="service_hub_list"
columns={[...columns]}
request={()=>getServiceList()}
addNewBtnTitle={$t("添加服务")}
searchPlaceholder={$t("输入名称、ID 查找服务")}
onAddNewBtnClick={addNewApp}
onChange={() => {
setTableHttpReload(false)
}}
onSearchWordChange={(e) => {
setTableSearchWord(e.target.value)
}}
onRowClick={(row:ServiceHubAppListItem)=>editApp(row)}
/>
)})
@@ -5,14 +5,14 @@ import { $t } from "@common/locales/index.ts";
export const OPENAPI_LIST_COLUMNS: PageProColumns<OpenApiTableListItem>[] = [
{
title:$t('应用名称'),
title:$t('消费者名称'),
dataIndex: 'name',
ellipsis:true,
width:160,
fixed:'left'
},
{
title:$t('应用 ID'),
title:$t('消费者 ID'),
dataIndex: 'id',
ellipsis:true,
width: 140,
@@ -69,7 +69,7 @@ export const OpenApiConfig = forwardRef<OpenApiConfigHandle,OpenApiConfigProps>(
autoComplete="off"
>
<Form.Item<OpenApiConfigFieldType>
label={$t("应用名称")}
label={$t("消费者名称")}
name="name"
rules={[{ required: true,whitespace:true }]}
>
@@ -77,7 +77,7 @@ export const OpenApiConfig = forwardRef<OpenApiConfigHandle,OpenApiConfigProps>(
</Form.Item>
<Form.Item<OpenApiConfigFieldType>
label={$t("应用 ID")}
label={$t("消费者 ID")}
name="id"
rules={[{ required: true ,whitespace:true }]}
>
@@ -216,7 +216,7 @@ export default function OpenApiList(){
dataSource={tableListDataSource}
showPagination={false}
primaryKey="id"
addNewBtnTitle={$t("添加应用")}
addNewBtnTitle={$t("添加消费者")}
addNewBtnAccess="system.openapi.self.add"
onChange={() => {
setTableHttpReload(false)