diff --git a/frontend/README.md b/frontend/README.md index 68a7459a..61e84890 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,9 +1,3 @@ - # 部署 ## 安装依赖 diff --git a/frontend/i18next-scanner.config.js b/frontend/i18next-scanner.config.js index 9bcc8a4d..ed5a320b 100644 --- a/frontend/i18next-scanner.config.js +++ b/frontend/i18next-scanner.config.js @@ -1,24 +1,37 @@ const fs = require('fs'); +const path = require('path'); const { crc32 } = require('crc'); const systemLanguage = { + en_US: 'en-US', zh_CN: 'zh-CN', - en_GB: 'en-GB' + ja_JP: 'ja-JP', + zh_TW: 'zh-TW' }; -// 读取已经存在在en.json文件的词条 +const localesDir = 'packages/common/src/locales/scan'; +const newJsonDir = 'packages/common/src/locales/scan/newJson'; +const keyHashFile = 'packages/common/src/locales/keyHashMap.json'; let existData = {}; -try { - console.log('Current working directory:', process.cwd()); - const existJsonData = fs.readFileSync('packages/common/src/locales/scan/en-GB.json'); - existData = JSON.parse(existJsonData); -} catch (error) { - if (error.code === 'ENOENT') { - console.warn('File not found: packages/common/src/locales/scan/en-GB.json. Creating an empty file.'); - fs.writeFileSync('packages/common/src/locales/scan/en-GB.json', JSON.stringify({})); - } else { - throw error; +let keyHashMap = {}; +fs.readdirSync(localesDir).forEach(file => { + if (path.extname(file) === '.json') { + const lang = path.basename(file, '.json'); + const filePath = path.join(localesDir, file); + try { + console.log('Current working directory:', process.cwd(),filePath); + const existJsonData = fs.readFileSync(filePath); + existData[lang] = JSON.parse(existJsonData); + } catch (error) { + if (error.code === 'ENOENT') { + console.warn(`File not found: ${filePath}. Creating an empty file.`); + fs.writeFileSync(filePath, JSON.stringify({})); + existData[lang] = {}; + } else { + throw error; + } + } } -} +}); const keyList = Object.keys(existData); @@ -34,7 +47,7 @@ module.exports = { debug: true, func: false, trans: false, - lngs: [systemLanguage.zh_CN, systemLanguage.en_GB], + lngs: [systemLanguage.zh_CN, systemLanguage.en_US, systemLanguage.ja_JP, systemLanguage.zh_TW], defaultLng: systemLanguage.zh_CN, resource: { loadPath: './newJson/{{lng}}.json', // 输入路径 (手动新建目录) @@ -58,11 +71,45 @@ module.exports = { parser.parseFuncFromString(content, { list: ['t'] }, (key, options) => { options.defaultValue = key; const hashKey = `K${crc32(key).toString(16)}`; // crc32转换格式 - // 如果词条不存在,则写入 - if (!keyList.includes(hashKey)) { - parser.set(hashKey, options); - } + keyHashMap[key] = hashKey; + + + // 遍历每种语言,逐个语言检查翻译是否存在 + keyList.forEach((lng) => { + const langData = existData[lng] || {}; + + // 如果某语言没有翻译该字段,则记录到该语言的 newJson 文件中 + if (!langData[hashKey]) { + const newJsonPath = path.join(newJsonDir, `${lng}.json`); + let newJsonData = {}; + + // 读取当前语言的 newJson 文件,如果已存在,则加载 + try { + const newJsonRaw = fs.readFileSync(newJsonPath); + newJsonData = JSON.parse(newJsonRaw); + } catch (error) { + if (error.code !== 'ENOENT') { + throw error; + } + } + + // 只添加尚未存在的 key + if (!newJsonData[hashKey]) { + newJsonData[hashKey] = options.defaultValue; // 使用原始 key 作为默认值 + fs.writeFileSync(newJsonPath, JSON.stringify(newJsonData, null, 2)); + } + } + }); + // // 如果词条不存在,则写入 + // if (!keyList.includes(hashKey)) { + // parser.set(hashKey, options); + // } }); done(); + }, + flush: function(done) { + // 将 keyHashMap 写入文件 + fs.writeFileSync(keyHashFile, JSON.stringify(keyHashMap, null, 2)); + done(); } }; \ No newline at end of file diff --git a/frontend/packages/businessEntry/src/components/aoplatform/RenderRoutes.tsx b/frontend/packages/businessEntry/src/components/aoplatform/RenderRoutes.tsx index f59db307..76e06bfd 100644 --- a/frontend/packages/businessEntry/src/components/aoplatform/RenderRoutes.tsx +++ b/frontend/packages/businessEntry/src/components/aoplatform/RenderRoutes.tsx @@ -248,8 +248,8 @@ const PUBLIC_ROUTES:RouteConfig[] = [ }] }, { - path:'servicecategories', - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/serviceCategory/ServiceCategory.tsx')), + path:'commonsetting', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/common/CommonPage.tsx')), key:uuidv4(), }, { diff --git a/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx b/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx index 86e851d0..4bba087c 100644 --- a/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx +++ b/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx @@ -49,31 +49,27 @@ const themeToken = { getNavItem($t('工作空间'), 'workspace','/guide/page',, [ getNavItem({$t('首页')}, 'guide','/guide/page',,undefined,undefined,'all'), getNavItem({$t('应用')}, 'tenantManagement','/tenantManagement',,undefined,undefined,'all'), + getNavItem({$t('服务')}, 'service','/service',,undefined,undefined,'all'), getNavItem({$t('团队')}, 'team','/team',,undefined,undefined,'all'), - getNavItem($t('服务'), 'my','/service',null,[ - getNavItem({$t('REST 服务')}, 'service','/service',,undefined,undefined,''), - getNavItem({$t('AI 服务')}, 'aiservice','/aiservice',,undefined,undefined,''), - ],undefined,''), ]), - getNavItem({$t('API 市场')}, 'serviceHub','/serviceHub',,undefined,undefined,'system.workspace.api_market.view'), + getNavItem($t('API 市场'), 'serviceHub','/serviceHub',,undefined,undefined,'system.workspace.api_market.view'), getNavItem($t('仪表盘'), 'mainPage', APP_MODE === 'pro' ? '/analytics' : '/analytics/total',,[ getNavItem({$t('运行视图')}, 'analytics',APP_MODE === 'pro' ? '/analytics' : '/analytics/total' ,,undefined,undefined,'system.dashboard.run_view.view'), APP_MODE === 'pro' ? getNavItem({$t('系统拓扑图')}, 'systemrunning','/systemrunning',,undefined,undefined,'system.dashboard.systemrunning.view') : null, ],undefined,'system.dashboard.run_view.view'), - getNavItem($t('系统设置'), 'operationCenter','/member',, [ - getNavItem($t('组织'), 'organization','/member',null,[ - getNavItem({$t('成员')}, 'member','/member',,undefined,undefined,'system.organization.member.view'), + getNavItem($t('系统设置'), 'operationCenter','/commonsetting',, [ + getNavItem($t('系统'), 'serviceHubSetting','/commonsetting',null,[ + getNavItem({$t('常规')}, 'commonsetting','/commonsetting',,undefined,undefined,'system.api_market.service_classification.view'), + getNavItem({$t('API 网关')}, 'cluster','/cluster',,undefined,undefined,'system.devops.cluster.view'), + getNavItem({$t('AI 模型')}, 'aisetting','/aisetting',,undefined,undefined,'system.devops.cluster.view'), + ],undefined,'system.api_market.service_classification.view'), + getNavItem($t('用户'), 'organization','/member',null,[ + getNavItem({$t('账号')}, 'member','/member',,undefined,undefined,'system.organization.member.view'), getNavItem({$t('角色')}, 'role','/role',,undefined,undefined,'system.organization.role.view'), ],undefined,''), - getNavItem($t('API 市场'), 'serviceHubSetting','/servicecategories',null,[ - getNavItem({$t('服务分类管理')}, 'servicecategories','/servicecategories',,undefined,undefined,'system.api_market.service_classification.view'), - ],undefined,'system.api_market.service_classification.view'), - - getNavItem($t('运维与集成'), 'maintenanceCenter','/cluster', null, [ - getNavItem({$t('集群')}, 'cluster','/cluster',,undefined,undefined,'system.devops.cluster.view'), - getNavItem({$t('AI 配置')}, 'aisetting','/aisetting',,undefined,undefined,'system.devops.cluster.view'), + getNavItem($t('集成'), 'maintenanceCenter','/datasourcing', null, [ getNavItem({$t('数据源')}, 'datasourcing','/datasourcing',,undefined,undefined,'system.devops.data_source.view'), getNavItem({$t('证书')}, 'cert','/cert',,undefined,undefined,'system.devops.ssl_certificate.view'), getNavItem({$t('日志')}, 'logsettings','/logsettings',,undefined,undefined,'system.devops.log_configuration.view'), @@ -171,14 +167,14 @@ const themeToken = { { key: '2', label: ( - ) }, { key: '3', label: ( - ) }, @@ -200,7 +196,6 @@ const themeToken = { return document.getElementById('test-pro-layout') || document.body; }} > - { const { dispatch,state} = useGlobalContext() const items = [ - { - key: 'cn', - label: , - title: $t('简体'), - }, - { - key: 'en', - label:, - title:$t('英文') - } + title:'English' + }, + { + key: 'ja-JP', + label: , + title: '日本語', + }, + { + key: 'zh-TW', + label: , + title: '繁體中文', + }, + { + key: 'zh-CN', + label: , + title: '简体中文', + }, ]; const langLabel = useMemo(()=>items.find((item) => item?.key === state.language)?.title,[state.language]) @@ -30,9 +44,9 @@ const LanguageSetting = ({mode = 'light'}:{mode?:'dark'|'light'}) => { const savedLang = sessionStorage.getItem('i18nextLng') const browserLang = navigator.language || navigator.userLanguage if(savedLang){ - dispatch({ type: 'UPDATE_LANGUAGE', language: savedLang.startsWith('cn') ? 'cn' : 'en' }); + dispatch({ type: 'UPDATE_LANGUAGE', language: savedLang }); }else{ - dispatch({ type: 'UPDATE_LANGUAGE', language: browserLang.startsWith('zh') ? 'cn' : 'en' }); + dispatch({ type: 'UPDATE_LANGUAGE', language: browserLang }); } },[ ]) diff --git a/frontend/packages/common/src/components/aoplatform/UnUsedWordForTranslate.tsx b/frontend/packages/common/src/components/aoplatform/UnUsedWordForTranslate.tsx index ded5ec87..5dc6f1b2 100644 --- a/frontend/packages/common/src/components/aoplatform/UnUsedWordForTranslate.tsx +++ b/frontend/packages/common/src/components/aoplatform/UnUsedWordForTranslate.tsx @@ -1,15 +1,65 @@ import { $t } from "@common/locales" -/* 本组件不在页面渲染,只是为了让i18next-scanner能找到从接口传递的、需要翻译的字段 */ +/* 本组件不在页面渲染,只是为了让i18next-scanner能找到从接口传递的、需要翻译的字段 , 此处的字段除非确认不在页面上渲染了,否则不应删除,容易导致翻译遗漏*/ export const TranslateWord = ()=>{ return ( - <> + <> + {$t('文件日志')} + {$t('HTTP日志')} + {$t('Kafka日志')} + {$t('NSQ日志')} + {$t('Syslog日志')} + {$t('未分配')} + {$t('超级管理员')} + {$t('团队管理员')} + {$t('运维管理员')} + {$t('普通成员')} + {$t('只读成员')} + {$t('服务管理员')} + {$t('服务开发者')} + {$t('应用开发者')} + {$t('应用管理员')} + {$t('驱动名称')} + {$t('请求失败数')} + {$t('转发失败数')} + {$t('作用范围')} + {$t('添加条目')} + {$t('添加地址')} + {$t('文件名称')} + {$t('存放目录')} + {$t('日志分割周期')} + {$t('过期时间')} + {$t('单位:天')} + {$t('输出格式')} + {$t('格式化配置')} + {$t('服务器地址')} + {$t('Access日志')} + {$t('NSQD地址列表')} + {$t('鉴权Secret')} + {$t('网络协议')} + {$t('日志等级')} + {$t('单行')} + {$t('小时')} + {$t('天')} + {$t('未发布')} + {$t('待发布')} + {$t('单位:s,最小值:1')} {$t('上传文件')} {$t('替换文件')} {$t('是否放行')} {$t('监控')} {$t('必填')} {$t('字符非法,仅支持英文')} + {$t('上传 OpenAPI 文档 (.json/.yaml)')} + {$t('替换 OpenAPI 文档 (.json/.yaml)')} + {$t('打开 OpenAPI YAML 编辑器')} + {$t('无需审批:允许任何应用调用该服务')} + {$t('人工审批:仅允许通过人工审批的应用调用该服务')} + {$t('永久')} + {$t('否')} + {$t('是')} + {$t('无需审批')} + {$t('需要审批')} ) } \ No newline at end of file diff --git a/frontend/packages/common/src/components/aoplatform/WithPermission.tsx b/frontend/packages/common/src/components/aoplatform/WithPermission.tsx index 72ab3525..e092d411 100644 --- a/frontend/packages/common/src/components/aoplatform/WithPermission.tsx +++ b/frontend/packages/common/src/components/aoplatform/WithPermission.tsx @@ -32,13 +32,14 @@ const WithPermission = ({access, tooltip, children,disabled, showDisabled = true return ( - <> + <>{ + } {editAccess && !disabled && cloneElement(children)} {editAccess && disabled && { cloneElement(children, {disabled:true})} } - {!editAccess && (children?.type !== Button && children?.type !== Upload && showDisabled ) && - { cloneElement(children, {disabled:true})} + {!editAccess && (children?.type !== Button && children?.type !== Upload && showDisabled) && + { cloneElement(children, {disabled:true,okButtonProps:{disabled:true}})} } diff --git a/frontend/packages/common/src/components/aoplatform/intelligent-plugin/IntelligentPluginConfig.tsx b/frontend/packages/common/src/components/aoplatform/intelligent-plugin/IntelligentPluginConfig.tsx index 4b52bc89..aa3c3e8a 100644 --- a/frontend/packages/common/src/components/aoplatform/intelligent-plugin/IntelligentPluginConfig.tsx +++ b/frontend/packages/common/src/components/aoplatform/intelligent-plugin/IntelligentPluginConfig.tsx @@ -176,7 +176,7 @@ export const IntelligentPluginConfig = forwardRef{ - setValidateLanguage(state.language === 'cn' ? 'zh-CN' : 'en-US') + setValidateLanguage(state.language) },[state.language]) const pluginEditSchema = { diff --git a/frontend/packages/common/src/const/const.tsx b/frontend/packages/common/src/const/const.tsx index 3476e58f..ee59a90a 100644 --- a/frontend/packages/common/src/const/const.tsx +++ b/frontend/packages/common/src/const/const.tsx @@ -23,9 +23,9 @@ export const routerKeyMap = new Map([ ['workspace',['tenantManagement','service','team','guide']], ['my',['tenantManagement','service','team']], ['mainPage',['dashboard','systemrunning']], - ['operationCenter',['member','user','role','servicecategories']], + ['operationCenter',['member','user','role','common']], ['organization',['member','user','role']], - ['serviceHubSetting',['servicecategories']], + ['serviceHubSetting',['common']], ['maintenanceCenter',['aisetting','datasourcing','cluster','cert','logsettings','resourcesettings','openapi'] ]]) diff --git a/frontend/packages/common/src/const/permissions.ts b/frontend/packages/common/src/const/permissions.ts index 954be69c..9d6ff2f7 100644 --- a/frontend/packages/common/src/const/permissions.ts +++ b/frontend/packages/common/src/const/permissions.ts @@ -121,22 +121,32 @@ export const PERMISSION_DEFINITION = [ }, "system.api_market.service_classification.view": { "granted": { - "anyOf": [{ "backend": ["system.api_market.service_classification.view"] }] + "anyOf": [{ "backend": ["system.settings.service_classification.view"] }] } }, "system.api_market.service_classification.add": { "granted": { - "anyOf": [{ "backend": ["system.api_market.service_classification.manager"] }] + "anyOf": [{ "backend": ["system.settings.service_classification.manager"] }] } }, "system.api_market.service_classification.edit": { "granted": { - "anyOf": [{ "backend": ["system.api_market.service_classification.manager"] }] + "anyOf": [{ "backend": ["system.settings.service_classification.manager"] }] } }, "system.api_market.service_classification.delete": { "granted": { - "anyOf": [{ "backend": ["system.api_market.service_classification.manager"] }] + "anyOf": [{ "backend": ["system.settings.service_classification.manager"] }] + } + }, + "system.devops.system_setting.view": { + "granted": { + "anyOf": [{ "backend": ["system.settings.general.view"] }] + } + }, + "system.devops.system_setting.edit": { + "granted": { + "anyOf": [{ "backend": ["system.settings.general.manager"] }] } }, "system.dashboard.run_view.view":{ @@ -459,6 +469,16 @@ export const PERMISSION_DEFINITION = [ "anyOf": [{ "backend": ["team.application.authorization.manager"] }] } }, + "team.application.authorization.cancelSubApply": { + "granted": { + "anyOf": [{ "backend": ["team.application.authorization.manager"] }] + } + }, + "team.application.authorization.cancelSub": { + "granted": { + "anyOf": [{ "backend": ["team.application.authorization.manager"] }] + } + }, "team.team.team.view": { "granted": { "anyOf": [{ "backend": ["team.team.team.view"] }] diff --git a/frontend/packages/common/src/locales/index.ts b/frontend/packages/common/src/locales/index.ts index c4899f1d..f83c77e2 100644 --- a/frontend/packages/common/src/locales/index.ts +++ b/frontend/packages/common/src/locales/index.ts @@ -5,19 +5,19 @@ import LanguageDetector from 'i18next-browser-languagedetector'; import crc32 from 'crc/crc32'; // 引入需要实现国际化的简体、繁体、英文三种数据的json文件 import zhCN from 'antd/locale/zh_CN'; -import enGB from 'antd/locale/en_GB'; +import enUS from 'antd/locale/en_US'; import localZh_CN from './scan/zh-CN.json'; // 本地翻译中文文件 -import localEn_GB from './scan/en-GB.json'; // 本地翻译英文文件 +import localEn_US from './scan/en-US.json'; // 本地翻译英文文件 // import config from '../../../../i18next-scanner.config.js'; const resources = { - cn: { + 'zh-CH': { translation: localZh_CN, ...zhCN }, - en: { - translation: localEn_GB, - ...enGB + 'en-US': { + translation: localEn_US, + ...enUS } }; diff --git a/frontend/packages/common/src/locales/keyHashMap.json b/frontend/packages/common/src/locales/keyHashMap.json new file mode 100644 index 00000000..537f805e --- /dev/null +++ b/frontend/packages/common/src/locales/keyHashMap.json @@ -0,0 +1,580 @@ +{ + "工作空间": "Kc0e5ef9f", + "首页": "K4de11e23", + "应用": "Kfe93ef35", + "服务": "Kb58e0c3f", + "团队": "Kc9e489f5", + "API 市场": "K61c89f5f", + "仪表盘": "K16d71239", + "运行视图": "K714c192d", + "系统拓扑图": "Kd57dfe97", + "系统设置": "K3fe97dcc", + "系统": "Kecbb0e45", + "常规": "Ka358e23d", + "API 网关": "K449058e9", + "AI 模型": "K99935e6f", + "用户": "K1deaa2dd", + "账号": "K80a560a1", + "角色": "Kf644225f", + "集成": "K4057391a", + "数据源": "K8fa58214", + "证书": "K481e8a05", + "日志": "Kca53edd0", + "资源": "Kb283e720", + "Open API": "K631d646f", + "账号设置": "K6535ff9c", + "退出登录": "Kf15499b4", + "文档": "Kabbd6e6", + "APIPark - 企业API数据开放平台": "K1196b104", + "HTTP 状态码": "K1f42de3", + "系统状态码": "K4770dff4", + "描述": "Kf89e58f1", + "提交": "K9e53c664", + "上一步": "Kf8e7294c", + "取消": "Ka0451c97", + "关闭": "Kb1dedda3", + "添加配置": "Kb2fc7600", + "编辑配置": "K4e07217d", + "编辑(0)": "K4ea968fe", + "添加(0)": "Ka7aaaeb", + "请输入Key": "Kaff78ecf", + "请输入Value": "K65d46535", + "返回": "Kc14b2ea3", + "ID": "K11d3633a", + "名称": "Kbff43de3", + "Driver": "K16ca79ef", + "已发布": "K7a369eef", + "下线": "Kcfa1a4d2", + "上线": "K771dc3b7", + "查看": "K530f5951", + "删除": "Kecbd7449", + "确认": "K1cbe2507", + "搜索(0)名称": "K48325b6", + "上下文": "Kc6340091", + "查询内容": "K74ecb1fa", + "会话历史": "K79f2e2f9", + "添加新变量": "K3a8912ee", + "添加工具": "Kb291a19", + "AI 模型调用默认仅使用 Query 变量,可输入 “{” 增加新变量。": "K27ece71d", + "静态上游": "Kdeed8399", + "该 API 缺失(0)(1)(2)请先补充": "K4ee62e8", + "转发信息,": "K385591f3", + "文档信息,": "K68415c14", + "上游信息,": "K133b75e9", + "成功": "K43fcaf94", + "上线失败": "Kc71c6a9", + "失败": "K56c686f8", + "申请系统": "K1ff96ff", + "所属团队": "K9bf855d6", + "申请人": "K11b994ed", + "申请时间": "K939baba7", + "版本号": "Kdab2e63b", + "版本说明": "K8b29c460", + "路由列表": "K4758140d", + "上游列表": "K54e44357", + "备注": "Kb8e8e6f5", + "上线情况": "K7e52ffa3", + "申请原因": "K1ab0ae5b", + "审核意见": "K53c00c3c", + "暂无(0)权限,请联系管理员分配。": "Kfd50704d", + "时间": "K7edf331d", + "近1小时": "Kef45b208", + "近24小时": "K9dbf22b8", + "近3天": "K820fbfab", + "近7天": "Kd6d28fc", + "文件日志": "K3d7465f7", + "HTTP日志": "Kc87167a0", + "Kafka日志": "K54630fe8", + "NSQ日志": "Kd5c3966e", + "Syslog日志": "K2e3de2c1", + "未分配": "K48322168", + "超级管理员": "K98f247f9", + "团队管理员": "K9c8a571f", + "运维管理员": "K929b485b", + "普通成员": "K82cc5ec2", + "只读成员": "Ke41d7451", + "服务管理员": "Kf99e8b66", + "服务开发者": "Kda8db57a", + "应用开发者": "K216a1ac7", + "应用管理员": "K27924db", + "驱动名称": "K8dc5c723", + "请求失败数": "Kda249fe8", + "转发失败数": "Kcf2df651", + "作用范围": "K7e6a859d", + "添加条目": "K3a008b34", + "添加地址": "Ke0599ef7", + "文件名称": "K48d3b5c4", + "存放目录": "Kafde0d2a", + "日志分割周期": "Kfb2926ac", + "过期时间": "K1a78e6f0", + "单位:天": "Kd96c2c69", + "输出格式": "Kc2b776fa", + "格式化配置": "K7b7cdac2", + "服务器地址": "K2f59807a", + "Access日志": "Kb1cfa6e7", + "NSQD地址列表": "K540488a8", + "鉴权Secret": "K8bc33a11", + "网络协议": "K1cd3002f", + "日志等级": "Kdfaa32c8", + "单行": "Kc0408d9c", + "小时": "Ke3db239d", + "天": "K3509a9f8", + "未发布": "Kb3960e83", + "待发布": "K8bd1e18", + "单位:s,最小值:1": "K225a6c43", + "上传文件": "Ke00c858c", + "替换文件": "K6d9dd1f5", + "是否放行": "K71753476", + "监控": "K597435c5", + "必填": "Ke66a17dd", + "字符非法,仅支持英文": "K28b68036", + "上传 OpenAPI 文档 (.json/.yaml)": "K6206e4ad", + "替换 OpenAPI 文档 (.json/.yaml)": "Kfba46e6d", + "打开 OpenAPI YAML 编辑器": "Kdac8ce7e", + "无需审批:允许任何应用调用该服务": "Kf5da1284", + "人工审批:仅允许通过人工审批的应用调用该服务": "Kc59ff06d", + "永久": "Kbfe02d7f", + "否": "K1e9c479e", + "是": "Kaddfcb6b", + "无需审批": "K6a7fa303", + "需要审批": "Kd196e8a4", + "暂无操作权限,请联系管理员分配。": "K23fda291", + "微信小程序": "K4618cb0a", + "获取文件,需填路径": "Ka854f511", + "暂不支持生成非 HTTPS 或非 HTTP 协议的代码示例": "Kaa11a695", + "搜索编程语言...": "Kbe46924e", + "编程语言": "Ke8e4f258", + "成功示例": "K29c07a47", + "失败示例": "K1f5c814d", + "默认 text/html;charset=UTF-8": "K4ef022d7", + "暂未填写示例": "Kd061b5bf", + "Binary": "Kc14cec33", + "请求头部": "K48b4d9e3", + "请求体": "Kcd347eaf", + "Query 参数": "K9e100bfe", + "REST 参数": "K3e9f12fd", + "api request editor": "K2bfa290c", + "返回头部": "Kb36d111a", + "返回值": "K980bde79", + "更多设置": "Kb04d201a", + "添加子参数": "Kee74f5b4", + "向下添加行": "Kc7d3106c", + "标签": "Keaabd222", + "参数名": "K8ad2c50e", + "类型": "K67d68dd1", + "必需": "K29245f47", + "示例": "Ke32cbcd3", + "输入 URL 或 cURL": "Kc13936c6", + "HTTP": "Ka1ede006", + "参数位置": "K152ac44e", + "匹配类型": "K1660ae72", + "参数值": "K91ced765", + "操作类型": "K5b265628", + "新增或修改": "K1826982d", + "匹配参数值": "Kd65b55f5", + "转发上游路径": "K15f35bf2", + "请求超时时间": "K79dec0dd", + "绑定上游服务": "K7d465645", + "重试时间": "K63a6404d", + "转发上游请求头": "K47740727", + "More": "K2b605d42", + "导入": "K1df9fbd5", + "导入格式": "K5e85df18", + "全量替换": "K9eaf7885", + "在末端插入": "Kf8c3a80b", + "增量更新": "Kd96b2d7d", + "请求头": "Kf2fc08eb", + "Rest 参数": "Ka45f1d8", + "大小": "K94bb113a", + "另存为文件": "K359919b5", + "响应": "K38bf1b90", + "响应头": "K59f4186e", + "正文": "K5f1e23fd", + "发送(Enter)": "Kf404ef7d", + "中止": "K2dbfd648", + "秒": "Kacabc771", + "复制": "K13ae6a93", + "格式化": "Ke54a14a3", + "搜索": "K43934f6d", + "替代": "K741decac", + "确定": "Kd507abff", + "The (0) must not be negative.": "Kca2d1624", + "The (0) must be greater than or equal to the (1).": "K792b255a", + "值枚举": "Kf0bed26d", + "枚举": "K633a03ca", + "最小长度": "Kd2766caf", + "最大长度": "Kd6d52485", + "最小值": "Kea15f66c", + "最大值": "K1af340ff", + "将文件拖拽至此处上传,或点击选择文件上传": "K68691e16", + "Upload Files": "Kcec46ae", + "Files Selected": "K760fb044", + "请填写接口名称": "Kea2bdee0", + "详细说明": "K49053438", + "高级匹配": "K148f6fa4", + "转发配置": "K3ae4c789", + "请求参数": "K2f4d0a37", + "返回示例": "Kde2d6dbd", + "测试 API": "K70e6069c", + "请求 Header": "Ke4603448", + "请求 Body": "K89fd86b3", + "请求示例代码": "K8747e3c4", + "响应示例": "K8613e6e7", + "响应 Header": "Kab1c2159", + "响应 Body": "Kd2be51d1", + "默认工作表": "K2a3f24ac", + "至": "K7e1ab4b0", + "详情": "Kf1b166e7", + "暂不支持带有双斜杠//的url": "K28555332", + "必填项": "K71661ee8", + "不是有效邮箱地址": "Kcbee3f8", + "最近一次更新者": "K617f34f1", + "最近一次更新时间": "K6ebca204", + "保存": "Kabfe9512", + "API 路由": "K51d1eb5d", + "API 文档": "Ka2b6d281", + "使用说明": "Kdefa9caa", + "发布": "K36856e71", + "订阅管理": "K6382bbfd", + "订阅审批": "K2eef4e4", + "订阅方管理": "Ka97bd9e5", + "管理": "K5974bf24", + "调用拓扑图": "K3fa5c4c3", + "设置": "Kb5c7b82d", + "服务 ID": "K1e84ad04", + "新增订阅方": "K39ab0358", + "手动添加": "K18307d56", + "订阅申请": "K705fe9f5", + "订阅方": "K3a67ea90", + "AI 路由设置": "Kefa2a4cf", + "路由名称": "K66060758", + "请求路径": "K5582ac8", + "提示词": "K2bb86fb4", + "变量": "K13ffbe88", + "输入这个接口的描述": "K79c8cfaf", + "重试次数": "K469e475a", + "模型配置": "K8a35059b", + "路由": "Kf9dcef3a", + "添加路由": "K6134bbe8", + "输入 URL 查找路由": "Kf85b83a0", + "模型供应商": "Kcf9f90b8", + "模型": "Kfede1c7c", + "参数": "Ke99513a0", + "审批": "K3818f03d", + "通过": "K54e27f57", + "拒绝": "K8582af3f", + "发布结果": "Kd568e15c", + "查看详情": "K35f990b0", + "申请发布": "Kdbc1f6cb", + "回滚": "Kb6860a3f", + "请确认是否回滚?": "Ka3494f4b", + "撤销申请": "Kb397a99f", + "请确认是否撤销申请?": "K7d401c0f", + "终止发布": "Ke1b79b93", + "请确认是否终止发布?": "Ka2449180", + "新建版本": "K2cb02f38", + "从 (0) 获取 API KEY": "Kb3e34847", + "已配置": "K66a7d24c", + "未配置": "Kaf074220", + "默认": "Kd9a46c29", + "AI 模型管理": "K7ac2be34", + "配置好 AI 模型后,你可以使用对应的大模型来创建 AI 服务": "K2260837a", + "同步最新模型": "K18dccc1a", + "待审批": "K6208054", + "已审批": "K74ab00a3", + "发布申请": "K56b4254f", + "API 调用地址": "Kea2f9279", + "API base URL 一般设置为API 网关的外部网络访问地址,或者是API网关绑定的域名。": "K7fc496a1", + "常规设置": "K8ab0fc95", + "API 请求设置": "Kb66fec9d", + "服务分类": "K4de0af74", + "添加子分类": "Kb4ceecea", + "修改分类名称": "K67479e88", + "添加分类": "K2bc75e2c", + "重命名分类": "Kab4aab44", + "分类名称": "Ke595a20a", + "父分类 ID": "K9679728f", + "子分类名称": "K9b2d08fd", + "快速接入 AI": "K71671763", + "配置你的 AI 模型": "Ka8a5ec5", + "通过 APIPark 快速接入各种 AI 模型,使用统一的格式来调用API,并且可以随意切换模型。": "K10d7e99f", + "创建 AI 服务和 API": "Kc057704a", + "创建 AI 类型的服务,并且你可以将 Prompt 提示词设置为一个 API,简化使用 AI 的流程。": "K76bb4a09", + "创建调用 Token": "K71b2c70f", + "为了安全地调用 API,你需要创建一个应用以及Token。": "K9bdd8403", + "调用": "Kc5738b6c", + "现在你可以通过 Token 来调用这些 API。": "Kd6d7ca1f", + "快速接入 REST API": "K86cf95f", + "创建 REST 服务和 API": "K7a3a8417", + "统计 API 调用情况": "K4a84214e", + "仪表盘中提供了多种统计图表,帮助我们了解 API 的运行情况。": "K297d8563", + "核心功能": "K2cdbb773", + "账号与角色": "K3378c50d", + "邀请你的团队成员加入 APIPark,共同管理和调用 API。": "Kda5bb930", + "团队中包含了人员、应用和服务,不同团队之间的应用和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。": "Kc8239422", + "服务内包含一组 API,并且可以发布到 API 市场被其他团队使用。": "Kd5be0cd7", + "权限管理": "K62e89ee7", + "订阅服务": "K8f7808e6", + "如果需要调用某个服务的 API,需要先订阅该服务,并且等待提供服务的团队审批后才可发起 API 请求。": "Kb0755523", + "审批订阅申请": "Kd28a1aa5", + "提供服务的团队可以审批来自其他团队的订阅申请,审批通过后的应用才可发起 API 请求。": "K1c15bb2e", + "APIPark 提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。": "K3453272", + "Hello!欢迎使用 APIPark": "Kd518ba3e", + "你能通过 APIPark 快速在企业内部构建 API 开放门户/市场,享受极致的转发性能、API 可观测、服务治理、多租户管理、订阅审批流程等诸多好处。": "Ke66e4182", + "如果你喜欢我们的产品,欢迎给我们 Star 或提供产品反馈意见。": "Kedd41c18", + "快速入门": "Kef02fd87", + "我们提供了一些任务来帮你快速了解 APIPark": "K43a3b38d", + "进阶教程": "K408bfcf1", + "了解 APIPark 如何更好地管理 API 和 AI": "K1afaf20e", + "了解更多功能": "K48f7e21f", + "隐藏该教程": "K698296e2", + "登录": "Kd2c1a316", + "请输入账号": "Kf076f63c", + "请输入密码": "K25c895d5", + "密码": "K551b0348", + "访客模式": "K192b3e38", + "您可通过访客模式查看所有页面和功能,但是无法编辑数据。访客模式仅用于了解产品功能,您可以在正式产品中关闭该功能。": "K91aa4801", + "Version (0)-(1)": "K480045ce", + "日志配置": "Kadee8e49", + "提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。": "K2724314b", + "部门名称": "K33c76dbc", + "父部门 ID": "K84829ca9", + "子部门名称": "K4d7fc74b", + "用户名": "Keb9fcdad", + "邮箱": "Kc654b275", + "部门": "Kbe2ecc69", + "未激活、已禁用的成员无法加入到部门": "Ka16e6c44", + "请选择成员需要新加入的部门": "Ked03ba97", + "添加账号": "K184d3473", + "编辑成员信息": "K1ecb35f2", + "加入部门": "Ke6f00b44", + "确定删除成员?此操作无法恢复,确认操作?": "K501cb1e7", + "成员与部门": "Kf20863b5", + "启用": "K52c8a730", + "禁用": "K718c9310", + "输入用户名、邮箱查找成员": "K5f27a546", + "移出当前部门": "K7c97c5df", + "禁用成员": "K1362a512", + "启用成员": "K6e1289b1", + "删除成员": "K1f4b5385", + "添加部门": "K26c698bb", + "添加子部门": "Kb9cf2a7d", + "重命名": "Kc83551f5", + "该数据删除后将无法找回,请确认是否删除?": "K5cfdd950", + "成员": "K74aef1ad", + "设置成员和对应的角色,成员只能够看到权限范围内的功能和数据。": "K3f1077c9", + "搜索部门": "Kdce62a6", + "数据源类型": "Ka46b9b24", + "数据源地址": "Kbb0cdcd0", + "Organization": "Kd9dfb884", + "鉴权 Token": "K3e770a75", + "密钥": "K8ef69ee2", + "上传密钥": "Kba3507d6", + "密钥文件的后缀名一般为 .key 的文件内容": "K93ac0f23", + "上传证书": "K7cdd1331", + "证书文件的后缀名一般为 .crt 或 .pem 的文件内容": "K6d91905d", + "添加证书": "Kd0f6ded7", + "修改证书": "Ke5732d60", + "证书管理": "K3ca07a70", + "通过为 API 服务配置和管理 SSL 证书,企业可以加密数据传输,防止敏感信息被窃取或篡改。": "Kdb927f83", + "集群": "Ke93d36ed", + "修改配置": "K877985b7", + "设置访问 API 的集群,让 API 在分布式环境中稳定运行,并且能够根据业务需求进行灵活扩展和优化。": "Kdf66a675", + "正常": "Ke039b9b5", + "异常": "K23a3bd72", + "管理地址": "Kf12b3034", + "服务地址": "K867e6faf", + "同步地址": "K2a49373f", + "集群地址": "K5878440c", + "下一步": "K5e9022f8", + "设置监控报表的数据来源,设置完成之后即可获得详细的API调用统计图表。": "Kdbafd6f9", + "统计图表": "K1358acf", + "地址(IP:端口)": "K62dabdf6", + "组织(Organization)": "K2db12335", + "资源配置": "K8e7a0f80", + "设置角色的权限范围。": "K95c3fd8b", + "系统级别角色": "K138facd3", + "添加角色": "K6eac768d", + "团队级别角色": "Kb9c2cf02", + "单位:ms,最小值:1": "K2a16c93b", + "API 路由设置": "Ka945cfb1", + "API 基础信息": "K2e050340", + "拦截该接口的请求": "Kba92c499", + "开启拦截后,网关会拦截所有该路径的请求,相当于防火墙禁用了特定路径的访问。": "Kde9d6e8e", + "请求协议": "K6bc47edb", + "请求方式": "K1365fe45", + "转发规则设置": "K90f3c02f", + "拦截": "Kb7df6ac1", + "放行": "K5c1722fe", + "路由详情": "K28435c5c", + "只允许上传PNG、JPG或SVG格式的图片": "Ka9c08390", + "服务名称": "K413b9869", + "服务类型": "K9919285b", + "默认 AI 供应商": "Kcef64f4d", + "创建 API 时会默认选择该供应商,修改默认供应商不会影响现有 API": "K300c89d4", + "未配置任何 AI 模型供应商,": "Kcab588a9", + "立即配置": "Kb9b56111", + "API 调用前缀": "Kcf756b7a", + "作为服务内所有API的前缀,比如host/{service_name}/{api_path},一旦保存无法修改": "K13edc043", + "所属服务分类": "Kf52a584d", + "设置服务展示在服务市场中的哪个分类下": "K72b21be5", + "图标": "Kdc840242", + "仅支持 .png .jpg .jpeg .svg 格式的图片文件, 大于 1KB 的文件将被压缩": "K427a5bd5", + "Logo": "K44bc352d", + "删除服务": "Kde6bae17", + "删除操作不可恢复,请谨慎操作!": "K885ea699", + "上游": "Kda8d5ea1", + "服务提供了高性能 API 网关,并且可以无缝接入多种大型 AI 模型,并将这些 AI 能力打包成 API 进行调用,从而大幅简化了 AI 模型的使用门槛。同时,我们的平台提供了完善的 API 管理功能,支持 API 的创建、监控、访问控制等,保障开发者可以高效、安全地开发和管理 API 服务。": "K12f58863", + "添加服务": "K2d6658ed", + "输入名称、ID、所属团队、负责人查找服务": "K7b8f623f", + "上游类型": "Kad98e030", + "后端默认使用的IP地址": "Kdd9b5008", + "负载均衡": "Kc9acdb25", + "转发 Host": "K632dba5c", + "重写域名": "Kc1f08a63", + "超时时间": "K628f6851", + "超时重试次数": "Kaff62621", + "次": "Kf14d159b", + "调用频率限制": "Kc41ca30e", + "次/秒": "K753e8aeb", + "团队名称": "K813e1c0a", + "团队 ID": "K692f5aa6", + "团队 ID(team_id)可用于检索团队,一旦保存无法修改。": "K5de0bc2", + "团队负责人": "Ka63dd985", + "负责人对团队内的团队、服务、成员有管理权限": "Ka6bcd272", + "删除团队": "Ka2012bdd", + "服务数据清除后,方可删除": "Kbde1f3d", + "移除成员": "K395acc14", + "添加成员": "Kec46a57f", + "输入姓名查找": "K48724410", + "搜索用户名、邮箱": "Kb9052305", + "设置团队和成员,然后你可以在团队内创建服务和应用、订阅API,成员只能看到所属团队内的服务和应用。": "K5ece3bac", + "添加团队": "K510cdd27", + "输入名称、ID、负责人查找团队": "K9244ae14", + "配置团队": "Kc7b24b4b", + "旧密码": "Kecb51e2c", + "新密码": "K8266bcf2", + "确认密码": "Ka9aef039", + "两次密码不一致": "Kcf42dcda", + "修改密码": "Kf876a42d", + "管理个人账号": "K8ed884f", + "API调用统计": "K9be8e1d7", + "选择服务": "K521ab28e", + "选择API": "Kcc8265e1", + "路径": "Kc380335f", + "请输入请求路径进行搜索": "K8aefc1e4", + "重置": "K50d471b2", + "查询": "Kee8ae330", + "导出": "Ka2c794a2", + "退出全屏": "Kaf70c3b", + "(0)调用详情": "Kd22841a4", + "应用调用统计": "K1512e983", + "请选择应用": "Kb4d2007f", + "调用趋势": "K8c7f2d2e", + "(0)-(1)调用趋势": "K657c3452", + "调用量统计": "Kc04efb87", + "加入总体数据对比": "Keb98266e", + "(0)调用量": "K18c2ed46", + "(0)调用成功率": "Kc3741830", + "请求总数": "Ka6aa5863", + "请求成功率": "K9eaef42", + "转发总数": "K7082a4af", + "转发成功率": "K1ce386fb", + "状态码4xx数": "K87d6877e", + "状态码5xx数": "K4c8a54db", + "调用总体趋势": "Kd566283e", + "(0)报文量": "K21ad4a6a", + "请求报文量": "Kd23a0be6", + "响应报文量": "Kec3e8361", + "状态码4XX数": "Ke6250744", + "状态码5XX数": "K2d79d4e1", + "服务调用统计": "Kcf6553c6", + "请选择服务": "Kffcfe375", + "调用详情": "Ka65f739c", + "API 请求量 Top10": "K89b7ac79", + "应用调用量 Top10": "Kc0915603", + "服务被调用量 Top10": "Kf90b54", + "暂无请求统计数据": "Kfb26388", + "请求统计": "Kc8cbd8f8", + "暂无转发统计数据": "K8dece48", + "转发统计": "K1ee32434", + "暂无调用量统计数据": "Kcd125e4d", + "暂无报文量统计数据": "Kaa114e8b", + "报文量统计": "K3ad84406", + "集群配置并开启监控": "Kfa088d49", + "监控功能用于辅助管理集群内信息,请配置集群、设置监控信息后查看当前集群监控情况;": "K3da3b9a0", + "集群配置": "Kaddacfb", + "配置集群地址,以确保监控系统能够正确识别和连接到集群": "K4ac33975", + "配置集群信息": "Ke5ed9810", + "监控设置": "K1a132228", + "配置监控信息": "K6af08c3c", + "监控总览": "K4a1a14", + "服务被调用统计": "K69741ea7", + "API 调用统计": "K9c8d9933", + "亿": "K145e4941", + "万": "Ke6a935d", + "搜索分类或标签": "Kd59290a2", + "暂无API数据": "K6b75bdbc", + "搜索或选择应用": "Kd8a7a689", + "申请理由": "K4b15d6f5", + "应用管理": "Kb7e869a4", + "鉴权类型": "Kb71b5a13", + "Iss": "K4d1465ee", + "签名算法": "K5dcd7ed8", + "Secret": "K5b0eedd3", + "RSA 公钥": "K44f4ffe1", + "用户名 JsonPath": "Kc5ecd7d9", + "校验字段": "K417d85cf", + "是否 Base64 加密": "K3b82fe1d", + "AK": "K49b5f4a3", + "SK": "K31418470", + "Apikey": "Kbfeb5297", + "隐藏鉴权信息": "Ke64e43a", + "应用名称": "K5168eb63", + "应用 ID": "K546e46f", + "删除应用": "K95764d1d", + "鉴权详情": "K217cb125", + "添加鉴权": "K2bb63eca", + "编辑鉴权": "Kd74d69b7", + "修改": "K9cbe1e0", + "访问授权": "Kb6e9328f", + "添加授权": "Kd23d1716", + "永不过期": "K9dfa2c97", + "到期时间": "Kfa920c0", + "订阅的服务": "Kcce1af60", + "审批详情": "Kbeb4e991", + "取消订阅": "K3118fdb0", + "请确认是否取消订阅?": "Ked811bb1", + "取消订阅申请": "K50c39a62", + "请确认是否取消订阅申请?": "K1856c229", + "搜索服务": "K66ea2f0", + "审批中": "Kfeb2559b", + "添加应用": "K667bbbe7", + "暂无服务描述": "Ka4b45550", + "订阅的服务数量:已通过 (0) 个,申请中 (1) 个": "K3c7b175f", + "退出测试": "Kbe3e9335", + "服务市场": "K370a3eb2", + "服务详情": "Kf7ec36d", + "申请服务": "K58ca9485", + "介绍": "K59cdbec3", + "Basic URL": "K1b6777bb", + "申请": "K4aa9ed2c", + "服务信息": "K6c060779", + "接入应用": "K8723422e", + "供应方": "Kb97544cb", + "申请审批": "Kd55c6887", + "分类": "Kb32f0afe", + "版本": "K81634069", + "更新时间": "Keefda53d", + "无标签": "K96a2f1c8", + "API 数量": "K72b0c0b3", + "接入应用数量": "K93d5a66e", + "关联标签": "K96059c69", + "更新者": "K8b7c2592", + "添加 Open Api": "K32263abd", + "配置 Open Api": "K7829bb78", + "Open Api": "Kcdf76005", + "调用服务": "Ke2601944", + "放大": "K8504bca8", + "缩小": "K693c1b41" +} \ No newline at end of file diff --git a/frontend/packages/common/src/locales/scan/en-US.json b/frontend/packages/common/src/locales/scan/en-US.json new file mode 100644 index 00000000..7c8e4bb5 --- /dev/null +++ b/frontend/packages/common/src/locales/scan/en-US.json @@ -0,0 +1,747 @@ +{ + "Kc0e5ef9f": "Workspace", + "K3863c722": "My", + "K4de11e23": "Home", + "Kfe93ef35": "Applications", + "Kb58e0c3f": "Services", + "Kc9e489f5": "Team", + "K61c89f5f": "API Portal", + "K16d71239": "Analytics", + "K714c192d": "Runtime", + "Kd57dfe97": "Topology", + "K3fe97dcc": "System Settings", + "K67ef3525": "Organization", + "K74aef1ad": "Members", + "Kf644225f": "Roles", + "K958da71f": "Category", + "Kf270ca55": "Operations & Integrations", + "Ke93d36ed": "Cluster", + "K9708a557": "Monitoring Reports", + "K481e8a05": "Certificate", + "Kca53edd0": "Logs", + "Kb283e720": "Resources", + "K631d646f": "Open API", + "K6535ff9c": "Account Settings", + "Kf15499b4": "Log Out", + "Kabbd6e6": "Docs", + "K1196b104": "APIPark - API Developer Portal", + "K1f42de3": "HTTP Status Codes", + "K4770dff4": "System Status Codes", + "Kf89e58f1": "Description", + "K9e53c664": "Submit", + "Kf8e7294c": "Previous Step", + "Ka0451c97": "Cancel", + "Kb1dedda3": "Close", + "Kb2fc7600": "Add Configuration", + "K4e07217d": "Edit Configuration", + "K4ea968fe": "Edit (0)", + "Ka7aaaeb": "Add (0)", + "Kaff78ecf": "Please Enter Key", + "K65d46535": "Please Enter Value", + "Kc14b2ea3": "Back", + "K11d3633a": "ID", + "Kbff43de3": "Name", + "K16ca79ef": "Driver", + "K7a369eef": "Published", + "Kcfa1a4d2": "Offline", + "K771dc3b7": "Online", + "K530f5951": "View", + "Kecbd7449": "Delete", + "K1cbe2507": "Confirm", + "K48325b6": "Search (0)", + "Ka1d885c1": "Add", + "Kad207008": "Edit", + "Ke4b7722": "简体中文", + "Kd185073d": "English", + "K1ff96ff": "Apply System", + "K9bf855d6": "Team", + "K11b994ed": "Applicant", + "K939baba7": "Application Date", + "Kdab2e63b": "Version Number", + "K8b29c460": "Version Description", + "K36a72ad1": "API List", + "K54e44357": "Upstream List", + "Kb8e8e6f5": "Remarks", + "K1ab0ae5b": "Application Reason", + "K53c00c3c": "Review Comments", + "K7edf331d": "Time", + "Kef45b208": "1 Hour", + "K9dbf22b8": "24 Hours", + "K820fbfab": "3 Days", + "Kd6d28fc": "7 Days", + "K3d7465f7": "File Logs", + "Kc87167a0": "HTTP Logs", + "K54630fe8": "Kafka Logs", + "Kd5c3966e": "NSQ Logs", + "K2e3de2c1": "Syslog Logs", + "Kb1cfa6e7": "Access Logs", + "K23fda291": "No Permission, Please Contact Administrator.", + "K4618cb0a": "WeChat Mini Program", + "Ka854f511": "Path Required for File Retrieval", + "Kaa11a695": "Non-HTTPS or Non-HTTP Code Samples Are Not Supported", + "Kbe46924e": "Search Programming Language...", + "Ke8e4f258": "Programming Language", + "K29c07a47": "Success Example", + "K1f5c814d": "Failure Example", + "K4ef022d7": "Default text/html;charset=UTF-8", + "Kd061b5bf": "No Sample Provided", + "Kc14cec33": "Binary", + "K48b4d9e3": "Request Header", + "Kcd347eaf": "Request Body", + "K9e100bfe": "Query Parameters", + "K3e9f12fd": "REST Parameters", + "K2bfa290c": "API Request Editor", + "Kb36d111a": "Response Header", + "K980bde79": "Response", + "Kb04d201a": "More Settings", + "Kee74f5b4": "Add Sub-Parameter", + "Kc7d3106c": "Add Row Below", + "Keaabd222": "Tag", + "K8ad2c50e": "Parameter Key", + "K67d68dd1": "Type", + "K29245f47": "Required", + "Ke32cbcd3": "Example", + "Kc13936c6": "Enter URL or cURL", + "Ka1ede006": "HTTP", + "K152ac44e": "Parameter Location", + "K1660ae72": "Match Type", + "K91ced765": "Parameter Value", + "K5b265628": "Operation Type", + "K1826982d": "Add or Modify", + "Kd65b55f5": "Match Parameter Value", + "K15f35bf2": "Forward Path", + "K79dec0dd": "Request Timeout", + "K7d465645": "Bind Upstream Service", + "K63a6404d": "Retry Time", + "K47740727": "Forward Header", + "K2b605d42": "More", + "K1df9fbd5": "Import", + "K5e85df18": "Import Format", + "K9eaf7885": "Full Replacement", + "Kf8c3a80b": "Insert at End", + "Kd96b2d7d": "Incremental Update", + "Kf2fc08eb": "Request Header", + "Ka45f1d8": "REST Parameters", + "K94bb113a": "Size", + "K359919b5": "Save As File", + "K38bf1b90": "Response", + "K59f4186e": "Response Header", + "K5f1e23fd": "Body", + "Kf404ef7d": "Send (Enter)", + "K2dbfd648": "Abort", + "Kacabc771": "Seconds", + "K13ae6a93": "Copy", + "Ke54a14a3": "Format", + "K43934f6d": "Search", + "K741decac": "Replace", + "Kd507abff": "Confirm", + "Kca2d1624": "(0) cannot be negative.", + "K792b255a": "(0) must be greater than or equal to (1).", + "Kf0bed26d": "Value Enumeration", + "K633a03ca": "Enumeration", + "Kd2766caf": "Minimum Length", + "Kd6d52485": "Maximum Length", + "Kea15f66c": "Minimum Value", + "K1af340ff": "Maximum Value", + "K68691e16": "Drag Files Here to Upload, or Click to Select Files", + "Kcec46ae": "Upload Files", + "K760fb044": "Files Selected", + "Kea2bdee0": "Please Enter Interface Name", + "K49053438": "Detailed Description", + "K148f6fa4": "Parameters Matching", + "K3ae4c789": "Forwarding Configuration", + "K2f4d0a37": "Request Parameters", + "Kde2d6dbd": "Return Example", + "K70e6069c": "Test API", + "Ke4603448": "Request Header", + "K89fd86b3": "Request Body", + "K8747e3c4": "Request Sample Code", + "K8613e6e7": "Response Example", + "Kab1c2159": "Response Header", + "Kd2be51d1": "Response Body", + "K831aa6c0": "Applicant - Application", + "K58ca9485": "Apply Service", + "K283f55b4": "Service System", + "Kd60d204": "Service Team", + "K3a9a3b75": "Approval Status", + "K4f57b2de": "Approver", + "K31dabc6b": "Approval Time", + "K8582af3f": "Reject", + "K54e27f57": "Approve", + "K7eeca185": "Approval Complete", + "Kd4061161": "Publishing Under Review", + "K823bfe63": "Online", + "K97ddb3f8": "-", + "Kc9315fa1": "Rejected", + "K3fbe7511": "Publishing Error", + "Ke64e695c": "Publishing", + "K17f93984": "API", + "K1365fe45": "Request Method", + "Kc380335f": "Path", + "K4ee62e8": "This API Lacks (0)(1)(2), Please Provide", + "K385591f3": "Forwarding Info,", + "K68415c14": "Document Info,", + "K133b75e9": "Upstream Info,", + "Kad98e030": "Upstream Type", + "Kdeed8399": "Static Upstream", + "K78b1ca25": "Address", + "K6208054": "Pending Approval", + "K1be7f021": "Approved", + "K677a4959": "Publishing Terminated", + "Kfd6d2d3d": "Closed", + "K9d7e880a": "Version", + "K855135f": "Create Time", + "Kcbf39b82": "Status", + "K339d15b5": "Creator", + "K7194cea2": "Review Time", + "K69827c60": "Publishing Status", + "K1644b775": "New", + "K4fdf4dcc": "Change", + "K33d66e26": "No Change", + "K9b70c007": "Missing Fields", + "Kd85208a3": "Rejected", + "K8adf7f8b": "Under Review", + "Kad6aa439": "Subscribed", + "K3118fdb0": "Unsubscribe", + "K9a68443b": "Cancel", + "K18307d56": "Manual Addition", + "K705fe9f5": "Subscription Application", + "Kbc96ebec": "Applicant Application", + "K1f89176d": "Team", + "Kfe731dfc": "Action", + "K71661ee8": "Required Field", + "Kcbee3f8": "Invalid Email Address", + "K442cfba1": "Please Enter", + "K3bb646e4": "Please Select", + "Ka4ecfa40": "English, Numbers, or Underscores Only; Must Start with a Letter", + "K39686a7f": "Supports Combination of Letters, Numbers, Hyphens, and Underscores", + "K4d6a0190": "Approval Comments Required When Rejecting", + "K37318b68": "Unable to Connect to Cluster; Please Check Address or Firewall Configuration", + "K7f0c746d": "Success", + "K6a365d01": "Failed, Please try again", + "K978062b6": "In Progress", + "Kca7bd6d4": "Loading Data", + "K3c93b77e": "Failed to Retrieve Data", + "Ke108c369": "Success", + "K9168d3e": "Redirecting to Login Page", + "K2f8a7ab7": "Review Comments Not Provided", + "Kb858d78a": "Copy Successful", + "K26e85d15": "Copy Failed, Please Copy Manually", + "K5cfdd950": "This Data Will Be Permanently Deleted, Are You Sure You Want to Delete?", + "K2a3f24ac": "Default Worksheet", + "K7e1ab4b0": "To", + "Kf1b166e7": "Details", + "K28555332": "URLs with Double Slashes // Are Not Supported", + "Keb9fcdad": "Username", + "Kc654b275": "Email", + "Kbe2ecc69": "Department", + "K759fb403": "Status", + "K52c8a730": "Enable", + "K718c9310": "Disable", + "K2c5882be": "Bind Domain", + "K1cc07937": "Expiration Date", + "K8b7c2592": "Updated By", + "Keefda53d": "Update Time", + "K9f3db3ca": "Cluster Name", + "Ke7487049": "Cluster ID", + "Kb660ffe8": "Node Name", + "Kf12b3034": "Management Address", + "K867e6faf": "Service Address", + "K37348a5e": "Cluster Sync Address", + "K2a49373f": "Cluster Sync Address", + "K151d2bb7": "Environment Name", + "Kfa744afd": "Clusters", + "K23a3bd72": "Error", + "Ke039b9b5": "Normal", + "K5c123bad": "Role", + "K76036e25": "HTTP Request Header", + "K8d4cbf50": "Cookie", + "K44607e3f": "Exact Match", + "Kc287500a": "Prefix Match", + "Kfc0b1147": "Suffix Match", + "Ka4a92043": "Substring Match", + "K30b2e44f": "Non-Exact Match", + "Kb1587991": "Null Match", + "K1e97dbd8": "Exists Match", + "Kc8ee3e62": "Does Not Exist Match", + "K87c5a801": "Case-Sensitive Regex Match", + "K95f062f1": "Case-Insensitive Regex Match", + "Kfbd230a5": "Any Match", + "K413b9869": "Service Name", + "K1e84ad04": "Service ID", + "K72b0c0b3": "APIs", + "Kf7200cd9": "Admin", + "Kefaf9956": "Create Time", + "K98db2cb9": "Application Status", + "Ke792d01c": "Service Association", + "K61b62ace": "Source", + "Ke63767cf": "Addition Time", + "K3a67ea90": "Subscriber", + "K442937c4": "Subscription Time", + "K34111022": "Protocol/Method", + "K62d10724": "URL", + "Ka9481f95": "Creator", + "Kf88d56fd": "Upstream ID", + "K11a92fb2": "Updater", + "K2c2bc64f": "Dynamic Service Discovery", + "Kc9a2a716": "HTTPS", + "Ka7f8266f": "Weighted Round-Robin", + "Kd17edabd": "IP Hash", + "Kaeba0229": "Pass Through Client Request Host", + "K6d7e2fd0": "Use Upstream Service Host", + "K31332633": "Rewrite Host", + "Ke65db976": "Weight", + "Kf966b12d": "Internal Service: Accessible via Gateway, but Not Listed in Service Plaza", + "Kfc939e49": "Public Service: Accessible via Gateway, Listed in Service Plaza, and Subscribable by Other Applications", + "Ke96ccf45": " ", + "K5582ac8": "Request Path", + "K92485dd1": "All APIs", + "Ke64e43a": "Hide Auth Info", + "K1a78e6f0": "Expiration Time", + "K40bbb0a3": "Service ID", + "K9919285": "Service Type", + "K63938137": "Public Service", + "Kfb20a12": "Internal Service", + "Kedd64e4d": "Disabled", + "Ka29b346f": "Address (IP Port or Domain)", + "K63b1e0dc": "Weight (0-999)", + "K74ab00a3": "Approved", + "Kea996156": "Publishing Application Record", + "Kbea7d266": "Associated System", + "Ka36c13cc": "Calling System Name", + "Kd78d73a7": "Calling Service Name", + "K73c144eb": "Current System Name", + "K285bd65e": "Called Service Name", + "K5cbab635": "Called System Name", + "K93c2696e": "Online Result", + "K43fcaf94": "Success", + "Kc71c6a9": "Online Failed", + "K56c686f8": "Failed", + "K3ba29a85": "API", + "Kda8d5ea1": "Upstream", + "Kdefa9caa": "Introduction", + "K36856e71": "Publish", + "K6382bbfd": "Subscription Management", + "K2eef4e4": "Subscription Review", + "Ka97bd9e5": "Subscription Management", + "K5974bf24": "Management", + "K3fa5c4c3": "Call Topology", + "Kb5c7b82d": "Settings", + "K2472615e": "Services", + "Kc02aa5f1": "APIs", + "Ke08ff808": "Addition Date", + "Kd7d84192": "Name", + "Kc88e03b6": "Team Roles", + "Kdf35c48c": "All Members", + "K3818f03d": "Approval", + "K56b4254f": "Publishing Application", + "Kd518ba3e": "Hello! Welcome to APIPark", + "Ke66e4182": "APIPark allows you to quickly build an API Developer Portal within your enterprise, offering extreme forwarding performance, API observability, service governance, multi-tenant management, subscription approval processes, and many other benefits.", + "Kedd41c18": "Welcome to Star ✨ our Github Repository or give us some feedback.", + "Kef02fd87": "Quick Start", + "K43a3b38d": "We've provided some tasks to help you quickly get acquainted with APIPark.", + "Kc8239422": "Teams include personnel, applications, and services. Data between different teams is isolated, and can be used to manage different departments/project teams/teams within the enterprise.", + "Kd5be0cd7": "Services include a set of APIs and can be published to the API Developer Portal for use by other teams.", + "K4ea67613": "Applications serve as identities for applying for services and calling APIs. They can apply for service calls in the API Developer Portal, and each application has its own independent API access Auth.", + "Ka4748416": "Search for Services and APIs", + "K383e17e5": "You can view all public services in the API Developer Portal.", + "K8f7808e6": "Subscribe to Services", + "Kb0755523": "To call an API of a particular service, you need to subscribe to the service first and wait for approval from the team providing the service before initiating API requests.", + "Kd28a1aa5": "Review Subscription Applications", + "K4472e361": "The team providing the service can review subscription applications from other teams. Only after approval can applications initiate API requests.", + "K297d8563": "The Dashboard provides various statistical charts to help us understand the API's operating status.", + "K48f7e21f": "Learn More Features", + "Ka3626c8c": "Hide Quick Start", + "Kd2c1a316": "Log In", + "Kf076f63c": "Please Enter Account", + "K80a560a1": "Account", + "K25c895d5": "Please Enter Password", + "K551b0348": "Password", + "K192b3e38": "Guest Mode", + "K91aa4801": "In guest mode, you can view all pages and features, but cannot edit data. Guest mode is for product feature exploration only.", + "K480045ce": "Version (0)-(1)", + "Kadee8e49": "Log Configuration", + "K33c76dbc": "Department", + "K84829ca9": "Parent Department ID", + "K4d7fc74b": "Sub-department", + "Ka16e6c44": "Inactive or Disabled Members Cannot Be Added to Departments", + "Ked03ba97": "Please Select the Department to Which the Member Should Be Added", + "K5e237e06": "Name", + "K184d3473": "Add Account", + "K1ecb35f2": "Edit Member", + "Ke6f00b44": "Join Department", + "K501cb1e7": "Are You Sure You Want to Delete This Member? This Action Cannot Be Undone.", + "Kf20863b5": "Members and Departments", + "K5f27a546": "Enter Username, Email to Search for Members", + "K26c698bb": "Add Department", + "Kb9cf2a7d": "Add Sub-department", + "Kc83551f5": "Rename", + "K3f1077c9": "Set Member Roles; Members Can Only See Features and Data Within Their Permission Scope.", + "Kdce62a6": "Search Department", + "K8ef69ee2": "Key", + "Kba3507d6": "Upload Key", + "K93ac0f23": "Key Files Usually Have a .key File Extension", + "K7cdd1331": "Upload Certificate", + "K6d91905d": "Certificate Files Usually Have a .crt or .pem File Extension", + "Kd0f6ded7": "Add Certificate", + "Ke5732d60": "Modify Certificate", + "K3ca07a70": "Certificate Management", + "Kdb927f83": "By Configuring and Managing SSL Certificates for API Services, Enterprises Can Encrypt Data Transmission to Prevent Sensitive info from Being Stolen or Tampered With.", + "K877985b7": "Modify Configuration", + "Kdf66a675": "Set the Cluster Accessing the API to Ensure Stable Operation in a Distributed Environment and Flexibly Scale and Optimize According to Business Needs.", + "Kaf074220": "Not Configured", + "K5878440c": "Cluster Address", + "K5e9022f8": "Next Step", + "Kdbafd6f9": "Set Data Sources for Monitoring Reports; Once Configured, You Can Get Detailed API Call Statistical Charts.", + "K1358acf": "Statistical Charts", + "K8fa58214": "Data Source", + "K62dabdf6": "Address (IP:Port)", + "K2db12335": "Organization", + "K8e7a0f80": "Resource Configuration", + "Kabfe9512": "Save", + "K95c3fd8b": "Set Role Permission Scope.", + "K138facd3": "System-Level Role", + "K6eac768d": "Add Role", + "Kb9c2cf02": "Team-Level Role", + "Kb4ceecea": "Add Subcategory", + "K67479e88": "Modify Category", + "K2bc75e2c": "Add Category", + "Kab4aab44": "Rename Category", + "K8e0e6977": "Set Service Categories to Facilitate Quick API Discovery by Team Members.", + "Ke595a20a": "Category", + "K9679728f": "Parent Category ID", + "K9b2d08fd": "Subcategory", + "Kf14e76e5": "Replica", + "K2e050340": "Request Settings", + "K90f3c02f": "Forwarding Settings", + "K6ea8d549": "Edit", + "Kff5c18ac": "Editor", + "K2eb99415": "Forwarding Rules", + "Ke93388fd": "Edit", + "K1b1ae3b0": "Copy API", + "K84aabfd4": "Add API", + "K6a662463": "Search Name, URL", + "K59bc6280": "Details", + "K2a16c93b": "Unit: ms, Minimum Value: 1", + "K469e475a": "Retry Count", + "Kd568e15c": "Publishing Result", + "K35f990b0": "View Details", + "Kdbc1f6cb": "Publishing Application", + "Kb6860a3f": "Rollback", + "Ka3494f4b": "Are You Sure You Want to Rollback?", + "Kb397a99f": "Revoke Application", + "K7d401c0f": "Are You Sure You Want to Revoke the Application?", + "Ke1b79b93": "Terminate Publishing", + "Ka2449180": "Are You Sure You Want to Terminate Publishing?", + "K2cb02f38": "New Version", + "Ka9c08390": "Only PNG, JPG, or SVG Format Images Are Allowed", + "Kcf756b7a": "API Call Prefix", + "K43d101a": "Optional, As Prefix for All APIs in Service, E.g., host/{service_name}/{api_path}, Cannot Be Modified Once Saved", + "Kdc840242": "Icon", + "K427a5bd5": "Only PNG, JPG, or SVG Format Images Are Allowed", + "K44bc352d": "Logo", + "Kf52a584d": "Service Category", + "K72b21be5": "Set the Category Where the Service Is Displayed in the Service Portal", + "Kde6bae17": "Delete Service", + "K885ea699": "This Action Is Irreversible, Please Proceed with Caution!", + "K617f34f1": "Updated By", + "K6ebca204": "Update Time", + "K39ab0358": "Add Subscriber", + "K2d6658ed": "Add Service", + "K7b8f623f": "Enter Name, ID, Associated Team, Person in Charge to Search Service", + "Kdd9b5008": "Default Backend IP Address", + "K6bc47edb": "Request Protocol", + "Kc9acdb25": "Load Balancing", + "K632dba5c": "Forward Host", + "Kc1f08a63": "Rewrite Domain Name", + "K628f6851": "Timeout", + "Kaff62621": "Timeout Retry Count", + "Kc41ca30e": "Rate Limiting", + "K813e1c0a": "Team Name", + "K692f5aa6": "Team ID", + "K5de0bc2": "Team ID (team_id) Can Be Used to Retrieve the Team, Cannot Be Modified Once Saved.", + "Ka63dd985": "Team Leader", + "Ka6bcd272": "Leader Has Management Authority over the Team, Services, and Members within the Team", + "Ka2012bdd": "Delete Team", + "Kbde1f3d": "Service Data Must Be Cleared Before Deletion", + "K395acc14": "Remove Member", + "Kec46a57f": "Add Member", + "K48724410": "Enter Name to Search", + "Kb9052305": "Search Username, Email", + "K5ece3bac": "Set Team and Members; You Can Then Create Services and Applications, Subscribe to APIs within the Team; Members Can Only See Services and Applications within Their Team.", + "K510cdd27": "Add Team", + "K9244ae14": "Enter Name, ID, Person in Charge to Search Team", + "Kc7b24b4b": "Configure Team", + "Kecb51e2c": "Old Password", + "K8266bcf2": "New Password", + "Ka9aef039": "Confirm Password", + "Kcf42dcda": "Passwords Do Not Match", + "Kf876a42d": "Change Password", + "K8ed884f": "Manage Personal Account", + "K9be8e1d7": "API Call Statistics", + "K521ab28e": "Select Service", + "Kcc8265e1": "Select API", + "K8aefc1e4": "Enter Request Path to Search", + "K50d471b2": "Reset", + "Kee8ae330": "Query", + "Ka2c794a2": "Export", + "Kaf70c3b": "Exit Fullscreen", + "Kd22841a4": "(0) Call Details", + "K1512e983": "Application Call Statistics", + "Kb4d2007f": "Please Select Application", + "K8c7f2d2e": "Call Trend", + "K657c3452": "(0)-(1) Call Trend", + "Kc04efb87": "Call Volume Statistics", + "Keb98266e": "Join Overall Data Comparison", + "K18c2ed46": "(0) Call Volume", + "Kc3741830": "(0) Success Rate", + "Ka6aa5863": "Total Requests", + "K9eaef42": "Success Rate", + "K7082a4af": "Total Forwards", + "K1ce386fb": "Forward Success Rate", + "K87d6877e": "4xx", + "K4c8a54db": "5xx", + "Kd566283e": "Overall Call Trend", + "Kd23a0be6": "Request Payload Volume", + "Kec3e8361": "Response Payload Volume", + "Ke6250744": "4XX", + "K2d79d4e1": "5XX", + "Kcf6553c6": "Service Call Statistics", + "Kffcfe375": "Please Select Service", + "Ka65f739c": "Call Details", + "K89b7ac79": "Top 10 API Requests", + "Kc0915603": "Top 10 Application Calls", + "Kf90b54": "Top 10 Service Calls", + "Kfb26388": "No Request Statistics Data", + "Kc8cbd8f8": "Request Statistics", + "K8dece48": "No Forwarding Statistics Data", + "K1ee32434": "Forwarding Statistics", + "Kcd125e4d": "No Call Volume Statistics Data", + "Kaa114e8b": "No Payload Volume Statistics Data", + "K3ad84406": "Payload Volume Statistics", + "K19a3ebe0": "Successful Requests", + "Kcaa8259": "Successful Forwards", + "K888f038f": "Failed Status Code Count", + "K42d2bef2": "Average Response Time (ms)", + "K9197c994": "Maximum Response Time (ms)", + "K7c2f3fee": "Minimum Response Time (ms)", + "K3d85ea54": "Average Request Traffic (KB)", + "Keec09d32": "Maximum Request Traffic (KB)", + "K3786b48": "Minimum Request Traffic (KB)", + "K5168eb63": "Application Name", + "K546e46f": "Application ID", + "K4a1a14": "Monitoring Overview", + "K69741ea7": "Service Call Statistics", + "K9c8d9933": "API Call Statistics", + "K28cf9613": "Per Minute", + "K18f25019": "Every 5 Minutes", + "Kf00f01ca": "Per Hour", + "Kfcda87fc": "Per Day", + "K29ec75dc": "Per Week", + "K145e4941": "B", + "Ke6a935d": "10K", + "K8f7abcab": " Times", + "K146477a8": "Service Tags", + "K4de0af74": "Service Categories", + "Kcce1af60": "Subscribed Services", + "Kb6e9328f": "Authorization", + "Kb7e869a4": "Settings", + "Kd59290a2": "Search Categories or Tags", + "K6b75bdbc": "No API Data", + "Kd8a7a689": "Search or Select Application", + "K4b15d6f5": "Application Reason", + "Kb71b5a13": "Auth Type", + "K4d1465ee": "ISS", + "K5dcd7ed8": "Signature Algorithm", + "K5b0eedd3": "Secret", + "K44f4ffe1": "RSA Public Key", + "Kc5ecd7d9": "Username JsonPath", + "K417d85cf": "Validation Field", + "K3b82fe1d": "Base64 Encryption", + "K49b5f4a3": "AK", + "K31418470": "SK", + "Kbfeb5297": "APIKey", + "K95764d1d": "Delete Application", + "K217cb125": "Auth Details", + "K2bb63eca": "Add Auth", + "Kd74d69b7": "Edit Auth", + "K9cbe1e0": "Modify", + "Kd23d1716": "Add Authorization", + "K9dfa2c97": "Never Expire", + "Kfa920c0": "Expiration Time", + "Kbeb4e991": "Review Details", + "Ked811bb1": "Do You Want to Unsubscribe?", + "K50c39a62": "Cancel", + "K1856c229": "Do You Want to Unsubscribe?", + "K66ea2f0": "Search Service", + "Kfeb2559b": "Under Review", + "Ka2b6d281": "API Document", + "K667bbbe7": "Add Application", + "Ka4b45550": "No Service Description", + "K3c7b175f": "Subscribed Services: (0) Approved, (1) Pending", + "K850b4b2d": "Status Code", + "Kbe3e9335": "Exit Test", + "K370a3eb2": "Service Portal", + "Kf7ec36d": "Service Details", + "K59cdbec3": "Documents", + "K4aa9ed2c": "Apply", + "K6c060779": "Service Info", + "K8723422e": "Application", + "Kb97544cb": "Supplier", + "Kb32f0afe": "Category", + "K81634069": "Version", + "K96a2f1c8": "No Tags", + "K93d5a66e": "Applications", + "K3e770a75": "Auth Token", + "K96059c69": "Associated Tags", + "K32263abd": "Add Open API", + "K7829bb78": "Configure Open API", + "Kcdf76005": "Open API", + "Ke2601944": "Invoke Service", + "K8504bca8": "Zoom In", + "K693c1b41": "Zoom Out", + "Kfd50704d": "No (0) permission, please contact the administrator.", + "K48322168": "Unassigned", + "K98f247f9": "System Admin", + "K9c8a571f": "Team Admin", + "K929b485b": "Operations Admin", + "K82cc5ec2": "Regular Member", + "Ke41d7451": "Read-Only Member", + "Kf99e8b66": "Service Admin", + "Kda8db57a": "Service Developer", + "K216a1ac7": "Application Developer", + "K27924db": "Application Admin", + "K8dc5c723": "Driver Name", + "K9919285b": "Service Type", + "Kf14d159b": "Times", + "K753e8aeb": "TPS", + "K21ad4a6a": "(0) Payload", + "Kda249fe8": "Failed Request", + "Kcf2df651": "Failed Forwarding", + "K7e6a859d": "Scope", + "K3a008b34": "Add Entry", + "Ke0599ef7": "Add Address", + "K48d3b5c4": "File Name", + "Kafde0d2a": "Storage Directory", + "Kfb2926ac": "Log Rotation Period", + "Kd96c2c69": "Unit: Days", + "Kc2b776fa": "Output Format", + "K7b7cdac2": "Format Configuration", + "K2f59807a": "Server Address", + "K540488a8": "NSQD Address List", + "K8bc33a11": "Auth Secret", + "K1cd3002f": "Network Protocol", + "Kdfaa32c8": "Log Level", + "Ka46b9b24": "Data Source Type", + "Kbb0cdcd0": "Data Source Address", + "Kd9dfb884": "Organization", + "Kc0408d9c": "Single line", + "Ke3db239d": "Hour", + "K3509a9f8": "Day", + "Kb3960e83": "Unpublished", + "K8bd1e18": "Pending", + "K225a6c43": "Unit: Seconds, Minimum Value: 1", + "Ka450909c": "Organization", + "K62933442": "View System Roles", + "Kd677d04a": "View Team Roles", + "Kd352fa1d": "API Portal", + "K39280ee": "Operations", + "K4bf109e8": "View All Applications", + "Keceae2": "View All Services", + "K7c866f28": "View All Teams", + "Kf9dcef3a": "Routes", + "K6134bbe8": "Add Route", + "Kad6d2797": "Search Routes by Name and URL", + "K28435c5c": "Route Details", + "Kfa088d49": "Configure Cluster and Enable Monitoring", + "K3da3b9a0": "Monitoring function is used to assist in managing cluster info. Please configure the cluster and set up monitoring info before viewing the current cluster monitoring status.", + "Kaddacfb": "Cluster Configuration", + "K4ac33975": "Configure cluster address to ensure monitoring system can correctly identify and connect to the cluster", + "Ke5ed9810": "Configure Cluster info", + "K1a132228": "Monitoring Settings", + "K6af08c3c": "Configure Monitoring info", + "K7e52ffa3": "Deployment Status", + "Kad1c674c": "Protocol", + "Kad01bc3e": "Method", + "Kca1dc104": "Open Editor", + "Kba92c499": "Intercept Requests to This Interface", + "Kb7df6ac1": "Block", + "K5c1722fe": "Allow", + "Ke00c858c": "Upload File", + "K6d9dd1f5": "Replace File", + "K71753476": "Allow Access", + "K597435c5": "Runtime", + "Kde9d6e8e": "When interception is enabled, the gateway will block all traffic of this API path.", + "K4758140d": "Routes", + "K7c97c5df": "Unassign Department", + "K1362a512": "Disable Member", + "K6e1289b1": "Enable Member", + "K1f4b5385": "Delete Member", + "Kf85b83a0": "Enter URL to Search Route", + "K62840d62": "REST Services", + "Kd2c34e2c": "AI Services", + "K4d5960c1": "AI Setting", + "Kc6340091": "Context", + "K74ecb1fa": "Query", + "K79f2e2f9": "Conversation History", + "K3a8912ee": "New variable", + "Kb291a19": "New tool", + "K27ece71d": "AI Model Invocation Defaults to Using Only Query Variables; Enter '{' to Add New Variables", + "K14700c7": "AI Model Provider", + "K1786a4c8": "Add AI Service", + "K66060758": "Name", + "K2bb86fb4": "Prompt", + "K13ffbe88": "Variable", + "K79c8cfaf": "Enter the Description for This Interface", + "K8a35059b": "Model Configuration", + "Kfede1c7c": "Model", + "Ke99513a0": "Parameters", + "K18dccc1a": "Synchronize Latest Model", + "Ke66a17dd": "Required", + "Kb3e34847": "Get API Key from (0)", + "Kd9a46c29": "Default", + "K66a7d24c": "Configured", + "K28b68036": "Invalid characters, only alphabetical characters are allowed", + "Kefa2a4cf": "AI Route Configuration", + "Kccbf1ee1": "Support mainstream AI models by turning LLMs and prompts into standard REST APIs, then publish them to the API Portal.", + "K7ac2be34": "AI Model Management", + "K2260837a": "After configuring the AI model, you can use the corresponding large model to create AI services", + "Kdac8ce7e": "Open OpenAPI YAML Editor", + "Ka945cfb1": "API Route Configuration", + "K51d1eb5d": "API Route", + "Ke2ad803": "REST services offer high-performance API gateways that provide quick access to existing HTTP APIs and publish them to the API Portal.", + "K6206e4ad": "Upload OpenAPI Document (.json/.yaml)", + "Kfba46e6d": "Replace OpenAPI Document (.json/.yaml)", + "Kf5da1284": "No Approval Required: Allows any application to call the service", + "Kc59ff06d": "Manual Approval: Only applications that pass manual approval are allowed to call the service", + "Kcab588a9": "No AI model provider configured, ", + "Kb9b56111": "Configure Now", + "Kbfe02d7f": "Permanent", + "K1e9c479e": "No", + "Kaddfcb6b": "Yes", + "K12f58863": "services offer high-performance API gateways that provide quick access to existing HTTP APIs and publish them to the API Portal.", + "K8ab0fc95": "Common Setting", + "K2724314b": "provides detailed API call logs to help enterprises monitor, analyze, and audit API operation statuses.", + "Kecbb0e45": "System", + "Ka358e23d": "General", + "K449058e9": "API Gateway", + "K99935e6f": "AI Model", + "K1deaa2dd": "User", + "K4057391a": "Integration", + "K408bfcf1": "Advanced Tutorial", + "K2cdbb773": "Core Features", + "K3378c50d": "Account and Roles", + "Kda5bb930": "Invite your team members to join APIPark to manage and call APIs together.", + "K62e89ee7": "Permission Management", + "K3596804a": "To call an API of a particular service, you need to subscribe to the service first and wait for approval from the team providing the service before initiating API requests.", + "K1c15bb2e": "The team providing the service can review subscription applications from other teams. Only after approval can applications initiate API requests.", + "K3453272": "APIPark provides detailed API call logs to help enterprises monitor, analyze, and audit API operation statuses.", + "K1afaf20e": "Learn how APIPark can better manage APIs and AI", + "Kcef64f4d": "Default AI Provider", + "K13edc043": "As a prefix for all APIs in the service, e.g., host/{service_name}/{api_path}, cannot be modified once saved", + "Ka7bb958f": "AI", + "Kcb81cc64": "REST", + "Kea2f9279": "API Request Base URL", + "K7fc496a1": "The API base URL is typically set to the external network access address of the API gateway or the domain name bound to the API gateway.", + "Kb66fec9d": "API Request" + } \ No newline at end of file diff --git a/frontend/packages/common/src/locales/scan/ja-JP.json b/frontend/packages/common/src/locales/scan/ja-JP.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/frontend/packages/common/src/locales/scan/ja-JP.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/frontend/packages/common/src/locales/scan/newJson/en-US.json b/frontend/packages/common/src/locales/scan/newJson/en-US.json new file mode 100644 index 00000000..b793f6fd --- /dev/null +++ b/frontend/packages/common/src/locales/scan/newJson/en-US.json @@ -0,0 +1,22 @@ +{ + "K1c15bb2e": "提供服务的团队可以审批来自其他团队的订阅申请,审批通过后的应用才可发起 API 请求。", + "Kcf9f90b8": "模型供应商", + "K71671763": "快速接入 AI", + "Ka8a5ec5": "配置你的 AI 模型", + "K10d7e99f": "通过 APIPark 快速接入各种 AI 模型,使用统一的格式来调用API,并且可以随意切换模型。", + "Kc057704a": "创建 AI 服务和 API", + "K76bb4a09": "创建 AI 类型的服务,并且你可以将 Prompt 提示词设置为一个 API,简化使用 AI 的流程。", + "K71b2c70f": "创建调用 Token", + "K9bdd8403": "为了安全地调用 API,你需要创建一个应用以及Token。", + "Kc5738b6c": "调用", + "Kd6d7ca1f": "现在你可以通过 Token 来调用这些 API。", + "K86cf95f": "快速接入 REST API", + "K7a3a8417": "创建 REST 服务和 API", + "K4a84214e": "统计 API 调用情况", + "K698296e2": "隐藏该教程", + "K6a7fa303": "无需审批", + "Kd196e8a4": "需要审批", + "K1b6777bb": "Basic URL", + "Kd55c6887": "申请审批", + "K300c89d4": "创建 API 时会默认选择该供应商,修改默认供应商不会影响现有 API" +} \ No newline at end of file diff --git a/frontend/packages/common/src/locales/scan/newJson/ja-JP.json b/frontend/packages/common/src/locales/scan/newJson/ja-JP.json new file mode 100644 index 00000000..449ff8f0 --- /dev/null +++ b/frontend/packages/common/src/locales/scan/newJson/ja-JP.json @@ -0,0 +1,580 @@ +{ + "Kc0e5ef9f": "工作空间", + "K4de11e23": "首页", + "Kfe93ef35": "应用", + "Kb58e0c3f": "服务", + "Kc9e489f5": "团队", + "K61c89f5f": "API 市场", + "K16d71239": "仪表盘", + "K714c192d": "运行视图", + "Kd57dfe97": "系统拓扑图", + "K3fe97dcc": "系统设置", + "Kecbb0e45": "系统", + "Ka358e23d": "常规", + "K449058e9": "API 网关", + "K99935e6f": "AI 模型", + "K1deaa2dd": "用户", + "K80a560a1": "账号", + "Kf644225f": "角色", + "K4057391a": "集成", + "K8fa58214": "数据源", + "K481e8a05": "证书", + "Kca53edd0": "日志", + "Kb283e720": "资源", + "K631d646f": "Open API", + "K6535ff9c": "账号设置", + "Kf15499b4": "退出登录", + "Kabbd6e6": "文档", + "K1196b104": "APIPark - 企业API数据开放平台", + "K1f42de3": "HTTP 状态码", + "K4770dff4": "系统状态码", + "Kf89e58f1": "描述", + "K9e53c664": "提交", + "Kf8e7294c": "上一步", + "Ka0451c97": "取消", + "Kb1dedda3": "关闭", + "Kb2fc7600": "添加配置", + "K4e07217d": "编辑配置", + "K4ea968fe": "编辑(0)", + "Ka7aaaeb": "添加(0)", + "Kaff78ecf": "请输入Key", + "K65d46535": "请输入Value", + "Kc14b2ea3": "返回", + "K11d3633a": "ID", + "Kbff43de3": "名称", + "K16ca79ef": "Driver", + "K7a369eef": "已发布", + "Kcfa1a4d2": "下线", + "K771dc3b7": "上线", + "K530f5951": "查看", + "Kecbd7449": "删除", + "K1cbe2507": "确认", + "K48325b6": "搜索(0)名称", + "Kc6340091": "上下文", + "K74ecb1fa": "查询内容", + "K79f2e2f9": "会话历史", + "K3a8912ee": "添加新变量", + "Kb291a19": "添加工具", + "K27ece71d": "AI 模型调用默认仅使用 Query 变量,可输入 “{” 增加新变量。", + "Kdeed8399": "静态上游", + "K4ee62e8": "该 API 缺失(0)(1)(2)请先补充", + "K385591f3": "转发信息,", + "K68415c14": "文档信息,", + "K133b75e9": "上游信息,", + "K43fcaf94": "成功", + "Kc71c6a9": "上线失败", + "K56c686f8": "失败", + "K1ff96ff": "申请系统", + "K9bf855d6": "所属团队", + "K11b994ed": "申请人", + "K939baba7": "申请时间", + "Kdab2e63b": "版本号", + "K8b29c460": "版本说明", + "K4758140d": "路由列表", + "K54e44357": "上游列表", + "Kb8e8e6f5": "备注", + "K7e52ffa3": "上线情况", + "K1ab0ae5b": "申请原因", + "K53c00c3c": "审核意见", + "Kfd50704d": "暂无(0)权限,请联系管理员分配。", + "K7edf331d": "时间", + "Kef45b208": "近1小时", + "K9dbf22b8": "近24小时", + "K820fbfab": "近3天", + "Kd6d28fc": "近7天", + "Ke00c858c": "上传文件", + "K6d9dd1f5": "替换文件", + "K71753476": "是否放行", + "K597435c5": "监控", + "Ke66a17dd": "必填", + "K28b68036": "字符非法,仅支持英文", + "K6206e4ad": "上传 OpenAPI 文档 (.json/.yaml)", + "Kfba46e6d": "替换 OpenAPI 文档 (.json/.yaml)", + "Kdac8ce7e": "打开 OpenAPI YAML 编辑器", + "Kf5da1284": "无需审批:允许任何应用调用该服务", + "Kc59ff06d": "人工审批:仅允许通过人工审批的应用调用该服务", + "Kbfe02d7f": "永久", + "K1e9c479e": "否", + "Kaddfcb6b": "是", + "K23fda291": "暂无操作权限,请联系管理员分配。", + "K4618cb0a": "微信小程序", + "Ka854f511": "获取文件,需填路径", + "Kaa11a695": "暂不支持生成非 HTTPS 或非 HTTP 协议的代码示例", + "Kbe46924e": "搜索编程语言...", + "Ke8e4f258": "编程语言", + "K29c07a47": "成功示例", + "K1f5c814d": "失败示例", + "K4ef022d7": "默认 text/html;charset=UTF-8", + "Kd061b5bf": "暂未填写示例", + "Kc14cec33": "Binary", + "K48b4d9e3": "请求头部", + "Kcd347eaf": "请求体", + "K9e100bfe": "Query 参数", + "K3e9f12fd": "REST 参数", + "K2bfa290c": "api request editor", + "Kb36d111a": "返回头部", + "K980bde79": "返回值", + "Kb04d201a": "更多设置", + "Kee74f5b4": "添加子参数", + "Kc7d3106c": "向下添加行", + "Keaabd222": "标签", + "K8ad2c50e": "参数名", + "K67d68dd1": "类型", + "K29245f47": "必需", + "Ke32cbcd3": "示例", + "Kc13936c6": "输入 URL 或 cURL", + "Ka1ede006": "HTTP", + "K152ac44e": "参数位置", + "K1660ae72": "匹配类型", + "K91ced765": "参数值", + "K5b265628": "操作类型", + "K1826982d": "新增或修改", + "Kd65b55f5": "匹配参数值", + "K15f35bf2": "转发上游路径", + "K79dec0dd": "请求超时时间", + "K7d465645": "绑定上游服务", + "K63a6404d": "重试时间", + "K47740727": "转发上游请求头", + "K2b605d42": "More", + "K1df9fbd5": "导入", + "K5e85df18": "导入格式", + "K9eaf7885": "全量替换", + "Kf8c3a80b": "在末端插入", + "Kd96b2d7d": "增量更新", + "Kf2fc08eb": "请求头", + "Ka45f1d8": "Rest 参数", + "K94bb113a": "大小", + "K359919b5": "另存为文件", + "K38bf1b90": "响应", + "K59f4186e": "响应头", + "K5f1e23fd": "正文", + "Kf404ef7d": "发送(Enter)", + "K2dbfd648": "中止", + "Kacabc771": "秒", + "K13ae6a93": "复制", + "Ke54a14a3": "格式化", + "K43934f6d": "搜索", + "K741decac": "替代", + "Kd507abff": "确定", + "Kca2d1624": "The (0) must not be negative.", + "K792b255a": "The (0) must be greater than or equal to the (1).", + "Kf0bed26d": "值枚举", + "K633a03ca": "枚举", + "Kd2766caf": "最小长度", + "Kd6d52485": "最大长度", + "Kea15f66c": "最小值", + "K1af340ff": "最大值", + "K68691e16": "将文件拖拽至此处上传,或点击选择文件上传", + "Kcec46ae": "Upload Files", + "K760fb044": "Files Selected", + "Kea2bdee0": "请填写接口名称", + "K49053438": "详细说明", + "K148f6fa4": "高级匹配", + "K3ae4c789": "转发配置", + "K2f4d0a37": "请求参数", + "Kde2d6dbd": "返回示例", + "K70e6069c": "测试 API", + "Ke4603448": "请求 Header", + "K89fd86b3": "请求 Body", + "K8747e3c4": "请求示例代码", + "K8613e6e7": "响应示例", + "Kab1c2159": "响应 Header", + "Kd2be51d1": "响应 Body", + "K2a3f24ac": "默认工作表", + "K7e1ab4b0": "至", + "Kf1b166e7": "详情", + "K28555332": "暂不支持带有双斜杠//的url", + "K71661ee8": "必填项", + "Kcbee3f8": "不是有效邮箱地址", + "K617f34f1": "最近一次更新者", + "K6ebca204": "最近一次更新时间", + "Kabfe9512": "保存", + "K51d1eb5d": "API 路由", + "Ka2b6d281": "API 文档", + "Kdefa9caa": "使用说明", + "K36856e71": "发布", + "K6382bbfd": "订阅管理", + "K2eef4e4": "订阅审批", + "Ka97bd9e5": "订阅方管理", + "K5974bf24": "管理", + "K3fa5c4c3": "调用拓扑图", + "Kb5c7b82d": "设置", + "K1e84ad04": "服务 ID", + "K39ab0358": "新增订阅方", + "K18307d56": "手动添加", + "K705fe9f5": "订阅申请", + "K3a67ea90": "订阅方", + "Kefa2a4cf": "AI 路由设置", + "K66060758": "路由名称", + "K5582ac8": "请求路径", + "K2bb86fb4": "提示词", + "K13ffbe88": "变量", + "K79c8cfaf": "输入这个接口的描述", + "K469e475a": "重试次数", + "K8a35059b": "模型配置", + "Kf9dcef3a": "路由", + "K6134bbe8": "添加路由", + "Kf85b83a0": "输入 URL 查找路由", + "Kcf9f90b8": "模型供应商", + "Kfede1c7c": "模型", + "Ke99513a0": "参数", + "K3818f03d": "审批", + "K54e27f57": "通过", + "K8582af3f": "拒绝", + "Kd568e15c": "发布结果", + "K35f990b0": "查看详情", + "Kdbc1f6cb": "申请发布", + "Kb6860a3f": "回滚", + "Ka3494f4b": "请确认是否回滚?", + "Kb397a99f": "撤销申请", + "K7d401c0f": "请确认是否撤销申请?", + "Ke1b79b93": "终止发布", + "Ka2449180": "请确认是否终止发布?", + "K2cb02f38": "新建版本", + "Kb3e34847": "从 (0) 获取 API KEY", + "K66a7d24c": "已配置", + "Kaf074220": "未配置", + "Kd9a46c29": "默认", + "K7ac2be34": "AI 模型管理", + "K2260837a": "配置好 AI 模型后,你可以使用对应的大模型来创建 AI 服务", + "K18dccc1a": "同步最新模型", + "K6208054": "待审批", + "K74ab00a3": "已审批", + "K56b4254f": "发布申请", + "Kea2f9279": "API 调用地址", + "K7fc496a1": "API base URL 一般设置为API 网关的外部网络访问地址,或者是API网关绑定的域名。", + "K8ab0fc95": "常规设置", + "Kb66fec9d": "API 请求设置", + "K4de0af74": "服务分类", + "Kb4ceecea": "添加子分类", + "K67479e88": "修改分类名称", + "K2bc75e2c": "添加分类", + "Kab4aab44": "重命名分类", + "Ke595a20a": "分类名称", + "K9679728f": "父分类 ID", + "K9b2d08fd": "子分类名称", + "K71671763": "快速接入 AI", + "Ka8a5ec5": "配置你的 AI 模型", + "K10d7e99f": "通过 APIPark 快速接入各种 AI 模型,使用统一的格式来调用API,并且可以随意切换模型。", + "Kc057704a": "创建 AI 服务和 API", + "K76bb4a09": "创建 AI 类型的服务,并且你可以将 Prompt 提示词设置为一个 API,简化使用 AI 的流程。", + "K71b2c70f": "创建调用 Token", + "K9bdd8403": "为了安全地调用 API,你需要创建一个应用以及Token。", + "Kc5738b6c": "调用", + "Kd6d7ca1f": "现在你可以通过 Token 来调用这些 API。", + "K86cf95f": "快速接入 REST API", + "K7a3a8417": "创建 REST 服务和 API", + "K4a84214e": "统计 API 调用情况", + "K297d8563": "仪表盘中提供了多种统计图表,帮助我们了解 API 的运行情况。", + "K2cdbb773": "核心功能", + "K3378c50d": "账号与角色", + "Kda5bb930": "邀请你的团队成员加入 APIPark,共同管理和调用 API。", + "Kc8239422": "团队中包含了人员、应用和服务,不同团队之间的应用和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。", + "Kd5be0cd7": "服务内包含一组 API,并且可以发布到 API 市场被其他团队使用。", + "K62e89ee7": "权限管理", + "K8f7808e6": "订阅服务", + "Kb0755523": "如果需要调用某个服务的 API,需要先订阅该服务,并且等待提供服务的团队审批后才可发起 API 请求。", + "Kd28a1aa5": "审批订阅申请", + "K1c15bb2e": "提供服务的团队可以审批来自其他团队的订阅申请,审批通过后的应用才可发起 API 请求。", + "K3453272": "APIPark 提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。", + "Kd518ba3e": "Hello!欢迎使用 APIPark", + "Ke66e4182": "你能通过 APIPark 快速在企业内部构建 API 开放门户/市场,享受极致的转发性能、API 可观测、服务治理、多租户管理、订阅审批流程等诸多好处。", + "Kedd41c18": "如果你喜欢我们的产品,欢迎给我们 Star 或提供产品反馈意见。", + "Kef02fd87": "快速入门", + "K43a3b38d": "我们提供了一些任务来帮你快速了解 APIPark", + "K408bfcf1": "进阶教程", + "K1afaf20e": "了解 APIPark 如何更好地管理 API 和 AI", + "K48f7e21f": "了解更多功能", + "K698296e2": "隐藏该教程", + "Kd2c1a316": "登录", + "Kf076f63c": "请输入账号", + "K25c895d5": "请输入密码", + "K551b0348": "密码", + "K192b3e38": "访客模式", + "K91aa4801": "您可通过访客模式查看所有页面和功能,但是无法编辑数据。访客模式仅用于了解产品功能,您可以在正式产品中关闭该功能。", + "K480045ce": "Version (0)-(1)", + "Kadee8e49": "日志配置", + "K2724314b": "提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。", + "K33c76dbc": "部门名称", + "K84829ca9": "父部门 ID", + "K4d7fc74b": "子部门名称", + "Keb9fcdad": "用户名", + "Kc654b275": "邮箱", + "Kbe2ecc69": "部门", + "Ka16e6c44": "未激活、已禁用的成员无法加入到部门", + "Ked03ba97": "请选择成员需要新加入的部门", + "K184d3473": "添加账号", + "K1ecb35f2": "编辑成员信息", + "Ke6f00b44": "加入部门", + "K501cb1e7": "确定删除成员?此操作无法恢复,确认操作?", + "Kf20863b5": "成员与部门", + "K52c8a730": "启用", + "K718c9310": "禁用", + "K5f27a546": "输入用户名、邮箱查找成员", + "K7c97c5df": "移出当前部门", + "K1362a512": "禁用成员", + "K6e1289b1": "启用成员", + "K1f4b5385": "删除成员", + "K26c698bb": "添加部门", + "Kb9cf2a7d": "添加子部门", + "Kc83551f5": "重命名", + "K5cfdd950": "该数据删除后将无法找回,请确认是否删除?", + "K74aef1ad": "成员", + "K3f1077c9": "设置成员和对应的角色,成员只能够看到权限范围内的功能和数据。", + "Kdce62a6": "搜索部门", + "Ka46b9b24": "数据源类型", + "Kbb0cdcd0": "数据源地址", + "Kd9dfb884": "Organization", + "K3e770a75": "鉴权 Token", + "K8ef69ee2": "密钥", + "Kba3507d6": "上传密钥", + "K93ac0f23": "密钥文件的后缀名一般为 .key 的文件内容", + "K7cdd1331": "上传证书", + "K6d91905d": "证书文件的后缀名一般为 .crt 或 .pem 的文件内容", + "Kd0f6ded7": "添加证书", + "Ke5732d60": "修改证书", + "K3ca07a70": "证书管理", + "Kdb927f83": "通过为 API 服务配置和管理 SSL 证书,企业可以加密数据传输,防止敏感信息被窃取或篡改。", + "Ke93d36ed": "集群", + "K877985b7": "修改配置", + "Kdf66a675": "设置访问 API 的集群,让 API 在分布式环境中稳定运行,并且能够根据业务需求进行灵活扩展和优化。", + "Ke039b9b5": "正常", + "K23a3bd72": "异常", + "Kf12b3034": "管理地址", + "K867e6faf": "服务地址", + "K2a49373f": "同步地址", + "K5878440c": "集群地址", + "K5e9022f8": "下一步", + "Kdbafd6f9": "设置监控报表的数据来源,设置完成之后即可获得详细的API调用统计图表。", + "K1358acf": "统计图表", + "K62dabdf6": "地址(IP:端口)", + "K2db12335": "组织(Organization)", + "K8e7a0f80": "资源配置", + "K95c3fd8b": "设置角色的权限范围。", + "K138facd3": "系统级别角色", + "K6eac768d": "添加角色", + "Kb9c2cf02": "团队级别角色", + "K2a16c93b": "单位:ms,最小值:1", + "Ka945cfb1": "API 路由设置", + "K2e050340": "API 基础信息", + "Kba92c499": "拦截该接口的请求", + "Kde9d6e8e": "开启拦截后,网关会拦截所有该路径的请求,相当于防火墙禁用了特定路径的访问。", + "K6bc47edb": "请求协议", + "K1365fe45": "请求方式", + "K90f3c02f": "转发规则设置", + "Kb7df6ac1": "拦截", + "K5c1722fe": "放行", + "K28435c5c": "路由详情", + "Ka9c08390": "只允许上传PNG、JPG或SVG格式的图片", + "K413b9869": "服务名称", + "K9919285b": "服务类型", + "Kcef64f4d": "默认 AI 供应商", + "Kcab588a9": "未配置任何 AI 模型供应商,", + "Kb9b56111": "立即配置", + "Kcf756b7a": "API 调用前缀", + "K13edc043": "作为服务内所有API的前缀,比如host/{service_name}/{api_path},一旦保存无法修改", + "Kf52a584d": "所属服务分类", + "K72b21be5": "设置服务展示在服务市场中的哪个分类下", + "Kdc840242": "图标", + "K427a5bd5": "仅支持 .png .jpg .jpeg .svg 格式的图片文件, 大于 1KB 的文件将被压缩", + "K44bc352d": "Logo", + "Kde6bae17": "删除服务", + "K885ea699": "删除操作不可恢复,请谨慎操作!", + "Kda8d5ea1": "上游", + "K12f58863": "服务提供了高性能 API 网关,并且可以无缝接入多种大型 AI 模型,并将这些 AI 能力打包成 API 进行调用,从而大幅简化了 AI 模型的使用门槛。同时,我们的平台提供了完善的 API 管理功能,支持 API 的创建、监控、访问控制等,保障开发者可以高效、安全地开发和管理 API 服务。", + "K2d6658ed": "添加服务", + "K7b8f623f": "输入名称、ID、所属团队、负责人查找服务", + "Kad98e030": "上游类型", + "Kdd9b5008": "后端默认使用的IP地址", + "Kc9acdb25": "负载均衡", + "K632dba5c": "转发 Host", + "Kc1f08a63": "重写域名", + "K628f6851": "超时时间", + "Kaff62621": "超时重试次数", + "Kf14d159b": "次", + "Kc41ca30e": "调用频率限制", + "K753e8aeb": "次/秒", + "K813e1c0a": "团队名称", + "K692f5aa6": "团队 ID", + "K5de0bc2": "团队 ID(team_id)可用于检索团队,一旦保存无法修改。", + "Ka63dd985": "团队负责人", + "Ka6bcd272": "负责人对团队内的团队、服务、成员有管理权限", + "Ka2012bdd": "删除团队", + "Kbde1f3d": "服务数据清除后,方可删除", + "K395acc14": "移除成员", + "Kec46a57f": "添加成员", + "K48724410": "输入姓名查找", + "Kb9052305": "搜索用户名、邮箱", + "K5ece3bac": "设置团队和成员,然后你可以在团队内创建服务和应用、订阅API,成员只能看到所属团队内的服务和应用。", + "K510cdd27": "添加团队", + "K9244ae14": "输入名称、ID、负责人查找团队", + "Kc7b24b4b": "配置团队", + "Kecb51e2c": "旧密码", + "K8266bcf2": "新密码", + "Ka9aef039": "确认密码", + "Kcf42dcda": "两次密码不一致", + "Kf876a42d": "修改密码", + "K8ed884f": "管理个人账号", + "K9be8e1d7": "API调用统计", + "K521ab28e": "选择服务", + "Kcc8265e1": "选择API", + "Kc380335f": "路径", + "K8aefc1e4": "请输入请求路径进行搜索", + "K50d471b2": "重置", + "Kee8ae330": "查询", + "Ka2c794a2": "导出", + "Kaf70c3b": "退出全屏", + "Kd22841a4": "(0)调用详情", + "K1512e983": "应用调用统计", + "Kb4d2007f": "请选择应用", + "K8c7f2d2e": "调用趋势", + "K657c3452": "(0)-(1)调用趋势", + "Kc04efb87": "调用量统计", + "Keb98266e": "加入总体数据对比", + "K18c2ed46": "(0)调用量", + "Kc3741830": "(0)调用成功率", + "Ka6aa5863": "请求总数", + "K9eaef42": "请求成功率", + "K7082a4af": "转发总数", + "K1ce386fb": "转发成功率", + "K87d6877e": "状态码4xx数", + "K4c8a54db": "状态码5xx数", + "Kd566283e": "调用总体趋势", + "K21ad4a6a": "(0)报文量", + "Kd23a0be6": "请求报文量", + "Kec3e8361": "响应报文量", + "Ke6250744": "状态码4XX数", + "K2d79d4e1": "状态码5XX数", + "Kcf6553c6": "服务调用统计", + "Kffcfe375": "请选择服务", + "Ka65f739c": "调用详情", + "K89b7ac79": "API 请求量 Top10", + "Kc0915603": "应用调用量 Top10", + "Kf90b54": "服务被调用量 Top10", + "Kfb26388": "暂无请求统计数据", + "Kc8cbd8f8": "请求统计", + "K8dece48": "暂无转发统计数据", + "K1ee32434": "转发统计", + "Kcd125e4d": "暂无调用量统计数据", + "Kaa114e8b": "暂无报文量统计数据", + "K3ad84406": "报文量统计", + "Kfa088d49": "集群配置并开启监控", + "K3da3b9a0": "监控功能用于辅助管理集群内信息,请配置集群、设置监控信息后查看当前集群监控情况;", + "Kaddacfb": "集群配置", + "K4ac33975": "配置集群地址,以确保监控系统能够正确识别和连接到集群", + "Ke5ed9810": "配置集群信息", + "K1a132228": "监控设置", + "K6af08c3c": "配置监控信息", + "K4a1a14": "监控总览", + "K69741ea7": "服务被调用统计", + "K9c8d9933": "API 调用统计", + "K145e4941": "亿", + "Ke6a935d": "万", + "Kd59290a2": "搜索分类或标签", + "K6b75bdbc": "暂无API数据", + "Kd8a7a689": "搜索或选择应用", + "K4b15d6f5": "申请理由", + "Kb7e869a4": "应用管理", + "Kb71b5a13": "鉴权类型", + "K4d1465ee": "Iss", + "K5dcd7ed8": "签名算法", + "K5b0eedd3": "Secret", + "K44f4ffe1": "RSA 公钥", + "Kc5ecd7d9": "用户名 JsonPath", + "K417d85cf": "校验字段", + "K3b82fe1d": "是否 Base64 加密", + "K49b5f4a3": "AK", + "K31418470": "SK", + "Kbfeb5297": "Apikey", + "K1a78e6f0": "过期时间", + "Ke64e43a": "隐藏鉴权信息", + "K5168eb63": "应用名称", + "K546e46f": "应用 ID", + "K95764d1d": "删除应用", + "K217cb125": "鉴权详情", + "K2bb63eca": "添加鉴权", + "Kd74d69b7": "编辑鉴权", + "K9cbe1e0": "修改", + "Kb6e9328f": "访问授权", + "Kd23d1716": "添加授权", + "K9dfa2c97": "永不过期", + "Kfa920c0": "到期时间", + "Kcce1af60": "订阅的服务", + "Kbeb4e991": "审批详情", + "K3118fdb0": "取消订阅", + "Ked811bb1": "请确认是否取消订阅?", + "K50c39a62": "取消订阅申请", + "K1856c229": "请确认是否取消订阅申请?", + "K66ea2f0": "搜索服务", + "Kfeb2559b": "审批中", + "K667bbbe7": "添加应用", + "Ka4b45550": "暂无服务描述", + "K3c7b175f": "订阅的服务数量:已通过 (0) 个,申请中 (1) 个", + "Kbe3e9335": "退出测试", + "K370a3eb2": "服务市场", + "Kf7ec36d": "服务详情", + "K58ca9485": "申请服务", + "K59cdbec3": "介绍", + "K4aa9ed2c": "申请", + "K6c060779": "服务信息", + "K8723422e": "接入应用", + "Kb97544cb": "供应方", + "Kb32f0afe": "分类", + "K81634069": "版本", + "Keefda53d": "更新时间", + "K96a2f1c8": "无标签", + "K72b0c0b3": "API 数量", + "K93d5a66e": "接入应用数量", + "K96059c69": "关联标签", + "K8b7c2592": "更新者", + "K32263abd": "添加 Open Api", + "K7829bb78": "配置 Open Api", + "Kcdf76005": "Open Api", + "Ke2601944": "调用服务", + "K8504bca8": "放大", + "K693c1b41": "缩小", + "K3d7465f7": "文件日志", + "Kc87167a0": "HTTP日志", + "K54630fe8": "Kafka日志", + "Kd5c3966e": "NSQ日志", + "K2e3de2c1": "Syslog日志", + "K48322168": "未分配", + "K98f247f9": "超级管理员", + "K9c8a571f": "团队管理员", + "K929b485b": "运维管理员", + "K82cc5ec2": "普通成员", + "Ke41d7451": "只读成员", + "Kf99e8b66": "服务管理员", + "Kda8db57a": "服务开发者", + "K216a1ac7": "应用开发者", + "K27924db": "应用管理员", + "K8dc5c723": "驱动名称", + "Kda249fe8": "请求失败数", + "Kcf2df651": "转发失败数", + "K7e6a859d": "作用范围", + "K3a008b34": "添加条目", + "Ke0599ef7": "添加地址", + "K48d3b5c4": "文件名称", + "Kafde0d2a": "存放目录", + "Kfb2926ac": "日志分割周期", + "Kd96c2c69": "单位:天", + "Kc2b776fa": "输出格式", + "K7b7cdac2": "格式化配置", + "K2f59807a": "服务器地址", + "Kb1cfa6e7": "Access日志", + "K540488a8": "NSQD地址列表", + "K8bc33a11": "鉴权Secret", + "K1cd3002f": "网络协议", + "Kdfaa32c8": "日志等级", + "Kc0408d9c": "单行", + "Ke3db239d": "小时", + "K3509a9f8": "天", + "Kb3960e83": "未发布", + "K8bd1e18": "待发布", + "K225a6c43": "单位:s,最小值:1", + "K6a7fa303": "无需审批", + "Kd196e8a4": "需要审批", + "K1b6777bb": "Basic URL", + "Kd55c6887": "申请审批", + "K300c89d4": "创建 API 时会默认选择该供应商,修改默认供应商不会影响现有 API" +} \ No newline at end of file diff --git a/frontend/packages/common/src/locales/scan/newJson/zh-CN.json b/frontend/packages/common/src/locales/scan/newJson/zh-CN.json index b2fbe168..955e3704 100644 --- a/frontend/packages/common/src/locales/scan/newJson/zh-CN.json +++ b/frontend/packages/common/src/locales/scan/newJson/zh-CN.json @@ -1,3 +1,104 @@ { - "K28b68036": "字符非法,仅支持英文" -} + "K1c15bb2e": "提供服务的团队可以审批来自其他团队的订阅申请,审批通过后的应用才可发起 API 请求。", + "Kc6340091": "上下文", + "K74ecb1fa": "查询内容", + "K79f2e2f9": "会话历史", + "K3a8912ee": "添加新变量", + "Kb291a19": "添加工具", + "K27ece71d": "AI 模型调用默认仅使用 Query 变量,可输入 “{” 增加新变量。", + "K7e52ffa3": "上线情况", + "Ke00c858c": "上传文件", + "K6d9dd1f5": "替换文件", + "Ke66a17dd": "必填", + "K28b68036": "字符非法,仅支持英文", + "K6206e4ad": "上传 OpenAPI 文档 (.json/.yaml)", + "Kfba46e6d": "替换 OpenAPI 文档 (.json/.yaml)", + "Kdac8ce7e": "打开 OpenAPI YAML 编辑器", + "Kf5da1284": "无需审批:允许任何应用调用该服务", + "Kc59ff06d": "人工审批:仅允许通过人工审批的应用调用该服务", + "Kbfe02d7f": "永久", + "K1e9c479e": "否", + "Kaddfcb6b": "是", + "K51d1eb5d": "API 路由", + "Kefa2a4cf": "AI 路由设置", + "K66060758": "路由名称", + "K2bb86fb4": "提示词", + "K13ffbe88": "变量", + "K79c8cfaf": "输入这个接口的描述", + "K8a35059b": "模型配置", + "Kf9dcef3a": "路由", + "K6134bbe8": "添加路由", + "Kf85b83a0": "输入 URL 查找路由", + "Kcf9f90b8": "模型供应商", + "Kfede1c7c": "模型", + "Ke99513a0": "参数", + "Kb3e34847": "从 (0) 获取 API KEY", + "K66a7d24c": "已配置", + "Kd9a46c29": "默认", + "K7ac2be34": "AI 模型管理", + "K2260837a": "配置好 AI 模型后,你可以使用对应的大模型来创建 AI 服务", + "K18dccc1a": "同步最新模型", + "Kea2f9279": "API 调用地址", + "K7fc496a1": "API base URL 一般设置为API 网关的外部网络访问地址,或者是API网关绑定的域名。", + "Kb66fec9d": "API 请求设置", + "K71671763": "快速接入 AI", + "Ka8a5ec5": "配置你的 AI 模型", + "K10d7e99f": "通过 APIPark 快速接入各种 AI 模型,使用统一的格式来调用API,并且可以随意切换模型。", + "Kc057704a": "创建 AI 服务和 API", + "K76bb4a09": "创建 AI 类型的服务,并且你可以将 Prompt 提示词设置为一个 API,简化使用 AI 的流程。", + "K71b2c70f": "创建调用 Token", + "K9bdd8403": "为了安全地调用 API,你需要创建一个应用以及Token。", + "Kc5738b6c": "调用", + "Kd6d7ca1f": "现在你可以通过 Token 来调用这些 API。", + "K86cf95f": "快速接入 REST API", + "K7a3a8417": "创建 REST 服务和 API", + "K4a84214e": "统计 API 调用情况", + "K698296e2": "隐藏该教程", + "K7c97c5df": "移出当前部门", + "K1362a512": "禁用成员", + "K6e1289b1": "启用成员", + "K1f4b5385": "删除成员", + "Ka46b9b24": "数据源类型", + "Kbb0cdcd0": "数据源地址", + "Kd9dfb884": "Organization", + "K2a49373f": "同步地址", + "Ka945cfb1": "API 路由设置", + "Kba92c499": "拦截该接口的请求", + "Kb7df6ac1": "拦截", + "K5c1722fe": "放行", + "K28435c5c": "路由详情", + "Kcab588a9": "未配置任何 AI 模型供应商,", + "Kb9b56111": "立即配置", + "Kfa088d49": "集群配置并开启监控", + "K3da3b9a0": "监控功能用于辅助管理集群内信息,请配置集群、设置监控信息后查看当前集群监控情况;", + "Kaddacfb": "集群配置", + "K4ac33975": "配置集群地址,以确保监控系统能够正确识别和连接到集群", + "Ke5ed9810": "配置集群信息", + "K1a132228": "监控设置", + "K6af08c3c": "配置监控信息", + "K54630fe8": "Kafka日志", + "Kd5c3966e": "NSQ日志", + "K2e3de2c1": "Syslog日志", + "Kda249fe8": "请求失败数", + "Kcf2df651": "转发失败数", + "K7e6a859d": "作用范围", + "K3a008b34": "添加条目", + "Ke0599ef7": "添加地址", + "K48d3b5c4": "文件名称", + "Kafde0d2a": "存放目录", + "Kfb2926ac": "日志分割周期", + "Kd96c2c69": "单位:天", + "Kc2b776fa": "输出格式", + "K7b7cdac2": "格式化配置", + "K2f59807a": "服务器地址", + "Kb1cfa6e7": "Access日志", + "K540488a8": "NSQD地址列表", + "K8bc33a11": "鉴权Secret", + "K1cd3002f": "网络协议", + "Kdfaa32c8": "日志等级", + "K6a7fa303": "无需审批", + "Kd196e8a4": "需要审批", + "K1b6777bb": "Basic URL", + "Kd55c6887": "申请审批", + "K300c89d4": "创建 API 时会默认选择该供应商,修改默认供应商不会影响现有 API" +} \ No newline at end of file diff --git a/frontend/packages/common/src/locales/scan/newJson/zh-TW.json b/frontend/packages/common/src/locales/scan/newJson/zh-TW.json new file mode 100644 index 00000000..449ff8f0 --- /dev/null +++ b/frontend/packages/common/src/locales/scan/newJson/zh-TW.json @@ -0,0 +1,580 @@ +{ + "Kc0e5ef9f": "工作空间", + "K4de11e23": "首页", + "Kfe93ef35": "应用", + "Kb58e0c3f": "服务", + "Kc9e489f5": "团队", + "K61c89f5f": "API 市场", + "K16d71239": "仪表盘", + "K714c192d": "运行视图", + "Kd57dfe97": "系统拓扑图", + "K3fe97dcc": "系统设置", + "Kecbb0e45": "系统", + "Ka358e23d": "常规", + "K449058e9": "API 网关", + "K99935e6f": "AI 模型", + "K1deaa2dd": "用户", + "K80a560a1": "账号", + "Kf644225f": "角色", + "K4057391a": "集成", + "K8fa58214": "数据源", + "K481e8a05": "证书", + "Kca53edd0": "日志", + "Kb283e720": "资源", + "K631d646f": "Open API", + "K6535ff9c": "账号设置", + "Kf15499b4": "退出登录", + "Kabbd6e6": "文档", + "K1196b104": "APIPark - 企业API数据开放平台", + "K1f42de3": "HTTP 状态码", + "K4770dff4": "系统状态码", + "Kf89e58f1": "描述", + "K9e53c664": "提交", + "Kf8e7294c": "上一步", + "Ka0451c97": "取消", + "Kb1dedda3": "关闭", + "Kb2fc7600": "添加配置", + "K4e07217d": "编辑配置", + "K4ea968fe": "编辑(0)", + "Ka7aaaeb": "添加(0)", + "Kaff78ecf": "请输入Key", + "K65d46535": "请输入Value", + "Kc14b2ea3": "返回", + "K11d3633a": "ID", + "Kbff43de3": "名称", + "K16ca79ef": "Driver", + "K7a369eef": "已发布", + "Kcfa1a4d2": "下线", + "K771dc3b7": "上线", + "K530f5951": "查看", + "Kecbd7449": "删除", + "K1cbe2507": "确认", + "K48325b6": "搜索(0)名称", + "Kc6340091": "上下文", + "K74ecb1fa": "查询内容", + "K79f2e2f9": "会话历史", + "K3a8912ee": "添加新变量", + "Kb291a19": "添加工具", + "K27ece71d": "AI 模型调用默认仅使用 Query 变量,可输入 “{” 增加新变量。", + "Kdeed8399": "静态上游", + "K4ee62e8": "该 API 缺失(0)(1)(2)请先补充", + "K385591f3": "转发信息,", + "K68415c14": "文档信息,", + "K133b75e9": "上游信息,", + "K43fcaf94": "成功", + "Kc71c6a9": "上线失败", + "K56c686f8": "失败", + "K1ff96ff": "申请系统", + "K9bf855d6": "所属团队", + "K11b994ed": "申请人", + "K939baba7": "申请时间", + "Kdab2e63b": "版本号", + "K8b29c460": "版本说明", + "K4758140d": "路由列表", + "K54e44357": "上游列表", + "Kb8e8e6f5": "备注", + "K7e52ffa3": "上线情况", + "K1ab0ae5b": "申请原因", + "K53c00c3c": "审核意见", + "Kfd50704d": "暂无(0)权限,请联系管理员分配。", + "K7edf331d": "时间", + "Kef45b208": "近1小时", + "K9dbf22b8": "近24小时", + "K820fbfab": "近3天", + "Kd6d28fc": "近7天", + "Ke00c858c": "上传文件", + "K6d9dd1f5": "替换文件", + "K71753476": "是否放行", + "K597435c5": "监控", + "Ke66a17dd": "必填", + "K28b68036": "字符非法,仅支持英文", + "K6206e4ad": "上传 OpenAPI 文档 (.json/.yaml)", + "Kfba46e6d": "替换 OpenAPI 文档 (.json/.yaml)", + "Kdac8ce7e": "打开 OpenAPI YAML 编辑器", + "Kf5da1284": "无需审批:允许任何应用调用该服务", + "Kc59ff06d": "人工审批:仅允许通过人工审批的应用调用该服务", + "Kbfe02d7f": "永久", + "K1e9c479e": "否", + "Kaddfcb6b": "是", + "K23fda291": "暂无操作权限,请联系管理员分配。", + "K4618cb0a": "微信小程序", + "Ka854f511": "获取文件,需填路径", + "Kaa11a695": "暂不支持生成非 HTTPS 或非 HTTP 协议的代码示例", + "Kbe46924e": "搜索编程语言...", + "Ke8e4f258": "编程语言", + "K29c07a47": "成功示例", + "K1f5c814d": "失败示例", + "K4ef022d7": "默认 text/html;charset=UTF-8", + "Kd061b5bf": "暂未填写示例", + "Kc14cec33": "Binary", + "K48b4d9e3": "请求头部", + "Kcd347eaf": "请求体", + "K9e100bfe": "Query 参数", + "K3e9f12fd": "REST 参数", + "K2bfa290c": "api request editor", + "Kb36d111a": "返回头部", + "K980bde79": "返回值", + "Kb04d201a": "更多设置", + "Kee74f5b4": "添加子参数", + "Kc7d3106c": "向下添加行", + "Keaabd222": "标签", + "K8ad2c50e": "参数名", + "K67d68dd1": "类型", + "K29245f47": "必需", + "Ke32cbcd3": "示例", + "Kc13936c6": "输入 URL 或 cURL", + "Ka1ede006": "HTTP", + "K152ac44e": "参数位置", + "K1660ae72": "匹配类型", + "K91ced765": "参数值", + "K5b265628": "操作类型", + "K1826982d": "新增或修改", + "Kd65b55f5": "匹配参数值", + "K15f35bf2": "转发上游路径", + "K79dec0dd": "请求超时时间", + "K7d465645": "绑定上游服务", + "K63a6404d": "重试时间", + "K47740727": "转发上游请求头", + "K2b605d42": "More", + "K1df9fbd5": "导入", + "K5e85df18": "导入格式", + "K9eaf7885": "全量替换", + "Kf8c3a80b": "在末端插入", + "Kd96b2d7d": "增量更新", + "Kf2fc08eb": "请求头", + "Ka45f1d8": "Rest 参数", + "K94bb113a": "大小", + "K359919b5": "另存为文件", + "K38bf1b90": "响应", + "K59f4186e": "响应头", + "K5f1e23fd": "正文", + "Kf404ef7d": "发送(Enter)", + "K2dbfd648": "中止", + "Kacabc771": "秒", + "K13ae6a93": "复制", + "Ke54a14a3": "格式化", + "K43934f6d": "搜索", + "K741decac": "替代", + "Kd507abff": "确定", + "Kca2d1624": "The (0) must not be negative.", + "K792b255a": "The (0) must be greater than or equal to the (1).", + "Kf0bed26d": "值枚举", + "K633a03ca": "枚举", + "Kd2766caf": "最小长度", + "Kd6d52485": "最大长度", + "Kea15f66c": "最小值", + "K1af340ff": "最大值", + "K68691e16": "将文件拖拽至此处上传,或点击选择文件上传", + "Kcec46ae": "Upload Files", + "K760fb044": "Files Selected", + "Kea2bdee0": "请填写接口名称", + "K49053438": "详细说明", + "K148f6fa4": "高级匹配", + "K3ae4c789": "转发配置", + "K2f4d0a37": "请求参数", + "Kde2d6dbd": "返回示例", + "K70e6069c": "测试 API", + "Ke4603448": "请求 Header", + "K89fd86b3": "请求 Body", + "K8747e3c4": "请求示例代码", + "K8613e6e7": "响应示例", + "Kab1c2159": "响应 Header", + "Kd2be51d1": "响应 Body", + "K2a3f24ac": "默认工作表", + "K7e1ab4b0": "至", + "Kf1b166e7": "详情", + "K28555332": "暂不支持带有双斜杠//的url", + "K71661ee8": "必填项", + "Kcbee3f8": "不是有效邮箱地址", + "K617f34f1": "最近一次更新者", + "K6ebca204": "最近一次更新时间", + "Kabfe9512": "保存", + "K51d1eb5d": "API 路由", + "Ka2b6d281": "API 文档", + "Kdefa9caa": "使用说明", + "K36856e71": "发布", + "K6382bbfd": "订阅管理", + "K2eef4e4": "订阅审批", + "Ka97bd9e5": "订阅方管理", + "K5974bf24": "管理", + "K3fa5c4c3": "调用拓扑图", + "Kb5c7b82d": "设置", + "K1e84ad04": "服务 ID", + "K39ab0358": "新增订阅方", + "K18307d56": "手动添加", + "K705fe9f5": "订阅申请", + "K3a67ea90": "订阅方", + "Kefa2a4cf": "AI 路由设置", + "K66060758": "路由名称", + "K5582ac8": "请求路径", + "K2bb86fb4": "提示词", + "K13ffbe88": "变量", + "K79c8cfaf": "输入这个接口的描述", + "K469e475a": "重试次数", + "K8a35059b": "模型配置", + "Kf9dcef3a": "路由", + "K6134bbe8": "添加路由", + "Kf85b83a0": "输入 URL 查找路由", + "Kcf9f90b8": "模型供应商", + "Kfede1c7c": "模型", + "Ke99513a0": "参数", + "K3818f03d": "审批", + "K54e27f57": "通过", + "K8582af3f": "拒绝", + "Kd568e15c": "发布结果", + "K35f990b0": "查看详情", + "Kdbc1f6cb": "申请发布", + "Kb6860a3f": "回滚", + "Ka3494f4b": "请确认是否回滚?", + "Kb397a99f": "撤销申请", + "K7d401c0f": "请确认是否撤销申请?", + "Ke1b79b93": "终止发布", + "Ka2449180": "请确认是否终止发布?", + "K2cb02f38": "新建版本", + "Kb3e34847": "从 (0) 获取 API KEY", + "K66a7d24c": "已配置", + "Kaf074220": "未配置", + "Kd9a46c29": "默认", + "K7ac2be34": "AI 模型管理", + "K2260837a": "配置好 AI 模型后,你可以使用对应的大模型来创建 AI 服务", + "K18dccc1a": "同步最新模型", + "K6208054": "待审批", + "K74ab00a3": "已审批", + "K56b4254f": "发布申请", + "Kea2f9279": "API 调用地址", + "K7fc496a1": "API base URL 一般设置为API 网关的外部网络访问地址,或者是API网关绑定的域名。", + "K8ab0fc95": "常规设置", + "Kb66fec9d": "API 请求设置", + "K4de0af74": "服务分类", + "Kb4ceecea": "添加子分类", + "K67479e88": "修改分类名称", + "K2bc75e2c": "添加分类", + "Kab4aab44": "重命名分类", + "Ke595a20a": "分类名称", + "K9679728f": "父分类 ID", + "K9b2d08fd": "子分类名称", + "K71671763": "快速接入 AI", + "Ka8a5ec5": "配置你的 AI 模型", + "K10d7e99f": "通过 APIPark 快速接入各种 AI 模型,使用统一的格式来调用API,并且可以随意切换模型。", + "Kc057704a": "创建 AI 服务和 API", + "K76bb4a09": "创建 AI 类型的服务,并且你可以将 Prompt 提示词设置为一个 API,简化使用 AI 的流程。", + "K71b2c70f": "创建调用 Token", + "K9bdd8403": "为了安全地调用 API,你需要创建一个应用以及Token。", + "Kc5738b6c": "调用", + "Kd6d7ca1f": "现在你可以通过 Token 来调用这些 API。", + "K86cf95f": "快速接入 REST API", + "K7a3a8417": "创建 REST 服务和 API", + "K4a84214e": "统计 API 调用情况", + "K297d8563": "仪表盘中提供了多种统计图表,帮助我们了解 API 的运行情况。", + "K2cdbb773": "核心功能", + "K3378c50d": "账号与角色", + "Kda5bb930": "邀请你的团队成员加入 APIPark,共同管理和调用 API。", + "Kc8239422": "团队中包含了人员、应用和服务,不同团队之间的应用和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。", + "Kd5be0cd7": "服务内包含一组 API,并且可以发布到 API 市场被其他团队使用。", + "K62e89ee7": "权限管理", + "K8f7808e6": "订阅服务", + "Kb0755523": "如果需要调用某个服务的 API,需要先订阅该服务,并且等待提供服务的团队审批后才可发起 API 请求。", + "Kd28a1aa5": "审批订阅申请", + "K1c15bb2e": "提供服务的团队可以审批来自其他团队的订阅申请,审批通过后的应用才可发起 API 请求。", + "K3453272": "APIPark 提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。", + "Kd518ba3e": "Hello!欢迎使用 APIPark", + "Ke66e4182": "你能通过 APIPark 快速在企业内部构建 API 开放门户/市场,享受极致的转发性能、API 可观测、服务治理、多租户管理、订阅审批流程等诸多好处。", + "Kedd41c18": "如果你喜欢我们的产品,欢迎给我们 Star 或提供产品反馈意见。", + "Kef02fd87": "快速入门", + "K43a3b38d": "我们提供了一些任务来帮你快速了解 APIPark", + "K408bfcf1": "进阶教程", + "K1afaf20e": "了解 APIPark 如何更好地管理 API 和 AI", + "K48f7e21f": "了解更多功能", + "K698296e2": "隐藏该教程", + "Kd2c1a316": "登录", + "Kf076f63c": "请输入账号", + "K25c895d5": "请输入密码", + "K551b0348": "密码", + "K192b3e38": "访客模式", + "K91aa4801": "您可通过访客模式查看所有页面和功能,但是无法编辑数据。访客模式仅用于了解产品功能,您可以在正式产品中关闭该功能。", + "K480045ce": "Version (0)-(1)", + "Kadee8e49": "日志配置", + "K2724314b": "提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。", + "K33c76dbc": "部门名称", + "K84829ca9": "父部门 ID", + "K4d7fc74b": "子部门名称", + "Keb9fcdad": "用户名", + "Kc654b275": "邮箱", + "Kbe2ecc69": "部门", + "Ka16e6c44": "未激活、已禁用的成员无法加入到部门", + "Ked03ba97": "请选择成员需要新加入的部门", + "K184d3473": "添加账号", + "K1ecb35f2": "编辑成员信息", + "Ke6f00b44": "加入部门", + "K501cb1e7": "确定删除成员?此操作无法恢复,确认操作?", + "Kf20863b5": "成员与部门", + "K52c8a730": "启用", + "K718c9310": "禁用", + "K5f27a546": "输入用户名、邮箱查找成员", + "K7c97c5df": "移出当前部门", + "K1362a512": "禁用成员", + "K6e1289b1": "启用成员", + "K1f4b5385": "删除成员", + "K26c698bb": "添加部门", + "Kb9cf2a7d": "添加子部门", + "Kc83551f5": "重命名", + "K5cfdd950": "该数据删除后将无法找回,请确认是否删除?", + "K74aef1ad": "成员", + "K3f1077c9": "设置成员和对应的角色,成员只能够看到权限范围内的功能和数据。", + "Kdce62a6": "搜索部门", + "Ka46b9b24": "数据源类型", + "Kbb0cdcd0": "数据源地址", + "Kd9dfb884": "Organization", + "K3e770a75": "鉴权 Token", + "K8ef69ee2": "密钥", + "Kba3507d6": "上传密钥", + "K93ac0f23": "密钥文件的后缀名一般为 .key 的文件内容", + "K7cdd1331": "上传证书", + "K6d91905d": "证书文件的后缀名一般为 .crt 或 .pem 的文件内容", + "Kd0f6ded7": "添加证书", + "Ke5732d60": "修改证书", + "K3ca07a70": "证书管理", + "Kdb927f83": "通过为 API 服务配置和管理 SSL 证书,企业可以加密数据传输,防止敏感信息被窃取或篡改。", + "Ke93d36ed": "集群", + "K877985b7": "修改配置", + "Kdf66a675": "设置访问 API 的集群,让 API 在分布式环境中稳定运行,并且能够根据业务需求进行灵活扩展和优化。", + "Ke039b9b5": "正常", + "K23a3bd72": "异常", + "Kf12b3034": "管理地址", + "K867e6faf": "服务地址", + "K2a49373f": "同步地址", + "K5878440c": "集群地址", + "K5e9022f8": "下一步", + "Kdbafd6f9": "设置监控报表的数据来源,设置完成之后即可获得详细的API调用统计图表。", + "K1358acf": "统计图表", + "K62dabdf6": "地址(IP:端口)", + "K2db12335": "组织(Organization)", + "K8e7a0f80": "资源配置", + "K95c3fd8b": "设置角色的权限范围。", + "K138facd3": "系统级别角色", + "K6eac768d": "添加角色", + "Kb9c2cf02": "团队级别角色", + "K2a16c93b": "单位:ms,最小值:1", + "Ka945cfb1": "API 路由设置", + "K2e050340": "API 基础信息", + "Kba92c499": "拦截该接口的请求", + "Kde9d6e8e": "开启拦截后,网关会拦截所有该路径的请求,相当于防火墙禁用了特定路径的访问。", + "K6bc47edb": "请求协议", + "K1365fe45": "请求方式", + "K90f3c02f": "转发规则设置", + "Kb7df6ac1": "拦截", + "K5c1722fe": "放行", + "K28435c5c": "路由详情", + "Ka9c08390": "只允许上传PNG、JPG或SVG格式的图片", + "K413b9869": "服务名称", + "K9919285b": "服务类型", + "Kcef64f4d": "默认 AI 供应商", + "Kcab588a9": "未配置任何 AI 模型供应商,", + "Kb9b56111": "立即配置", + "Kcf756b7a": "API 调用前缀", + "K13edc043": "作为服务内所有API的前缀,比如host/{service_name}/{api_path},一旦保存无法修改", + "Kf52a584d": "所属服务分类", + "K72b21be5": "设置服务展示在服务市场中的哪个分类下", + "Kdc840242": "图标", + "K427a5bd5": "仅支持 .png .jpg .jpeg .svg 格式的图片文件, 大于 1KB 的文件将被压缩", + "K44bc352d": "Logo", + "Kde6bae17": "删除服务", + "K885ea699": "删除操作不可恢复,请谨慎操作!", + "Kda8d5ea1": "上游", + "K12f58863": "服务提供了高性能 API 网关,并且可以无缝接入多种大型 AI 模型,并将这些 AI 能力打包成 API 进行调用,从而大幅简化了 AI 模型的使用门槛。同时,我们的平台提供了完善的 API 管理功能,支持 API 的创建、监控、访问控制等,保障开发者可以高效、安全地开发和管理 API 服务。", + "K2d6658ed": "添加服务", + "K7b8f623f": "输入名称、ID、所属团队、负责人查找服务", + "Kad98e030": "上游类型", + "Kdd9b5008": "后端默认使用的IP地址", + "Kc9acdb25": "负载均衡", + "K632dba5c": "转发 Host", + "Kc1f08a63": "重写域名", + "K628f6851": "超时时间", + "Kaff62621": "超时重试次数", + "Kf14d159b": "次", + "Kc41ca30e": "调用频率限制", + "K753e8aeb": "次/秒", + "K813e1c0a": "团队名称", + "K692f5aa6": "团队 ID", + "K5de0bc2": "团队 ID(team_id)可用于检索团队,一旦保存无法修改。", + "Ka63dd985": "团队负责人", + "Ka6bcd272": "负责人对团队内的团队、服务、成员有管理权限", + "Ka2012bdd": "删除团队", + "Kbde1f3d": "服务数据清除后,方可删除", + "K395acc14": "移除成员", + "Kec46a57f": "添加成员", + "K48724410": "输入姓名查找", + "Kb9052305": "搜索用户名、邮箱", + "K5ece3bac": "设置团队和成员,然后你可以在团队内创建服务和应用、订阅API,成员只能看到所属团队内的服务和应用。", + "K510cdd27": "添加团队", + "K9244ae14": "输入名称、ID、负责人查找团队", + "Kc7b24b4b": "配置团队", + "Kecb51e2c": "旧密码", + "K8266bcf2": "新密码", + "Ka9aef039": "确认密码", + "Kcf42dcda": "两次密码不一致", + "Kf876a42d": "修改密码", + "K8ed884f": "管理个人账号", + "K9be8e1d7": "API调用统计", + "K521ab28e": "选择服务", + "Kcc8265e1": "选择API", + "Kc380335f": "路径", + "K8aefc1e4": "请输入请求路径进行搜索", + "K50d471b2": "重置", + "Kee8ae330": "查询", + "Ka2c794a2": "导出", + "Kaf70c3b": "退出全屏", + "Kd22841a4": "(0)调用详情", + "K1512e983": "应用调用统计", + "Kb4d2007f": "请选择应用", + "K8c7f2d2e": "调用趋势", + "K657c3452": "(0)-(1)调用趋势", + "Kc04efb87": "调用量统计", + "Keb98266e": "加入总体数据对比", + "K18c2ed46": "(0)调用量", + "Kc3741830": "(0)调用成功率", + "Ka6aa5863": "请求总数", + "K9eaef42": "请求成功率", + "K7082a4af": "转发总数", + "K1ce386fb": "转发成功率", + "K87d6877e": "状态码4xx数", + "K4c8a54db": "状态码5xx数", + "Kd566283e": "调用总体趋势", + "K21ad4a6a": "(0)报文量", + "Kd23a0be6": "请求报文量", + "Kec3e8361": "响应报文量", + "Ke6250744": "状态码4XX数", + "K2d79d4e1": "状态码5XX数", + "Kcf6553c6": "服务调用统计", + "Kffcfe375": "请选择服务", + "Ka65f739c": "调用详情", + "K89b7ac79": "API 请求量 Top10", + "Kc0915603": "应用调用量 Top10", + "Kf90b54": "服务被调用量 Top10", + "Kfb26388": "暂无请求统计数据", + "Kc8cbd8f8": "请求统计", + "K8dece48": "暂无转发统计数据", + "K1ee32434": "转发统计", + "Kcd125e4d": "暂无调用量统计数据", + "Kaa114e8b": "暂无报文量统计数据", + "K3ad84406": "报文量统计", + "Kfa088d49": "集群配置并开启监控", + "K3da3b9a0": "监控功能用于辅助管理集群内信息,请配置集群、设置监控信息后查看当前集群监控情况;", + "Kaddacfb": "集群配置", + "K4ac33975": "配置集群地址,以确保监控系统能够正确识别和连接到集群", + "Ke5ed9810": "配置集群信息", + "K1a132228": "监控设置", + "K6af08c3c": "配置监控信息", + "K4a1a14": "监控总览", + "K69741ea7": "服务被调用统计", + "K9c8d9933": "API 调用统计", + "K145e4941": "亿", + "Ke6a935d": "万", + "Kd59290a2": "搜索分类或标签", + "K6b75bdbc": "暂无API数据", + "Kd8a7a689": "搜索或选择应用", + "K4b15d6f5": "申请理由", + "Kb7e869a4": "应用管理", + "Kb71b5a13": "鉴权类型", + "K4d1465ee": "Iss", + "K5dcd7ed8": "签名算法", + "K5b0eedd3": "Secret", + "K44f4ffe1": "RSA 公钥", + "Kc5ecd7d9": "用户名 JsonPath", + "K417d85cf": "校验字段", + "K3b82fe1d": "是否 Base64 加密", + "K49b5f4a3": "AK", + "K31418470": "SK", + "Kbfeb5297": "Apikey", + "K1a78e6f0": "过期时间", + "Ke64e43a": "隐藏鉴权信息", + "K5168eb63": "应用名称", + "K546e46f": "应用 ID", + "K95764d1d": "删除应用", + "K217cb125": "鉴权详情", + "K2bb63eca": "添加鉴权", + "Kd74d69b7": "编辑鉴权", + "K9cbe1e0": "修改", + "Kb6e9328f": "访问授权", + "Kd23d1716": "添加授权", + "K9dfa2c97": "永不过期", + "Kfa920c0": "到期时间", + "Kcce1af60": "订阅的服务", + "Kbeb4e991": "审批详情", + "K3118fdb0": "取消订阅", + "Ked811bb1": "请确认是否取消订阅?", + "K50c39a62": "取消订阅申请", + "K1856c229": "请确认是否取消订阅申请?", + "K66ea2f0": "搜索服务", + "Kfeb2559b": "审批中", + "K667bbbe7": "添加应用", + "Ka4b45550": "暂无服务描述", + "K3c7b175f": "订阅的服务数量:已通过 (0) 个,申请中 (1) 个", + "Kbe3e9335": "退出测试", + "K370a3eb2": "服务市场", + "Kf7ec36d": "服务详情", + "K58ca9485": "申请服务", + "K59cdbec3": "介绍", + "K4aa9ed2c": "申请", + "K6c060779": "服务信息", + "K8723422e": "接入应用", + "Kb97544cb": "供应方", + "Kb32f0afe": "分类", + "K81634069": "版本", + "Keefda53d": "更新时间", + "K96a2f1c8": "无标签", + "K72b0c0b3": "API 数量", + "K93d5a66e": "接入应用数量", + "K96059c69": "关联标签", + "K8b7c2592": "更新者", + "K32263abd": "添加 Open Api", + "K7829bb78": "配置 Open Api", + "Kcdf76005": "Open Api", + "Ke2601944": "调用服务", + "K8504bca8": "放大", + "K693c1b41": "缩小", + "K3d7465f7": "文件日志", + "Kc87167a0": "HTTP日志", + "K54630fe8": "Kafka日志", + "Kd5c3966e": "NSQ日志", + "K2e3de2c1": "Syslog日志", + "K48322168": "未分配", + "K98f247f9": "超级管理员", + "K9c8a571f": "团队管理员", + "K929b485b": "运维管理员", + "K82cc5ec2": "普通成员", + "Ke41d7451": "只读成员", + "Kf99e8b66": "服务管理员", + "Kda8db57a": "服务开发者", + "K216a1ac7": "应用开发者", + "K27924db": "应用管理员", + "K8dc5c723": "驱动名称", + "Kda249fe8": "请求失败数", + "Kcf2df651": "转发失败数", + "K7e6a859d": "作用范围", + "K3a008b34": "添加条目", + "Ke0599ef7": "添加地址", + "K48d3b5c4": "文件名称", + "Kafde0d2a": "存放目录", + "Kfb2926ac": "日志分割周期", + "Kd96c2c69": "单位:天", + "Kc2b776fa": "输出格式", + "K7b7cdac2": "格式化配置", + "K2f59807a": "服务器地址", + "Kb1cfa6e7": "Access日志", + "K540488a8": "NSQD地址列表", + "K8bc33a11": "鉴权Secret", + "K1cd3002f": "网络协议", + "Kdfaa32c8": "日志等级", + "Kc0408d9c": "单行", + "Ke3db239d": "小时", + "K3509a9f8": "天", + "Kb3960e83": "未发布", + "K8bd1e18": "待发布", + "K225a6c43": "单位:s,最小值:1", + "K6a7fa303": "无需审批", + "Kd196e8a4": "需要审批", + "K1b6777bb": "Basic URL", + "Kd55c6887": "申请审批", + "K300c89d4": "创建 API 时会默认选择该供应商,修改默认供应商不会影响现有 API" +} \ No newline at end of file diff --git a/frontend/packages/common/src/locales/scan/zh-CN.json b/frontend/packages/common/src/locales/scan/zh-CN.json index 5a720fe5..53a8d899 100644 --- a/frontend/packages/common/src/locales/scan/zh-CN.json +++ b/frontend/packages/common/src/locales/scan/zh-CN.json @@ -359,7 +359,6 @@ "K91aa4801": "您可通过访客模式查看所有页面和功能,但是无法编辑数据。访客模式仅用于了解产品功能,您可以在正式产品中关闭该功能。", "K480045ce": "Version (0)-(1)", "Kadee8e49": "日志配置", - "K3453272": "APIPark 提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。", "K33c76dbc": "部门名称", "K84829ca9": "父部门 ID", "K4d7fc74b": "子部门名称", @@ -623,5 +622,27 @@ "K71753476": "是否放行", "K597435c5": "监控", "Kde9d6e8e": "开启拦截后,网关会拦截该路径的请求", - "K4758140d": "路由列表" + "K4758140d": "路由列表", + "K12f58863": "服务提供了高性能 API 网关,并且可以无缝接入多种大型 AI 模型,并将这些 AI 能力打包成 API 进行调用,从而大幅简化了 AI 模型的使用门槛。同时,我们的平台提供了完善的 API 管理功能,支持 API 的创建、监控、访问控制等,保障开发者可以高效、安全地开发和管理 API 服务。", + "K8ab0fc95": "常规设置", + "K2724314b": "提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。", + "Kecbb0e45": "系统", + "Ka358e23d": "常规", + "K449058e9": "API 网关", + "K99935e6f": "AI 模型", + "K1deaa2dd": "用户", + "K4057391a": "集成", + "K408bfcf1": "进阶教程", + "K2cdbb773": "核心功能", + "K3378c50d": "账号与角色", + "Kda5bb930": "邀请你的团队成员加入 APIPark,共同管理和调用 API。", + "K62e89ee7": "权限管理", + "K3596804a": "如果需要调用某个服务的API,需要先订阅该服务,并且等待提供服务的团队审批后才可发起API请求。", + "K1c15bb2e": "提供服务的团队可以审批来自其他团队的订阅申请,审批通过后的应用才可发起 API 请求。", + "K3453272": "APIPark 提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。", + "K1afaf20e": "了解 APIPark 如何更好地管理 API 和 AI", + "Kcef64f4d": "默认 AI 供应商", + "K13edc043": "作为服务内所有API的前缀,比如host/{service_name}/{api_path},一旦保存无法修改", + "Ka7bb958f": "AI", + "Kcb81cc64": "REST" } \ No newline at end of file diff --git a/frontend/packages/common/src/locales/scan/zh-TW.json b/frontend/packages/common/src/locales/scan/zh-TW.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/frontend/packages/common/src/locales/scan/zh-TW.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/frontend/packages/common/src/utils/ip.ts b/frontend/packages/common/src/utils/ip.ts new file mode 100644 index 00000000..b27cc339 --- /dev/null +++ b/frontend/packages/common/src/utils/ip.ts @@ -0,0 +1,20 @@ +export const extractIPFromURL = (url:string|string[]) =>{ + if (Array.isArray(url)) { + url = url[0]; // 获取第一个 URL + } + if (typeof url !== 'string' || !url.includes("://")) { + console.warn("Invalid URL format"); + return null; + } + const match = url.match(/https?:\/\/([\d.]+):\d+/); + return match ? match[1] : null; +} + +export const isPrivateIP = (ip:string) =>{ + if (typeof ip !== 'string') { + console.error("Invalid IP format"); + return false; + } + const privateIpRegex = /^(10\.\d{1,3}\.\d{1,3}\.\d{1,3})$|^(172\.(1[6-9]|2[0-9]|3[0-1])\.\d{1,3}\.\d{1,3})$|^(192\.168\.\d{1,3}\.\d{1,3})$/; + return privateIpRegex.test(ip); +} \ No newline at end of file diff --git a/frontend/packages/common/src/utils/systemRunning.ts b/frontend/packages/common/src/utils/systemRunning.ts index fb9f269e..34e3304c 100644 --- a/frontend/packages/common/src/utils/systemRunning.ts +++ b/frontend/packages/common/src/utils/systemRunning.ts @@ -255,7 +255,7 @@ import { TopologyProjectItem, TopologyServiceItem } from "@core/pages/systemRun // labelCfg: { // style: { // fill: '5B8FF9', -// opacity: 0 // 将透明度设置为0,隐藏提示信息,hover 才出现 +// opacity: 0 // } // } // } diff --git a/frontend/packages/core/src/App.css b/frontend/packages/core/src/App.css index 24f83f0b..3b3d4e57 100644 --- a/frontend/packages/core/src/App.css +++ b/frontend/packages/core/src/App.css @@ -235,4 +235,17 @@ a{ background-color: transparent; border:none; } +} +.ant-menu .ant-menu-title-content{ + display:unset !important; +} + + +.ai-setting-svg-container svg{ + width: 100%; + height:100%; + display:block; +} +.ai-service-api-preview .swagger-ui h3.opblock-tag{ + display: none; } \ No newline at end of file diff --git a/frontend/packages/core/src/App.tsx b/frontend/packages/core/src/App.tsx index 7858813c..9e5f751b 100644 --- a/frontend/packages/core/src/App.tsx +++ b/frontend/packages/core/src/App.tsx @@ -6,15 +6,25 @@ import {BreadcrumbProvider} from "@common/contexts/BreadcrumbContext.tsx"; import { StyleProvider } from '@ant-design/cssinjs'; import zhCN from 'antd/locale/zh_CN'; import enUS from 'antd/locale/en_US'; +import zhTW from 'antd/locale/zh_TW'; +import jaJP from 'antd/locale/ja_JP'; import useInitializeMonaco from "@common/hooks/useInitializeMonaco"; import { useEffect, useMemo, useState } from 'react'; import 'dayjs/locale/zh-cn'; +import 'dayjs/locale/zh-tw'; +import 'dayjs/locale/ja'; import dayjs from 'dayjs'; import { useGlobalContext } from '@common/contexts/GlobalStateContext'; import { $t } from '@common/locales'; type Locale = ConfigProviderProps['locale']; +const languageMap: Record = { + 'zh-CN':zhCN, + 'en-US':enUS, + 'zh-TW':zhTW, + 'ja-JP':jaJP +} const antdComponentThemeToken = { @@ -147,7 +157,7 @@ function App() { useEffect(() => { dayjs.locale(state.language); - setLocal(state.language === 'cn' ? zhCN : enUS); + setLocal(languageMap[state.language]); },[state.language]) const validateMessages = useMemo(()=>({ diff --git a/frontend/packages/core/src/components/aoplatform/RenderRoutes.tsx b/frontend/packages/core/src/components/aoplatform/RenderRoutes.tsx index b842f1d9..4cf2c011 100644 --- a/frontend/packages/core/src/components/aoplatform/RenderRoutes.tsx +++ b/frontend/packages/core/src/components/aoplatform/RenderRoutes.tsx @@ -109,8 +109,8 @@ const PUBLIC_ROUTES:RouteConfig[] = [ }, { path:'service', - component:, key: uuidv4(), + component:, provider: SystemProvider, children:[ { @@ -143,6 +143,18 @@ const PUBLIC_ROUTES:RouteConfig[] = [ key: uuidv4(), lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/api/SystemInsideApiDocument.tsx')), }, + { + + path:'route/create', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/api/SystemInsideRouterCreate')), + }, + { + + path:'route/:routeId', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/api/SystemInsideRouterCreate')), + }, { path:'route', key: uuidv4(), @@ -216,121 +228,93 @@ const PUBLIC_ROUTES:RouteConfig[] = [ ] }, ] - } - ] - } - ] - }, - { - path:'aiservice', - component:, - key: uuidv4(), - provider: AiServiceProvider, - children:[ - { - path:'', - key:uuidv4(), - component: - }, - { - path:'list', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceList.tsx')), - }, - { - path:'list/:teamId', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceList.tsx')), - }, - { - path:':teamId', - component:, - key: uuidv4(), - children:[ + }, { - path:'inside/:serviceId', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceInsidePage.tsx')), - children:[ - { - path:'api', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideApiDocument')), - }, - { - - path:'route/create', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideRouterCreate')), - }, - { - - path:'route/:routeId', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideRouterCreate')), - }, - { - path:'route', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideRouterList')), - }, - { - path:'document', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceInsideDocument.tsx')), - }, - { - path:'subscriber', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceInsideSubscriber.tsx')), - children:[ - - ] - }, - { - path:'approval', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/approval/AiServiceInsideApproval')), - children:[ - { - path:'', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/approval/AiServiceInsideApprovalList')), - }, - { - path:'*', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/approval/AiServiceInsideApprovalList')), - } - ] - }, - { - path:'publish', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/publish/AiServiceInsidePublish')), - children:[ - { - path:'', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/publish/AiServiceInsidePublishList')), - }, - { - path:'*', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/publish/AiServiceInsidePublishList')), - } - ] - }, - { - path:'setting', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceConfig.tsx')), - children:[ - - ] - }, - ] - } + path:'aiInside/:serviceId', + component:, + provider: AiServiceProvider, + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceInsidePage.tsx')), + children:[ + { + path:'api', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideApiDocument')), + }, + { + + path:'route/create', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideRouterCreate')), + }, + { + + path:'route/:routeId', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideRouterCreate')), + }, + { + path:'route', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideRouterList')), + }, + { + path:'document', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceInsideDocument.tsx')), + }, + { + path:'subscriber', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceInsideSubscriber.tsx')), + children:[ + + ] + }, + { + path:'approval', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/approval/AiServiceInsideApproval')), + children:[ + { + path:'', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/approval/AiServiceInsideApprovalList')), + }, + { + path:'*', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/approval/AiServiceInsideApprovalList')), + } + ] + }, + { + path:'publish', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/publish/AiServiceInsidePublish')), + children:[ + { + path:'', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/publish/AiServiceInsidePublishList')), + }, + { + path:'*', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/publish/AiServiceInsidePublishList')), + } + ] + }, + { + path:'setting', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemConfig.tsx')), + children:[ + + ] + }, + ] + } ] } ] @@ -377,8 +361,8 @@ const PUBLIC_ROUTES:RouteConfig[] = [ }] }, { - path:'servicecategories', - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/serviceCategory/ServiceCategory.tsx')), + path:'commonsetting', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/common/CommonPage.tsx')), key:uuidv4(), }, { diff --git a/frontend/packages/core/src/const/ai-service/const.tsx b/frontend/packages/core/src/const/ai-service/const.tsx index c3424ae5..9dc270b1 100644 --- a/frontend/packages/core/src/const/ai-service/const.tsx +++ b/frontend/packages/core/src/const/ai-service/const.tsx @@ -1,61 +1,11 @@ -import { AiServiceTableListItem, AiServiceRouterTableListItem, VariableItems } from "./type"; +import { AiServiceRouterTableListItem, VariableItems } from "./type"; import { TabsProps } from "antd"; import { frontendTimeSorter } from "@common/utils/dataTransfer"; import { COLUMNS_TITLE, PLACEHOLDER } from "@common/const/const"; import { PageProColumns } from "@common/components/aoplatform/PageList"; -export const AI_SERVICE_TABLE_COLUMNS: PageProColumns[] = [ - { - title:('服务名称'), - dataIndex: 'name', - ellipsis:true, - width:160, - fixed:'left', - sorter: (a,b)=> { - return a.name.localeCompare(b.name) - }, - }, - { - title:('服务 ID'), - dataIndex: 'id', - width: 140, - ellipsis:true, - }, - { - title:('AI 模型供应商'), - dataIndex: ['provider','name'], - ellipsis:true, - }, - { - title:('所属团队'), - dataIndex: ['team','name'], - ellipsis:true, - // filters: true, - // onFilter: true, - // filterSearch: true, - }, - { - title:('API 数量'), - dataIndex: 'apiNum', - ellipsis:true, - sorter: (a,b)=> { - return a.apiNum - b.apiNum - }, - }, - { - title: ('描述'), - dataIndex: 'description', - ellipsis:true, - }, - { - title:('创建时间'), - dataIndex: 'createTime', - width:182, - ellipsis:true, - sorter: (a,b)=>frontendTimeSorter(a,b,'createTime') - } -]; + export const AI_SERVICE_ROUTER_TABLE_COLUMNS: PageProColumns[] = [ { @@ -72,7 +22,7 @@ export const AI_SERVICE_ROUTER_TABLE_COLUMNS: PageProColumns
{entity.model.id}
+ render: (_: React.ReactNode, entity: AiServiceRouterTableListItem) =>
{entity.model.id}
}, { title:('描述'), @@ -118,14 +68,21 @@ export const AI_SERVICE_VARIABLES_TABLE_COLUMNS: PageProColumns[] = [ width: 140, ellipsis:true, }, + { + title:('类型'), + dataIndex: 'service_kind', + width: 140, + ellipsis:true, + }, { title:('所属团队'), dataIndex: ['team','name'], ellipsis:true, - // filters: true, - // onFilter: true, - // filterSearch: true, }, { title:('API 数量'), @@ -349,6 +352,14 @@ export const SERVICE_VISUALIZATION_OPTIONS = [ {label:('内部服务:可通过网关访问,但不展示在服务广场'),value:'inner'}, {label:('公开服务:可通过网关访问,展示在服务广场,可被其他应用订阅'),value:'public'}]; + +export const SERVICE_APPROVAL_OPTIONS = [ + {label:('无需审批:允许任何应用调用该服务'),value:'auto'}, + {label:('人工审批:仅允许通过人工审批的应用调用该服务'),value:'manual'}]; +export const SERVICE_KIND_OPTIONS = [ + {label:('REST'),value:'rest'}, + {label:('AI'),value:'ai'}]; + export const SYSTEM_UPSTREAM_GLOBAL_CONFIG_TABLE_COLUMNS: PageProColumns[] = [ diff --git a/frontend/packages/core/src/const/system/type.ts b/frontend/packages/core/src/const/system/type.ts index 9dc7636a..dc34c2c9 100644 --- a/frontend/packages/core/src/const/system/type.ts +++ b/frontend/packages/core/src/const/system/type.ts @@ -1,9 +1,7 @@ import { FormInstance, UploadFile } from "antd"; -import { HeaderParamsType, BodyParamsType, QueryParamsType, RestParamsType, ResultListType, ApiBodyType } from "@common/const/api-detail"; import { EntityItem, MatchItem } from "@common/const/type"; import { SubscribeEnum, SubscribeFromEnum } from "./const"; -import { HTTPMethod, Protocol } from "@common/components/postcat/api/RequestMethod"; export type SystemTableListItem = { id:string; @@ -13,6 +11,7 @@ export type SystemTableListItem = { serviceNum: number, description:string; master:EntityItem; + service_kind:'ai'|'rest', createTime:string; }; @@ -27,7 +26,9 @@ export type SystemConfigFieldType = { team?:string; master?:string; serviceType?:'public'|'inner'; + serviceKind:'ai'|'rest'; catalogue?:string | string[]; + approvalType?:string; }; export type SystemSubServiceTableListItem = { @@ -94,6 +95,7 @@ export type SystemApiProxyFieldType = { protocols: string[]; id:string; description?:string; + disable:boolean; path:string; methods:string[]; match:MatchItem[] @@ -291,8 +293,6 @@ export type SystemInsideApiDocumentProps = { export type SystemInsideApiProxyProps = { className?:string - service:string - teamId:string initProxyValue?:SystemApiProxyType value?:SystemApiProxyType type:'add'|'edit' diff --git a/frontend/packages/core/src/pages/aiService/AiServiceInsidePage.tsx b/frontend/packages/core/src/pages/aiService/AiServiceInsidePage.tsx index 1b2c70f5..78101fc1 100644 --- a/frontend/packages/core/src/pages/aiService/AiServiceInsidePage.tsx +++ b/frontend/packages/core/src/pages/aiService/AiServiceInsidePage.tsx @@ -60,8 +60,8 @@ const AiServiceInsidePage:FC = ()=> { const SYSTEM_PAGE_MENU_ITEMS = useMemo(()=>[ getItem($t('服务'), 'assets', null, [ - getItem({$t('API')}, 'api',undefined,undefined,undefined,'team.service.api_doc.view'), - getItem({$t('路由')}, 'route',undefined,undefined,undefined,'team.service.router.view'), + getItem({$t('API 路由')}, 'route',undefined,undefined,undefined,'team.service.router.view'), + getItem({$t('API 文档')}, 'api',undefined,undefined,undefined,'team.service.api_doc.view'), getItem({$t('使用说明')}, 'document',undefined,undefined,undefined,''), getItem({$t('发布')}, 'publish',undefined,undefined,undefined,'team.service.release.view'), ], @@ -95,7 +95,7 @@ const AiServiceInsidePage:FC = ()=> { } const filteredMenu = filterMenu(SYSTEM_PAGE_MENU_ITEMS as MenuItemGroupType[]) setActiveMenu((pre)=>{ - return pre ?? 'api' + return pre ?? 'route' }) return filteredMenu || [] },[accessData,accessInit, SYSTEM_PAGE_MENU_ITEMS]) @@ -111,7 +111,7 @@ const AiServiceInsidePage:FC = ()=> { }else if(serviceId !== currentUrl.split('/')[currentUrl.split('/').length - 1]){ setActiveMenu(currentUrl.split('/')[currentUrl.split('/').length - 1]) }else{ - setActiveMenu('api') + setActiveMenu('route') } }, [currentUrl]); @@ -123,7 +123,7 @@ const AiServiceInsidePage:FC = ()=> { useEffect(()=>{ if( activeMenu && serviceId === currentUrl.split('/')[currentUrl.split('/').length - 1]){ - navigateTo(`/aiservice/${teamId}/inside/${serviceId}/${activeMenu}`) + navigateTo(`/service/${teamId}/aiInside/${serviceId}/${activeMenu}`) } },[activeMenu]) @@ -137,7 +137,7 @@ const AiServiceInsidePage:FC = ()=> { tagList={[{label: {$t('服务 ID')}:{serviceId || '-'} }]} - backUrl="/aiservice/list"> + backUrl="/service/list">
{ useEffect(() => { setBreadcrumb([ { - title:{$t('服务')} + title:{$t('服务')} }, { title:$t('订阅方管理') @@ -245,7 +245,7 @@ export const AiServiceSubscriberConfig = forwardRef diff --git a/frontend/packages/core/src/pages/aiService/api/AiServiceInsideApiDocument.tsx b/frontend/packages/core/src/pages/aiService/api/AiServiceInsideApiDocument.tsx index 2c5ebc5b..eb0369bd 100644 --- a/frontend/packages/core/src/pages/aiService/api/AiServiceInsideApiDocument.tsx +++ b/frontend/packages/core/src/pages/aiService/api/AiServiceInsideApiDocument.tsx @@ -36,7 +36,7 @@ const AiServiceInsideApiDocument = forwardRef{ return (
-
+
@@ -46,7 +46,7 @@ const AiServiceInsideApiDocument = forwardRef } spinning={loading} wrapperClassName=' h-full overflow-hidden '> -
+
{ apiDetail ? : } diff --git a/frontend/packages/core/src/pages/aiService/api/AiServiceInsideRouterCreate.tsx b/frontend/packages/core/src/pages/aiService/api/AiServiceInsideRouterCreate.tsx index 63b19785..69f14b86 100644 --- a/frontend/packages/core/src/pages/aiService/api/AiServiceInsideRouterCreate.tsx +++ b/frontend/packages/core/src/pages/aiService/api/AiServiceInsideRouterCreate.tsx @@ -63,12 +63,12 @@ const AiServiceInsideRouterCreate = () => { return variablesTableRef?.current?.validateFields().then(()=>{ return form.validateFields().then((formValue)=>{ const {name, path, description, variables, prompt, timeout, retry} = formValue - const body = {name, path: !routeId && prefixForce ? `${apiPrefix}/${path}`:path , description,timeout, retry,aiPrompt:{variables:variables, prompt:prompt},aiModel:{id:defaultLlm?.id, config:defaultLlm?.config}} + const body = {name, path: prefixForce ? `${apiPrefix}/${path}`:path , description,timeout, retry,aiPrompt:{variables:variables, prompt:prompt},aiModel:{id:defaultLlm?.id, provider:defaultLlm?.provider, config:defaultLlm?.config}} return fetchData>('service/ai-router',{method: routeId ? 'PUT' : 'POST',eoBody:(body), eoParams: {service:serviceId,team:teamId, ...(routeId ? {router:routeId}: {})},eoTransformKeys:['aiPrompt','aiModel']}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || $t(RESPONSE_TIPS.success)) - navigator(`/aiservice/${teamId}/inside/${serviceId}/route`) + navigator(`/service/${teamId}/aiInside/${serviceId}/route`) return Promise.resolve(true) }else{ message.error(msg || $t(RESPONSE_TIPS.error)) @@ -94,7 +94,8 @@ const AiServiceInsideRouterCreate = () => { const {path, aiPrompt,aiModel} = data.api form.setFieldsValue({...data.api,...aiPrompt, path:prefixForce && path?.startsWith(apiPrefix + '/')? path.slice((apiPrefix?.length || 0) + 1) : path }) setVariablesTable(aiPrompt.variables as VariableItems[]) - setDefaultLlm(prev => ({...prev, id:aiModel?.id, config:aiModel.config}) as (AiProviderDefaultConfig & { config: string; })) + setDefaultLlm(prev => ({...prev, provider: aiModel?.provider, id:aiModel?.id, config:aiModel.config}) as (AiProviderDefaultConfig & { config: string; })) + getDefaultModelConfig(aiModel?.provider) }else{ message.error(msg || $t(RESPONSE_TIPS.error)) } @@ -102,15 +103,16 @@ const AiServiceInsideRouterCreate = () => { .finally(()=>setLoading(false)) } - const getDefaultModelConfig = ()=>{ - fetchData>('ai/provider/llms',{method:'GET',eoParams:{provider:aiServiceInfo?.provider?.id}, eoTransformKeys:['default_llm']}).then(response=>{ + const getDefaultModelConfig = (provider?:string)=>{ + fetchData>('ai/provider/llms',{method:'GET',eoParams:{provider:provider ?? aiServiceInfo?.provider?.id}, eoTransformKeys:['default_llm']}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ setLlmList(data.llms) setDefaultLlm(prev => { const llmSetting = data.llms?.find((x:AiProviderLlmsItems)=>x.id ===( prev?.id ?? data.provider.defaultLlm)) return {...prev, - defaultLlm:data.provider.defaultLlm, + defaultLlm:data.provider.defaultLlm, + provider:data.provider.id, name:data.provider.name, config:llmSetting?.config || '', ...(llmSetting ?? {}) @@ -124,7 +126,7 @@ const AiServiceInsideRouterCreate = () => { useEffect(()=>{ - aiServiceInfo?.provider && getDefaultModelConfig() + !routeId && aiServiceInfo?.provider && getDefaultModelConfig() },[ aiServiceInfo ]) @@ -175,7 +177,7 @@ const AiServiceInsideRouterCreate = () => { const handlerSubmit:() => Promise|undefined= ()=>{ return drawerAddFormRef.current?.save()?.then((res:{id:string, config:string})=>{ - setDefaultLlm(prev => ({...prev, id:res.id, config:res.config, logo:llmList?.find((x:AiProviderLlmsItems)=>x.id === res.id)?.logo}) as (AiProviderDefaultConfig & { config: string; })) + setDefaultLlm(prev => ({...prev, provider:res.provider, id:res.id, config:res.config, logo:llmList?.find((x:AiProviderLlmsItems)=>x.id === res.id)?.logo}) as (AiProviderDefaultConfig & { config: string; })) return true}) } @@ -185,16 +187,16 @@ const AiServiceInsideRouterCreate = () => { return ( - +
- -
- - ))} -
:} + {aiSettingList && aiSettingList.length > 0 ?
+

{$t('已配置')}

+ item.configured) || [] }/> + { + aiSettingList.filter((item)=>!item.configured).length > 0 && <> + +

{$t('未配置')}

+ !item.configured) || [] }/> + + } +
:} ) diff --git a/frontend/packages/core/src/pages/common/ApiRequestSetting.tsx b/frontend/packages/core/src/pages/common/ApiRequestSetting.tsx new file mode 100644 index 00000000..8e756927 --- /dev/null +++ b/frontend/packages/core/src/pages/common/ApiRequestSetting.tsx @@ -0,0 +1,90 @@ +import WithPermission from "@common/components/aoplatform/WithPermission"; +import { BasicResponse, STATUS_CODE, RESPONSE_TIPS, PLACEHOLDER } from "@common/const/const"; +import { useFetch } from "@common/hooks/http"; +import { $t } from "@common/locales"; +import { App, Form, Input, Row, Button } from "antd"; +import { useEffect } from "react"; + +type ApiRequestSettingFieldType = { + siteName:string + siteLogo:string + invokeAddress:string + platformName:string +} + +export default function ApiRequestSetting(){ + const { message } = App.useApp() + const [form] = Form.useForm(); + const {fetchData} = useFetch() + + + const onFinish = () => { + form.validateFields().then((value)=>{ + return fetchData>('system/general',{method:'POST',eoBody:(value),eoTransformKeys:['invokeAddress','siteName','siteLogo','platformName']}).then(response=>{ + const {code,msg} = response + if(code === STATUS_CODE.SUCCESS){ + message.success(msg || $t(RESPONSE_TIPS.success)) + getSystemSetting() + return Promise.resolve(true) + }else{ + message.error(msg || $t(RESPONSE_TIPS.error)) + return Promise.reject(msg || $t(RESPONSE_TIPS.error)) + } + }).catch((errorInfo)=>{ + return Promise.reject(errorInfo) + }) + }) + }; + + const getSystemSetting = ()=>{ + fetchData>('system/general',{method:'GET',eoTransformKeys:['site_name', 'site_logo','invoke_address','platform_name']}).then(response=>{ + const {code,data,msg} = response + if(code === STATUS_CODE.SUCCESS){ + form.setFieldsValue(data.general) + }else{ + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }) + } + + useEffect(() => { + getSystemSetting() + return (form.setFieldsValue({})) + }, []); + + return ( + <> + + + + label={$t("API 调用地址")} + name="name" + rules={[{ required: true,whitespace:true }]} + extra={$t("API base URL 一般设置为API 网关的外部网络访问地址,或者是API网关绑定的域名。")} + > + + + + + + + + + + + + + ) +} \ No newline at end of file diff --git a/frontend/packages/core/src/pages/common/CommonPage.tsx b/frontend/packages/core/src/pages/common/CommonPage.tsx new file mode 100644 index 00000000..e1e9ae86 --- /dev/null +++ b/frontend/packages/core/src/pages/common/CommonPage.tsx @@ -0,0 +1,33 @@ +import InsidePage from "@common/components/aoplatform/InsidePage"; +import { $t } from "@common/locales"; +import ServiceCategory from "./ServiceCategory"; +import ApiRequestSetting from "./ApiRequestSetting"; +import { Row, Col } from "antd"; + +export default function CommonPage(){ + return ( + + + + + {$t('API 请求设置')} + + + + + + + + {$t('服务分类')} + + + + + + ) +} \ No newline at end of file diff --git a/frontend/packages/core/src/pages/common/ServiceCategory.tsx b/frontend/packages/core/src/pages/common/ServiceCategory.tsx new file mode 100644 index 00000000..0cf46083 --- /dev/null +++ b/frontend/packages/core/src/pages/common/ServiceCategory.tsx @@ -0,0 +1,265 @@ +import TreeWithMore from "@common/components/aoplatform/TreeWithMore"; +import WithPermission from "@common/components/aoplatform/WithPermission"; +import { BasicResponse, DELETE_TIPS, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const"; +import { PERMISSION_DEFINITION } from "@common/const/permissions"; +import { useFetch } from "@common/hooks/http"; +import { checkAccess } from "@common/utils/permission"; +import { CategorizesType, ServiceHubCategoryConfigHandle } from "@market/const/serviceHub/type"; +import { App, Button, Spin, Tree, TreeDataNode, TreeProps } from "antd"; +import { DataNode } from "antd/es/tree"; +import { Key, useEffect, useMemo, useRef, useState } from "react"; +import { ServiceHubCategoryConfig } from "./ServiceHubCategoryConfig"; +import { useGlobalContext } from "@common/contexts/GlobalStateContext"; +import { useBreadcrumb } from "@common/contexts/BreadcrumbContext"; +import { LoadingOutlined } from "@ant-design/icons"; +import { cloneDeep } from "lodash-es"; +import { Icon } from "@iconify/react/dist/iconify.js"; +import { EntityItem } from "@common/const/type"; +import { $t } from "@common/locales"; + +export default function ServiceCategory(){ + const [gData, setGData] = useState([]); + const [cateData, setCateData] = useState([]); + const [expandedKeys, setExpandedKeys] = useState([]); + const {message,modal} = App.useApp() + const {fetchData} = useFetch() + const addRef = useRef(null) + const addChildRef = useRef(null) + const renameRef = useRef(null) + const {accessData} = useGlobalContext() + const { setBreadcrumb } = useBreadcrumb() + const [loading, setLoading] = useState(false) + + const onDrop: TreeProps['onDrop'] = (info) => { + const dropKey = info.node.key; + const dragKey = info.dragNode.key; + const dropPos = info.node.pos.split('-'); + const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]); // the drop position relative to the drop node, inside 0, top -1, bottom 1 + + const loop = ( + data: TreeDataNode[], + key: React.Key, + callback: (node: TreeDataNode, i: number, data: TreeDataNode[]) => void, + ) => { + for (let i = 0; i < data.length; i++) { + if (data[i].id === key) { + return callback(data[i], i, data); + } + if (data[i].children) { + loop(data[i].children!, key, callback); + } + } + }; + const data = cloneDeep(gData); + + // Find dragObject + let dragObj: TreeDataNode; + loop(data, dragKey, (item, index, arr) => { + arr.splice(index, 1); + dragObj = item; + }); + + if (!info.dropToGap) { + // Drop on the content + loop(data, dropKey, (item) => { + item.children = item.children || []; + // where to insert. New item was inserted to the start of the array in this example, but can be anywhere + item.children.unshift(dragObj); + }); + } else { + let ar: TreeDataNode[] = []; + let i: number; + loop(data, dropKey, (_item, index, arr) => { + ar = arr; + i = index; + }); + if (dropPosition === -1) { + // Drop on the top of the drop node + ar.splice(i!, 0, dragObj!); + } else { + // Drop on the bottom of the drop node + ar.splice(i! + 1, 0, dragObj!); + } + } + + setGData(data); + sortCategories(data) + }; + + + const dropdownMenu = (entity:CategorizesType) => [ + { + key: 'addChildCate', + label: ( + + ), + }, + { + key: 'renameCate', + label: ( + + ), + }, + { + key: 'delete', + label: ( + + ), + }, + ]; + + const treeData = useMemo(() => { + setExpandedKeys([]) + const loop = (data: CategorizesType[]): DataNode[] => + data?.map((item) => { + if (item.children) { + setExpandedKeys(prev=>[...prev,item.id]) + return { + title: {item.name} , + key: item.id, children: loop(item.children) + }; + } + + return { + title: {item.name}, + key: item.id, + }; + }); + return loop(gData ?? []) + }, [gData]); + + const isActionAllowed = (type:'addCate'|'addChildCate'|'renameCate'|'delete') => { + const actionToPermissionMap = { + 'addCate': 'add', + 'addChildCate': 'add', + 'renameCate': 'edit', + 'delete': 'delete' + }; + + const action = actionToPermissionMap[type]; + const permission :keyof typeof PERMISSION_DEFINITION[0]= `system.api_market.service_classification.${action}`; + + return !checkAccess(permission, accessData); + }; + + const openModal = (type:'addCate'|'addChildCate'|'renameCate'|'delete',entity?:CategorizesType)=>{ + let title:string = '' + let content:string|React.ReactNode = '' + switch (type){ + case 'addCate': + title=$t('添加分类') + content= + break; + case 'addChildCate': + title=$t('添加子分类') + content= + break; + case 'renameCate': + title=$t('重命名分类') + content= + break; + case 'delete': + title=$t('删除') + content=$t(DELETE_TIPS.default) + break; + } + modal.confirm({ + title, + content, + onOk:()=>{ + switch (type){ + case 'addCate': + return addRef.current?.save().then((res)=>{if(res === true) getCategoryList()}) + case 'addChildCate': + return addChildRef.current?.save().then((res)=>{if(res === true) getCategoryList()}) + case 'renameCate': + return renameRef.current?.save().then((res)=>{if(res === true) getCategoryList()}) + case 'delete': + return deleteCate(entity!).then((res)=>{if(res === true) getCategoryList()}) + } + }, + width:600, + okText:$t('确认'), + okButtonProps:{ + disabled : isActionAllowed(type) + }, + cancelText:$t('取消'), + closable:true, + icon:<>, + }) + } + + const deleteCate = (entity:CategorizesType)=>{ + return new Promise((resolve, reject)=>{ + fetchData>('catalogue',{method:'DELETE',eoParams:{catalogue:entity.id},}).then(response=>{ + const {code,msg} = response + if(code === STATUS_CODE.SUCCESS){ + message.success(msg || $t(RESPONSE_TIPS.success)) + resolve(true) + }else{ + message.error(msg || $t(RESPONSE_TIPS.error)) + reject(msg || $t(RESPONSE_TIPS.error)) + } + }).catch((errorInfo)=> reject(errorInfo)) + }) + } + + const sortCategories = (newData:CategorizesType[])=>{ + setLoading(true) + fetchData>('catalogue/sort',{method:'PUT',eoBody:newData}).then(response=>{ + const {code,msg} = response + if(code === STATUS_CODE.SUCCESS){ + getCategoryList() + }else{ + setGData(cateData) + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }).catch(()=>{setGData(cateData)}).finally(()=>{setLoading(false)}) + } + + const getCategoryList = ()=>{ + setLoading(true) + fetchData>('catalogues',{method:'GET'}).then(response=>{ + const {code,data,msg} = response + if(code === STATUS_CODE.SUCCESS){ + setGData(data.catalogues) + setCateData(data.catalogues) + }else{ + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }).finally(()=>{setLoading(false)}) + } + + useEffect(()=>{ + getCategoryList() + },[]) + + return ( +
+ } spinning={loading} className=''> + {setExpandedKeys(expandedKeys as string[])}} + onDrop={onDrop} + treeData={treeData} + /> + + + + +
+ ) +} \ No newline at end of file diff --git a/frontend/packages/core/src/pages/common/ServiceHubCategoryConfig.tsx b/frontend/packages/core/src/pages/common/ServiceHubCategoryConfig.tsx new file mode 100644 index 00000000..7add0f3c --- /dev/null +++ b/frontend/packages/core/src/pages/common/ServiceHubCategoryConfig.tsx @@ -0,0 +1,122 @@ +import {App, Form, Input} from "antd"; +import {forwardRef, useEffect, useImperativeHandle} from "react"; +import {BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE, VALIDATE_MESSAGE} from "@common/const/const.tsx"; +import {useFetch} from "@common/hooks/http.ts"; +import { ServiceHubCategoryConfigHandle, ServiceHubCategoryConfigFieldType, ServiceHubCategoryConfigProps } from "@market/const/serviceHub/type.ts" +import WithPermission from "@common/components/aoplatform/WithPermission"; +import { $t } from "@common/locales"; + +export const ServiceHubCategoryConfig = forwardRef((props,ref)=>{ + const { message } = App.useApp() + const [form] = Form.useForm(); + const {type,entity} = props + const {fetchData} = useFetch() + + const save:()=>Promise = ()=>{ + const url:string = 'catalogue' + let method:string + switch (type){ + case 'addCate': + case 'addChildCate': + method = 'POST' + break; + case 'renameCate': + method = 'PUT' + break + } + return new Promise((resolve, reject)=>{ + if(!url || !method){ + reject($t(RESPONSE_TIPS.error)) + return + } + form.validateFields().then((value)=>{ + fetchData>(url,{method,eoBody:(value), eoParams:{ ...(type === 'renameCate' ? {catalogue:value.id} :undefined)}}).then(response=>{ + const {code,msg} = response + if(code === STATUS_CODE.SUCCESS){ + message.success(msg || $t(RESPONSE_TIPS.success)) + resolve(true) + }else{ + message.error(msg || $t(RESPONSE_TIPS.error)) + reject(msg || $t(RESPONSE_TIPS.error)) + } + }).catch((errorInfo)=> reject(errorInfo)) + }).catch((errorInfo)=> reject(errorInfo)) + }) + } + + useImperativeHandle(ref, ()=>({ + save + }) + ) + + useEffect(() => { + + switch(type){ + case 'addCate': + form.setFieldsValue({}) + break + case 'addChildCate': + form.setFieldsValue({parent:entity!.id}) + break + case 'renameCate': + form.setFieldsValue(entity) + break + } + + }, []); + + + return ( + +
+ + {type === 'renameCate' && + + label={$t("ID")} + name="id" + hidden + rules={[{ required: true,whitespace:true }]} + > + + + } + {(type === 'addCate' || type === 'renameCate') && + + label={$t("分类名称")} + name="name" + rules={[{ required: true ,whitespace:true }]} + > + + } + + {type === 'addChildCate' &&<> + + label={$t("父分类 ID")} + name="parent" + hidden + rules={[{ required: true,whitespace:true }]} + > + + + + + label={$t("子分类名称")} + name="name" + rules={[{ required: true ,whitespace:true }]} + > + + + + } + +
+) +}) \ No newline at end of file diff --git a/frontend/packages/core/src/pages/guide/Guide.tsx b/frontend/packages/core/src/pages/guide/Guide.tsx index 6b360c28..ef5f890e 100644 --- a/frontend/packages/core/src/pages/guide/Guide.tsx +++ b/frontend/packages/core/src/pages/guide/Guide.tsx @@ -8,15 +8,123 @@ import { useLocation, useNavigate } from "react-router-dom" export default function Guide(){ const [showGuide, setShowGuide] = useState(localStorage.getItem('showGuide') !== 'false' ) + const [showAdvancedGuide, setShowAdvancedGuide] = useState(localStorage.getItem('showAdvancedGuide') !== 'false' ) const [, forceUpdate] = useState(null); const {state} = useGlobalContext() const location = useLocation() const currentUrl = location.pathname const navigator = useNavigate() - + const guideSections = [ + { + title: $t('快速接入 AI'), + items: [ + { + title: $t("配置你的 AI 模型"), + description: $t('通过 APIPark 快速接入各种 AI 模型,使用统一的格式来调用API,并且可以随意切换模型。'), + link: 'https://docs.apipark.com/docs/quick/pre-work/team' + }, + { + title: $t("创建 AI 服务和 API"), + description: $t('创建 AI 类型的服务,并且你可以将 Prompt 提示词设置为一个 API,简化使用 AI 的流程。'), + link: 'https://docs.apipark.com/docs/quick/provider/service' + }, + { + title: $t("创建调用 Token"), + description: $t('为了安全地调用 API,你需要创建一个应用以及Token。'), + link: 'https://docs.apipark.com/docs/quick/suberscriber/application' + }, + { + title: $t("调用"), + description: $t('现在你可以通过 Token 来调用这些 API。'), + link: 'https://docs.apipark.com/docs/quick/suberscriber/application' + } + ] + }, + { + title: $t('快速接入 REST API'), + items: [ + { + title: $t("创建 REST 服务和 API"), + description: $t('创建 AI 类型的服务,并且你可以将 Prompt 提示词设置为一个 API,简化使用 AI 的流程。'), + link: 'https://docs.apipark.com/docs/tutorials/api-market/service' + }, + { + title: $t("创建调用 Token"), + description: $t('为了安全地调用 API,你需要创建一个应用以及Token。'), + link: 'https://docs.apipark.com/docs/quick/suberscriber/subscribe' + }, + { + title: $t("调用"), + description: $t('现在你可以通过 Token 来调用这些 API。'), + link: 'https://docs.apipark.com/docs/quick/provider/approve' + } + ] + }, + { + title: $t('仪表盘'), + items: [ + { + title: $t("统计 API 调用情况"), + description: $t('仪表盘中提供了多种统计图表,帮助我们了解 API 的运行情况。'), + link: 'https://docs.apipark.com/docs/quick/pre-work/monitor' + } + ] + } + ]; + const advanceGuideSections = [ + { + title: $t('核心功能'), + items: [ + { + title: $t("账号与角色"), + description: $t('邀请你的团队成员加入 APIPark,共同管理和调用 API。'), + link: 'https://docs.apipark.com/docs/quick/pre-work/team' + }, + { + title: $t("团队"), + description: $t('团队中包含了人员、应用和服务,不同团队之间的应用和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。'), + link: 'https://docs.apipark.com/docs/quick/provider/service' + }, + { + title: $t("服务"), + description: $t('服务内包含一组 API,并且可以发布到 API 市场被其他团队使用。'), + link: 'https://docs.apipark.com/docs/quick/suberscriber/application' + } + ] + }, + { + title: $t('权限管理'), + items: [ + { + title: $t("订阅服务"), + description: $t('如果需要调用某个服务的 API,需要先订阅该服务,并且等待提供服务的团队审批后才可发起 API 请求。'), + link: 'https://docs.apipark.com/docs/tutorials/api-market/service' + }, + { + title: $t("审批订阅申请"), + description: $t('提供服务的团队可以审批来自其他团队的订阅申请,审批通过后的应用才可发起 API 请求。'), + link: 'https://docs.apipark.com/docs/quick/suberscriber/subscribe' + } + ] + }, + { + title: $t('集成'), + items: [ + { + title: $t("日志"), + description: $t('APIPark 提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。'), + link: 'https://docs.apipark.com/docs/quick/pre-work/monitor' + } + ] + } + ]; useEffect(()=>{ localStorage.setItem('showGuide', showGuide.toString()) },[showGuide]) + useEffect(()=>{ + localStorage.setItem('showAdvancedGuide', showAdvancedGuide.toString()) + },[showAdvancedGuide]) + useEffect(()=>{ if(currentUrl === '/guide'){ setTimeout(()=>{ @@ -40,7 +148,8 @@ export default function Guide(){ scrollPage={false} contentClassName=" w-full pr-PAGE_INSIDE_X pb-PAGE_INSIDE_B" > - {showGuide && +
+ {showGuide && 🚀{`${$t('快速入门')}`}

{$t("我们提供了一些任务来帮你快速了解 APIPark")}

, - children: }]} + children: }]} />} + {showAdvancedGuide && + +

+ 🏍️{`${$t('进阶教程')}`}

+

{$t("了解 APIPark 如何更好地管理 API 和 AI")}

, + children: }]} + />} +
+ ) } -const QuickGuideContent = ({changeGuideShow}:{changeGuideShow:Dispatch>})=>{ +const QuickGuideContent = ({changeGuideShow,guideSections}:{changeGuideShow:Dispatch>,guideSections: { + title: string; + items: { + title: string; + description: string; + link: string; + }[]; +}[]})=>{ + + return (<>
-

{$t('工作空间')}

-
-
- {window.open('https://docs.apipark.com/docs/quick/pre-work/team','_blank')}}> - {$t('团队中包含了人员、应用和服务,不同团队之间的应用和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。')} - - {window.open('https://docs.apipark.com/docs/quick/provider/service','_blank')}}> - {$t('服务内包含一组 API,并且可以发布到 API 市场被其他团队使用。')} - - {window.open('https://docs.apipark.com/docs/quick/suberscriber/application','_blank')}}> - {$t('应用是申请服务和调用 API 的身份,可以在 API 市场申请调用服务,并且每个应用拥有独立的 API 访问鉴权。')} - -
-
-

{$t('API 市场')}

-
-
- {window.open('https://docs.apipark.com/docs/tutorials/api-market/service','_blank')}}> - {$t('你可以在 API 市场中查看所有公开的服务。')} - - {window.open('https://docs.apipark.com/docs/quick/suberscriber/subscribe','_blank')}}> - {$t('如果需要调用某个服务的 API,需要先订阅该服务,并且等待提供服务的团队审批后才可发起 API 请求。')} - - {window.open('https://docs.apipark.com/docs/quick/provider/approve','_blank')}}> - {$t('提供服务的团队可以审批来自其他团队的订阅申请,审批通过后的应用才可发起 API请求。')} - -
-
-

{$t('仪表盘')}

-
-
- {window.open('https://docs.apipark.com/docs/quick/pre-work/monitor','_blank')}}> - {$t('仪表盘中提供了多种统计图表,帮助我们了解 API 的运行情况。')} - -
-
+ {guideSections.map((section, index) => ( +
+

+ + {section.title} +

+
+
+ {section.items.map((item, itemIndex) => ( + { window.open(item.link, '_blank') }} + > + {item.description} + + ))} +
+
+
+ ))}

-

+
- +

diff --git a/frontend/packages/core/src/pages/logsettings/LogSettings.tsx b/frontend/packages/core/src/pages/logsettings/LogSettings.tsx index 6bf464fd..7a55d37a 100644 --- a/frontend/packages/core/src/pages/logsettings/LogSettings.tsx +++ b/frontend/packages/core/src/pages/logsettings/LogSettings.tsx @@ -69,7 +69,7 @@ const LogSettings = ()=>{
{ - fetchData>(url, + fetchData>(url, {method, + ...(type !== 'addDep' && type !== 'addMember' && {eoParams: {id:entity!.id}}), eoBody:({ ...value, ...(value?.departmentIds ?{ departmentIds:Array.isArray(value?.departmentIds)? value?.departmentIds : [value?.departmentIds]}:{}), - ...(type !== 'addDep' && type !== 'addMember' && {eoParams: {id:entity!.id}}) }),eoTransformKeys:['departmentIds']}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ @@ -154,14 +154,14 @@ export const MemberDropdownModal = forwardRef - + label={$t("邮箱")} name="email" rules={[{required: true,whitespace:true },{type:"email",message: $t(VALIDATE_MESSAGE.email)}]} > - + label={$t("部门")} @@ -169,7 +169,6 @@ export const MemberDropdownModal = forwardRef { fixed:'right', valueType: 'option', render: (_: React.ReactNode, entity: MemberTableListItem) => [ - {openModal('editMember',entity)}} btnTitle="编辑"/>, + {openModal('editMember',entity)}} btnTitle="编辑"/>, ], } ] diff --git a/frontend/packages/core/src/pages/partitions/PartitionInsideCluster.tsx b/frontend/packages/core/src/pages/partitions/PartitionInsideCluster.tsx index d4e3566d..241c5d33 100644 --- a/frontend/packages/core/src/pages/partitions/PartitionInsideCluster.tsx +++ b/frontend/packages/core/src/pages/partitions/PartitionInsideCluster.tsx @@ -9,6 +9,7 @@ import { ClusterNodeModal } from "./PartitionInsideClusterNode.tsx"; import { LoadingOutlined } from "@ant-design/icons"; import InsidePage from "@common/components/aoplatform/InsidePage.tsx"; import { $t } from "@common/locales/index.ts"; +import { extractIPFromURL, isPrivateIP} from '@common/utils/ip.ts' const PartitionInsideCluster:FC = ()=> { const {setBreadcrumb} = useBreadcrumb() @@ -86,11 +87,24 @@ const PartitionInsideCluster:FC = ()=> { ) } + +const IpTypeTag = ({ip:url}:{ip:string}) =>{ + const ip = extractIPFromURL(url); + const isPrivate :boolean= ip ? isPrivateIP(ip) : false + return ( + + {isPrivate ? '私有网络' : '公共网络'} + + ) +} export function ClusterConfigPreview (x:PartitionClusterNodeTableListItem){ return
- {$t('管理地址')}:{x.managerAddress.map(m=>(

{m}

))}
- {$t('服务地址')}:{x.serviceAddress.map(m=>(

{m}

))}
- {$t('同步地址')}:

{x.peerAddress}

+ {$t('管理地址')}:{x.managerAddress.map(m=>( +

{m}

))}
+ {$t('服务地址')}:{x.serviceAddress.map(m=>( +

{m}

))}
+ {$t('同步地址')}: +

{x.peerAddress}

} export default PartitionInsideCluster \ No newline at end of file diff --git a/frontend/packages/core/src/pages/system/SystemConfig.tsx b/frontend/packages/core/src/pages/system/SystemConfig.tsx index bea29e9a..1280e598 100644 --- a/frontend/packages/core/src/pages/system/SystemConfig.tsx +++ b/frontend/packages/core/src/pages/system/SystemConfig.tsx @@ -1,7 +1,7 @@ import {forwardRef, useEffect, useImperativeHandle, useMemo, useState} from "react"; import {App, Button, Form, Input, Radio, Row, Select, TreeSelect, Upload} from "antd"; -import { Link, useNavigate, useParams} from "react-router-dom"; +import { Link, useLocation, useNavigate, useParams} from "react-router-dom"; import {RouterParams} from "@core/components/aoplatform/RenderRoutes.tsx"; import {BasicResponse, DELETE_TIPS, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE, VALIDATE_MESSAGE} from "@common/const/const.tsx"; import {useFetch} from "@common/hooks/http.ts"; @@ -10,10 +10,10 @@ import { EntityItem, MemberItem, SimpleTeamItem} from "@common/const/type.ts"; import { v4 as uuidv4 } from 'uuid' import { SystemConfigFieldType, SystemConfigHandle } from "../../const/system/type.ts"; import { validateUrlSlash } from "@common/utils/validate.ts"; -import { compressImage, normFile } from "@common/utils/uploadPic.ts"; +import { normFile } from "@common/utils/uploadPic.ts"; import { useBreadcrumb } from "@common/contexts/BreadcrumbContext.tsx"; import { useSystemContext } from "../../contexts/SystemContext.tsx"; -import { SERVICE_VISUALIZATION_OPTIONS } from "@core/const/system/const.tsx"; +import { SERVICE_APPROVAL_OPTIONS, SERVICE_KIND_OPTIONS, SERVICE_VISUALIZATION_OPTIONS } from "@core/const/system/const.tsx"; import { RcFile, UploadChangeParam, UploadFile, UploadProps } from "antd/es/upload/interface"; import { LoadingOutlined } from "@ant-design/icons"; import { getImgBase64 } from "@common/utils/dataTransfer.ts"; @@ -22,8 +22,13 @@ import WithPermission from "@common/components/aoplatform/WithPermission.tsx"; import { Icon } from "@iconify/react/dist/iconify.js"; import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx"; import { $t } from "@common/locales/index.ts"; +import { AiServiceConfigFieldType } from "@core/const/ai-service/type.ts"; -const MAX_SIZE = 2 * 1024; // 1KB + +export type SimpleAiProviderItem = EntityItem & { + configured:boolean + logo:string +} const SystemConfig = forwardRef((_,ref) => { const { message,modal } = App.useApp() @@ -35,17 +40,45 @@ const SystemConfig = forwardRef((_,ref) => { const navigate = useNavigate(); const {setBreadcrumb} = useBreadcrumb() const { setSystemInfo} = useSystemContext() - const [showClassify, setShowClassify] = useState() + const [showClassify, setShowClassify] = useState(true) + const [showAI, setShowAI] = useState(false) const [imageBase64, setImageBase64] = useState(null); const [tagOptionList, setTagOptionList] = useState([]) const [serviceClassifyOptionList, setServiceClassifyOptionList] = useState() const [uploadLoading, setUploadLoading] = useState(false) - const {checkPermission,accessInit, getGlobalAccessData,state} = useGlobalContext() + const {checkPermission,accessInit, getGlobalAccessData,state, aiConfigFlushed, setAiConfigFlushed} = useGlobalContext() + const [providerOptionList, setProviderOptionList] = useState() + const location = useLocation() + const currentUrl = location.pathname useImperativeHandle(ref, () => ({ save:onFinish })); + useEffect(()=>{ + if(currentUrl.indexOf('aiInside') !== -1){ + setShowAI(true) + } + },[currentUrl]) + + const getProviderOptionList = ()=>{ + setProviderOptionList([]) + fetchData>('simple/ai/providers',{method:'GET',eoTransformKeys:[]}).then(response=>{ + const {code,data,msg} = response + if(code === STATUS_CODE.SUCCESS){ + const configuredProvider = data.providers?.filter(x=>x.configured)?.map((x:SimpleAiProviderItem)=>{return {...x, + label: x.name, value:x.id + }}) + setProviderOptionList(configuredProvider) + if(!serviceId && configuredProvider.length > 0){ + form.setFieldsValue({provider: configuredProvider[0]?.id}) + } + }else{ + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }) + } + const beforeUpload = async (file: RcFile) => { if (!['image/png', 'image/jpeg', 'image/svg+xml'].includes(file.type)) { alert($t('只允许上传PNG、JPG或SVG格式的图片')); @@ -72,6 +105,7 @@ const SystemConfig = forwardRef((_,ref) => { }; + const handleChange: UploadProps['onChange'] = (info: UploadChangeParam) => { if (info.file.status === 'uploading') { setUploadLoading(true); @@ -104,6 +138,10 @@ const SystemConfig = forwardRef((_,ref) => { }})||[]) setServiceClassifyOptionList(data.catalogues) + if(form.getFieldValue('catalogue') === undefined&&data.catalogues.length){ + form.setFieldValue('catalogue',data.catalogues[0].id); + } + }else{ message.error(msg || $t(RESPONSE_TIPS.error)) } @@ -113,7 +151,7 @@ const SystemConfig = forwardRef((_,ref) => { // 获取表单默认值 const getSystemInfo = () => { - fetchData>('service/info',{method:'GET',eoParams:{team:teamId, service:serviceId},eoTransformKeys:['team_id','service_type']}).then(response=>{ + fetchData>('service/info',{method:'GET',eoParams:{team:teamId, service:serviceId},eoTransformKeys:['team_id','service_type','approval_type','service_kind']}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ setTimeout(()=>{ @@ -122,6 +160,7 @@ const SystemConfig = forwardRef((_,ref) => { team:data.service.team.id, catalogue:data.service.catalogue?.id, tags:data.service.tags?.map((x:EntityItem)=>x.name), + provider:data.service.provider?.id, logoFile:[ { uid: '-1', // 文件唯一标识 @@ -142,7 +181,7 @@ const SystemConfig = forwardRef((_,ref) => { const onFinish:()=>Promise = () => { return form.validateFields().then((value)=>{ - return fetchData>(serviceId === undefined? 'team/service':'service/info',{method:serviceId === undefined? 'POST' : 'PUT',eoParams: {...(serviceId === undefined ? {team:value.team} :{service:serviceId,team:teamId})},eoBody:({...value,prefix:value.prefix?.trim()}), eoTransformKeys:['serviceType']},).then(response=>{ + return fetchData>(serviceId === undefined? 'team/service':'service/info',{method:serviceId === undefined? 'POST' : 'PUT',eoParams: {...(serviceId === undefined ? {team:value.team} :{service:serviceId,team:teamId})},eoBody:({...value,prefix:value.prefix?.trim()}), eoTransformKeys:['serviceType','approvalType','serviceKind']},).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || $t(RESPONSE_TIPS.success)) @@ -168,6 +207,9 @@ const SystemConfig = forwardRef((_,ref) => { setTeamOptionList(data.teams?.map((x:MemberItem)=>{return {...x, label:x.name, value:x.id }})) + if(form.getFieldValue('team') === undefined&&data.teams?.length){ + form.setFieldValue('team',data.teams[0].id); + } }else{ message.error(msg || $t(RESPONSE_TIPS.error)) } @@ -186,6 +228,11 @@ const SystemConfig = forwardRef((_,ref) => { }) } + + useEffect(()=>{ + aiConfigFlushed && getProviderOptionList() + },[aiConfigFlushed]) + useEffect(() => { if(accessInit){ getTeamOptionList() @@ -194,6 +241,7 @@ const SystemConfig = forwardRef((_,ref) => { getTeamOptionList() }) } + getProviderOptionList() getTagAndServiceClassifyList() if (serviceId !== undefined) { setOnEdit(true); @@ -205,12 +253,15 @@ const SystemConfig = forwardRef((_,ref) => { { title: $t('设置') }]) - } else { setOnEdit(false); - form.setFieldValue('id',uuidv4()); + const id = uuidv4() + form.setFieldValue('id',id); + form.setFieldValue('serviceKind',serviceTypeOptions[0].value) + form.setFieldValue('prefix',`${id.split('-')[0]}/`) form.setFieldValue('team',teamId); - form.setFieldValue('serviceType','inner'); + form.setFieldValue('serviceType','public'); + form.setFieldValue('approvalType','auto'); } return (form.setFieldsValue({})) }, [serviceId]); @@ -234,7 +285,9 @@ const SystemConfig = forwardRef((_,ref) => { }) } - const visualizationOptions = useMemo(()=>SERVICE_VISUALIZATION_OPTIONS.map((x)=>({...x, label:$t(x.label)})),[state.language]) + const serviceTypeOptions = useMemo(()=>SERVICE_KIND_OPTIONS.map((x)=>({...x, label:$t(x.label)})),[state.language]); + // const visualizationOptions = useMemo(()=>SERVICE_VISUALIZATION_OPTIONS.map((x)=>({...x, label:$t(x.label)})),[state.language]) + const approvalOptions = useMemo(()=>SERVICE_APPROVAL_OPTIONS.map((x)=>({...x, label:$t(x.label)})),[state.language]) return ( <> @@ -259,25 +312,90 @@ const SystemConfig = forwardRef((_,ref) => { - label={$t("服务ID")} + label={$t("服务 ID")} name="id" rules={[{ required: true ,whitespace:true }]} > + {!onEdit&& + + label={$t("服务类型")} + name="serviceKind" + rules={[{required: true}]} + > + + +} + {showAI && + label={$t("默认 AI 供应商")} + name="provider" + rules={[{ required: true }]} + extra={serviceId ? $t('创建 API 时会默认选择该供应商,修改默认供应商不会影响现有 API') : ''} + >{ + (providerOptionList && providerOptionList.length >0 ) ? :

{$t("未配置任何 AI 模型供应商,")}setAiConfigFlushed(false)}>{$t('立即配置')}

+ } + } + label={$t("API 调用前缀")} name="prefix" - extra={$t("选填,作为服务内所有API的前缀,比如host/{service_name}/{api_path},一旦保存无法修改")} - rules={[ + extra={$t("作为服务内所有API的前缀,比如host/{service_name}/{api_path},一旦保存无法修改")} + rules={[{ required: true ,whitespace:true }, { validator: validateUrlSlash, }]} > + {!onEdit && + label={$t("所属团队")} + name="team" + rules={[{ required: true }]} + > + + } + + + label={$t("订阅审批")} + name="approvalType" + rules={[{required: true}]} + > + + + {/* + label={$t("服务类型")} + name="serviceType" + rules={[{required: true}]} + > + {setShowClassify(e.target.value === 'public')}} /> + */} + + {showClassify && + + label={$t("所属服务分类")} + name="catalogue" + extra={$t("设置服务展示在服务市场中的哪个分类下")} + rules={[{required: true}]} + > + + + } + label={$t("图标")} name="logoFile" @@ -313,15 +431,7 @@ const SystemConfig = forwardRef((_,ref) => { > - {!onEdit && - label={$t("所属团队")} - name="team" - rules={[{ required: true }]} - > - - } - + label={$t("标签")} @@ -334,34 +444,7 @@ const SystemConfig = forwardRef((_,ref) => { options={tagOptionList}> - - - label={$t("服务类型")} - name="serviceType" - rules={[{required: true}]} - > - {setShowClassify(e.target.value === 'public')}} /> - - - {showClassify && - - label={$t("所属服务分类")} - name="catalogue" - extra={$t("设置服务展示在服务市场中的哪个分类下")} - rules={[{required: true}]} - > - - - } + {onEdit && <> { const { message } = App.useApp() - const { teamId,serviceId,apiId} = useParams(); + const { teamId,serviceId,apiId,routeId} = useParams(); const location = useLocation() const currentUrl = location.pathname const {fetchData} = useFetch() @@ -27,6 +27,7 @@ const SystemInsidePage:FC = ()=> { const { accessData,checkPermission,accessInit,state} = useGlobalContext() const [activeMenu, setActiveMenu] = useState() const navigateTo = useNavigate() + const [showMenu, setShowMenu] = useState(false) const getSystemInfo = ()=>{ fetchData>('service/info',{method:'GET',eoParams:{team:teamId, service:serviceId}}).then(response=>{ @@ -58,8 +59,8 @@ const SystemInsidePage:FC = ()=> { const SYSTEM_PAGE_MENU_ITEMS = useMemo(()=>[ getItem($t('服务'), 'assets', null, [ - getItem({$t('API')}, 'api',undefined,undefined,undefined,'team.service.api_doc.view'), - getItem({$t('路由')}, 'route',undefined,undefined,undefined,'team.service.router.view'), + getItem({$t('API 路由')}, 'route',undefined,undefined,undefined,'team.service.router.view'), + getItem({$t('API 文档')}, 'api',undefined,undefined,undefined,'team.service.api_doc.view'), getItem({$t('上游')}, 'upstream',undefined,undefined,undefined,'team.service.upstream.view'), getItem({$t('使用说明')}, 'document',undefined,undefined,undefined,''), getItem({$t('发布')}, 'publish',undefined,undefined,undefined,'team.service.release.view'), @@ -94,7 +95,7 @@ const SystemInsidePage:FC = ()=> { } const filteredMenu = filterMenu(SYSTEM_PAGE_MENU_ITEMS as MenuItemGroupType[]) setActiveMenu((pre)=>{ - return pre ?? 'api' + return pre ?? 'route' }) return filteredMenu || [] },[accessData,accessInit, SYSTEM_PAGE_MENU_ITEMS]) @@ -104,12 +105,13 @@ const SystemInsidePage:FC = ()=> { }; useEffect(() => { + setShowMenu(!routeId && !currentUrl.includes('route/create')) if(apiId !== undefined){ setActiveMenu('api') }else if(serviceId !== currentUrl.split('/')[currentUrl.split('/').length - 1]){ setActiveMenu(currentUrl.split('/')[currentUrl.split('/').length - 1]) }else{ - setActiveMenu('api') + setActiveMenu('route') } }, [currentUrl]); @@ -130,7 +132,7 @@ const SystemInsidePage:FC = ()=> { }, [serviceId]); return ( - <> + <>{showMenu ? {$t('服务 ID')}:{serviceId || '-'} @@ -149,7 +151,7 @@ const SystemInsidePage:FC = ()=> {
- + : } ) diff --git a/frontend/packages/core/src/pages/system/SystemList.tsx b/frontend/packages/core/src/pages/system/SystemList.tsx index 21e1c429..fe817614 100644 --- a/frontend/packages/core/src/pages/system/SystemList.tsx +++ b/frontend/packages/core/src/pages/system/SystemList.tsx @@ -9,12 +9,13 @@ import {BasicResponse, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx import {useFetch} from "@common/hooks/http.ts"; import { SimpleTeamItem ,SimpleMemberItem} from "@common/const/type.ts"; import { SystemConfigHandle, SystemTableListItem } from "../../const/system/type.ts"; -import { SYSTEM_TABLE_COLUMNS } from "../../const/system/const.tsx"; +import { SERVICE_KIND_OPTIONS, SYSTEM_TABLE_COLUMNS } from "../../const/system/const.tsx"; import { DrawerWithFooter } from "@common/components/aoplatform/DrawerWithFooter.tsx"; 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 = ()=>{ const navigate = useNavigate(); @@ -117,12 +118,21 @@ const SystemList:FC = ()=>{ const columns = useMemo(()=>{ const res = SYSTEM_TABLE_COLUMNS.map(x=>{ - if(x.filters &&((x.dataIndex as string[])?.indexOf('master') !== -1 ) ){ + const dataIndex=(x.dataIndex as string[]); + + if(x.filters &&dataIndex?.indexOf('master') !== -1 ){ x.valueEnum = memberValueEnum } - if(x.filters &&((x.dataIndex as string[])?.indexOf('team') !== -1 ) ){ + if(x.filters &&dataIndex?.indexOf('team') !== -1 ){ x.valueEnum = teamList } + if((x.dataIndex as string)==='service_kind'){ + x.valueEnum={}; + SERVICE_KIND_OPTIONS + .forEach(option => { + (x.valueEnum as any)[option.value] = { text: $t(option.label) }; + }); + } return {...x,title:typeof x.title === 'string' ? $t(x.title as string) : x.title}}) return res @@ -141,8 +151,13 @@ const SystemList:FC = ()=>{ ]; return ( -
- {/* */} + + { onSearchWordChange={(e) => { setTableSearchWord(e.target.value) }} - onRowClick={(row:SystemTableListItem)=>navigate(`/service/${row.team.id}/inside/${row.id}`)} + onRowClick={(row:SystemTableListItem)=>navigate(`/service/${row.team.id}/${row.service_kind==='ai'?'aiInside':'inside'}/${row.id}`)} /> drawerFormRef.current?.save()?.then((res)=>{res && manualReloadTable();return res})} > -
+ ) } diff --git a/frontend/packages/core/src/pages/system/api/SystemInsideApiDocument.tsx b/frontend/packages/core/src/pages/system/api/SystemInsideApiDocument.tsx index f6a20350..8991cdcd 100644 --- a/frontend/packages/core/src/pages/system/api/SystemInsideApiDocument.tsx +++ b/frontend/packages/core/src/pages/system/api/SystemInsideApiDocument.tsx @@ -60,7 +60,7 @@ const SystemInsideApiDocument = forwardRef - + ) @@ -113,7 +113,7 @@ const SystemInsideApiDocument = forwardRef - +
@@ -137,7 +137,7 @@ const SystemInsideApiDocument = forwardRef - +
} diff --git a/frontend/packages/core/src/pages/system/api/SystemInsideApiProxy.tsx b/frontend/packages/core/src/pages/system/api/SystemInsideApiProxy.tsx index 882d9071..c47b2b1e 100644 --- a/frontend/packages/core/src/pages/system/api/SystemInsideApiProxy.tsx +++ b/frontend/packages/core/src/pages/system/api/SystemInsideApiProxy.tsx @@ -4,7 +4,7 @@ import { forwardRef, useEffect, useImperativeHandle, useMemo } from "react" import EditableTableWithModal from "@common/components/aoplatform/EditableTableWithModal"; import { PROXY_HEADER_CONFIG, UPSTREAM_PROXY_HEADER_TYPE_OPTIONS } from "../../../const/system/const"; import { SystemApiProxyType, ProxyHeaderItem, SystemInsideApiProxyHandle, SystemInsideApiProxyProps } from "../../../const/system/type"; -import { PLACEHOLDER, VALIDATE_MESSAGE } from "@common/const/const"; +import { PLACEHOLDER, } from "@common/const/const"; import { $t } from "@common/locales"; import { useGlobalContext } from "@common/contexts/GlobalStateContext"; diff --git a/frontend/packages/core/src/pages/system/api/SystemInsideRouterCreate.tsx b/frontend/packages/core/src/pages/system/api/SystemInsideRouterCreate.tsx index 3885bd8a..62fd6c99 100644 --- a/frontend/packages/core/src/pages/system/api/SystemInsideRouterCreate.tsx +++ b/frontend/packages/core/src/pages/system/api/SystemInsideRouterCreate.tsx @@ -1,4 +1,4 @@ -import {App, Col, Form, Input, Row, Select, Spin, Switch} from "antd"; +import {App, Button, Col, Form, Input, Row, Select, Spin, Switch} from "antd"; import {forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState} from "react"; import EditableTableWithModal from "@common/components/aoplatform/EditableTableWithModal.tsx"; import styles from "./SystemInsideApi.module.css" @@ -12,23 +12,33 @@ import { $t } from "@common/locales/index.ts"; import SystemInsideApiProxy from "@core/pages/system/api/SystemInsideApiProxy.tsx"; import { LoadingOutlined } from "@ant-design/icons"; import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx"; +import { RouterParams } from "@core/components/aoplatform/RenderRoutes.tsx"; +import { useNavigate, useParams } from "react-router-dom"; +import { useSystemContext } from "@core/contexts/SystemContext.tsx"; +import InsidePage from "@common/components/aoplatform/InsidePage.tsx"; const SystemInsideRouterCreate = forwardRef((props, ref) => { const { message } = App.useApp() - const {type, entity, serviceId,teamId, modalApiPrefix:apiPrefix, modalPrefixForce:prefixForce} = props + const {serviceId, teamId, routeId} = useParams() const [form] = Form.useForm(); const {fetchData} = useFetch() const [loading, setLoading] = useState(false) const proxyRef = useRef(null) const { state } = useGlobalContext() + const {apiPrefix, prefixForce} = useSystemContext() + const navigator = useNavigate() const onFinish = ()=>{ return Promise.all([proxyRef.current?.validate?.(), form.validateFields()]).then(([,formValue])=>{ - const body = {...formValue,path:formValue.path.trim(),proxy:{...formValue.proxy,path:formValue.proxy.path ? (formValue.proxy.path.startsWith('/')? formValue.proxy.path: '/'+ formValue.proxy.path) : undefined}} - return fetchData>('service/router',{method: type === 'add' ? 'POST' : 'PUT',eoBody:(body), eoParams: {service:serviceId,team:teamId, ...(type === 'edit' ? {router:entity?.id}: {})},eoTransformKeys:['matchType','disable']}).then(response=>{ + const body = {...formValue, + path: prefixForce? `${apiPrefix}/${formValue.path.trim()}` : formValue.path.trim(), + proxy:{...formValue.proxy,path:formValue.proxy.path ? (formValue.proxy.path.startsWith('/')? formValue.proxy.path: '/'+ formValue.proxy.path) : undefined}} + return fetchData>('service/router',{ + method: routeId ? 'PUT' :'POST' ,eoBody:(body), eoParams: {service:serviceId,team:teamId, router:routeId },eoTransformKeys:['matchType','disable']}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || $t(RESPONSE_TIPS.success)) + navigator(`/service/${teamId}/inside/${serviceId}/route`) return Promise.resolve(true) }else{ message.error(msg || $t(RESPONSE_TIPS.error)) @@ -41,7 +51,7 @@ const SystemInsideRouterCreate = forwardRefPromise = ()=>{ return new Promise((resolve, reject)=>{ return form.validateFields().then((value)=>{ - fetchData>('service/api/copy',{method:'POST',eoParams:{service:serviceId,team:teamId, api:entity!.id},eoBody:({...value,path:value.path.trim()})}).then(response=>{ + fetchData>('service/api/copy',{method:'POST',eoParams:{service:serviceId,team:teamId, api:routeId},eoBody:({...value,path:value.path.trim()})}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || $t(RESPONSE_TIPS.success)) @@ -63,7 +73,7 @@ const SystemInsideRouterCreate = forwardRef{ setLoading(true) - fetchData>('service/router/detail',{method:'GET',eoParams:{service:serviceId,team:teamId, router:entity!.id}, eoTransformKeys:['create_time','update_time','match_type','upstream_id','opt_type']}).then(response=>{ + fetchData>('service/router/detail',{method:'GET',eoParams:{service:serviceId,team:teamId, router:routeId}, eoTransformKeys:['create_time','update_time','match_type','upstream_id','opt_type']}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ const {disable, protocols, path, methods, description, match, proxy} = data.router @@ -77,28 +87,15 @@ const SystemInsideRouterCreate = forwardRef { - switch(type){ - case 'edit': + if(routeId){ getRouterConfig() - break; - case 'add': - form.setFieldValue('prefix',apiPrefix) - form.setFieldValue(['proxy','timeout'],10000) - form.setFieldValue(['proxy','retry'],0) - form.setFieldValue('protocols',['HTTP','HTTPS']) - break; - case 'copy': - // form.setFieldsValue({ - // ...entity, - // name:`${$t('副本')}-${entity!.name}`, - // ...(prefixForce? - // {prefix:apiPrefix,path: entity!.path.substring(apiPrefix?.length|| 0)}: - // {}), - // proxy:{timeout:10000, retry:0, ...entity?.proxy} - // }); - break; + }else{ + form.setFieldValue('prefix',apiPrefix) + form.setFieldValue(['proxy','timeout'],10000) + form.setFieldValue(['proxy','retry'],0) + form.setFieldValue('protocols',['HTTP','HTTPS']) } - return (form.setFieldsValue({})) + return (form.setFieldsValue({})) }, []); @@ -118,7 +115,19 @@ const SystemInsideRouterCreate = forwardRef + return ( + + + + }> } spinning={loading} className=''>
{/* } */} - { type !== 'copy' &&<> {$t('转发规则设置')} className="mb-0 bg-transparent border-none p-0" name="proxy" > - + - }
- +
) }) export default SystemInsideRouterCreate \ No newline at end of file diff --git a/frontend/packages/core/src/pages/system/api/SystemInsideRouterList.tsx b/frontend/packages/core/src/pages/system/api/SystemInsideRouterList.tsx index 93ff1824..b033c321 100644 --- a/frontend/packages/core/src/pages/system/api/SystemInsideRouterList.tsx +++ b/frontend/packages/core/src/pages/system/api/SystemInsideRouterList.tsx @@ -1,21 +1,18 @@ import PageList, { PageProColumns } from "@common/components/aoplatform/PageList.tsx" import {ActionType} from "@ant-design/pro-components"; import {FC, useEffect, useMemo, useRef, useState} from "react"; -import {Link, useParams} from "react-router-dom"; +import {Link, useNavigate, useParams} from "react-router-dom"; import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx"; import {App, Divider} from "antd"; import {BasicResponse, COLUMNS_TITLE, DELETE_TIPS, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx"; import { SimpleMemberItem} from '@common/const/type.ts' import {useFetch} from "@common/hooks/http.ts"; import {RouterParams} from "@core/components/aoplatform/RenderRoutes.tsx"; -import SystemInsideRouterCreate from "./SystemInsideRouterCreate.tsx"; -import {useSystemContext} from "../../../contexts/SystemContext.tsx"; import { SYSTEM_API_TABLE_COLUMNS } from "../../../const/system/const.tsx"; -import {SystemApiTableListItem, SystemInsideRouterCreateHandle } from "../../../const/system/type.ts"; +import {SystemApiTableListItem } from "../../../const/system/type.ts"; import TableBtnWithPermission from "@common/components/aoplatform/TableBtnWithPermission.tsx"; import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx"; import { checkAccess } from "@common/utils/permission.ts"; -import { DrawerWithFooter } from "@common/components/aoplatform/DrawerWithFooter.tsx"; import { $t } from "@common/locales/index.ts"; const SystemInsideRouterList:FC = ()=>{ @@ -26,15 +23,10 @@ const SystemInsideRouterList:FC = ()=>{ const [tableHttpReload, setTableHttpReload] = useState(true); const {fetchData} = useFetch() const pageListRef = useRef(null); - const {apiPrefix, prefixForce} = useSystemContext() const [memberValueEnum, setMemberValueEnum] = useState([]) const {accessData,state} = useGlobalContext() - const [drawerType,setDrawerType]= useState<'add'|'edit'|'view'|'upstream'|undefined>() - const [open, setOpen] = useState(false); - const drawerAddFormRef = useRef(null) const {serviceId, teamId} = useParams() - - const [curApi, setCurApi] = useState() + const navigator = useNavigate() const getRoutesList = (): Promise<{ data: SystemApiTableListItem[], success: boolean }>=> { if(!tableHttpReload){ @@ -113,7 +105,7 @@ const SystemInsideRouterList:FC = ()=>{ fixed:'right', valueType: 'option', render: (_: React.ReactNode, entity: SystemApiTableListItem) => [ - {openDrawer('edit',entity)}} btnTitle="编辑"/>, + {navigator(`/service/${teamId}/inside/${serviceId}/route/${entity.id}`)}} btnTitle="编辑"/>, , {openModal('delete',entity)}} btnTitle="删除"/>, ], @@ -135,12 +127,12 @@ const SystemInsideRouterList:FC = ()=>{ } } - const openDrawer = (type:'add'|'edit'|'view',entity?:SystemApiTableListItem)=>{ - setCurApi(entity) - setDrawerType(type) - } + // const openDrawer = (type:'add'|'edit'|'view',entity?:SystemApiTableListItem)=>{ + // setCurApi(entity) + // setDrawerType(type) + // } - useEffect(()=>{drawerType !== undefined ? setOpen(true):setOpen(false)},[drawerType]) + // useEffect(()=>{drawerType !== undefined ? setOpen(true):setOpen(false)},[drawerType]) useEffect(() => { setBreadcrumb([ @@ -155,10 +147,10 @@ const SystemInsideRouterList:FC = ()=>{ manualReloadTable() }, [serviceId]); - const onClose = () => { - setDrawerType(undefined); - setCurApi(undefined) - }; + // const onClose = () => { + // setDrawerType(undefined); + // setCurApi(undefined) + // }; const columns = useMemo(()=>{ return [...SYSTEM_API_TABLE_COLUMNS].map(x=>{ @@ -179,17 +171,17 @@ const SystemInsideRouterList:FC = ()=>{ return {...x,title:typeof x.title === 'string' ? $t(x.title as string) : x.title}}) },[memberValueEnum,state.language]) - const handlerSubmit:() => Promise|undefined= ()=>{ - switch(drawerType){ - case 'add':{ - return drawerAddFormRef.current?.save()?.then((res)=>{res && manualReloadTable();return res}) - } - case 'edit':{ - return drawerAddFormRef.current?.save()?.then((res)=>{res && manualReloadTable();return res}) - } - default:return undefined - } - } + // const handlerSubmit:() => Promise|undefined= ()=>{ + // switch(drawerType){ + // case 'add':{ + // return drawerAddFormRef.current?.save()?.then((res)=>{res && manualReloadTable();return res}) + // } + // case 'edit':{ + // return drawerAddFormRef.current?.save()?.then((res)=>{res && manualReloadTable();return res}) + // } + // default:return undefined + // } + // } return ( <> @@ -201,7 +193,8 @@ const SystemInsideRouterList:FC = ()=>{ dataSource={tableListDataSource} addNewBtnTitle={$t('添加路由')} searchPlaceholder={$t('输入 URL 查找路由')} - onAddNewBtnClick={()=>{openDrawer('add')}} + // onAddNewBtnClick={()=>{openDrawer('add')}} + onAddNewBtnClick={()=>{navigator(`/service/${teamId}/inside/${serviceId}/route/create`)}} addNewBtnAccess="team.service.router.add" tableClickAccess="team.service.router.view" manualReloadTable={manualReloadTable} @@ -209,10 +202,10 @@ const SystemInsideRouterList:FC = ()=>{ onChange={() => { setTableHttpReload(false) }} - onRowClick={(row:SystemApiTableListItem)=>openDrawer('edit',row)} + onRowClick={(row:SystemApiTableListItem)=>navigator(`/service/${teamId}/inside/${serviceId}/route/${row.id}`)} tableClass="mr-PAGE_INSIDE_X " /> - { showOkBtn={drawerType !== 'view'} > - + */} ) diff --git a/frontend/packages/dashboard/src/component/MonitorPieGraph.tsx b/frontend/packages/dashboard/src/component/MonitorPieGraph.tsx index 7bea1e80..48888388 100644 --- a/frontend/packages/dashboard/src/component/MonitorPieGraph.tsx +++ b/frontend/packages/dashboard/src/component/MonitorPieGraph.tsx @@ -1,4 +1,4 @@ -import {FC, useMemo} from 'react'; +import {FC, useEffect, useMemo} from 'react'; import ECharts,{EChartsOption} from 'echarts-for-react'; import { changeNumberUnit } from '../utils/dashboard'; import { $t } from '@common/locales'; @@ -91,7 +91,7 @@ const MonitorPieGraph: FC = ({ className,title, pieData, labelNam data: transferData(pieData), }, ], - }),[state.language]) + }),[state.language,pieData]) return (
diff --git a/frontend/packages/dashboard/src/component/MonitorTotalPage.tsx b/frontend/packages/dashboard/src/component/MonitorTotalPage.tsx index 0cc108fa..c3732e9e 100644 --- a/frontend/packages/dashboard/src/component/MonitorTotalPage.tsx +++ b/frontend/packages/dashboard/src/component/MonitorTotalPage.tsx @@ -79,7 +79,7 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => { const [fullScreen, setFullScreen] = useState(false) const [recordQuery, setRecordQuery] = useState() const [queryBtnLoading, setQueryBtnLoading] = useState(false) - const [totalEmpty, setTotalEmpty] = useState(true) + const [totalEmpty, setTotalEmpty] = useState(false) const [requestStatus, dispatch] = useReducer(reducer, initialState); useEffect(() => { @@ -92,7 +92,7 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => { }, []); const getMonitorData = () => { - setTotalEmpty(true) + // setTotalEmpty(true) dispatch({ type: ACTIONS.RESET }); // ...根据时间和集群获取监控数据... let query = queryData @@ -126,7 +126,7 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => { // this.proxyPieRef?.changePieChart() setRequestSucRate(data.requestSummary.total === 0 ? '0%' : (data.requestSummary.success * 100 / data.requestSummary.total).toFixed(2) + '%') setProxySucRate(data.proxySummary.total === 0 ? '0%' : (data.proxySummary.success * 100 / data.proxySummary.total).toFixed(2) + '%') - setTotalEmpty(data.requestSummary.total === 0 && data.proxySummary.total === 0) + // setTotalEmpty(data.requestSummary.total === 0 && data.proxySummary.total === 0) }else{ setPieError(true) message.error(msg || $t(RESPONSE_TIPS.dataError)) diff --git a/frontend/packages/dashboard/src/pages/DashboardTotal.tsx b/frontend/packages/dashboard/src/pages/DashboardTotal.tsx index 721d52e4..09725d51 100644 --- a/frontend/packages/dashboard/src/pages/DashboardTotal.tsx +++ b/frontend/packages/dashboard/src/pages/DashboardTotal.tsx @@ -1,12 +1,10 @@ import { useNavigate, useParams } from "react-router-dom" -import { RouterParams } from "@core/components/aoplatform/RenderRoutes" import MonitorTotalPage from "@dashboard/component/MonitorTotalPage" import { BasicResponse } from "@common/const/const" import { InvokeData, MessageData, MonitorApiData, MonitorSubscriberData, PieData, SearchBody } from "@dashboard/const/type" import { useFetch } from "@common/hooks/http" import { objectToSearchParameters } from "@common/utils/router" -import { useEffect } from "react" export default function DashboardTotal() { const {fetchData } = useFetch() const navigateTo = useNavigate() diff --git a/frontend/packages/market/src/App.css b/frontend/packages/market/src/App.css index 86388012..c0397169 100644 --- a/frontend/packages/market/src/App.css +++ b/frontend/packages/market/src/App.css @@ -28,5 +28,3 @@ width:22px; } } - - diff --git a/frontend/packages/market/src/const/serviceHub/const.tsx b/frontend/packages/market/src/const/serviceHub/const.tsx index 7670fe10..bd054dcf 100644 --- a/frontend/packages/market/src/const/serviceHub/const.tsx +++ b/frontend/packages/market/src/const/serviceHub/const.tsx @@ -46,3 +46,7 @@ export const SERVICE_HUB_TABLE_COLUMNS: PageProColumns[ ]; +export const approvalTypeTranslate = { + 'auto':'无需审批', + 'manual':'需要审批' +} \ No newline at end of file diff --git a/frontend/packages/market/src/const/serviceHub/type.ts b/frontend/packages/market/src/const/serviceHub/type.ts index 6747e2ac..7ebbdab8 100644 --- a/frontend/packages/market/src/const/serviceHub/type.ts +++ b/frontend/packages/market/src/const/serviceHub/type.ts @@ -15,6 +15,8 @@ export type ServiceBasicInfoType = { updateTime:string version:string logo?:string + invokeAddress:string + approvalType:'auto'|'manual' } export type ServiceDetailType = { @@ -63,7 +65,7 @@ export type ServiceHubTableListItem = { export type ApplyServiceProps = { - entity:ServiceHubTableListItem & {app:EntityItem} + entity:ServiceBasicInfoType & EntityItem mySystemOptionList:DefaultOptionType[] reApply?:boolean } diff --git a/frontend/packages/market/src/pages/serviceHub/ApiTestGroup.tsx b/frontend/packages/market/src/pages/serviceHub/ApiTestGroup.tsx index 177d6369..7e8f673f 100644 --- a/frontend/packages/market/src/pages/serviceHub/ApiTestGroup.tsx +++ b/frontend/packages/market/src/pages/serviceHub/ApiTestGroup.tsx @@ -18,7 +18,6 @@ export default function ApiTestGroup({apiInfoList,selectedApiId }:ApiTestGroupTy const [selectedApi,setSelectedApi] = useState([selectedApiId]) const [selectedApiInfo, setSelectedApiInfo] = useState() const onSearchWordChange = (e:unknown)=>{ - //console.log(e) } useEffect(()=>{ diff --git a/frontend/packages/market/src/pages/serviceHub/ApplyServiceModal.tsx b/frontend/packages/market/src/pages/serviceHub/ApplyServiceModal.tsx index dd9521ea..06c7433e 100644 --- a/frontend/packages/market/src/pages/serviceHub/ApplyServiceModal.tsx +++ b/frontend/packages/market/src/pages/serviceHub/ApplyServiceModal.tsx @@ -63,14 +63,14 @@ export const ApplyServiceModal = forwardRef onDriverChange(e)} placeholder={$t(PLACEHOLDER.input)}/> + {label:'JWT',value:'jwt'}, + {label:'AK/SK',value:'aksk'}, + {label:'API Key',value:'apikey'}]} onChange={(e)=>onDriverChange(e)} placeholder={$t(PLACEHOLDER.input)}/>
{ detail?.length > 0 && detail.map((k,i)=>( - {$t(k.key)}: - { k.value || '-'} + {$t(k.key)}: + { ['永久','否','是'].indexOf(k.value)!== -1 ? $t(k.value) : (k.value || '-')} )) } diff --git a/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideAuth.tsx b/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideAuth.tsx index 9c753a4b..017ad08e 100644 --- a/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideAuth.tsx +++ b/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideAuth.tsx @@ -59,7 +59,6 @@ export default function ManagementInsideAuth(){ } const openModal =async (type:'view'|'delete'|'add'|'edit',entity?:SystemAuthorityTableListItem)=>{ - //console.log(type,entity) let title:string = '' let content:string|React.ReactNode = '' switch (type){ @@ -161,7 +160,7 @@ export default function ManagementInsideAuth(){ const item = authList[index]; return (
-
{item.name}
+
{item.name}
diff --git a/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideService.tsx b/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideService.tsx index d7bfa21f..8b5ee1d9 100644 --- a/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideService.tsx +++ b/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideService.tsx @@ -10,9 +10,10 @@ import { useOutletContext, useParams } from "react-router-dom" import { RouterParams } from "@core/components/aoplatform/RenderRoutes" import { TenantManagementServiceListItem } from "../../../const/serviceHub/type" import { ApprovalModalContent } from "./ApprovalModalContent" -import { checkAccess } from "@common/utils/permission" import { useGlobalContext } from "@common/contexts/GlobalStateContext" import { $t } from "@common/locales" +import WithPermission from "@common/components/aoplatform/WithPermission" +import { checkAccess } from "@common/utils/permission" export default function ManagementInsideService(){ const {message, modal} = App.useApp() @@ -99,10 +100,18 @@ export default function ManagementInsideService(){ }, width:600, okText:$t('确认'), - okButtonProps:{ - disabled : !checkAccess( `team.application.authorization.${type}`, accessData) - }, cancelText:$t('取消'), + okButtonProps:{ + disabled : !checkAccess( `team.application.authorization.${type}`, accessData ) + }, + footer: (_, { OkBtn, CancelBtn }) => ( + <> + + + + + + ), closable:true, icon:<>, }) @@ -132,11 +141,11 @@ export default function ManagementInsideService(){ }:{ key: 'cancelSub', label: ( - // + // - // + // ), }, ] diff --git a/frontend/packages/systemRunning/src/pages/SystemRunning.tsx b/frontend/packages/systemRunning/src/pages/SystemRunning.tsx index c06a2482..be94372a 100644 --- a/frontend/packages/systemRunning/src/pages/SystemRunning.tsx +++ b/frontend/packages/systemRunning/src/pages/SystemRunning.tsx @@ -353,14 +353,14 @@ export default function SystemRunning(){ labelCfg: { style: { fill: '5B8FF9', - opacity: 0 // 将透明度设置为0,隐藏提示信息,hover 才出现 + opacity: 0 } } }, defaultCombo: { labelCfg: { style: { - fill: '#666', // combo 的文本颜色 + fill: '#666' }, }, },