mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-14 20:41:15 +08:00
Merge branch 'feature/1.4' into 'main'
Feature/1.4 See merge request apipark/APIPark!144
This commit is contained in:
@@ -45,8 +45,6 @@
|
||||
"成功": "K43fcaf94",
|
||||
"上线失败": "Kc71c6a9",
|
||||
"失败": "K56c686f8",
|
||||
"正常": "Ke039b9b5",
|
||||
"无效": "K1da86266",
|
||||
"申请系统": "K1ff96ff",
|
||||
"所属团队": "K9bf855d6",
|
||||
"申请人": "K11b994ed",
|
||||
@@ -239,6 +237,10 @@
|
||||
"请输入IP地址或CIDR范围,每条以换行分割": "K49731763",
|
||||
"待更新": "K3a34d49b",
|
||||
"待删除": "Kd2850420",
|
||||
"内容": "K3e7aa0ad",
|
||||
"调用地址": "K2f5fdf5e",
|
||||
"消费者 IP": "K1bc5e0a3",
|
||||
"鉴权名称": "K6f39ea21",
|
||||
"暂无操作权限,请联系管理员分配。": "K23fda291",
|
||||
"微信小程序": "K4618cb0a",
|
||||
"获取文件,需填路径": "Ka854f511",
|
||||
@@ -324,12 +326,25 @@
|
||||
"响应 Body": "Kd2be51d1",
|
||||
"默认工作表": "K2a3f24ac",
|
||||
"至": "K7e1ab4b0",
|
||||
"详情": "Kf1b166e7",
|
||||
"暂不支持带有双斜杠//的url": "K28555332",
|
||||
"输入的IP或CIDR不符合格式": "K83237c89",
|
||||
"请正确输入路径,如/usr/*或*/usr/*": "K5ae2c87a",
|
||||
"必填项": "K71661ee8",
|
||||
"不是有效邮箱地址": "Kcbee3f8",
|
||||
"获取 AI providers 失败": "K94b48734",
|
||||
"AI 供应商": "Kf23a8988",
|
||||
"预览": "K4d81a657",
|
||||
"AI 服务": "Kd2c34e2c",
|
||||
"模型": "Kfede1c7c",
|
||||
"已用 Token": "K89f135a7",
|
||||
"拦截": "Kb7df6ac1",
|
||||
"放行": "K5c1722fe",
|
||||
"编辑时间": "K1acc30b2",
|
||||
"查看详情": "K35f990b0",
|
||||
"AI API 列表": "K91144ebd",
|
||||
"重置": "K50d471b2",
|
||||
"查询": "Kee8ae330",
|
||||
"请输入 APIURL 搜索": "Kf8187c33",
|
||||
"最近一次更新者": "K617f34f1",
|
||||
"最近一次更新时间": "K6ebca204",
|
||||
"保存": "Kabfe9512",
|
||||
@@ -357,18 +372,18 @@
|
||||
"变量": "K13ffbe88",
|
||||
"输入这个接口的描述": "K79c8cfaf",
|
||||
"重试次数": "K469e475a",
|
||||
"拦截接口": "Kee4139c2",
|
||||
"开启拦截后,网关会拦截所有该路径的请求。": "K3e38ea",
|
||||
"模型配置": "K8a35059b",
|
||||
"路由": "Kf9dcef3a",
|
||||
"添加路由": "K6134bbe8",
|
||||
"输入 URL 查找路由": "Kf85b83a0",
|
||||
"模型供应商": "Kcf9f90b8",
|
||||
"模型": "Kfede1c7c",
|
||||
"参数": "Ke99513a0",
|
||||
"审核": "Kb595f40",
|
||||
"通过": "K54e27f57",
|
||||
"拒绝": "K8582af3f",
|
||||
"发布结果": "Kd568e15c",
|
||||
"查看详情": "K35f990b0",
|
||||
"申请发布": "Kdbc1f6cb",
|
||||
"回滚": "Kb6860a3f",
|
||||
"请确认是否回滚?": "Ka3494f4b",
|
||||
@@ -377,13 +392,28 @@
|
||||
"终止发布": "Ke1b79b93",
|
||||
"请确认是否终止发布?": "Ka2449180",
|
||||
"新建版本": "K2cb02f38",
|
||||
"从 (0) 获取 API KEY": "Kb3e34847",
|
||||
"未配置 AI 模型": "Kd752a3a8",
|
||||
"前往设置": "K8b7ac871",
|
||||
"AI 模型": "K99935e6f",
|
||||
"配置好 AI 模型后,你可以使用对应的大模型来创建 AI 服务": "K2260837a",
|
||||
"已设置": "Kf97448b3",
|
||||
"未设置": "K30d4d8df",
|
||||
"默认模型": "Kc2ee5223",
|
||||
"负载优先级": "K608af899",
|
||||
"负载优先级决定在原供应商异常或停用后,优先使用哪一个供应商。优先级数字越小,优先级越高。": "K65b7a96",
|
||||
"优先级必须大于 0": "K9eccff16",
|
||||
"请输入优先级": "Kfcf02780",
|
||||
"API Key(默认 Key)": "K5c6dcf58",
|
||||
"LLM 状态管理": "K59bf8ed9",
|
||||
"正常": "Ke039b9b5",
|
||||
"停用": "Kedd64e4d",
|
||||
"异常": "K23a3bd72",
|
||||
"启用": "K52c8a730",
|
||||
"已配置": "K66a7d24c",
|
||||
"未配置": "Kaf074220",
|
||||
"默认": "Kd9a46c29",
|
||||
"AI 模型管理": "K7ac2be34",
|
||||
"配置好 AI 模型后,你可以使用对应的大模型来创建 AI 服务": "K2260837a",
|
||||
"同步最新模型": "K18dccc1a",
|
||||
"默认:": "K2a3aeb8d",
|
||||
"从 (0) 获取 API KEY": "Kb3e34847",
|
||||
"待审核": "K35612f29",
|
||||
"已审核": "K47eaafde",
|
||||
"发布申请": "K56b4254f",
|
||||
@@ -437,6 +467,27 @@
|
||||
"了解 APIPark 如何更好地管理 API 和 AI": "K1afaf20e",
|
||||
"了解更多功能": "K48f7e21f",
|
||||
"隐藏该教程": "K698296e2",
|
||||
"请输入 APIKey": "K8b88ef63",
|
||||
"API Key": "Kcbd30819",
|
||||
"请填写 APIKey": "Kcb6e2d3e",
|
||||
"永不过期": "K9dfa2c97",
|
||||
"设置过期时间": "Ke13e332a",
|
||||
"请选择过期时间": "K409aa8ba",
|
||||
"超额": "Kba69594c",
|
||||
"过期": "Kb9e7ceda",
|
||||
"错误": "Kac405b50",
|
||||
"请选择状态": "K3fde5b49",
|
||||
"编辑 APIKey": "K434b7e76",
|
||||
"删除成功": "K28190dbc",
|
||||
"停用成功": "Kb5fcf5b8",
|
||||
"启用成功": "K5940d788",
|
||||
"排序成功": "K8743bccd",
|
||||
"编辑": "Kad207008",
|
||||
"调用优先级": "K19590c2c",
|
||||
"APIKey 资源池": "Kefb03657",
|
||||
"支持单个 API 模型供应商下创建多个 APIKey APIKey 进行智能负载均衡": "Kc0352e64",
|
||||
"请输入名称搜索": "Kd25acba1",
|
||||
"添加 APIKey": "K6d0388a0",
|
||||
"请输入账号": "Kf076f63c",
|
||||
"账号": "K80a560a1",
|
||||
"请输入密码": "K25c895d5",
|
||||
@@ -460,7 +511,6 @@
|
||||
"加入部门": "Ke6f00b44",
|
||||
"确定删除成员?此操作无法恢复,确认操作?": "K501cb1e7",
|
||||
"成员与部门": "Kf20863b5",
|
||||
"启用": "K52c8a730",
|
||||
"禁用": "K718c9310",
|
||||
"输入用户名、邮箱查找成员": "K5f27a546",
|
||||
"移出当前部门": "K7c97c5df",
|
||||
@@ -473,10 +523,13 @@
|
||||
"成员": "K74aef1ad",
|
||||
"设置成员和对应的角色,成员只能够看到权限范围内的功能和数据。": "K3f1077c9",
|
||||
"搜索部门": "Kdce62a6",
|
||||
"操作成功,即将刷新页面": "K9ada4366",
|
||||
"数据源类型": "Ka46b9b24",
|
||||
"数据源地址": "Kbb0cdcd0",
|
||||
"Organization": "Kd9dfb884",
|
||||
"鉴权 Token": "K3e770a75",
|
||||
"请求前缀": "K9b332ab1",
|
||||
"HTTP 头部": "K3d78d483",
|
||||
"密钥": "K8ef69ee2",
|
||||
"上传密钥": "Kba3507d6",
|
||||
"密钥文件的后缀名一般为 .key 的文件内容": "K93ac0f23",
|
||||
@@ -490,7 +543,6 @@
|
||||
"集群": "Ke93d36ed",
|
||||
"修改配置": "K877985b7",
|
||||
"设置访问 API 的集群,让 API 在分布式环境中稳定运行,并且能够根据业务需求进行灵活扩展和优化。": "Kdf66a675",
|
||||
"异常": "K23a3bd72",
|
||||
"私有网络": "Ke1b1865",
|
||||
"公共网络": "K4786c57c",
|
||||
"管理地址": "Kf12b3034",
|
||||
@@ -501,14 +553,19 @@
|
||||
"数据源": "K8fa58214",
|
||||
"设置监控报表的数据来源,设置完成之后即可获得详细的API调用统计图表。": "Kdbafd6f9",
|
||||
"统计图表": "K1358acf",
|
||||
"数据日志": "K17dc3a62",
|
||||
"地址(IP:端口)": "K62dabdf6",
|
||||
"组织(Organization)": "K2db12335",
|
||||
"添加策略": "K34d0d409",
|
||||
"输入名称、筛选条件查找": "Kbb4298ac",
|
||||
"处理日志": "Ke429194e",
|
||||
"脱敏前": "K8c34c02f",
|
||||
"脱敏后": "K8e3d388d",
|
||||
"编辑策略": "Kc82b8374",
|
||||
"策略类型": "K4b34a5e5",
|
||||
"匹配条件": "K57f0fee8",
|
||||
"数据脱敏规则": "K10650c58",
|
||||
"输入调用地址、消费者IP和消费者条件查找": "K84ffb1dd",
|
||||
"配置脱敏规则": "K1b34a9ab",
|
||||
"匹配值": "K26d22405",
|
||||
"脱敏类型": "K1546e1fe",
|
||||
@@ -520,7 +577,6 @@
|
||||
"脱敏规则": "K4cd91d61",
|
||||
"自定义字符串; 值:": "K8dcad979",
|
||||
"起始位置:(0)位;长度:(1)位": "K82e3f7b7",
|
||||
"编辑": "Kad207008",
|
||||
"已选择(0)项(1)数据": "K49dfc123",
|
||||
"所有(0)": "K8457ea34",
|
||||
"属性名称": "K7ca9a795",
|
||||
@@ -543,13 +599,9 @@
|
||||
"请求协议": "K6bc47edb",
|
||||
"请求方式": "K1365fe45",
|
||||
"转发规则设置": "K90f3c02f",
|
||||
"拦截": "Kb7df6ac1",
|
||||
"放行": "K5c1722fe",
|
||||
"路由详情": "K28435c5c",
|
||||
"只允许上传PNG、JPG或SVG格式的图片": "Ka9c08390",
|
||||
"服务名称": "K413b9869",
|
||||
"服务类型": "K9919285b",
|
||||
"AI 服务": "Kd2c34e2c",
|
||||
"REST 服务": "K62840d62",
|
||||
"默认 AI 供应商": "Kcef64f4d",
|
||||
"创建 API 时会默认选择该供应商,修改默认供应商不会影响现有 API": "K300c89d4",
|
||||
@@ -604,8 +656,6 @@
|
||||
"选择API": "Kcc8265e1",
|
||||
"路径": "Kc380335f",
|
||||
"请输入请求路径进行搜索": "K8aefc1e4",
|
||||
"重置": "K50d471b2",
|
||||
"查询": "Kee8ae330",
|
||||
"导出": "Ka2c794a2",
|
||||
"退出全屏": "Kaf70c3b",
|
||||
"(0)调用详情": "Kd22841a4",
|
||||
@@ -695,7 +745,6 @@
|
||||
"修改": "K9cbe1e0",
|
||||
"访问授权": "Kb6e9328f",
|
||||
"添加授权": "Kd23d1716",
|
||||
"永不过期": "K9dfa2c97",
|
||||
"到期时间": "Kfa920c0",
|
||||
"订阅的服务": "Kcce1af60",
|
||||
"审核详情": "Kfefa9b58",
|
||||
@@ -710,7 +759,6 @@
|
||||
"创建并管理自己的消费者实体,每个消费者可以订阅多个API服务,确保在调用之前已获得相应权限。你可以为消费者生成 API 密钥等鉴权方式,用于安全地调用 API 服务": "K5c4e2865",
|
||||
"订阅的服务数量:已通过 (0) 个,申请中 (1) 个": "K3c7b175f",
|
||||
"输入名称、ID 查找消费者": "K3a6f905d",
|
||||
"退出测试": "Kbe3e9335",
|
||||
"服务市场": "K370a3eb2",
|
||||
"服务详情": "Kf7ec36d",
|
||||
"申请服务": "K58ca9485",
|
||||
|
||||
@@ -704,64 +704,105 @@
|
||||
"Kbdec9fa": "Filter Criteria",
|
||||
"Kbcbb7391": "Processed Count",
|
||||
"Kad207008": "Edit",
|
||||
"K630c9e6d": "APIPark",
|
||||
"Ka3e9f580": "Release Name",
|
||||
"Kb2480682": "Policy List",
|
||||
"K118d8d74": "Data Format",
|
||||
"Kfe7c7d2d": "Keyword",
|
||||
"K2f57a694": "Regular Expression",
|
||||
"K8953e0a6": "Mobile Number",
|
||||
"K6f86a038": "ID Card Number",
|
||||
"K7954e7c8": "Bank Card Number",
|
||||
"K320fdb17": "Amount",
|
||||
"K7867acda": "Date",
|
||||
"K7d327ae8": "Partial Display",
|
||||
"Kfbf38e3c": "Partial Masking",
|
||||
"Kd8c1fbb0": "Truncate",
|
||||
"K89829921": "Replace",
|
||||
"K480a7165": "Shuffle",
|
||||
"Kea0d69df": "Random String",
|
||||
"Ke7c84d1d": "Custom String",
|
||||
"K49731763": "Please enter IP address or CIDR range, each separated by a newline.",
|
||||
"K83237c89": "The entered IP or CIDR does not meet the format.",
|
||||
"K5ae2c87a": "Please enter the correct path, such as /usr/* or */usr/*.",
|
||||
"Kc82b8374": "Edit Policy",
|
||||
"K4b34a5e5": "Policy Type",
|
||||
"K57f0fee8": "Match Conditions",
|
||||
"K10650c58": "Data Masking Rules",
|
||||
"K1b34a9ab": "Configure Masking Rules",
|
||||
"K26d22405": "Match Value",
|
||||
"K1546e1fe": "Masking Type",
|
||||
"K9b9b0629": "Starting Position",
|
||||
"K52c84fe1": "Length",
|
||||
"Kde84409c": "Replace Type",
|
||||
"K338653b4": "Replace Value",
|
||||
"Kbaeed3b7": "JSON Path",
|
||||
"K4cd91d61": "Masking Rules",
|
||||
"K8dcad979": "Custom String; Value:",
|
||||
"K82e3f7b7": "Starting Position: (0); Length: (1)",
|
||||
"K49dfc123": "Selected (0) items (1) data",
|
||||
"K8457ea34": "All (0)",
|
||||
"K7ca9a795": "Attribute Name",
|
||||
"Kc4391744": "Attribute Value",
|
||||
"K678e13fc": "Configure (0)",
|
||||
"K508d8bf4": "Integration Address",
|
||||
"K67f4e9bb": "The domain name for obtaining API market documentation information when integrating with external platforms",
|
||||
"K1da86266": "Invalid",
|
||||
"K3a34d49b": "Pending Update",
|
||||
"Kd2850420": "Pending Deletion",
|
||||
"K9ada4366": "Operation successful, the page will refresh shortly",
|
||||
"K9b332ab1": "Request prefix",
|
||||
"K3d78d483": "HTTP headers",
|
||||
"K17dc3a62": "Data logs",
|
||||
"Ke429194e": "Processing logs",
|
||||
"K84ffb1dd": "Enter the invocation address, consumer IP, and consumer condition to search",
|
||||
"Kb147fabc": "Create",
|
||||
"K40ca4f2": "Update",
|
||||
"K3e7aa0ad": "Content",
|
||||
"K2f5fdf5e": "Call Address",
|
||||
"K1bc5e0a3": "Consumer IP",
|
||||
"K6f39ea21": "Authentication Name",
|
||||
"K8c34c02f": "Before Masking",
|
||||
"K8e3d388d": "After Masking"
|
||||
"K630c9e6d": "APIPark",
|
||||
"Ka3e9f580": "Release Name",
|
||||
"Kb2480682": "Policy List",
|
||||
"K118d8d74": "Data Format",
|
||||
"Kfe7c7d2d": "Keyword",
|
||||
"K2f57a694": "Regular Expression",
|
||||
"K8953e0a6": "Mobile Number",
|
||||
"K6f86a038": "ID Card Number",
|
||||
"K7954e7c8": "Bank Card Number",
|
||||
"K320fdb17": "Amount",
|
||||
"K7867acda": "Date",
|
||||
"K7d327ae8": "Partial Display",
|
||||
"Kfbf38e3c": "Partial Masking",
|
||||
"Kd8c1fbb0": "Truncate",
|
||||
"K89829921": "Replace",
|
||||
"K480a7165": "Shuffle",
|
||||
"Kea0d69df": "Random String",
|
||||
"Ke7c84d1d": "Custom String",
|
||||
"K49731763": "Please enter IP address or CIDR range, each separated by a newline.",
|
||||
"K83237c89": "The entered IP or CIDR does not meet the format.",
|
||||
"K5ae2c87a": "Please enter the correct path, such as /usr/* or */usr/*.",
|
||||
"Kc82b8374": "Edit Policy",
|
||||
"K4b34a5e5": "Policy Type",
|
||||
"K57f0fee8": "Match Conditions",
|
||||
"K10650c58": "Data Masking Rules",
|
||||
"K1b34a9ab": "Configure Masking Rules",
|
||||
"K26d22405": "Match Value",
|
||||
"K1546e1fe": "Masking Type",
|
||||
"K9b9b0629": "Starting Position",
|
||||
"K52c84fe1": "Length",
|
||||
"Kde84409c": "Replace Type",
|
||||
"K338653b4": "Replace Value",
|
||||
"Kbaeed3b7": "JSON Path",
|
||||
"K4cd91d61": "Masking Rules",
|
||||
"K8dcad979": "Custom String; Value:",
|
||||
"K82e3f7b7": "Starting Position: (0); Length: (1)",
|
||||
"K49dfc123": "Selected (0) items (1) data",
|
||||
"K8457ea34": "All (0)",
|
||||
"K7ca9a795": "Attribute Name",
|
||||
"Kc4391744": "Attribute Value",
|
||||
"K678e13fc": "Configure (0)",
|
||||
"K508d8bf4": "Integration Address",
|
||||
"K67f4e9bb": "The domain name for obtaining API market documentation information when integrating with external platforms",
|
||||
"K1da86266": "Invalid",
|
||||
"K3a34d49b": "Pending Update",
|
||||
"Kd2850420": "Pending Deletion",
|
||||
"K9ada4366": "Operation successful, the page will refresh shortly",
|
||||
"K9b332ab1": "Request prefix",
|
||||
"K3d78d483": "HTTP headers",
|
||||
"K17dc3a62": "Data logs",
|
||||
"Ke429194e": "Processing logs",
|
||||
"K84ffb1dd": "Enter the invocation address, consumer IP, and consumer condition to search",
|
||||
"Kb147fabc": "Create",
|
||||
"K40ca4f2": "Update",
|
||||
"K3e7aa0ad": "Content",
|
||||
"K2f5fdf5e": "Call Address",
|
||||
"K1bc5e0a3": "Consumer IP",
|
||||
"K6f39ea21": "Authentication Name",
|
||||
"K8c34c02f": "Before Masking",
|
||||
"K8e3d388d": "After Masking",
|
||||
"K94b48734": "Failed to get AI providers",
|
||||
"Kf23a8988": "AI Provider",
|
||||
"K4d81a657": "Preview",
|
||||
"K91144ebd": "AI API List",
|
||||
"Kf8187c33": "Please enter API URL to search",
|
||||
"Kee4139c2": "Intercept Interface",
|
||||
"K3e38ea": "After enabling interception, the gateway will intercept all requests on this path.",
|
||||
"Kd752a3a8": "AI Model Not Configured",
|
||||
"K8b7ac871": "Go to Settings",
|
||||
"Kf97448b3": "Configured",
|
||||
"K30d4d8df": "Not Configured",
|
||||
"Kc2ee5223": "Default Model",
|
||||
"K608af899": "Load Priority",
|
||||
"K65b7a96": "Load priority determines which provider to use first when the original provider is abnormal or disabled. The smaller the priority number, the higher the priority.",
|
||||
"K9eccff16": "Priority must be greater than 0",
|
||||
"Kfcf02780": "Please enter priority",
|
||||
"K5c6dcf58": "API Key (Default Key)",
|
||||
"K59bf8ed9": "LLM Status Management",
|
||||
"Kedd64e4d": "Disable",
|
||||
"K2a3aeb8d": "Default:",
|
||||
"K8b88ef63": "Please enter APIKey",
|
||||
"Kcbd30819": "API Key",
|
||||
"Kcb6e2d3e": "Please fill in APIKey",
|
||||
"Ke13e332a": "Set expiration time",
|
||||
"K409aa8ba": "Please select expiration time",
|
||||
"Kba69594c": "Overage",
|
||||
"Kb9e7ceda": "Expired",
|
||||
"Kac405b50": "Error",
|
||||
"K3fde5b49": "Please select status",
|
||||
"K434b7e76": "Edit APIKey",
|
||||
"K28190dbc": "Deleted successfully",
|
||||
"Kb5fcf5b8": "Disabled successfully",
|
||||
"K5940d788": "Enabled successfully",
|
||||
"K8743bccd": "Sorted successfully",
|
||||
"K19590c2c": "Call Priority",
|
||||
"K89f135a7": "Used Token",
|
||||
"K1acc30b2": "Edit Time",
|
||||
"Kefb03657": "APIKey Resource Pool",
|
||||
"Kc0352e64": "Supports creating multiple APIKeys under a single API model provider for intelligent load balancing",
|
||||
"Kd25acba1": "Please enter name to search",
|
||||
"K6d0388a0": "Add APIKey"
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,6 @@
|
||||
"K630c9e6d": "APIPark",
|
||||
"Ka3e9f580": "发布名称",
|
||||
"Kb2480682": "策略列表",
|
||||
"K1da86266": "无效",
|
||||
"K76036e25": "HTTP 请求头",
|
||||
"K44607e3f": "全等匹配",
|
||||
"Kc287500a": "前缀匹配",
|
||||
|
||||
@@ -6,11 +6,18 @@
|
||||
"Kecbb0e45": "System",
|
||||
"Ka358e23d": "General",
|
||||
"K449058e9": "API Gateway",
|
||||
"K99935e6f": "AI Model",
|
||||
"K1deaa2dd": "User",
|
||||
"K631d646f": "Open API",
|
||||
"K1196b104": "APIPark",
|
||||
"Kf1b166e7": "Details",
|
||||
"K7ac2be34": "AI Model Management",
|
||||
"K18dccc1a": "Sync Latest Model",
|
||||
"K5cfdd950": "This data cannot be recovered after deletion. Are you sure you want to delete?",
|
||||
"K28435c5c": "API Details",
|
||||
"Kb9052305": "Search Username, Email",
|
||||
"K40a89bd8": "Enter Name, ID to Search Member"
|
||||
"Kbe3e9335": "Exit Test",
|
||||
"K40a89bd8": "Enter Name, ID to Search Member",
|
||||
"K1da86266": "Invalid",
|
||||
"Kb147fabc": "Create",
|
||||
"K40ca4f2": "Update"
|
||||
}
|
||||
@@ -7,16 +7,19 @@
|
||||
"Kecbb0e45": "システム",
|
||||
"Ka358e23d": "一般",
|
||||
"K449058e9": "API ゲートウェイ",
|
||||
"K99935e6f": "AI モデル",
|
||||
"K1deaa2dd": "ユーザー",
|
||||
"K631d646f": "Open API",
|
||||
"K1196b104": "APIPark",
|
||||
"Kffd7e274": "無審査:すべてのアプリケーションがこのサービスにサブスクライブできます",
|
||||
"K8a8b13e4": "手動審査:承認されたアプリケーションのみがこのサービスにサブスクライブできます",
|
||||
"Kf1b166e7": "詳細",
|
||||
"K7ac2be34": "AI モデル管理",
|
||||
"K18dccc1a": "最新モデルを同期",
|
||||
"K9bdd8403": "API を安全に呼び出すためには、アプリケーションとトークンを作成する必要があります。",
|
||||
"Kc8239422": "チームにはユーザー、アプリケーション、サービスが含まれ、異なるチームのアプリケーションとサービスのデータは分離されています。企業内の部門/プロジェクトグループ/チームの管理に使用できます。",
|
||||
"Ka0a8840a": "他のアプリケーションのサブスクリプション申請をレビューし、承認後に API リクエストが発行できます。",
|
||||
"K5cfdd950": "このデータを削除すると、復元できません。削除しますか?",
|
||||
"K28435c5c": "API 詳細",
|
||||
"Kb9052305": "ユーザー名またはメールを検索",
|
||||
"K5ece3bac": "チームとメンバーを設定してから、チーム内でサービスとアプリケーションを作成し、API をサブスクライブできます。メンバーは所属チーム内のサービスとアプリケーションのみを表示できます。",
|
||||
"K1512e983": "アプリケーション呼び出し統計",
|
||||
@@ -28,11 +31,15 @@
|
||||
"K546e46f": "Application ID",
|
||||
"K95764d1d": "Application を削除",
|
||||
"K667bbbe7": "Application を追加",
|
||||
"Kbe3e9335": "テスト終了",
|
||||
"K8723422e": "アプリケーションを接続",
|
||||
"K93d5a66e": "接続アプリケーション数",
|
||||
"K216a1ac7": "アプリケーション開発者",
|
||||
"K27924db": "アプリケーション管理者",
|
||||
"Kd55c6887": "レビュー",
|
||||
"K831aa6c0": "申請元-アプリケーション",
|
||||
"K40a89bd8": "名前または ID を入力してサービスを検索"
|
||||
"K40a89bd8": "名前または ID を入力してサービスを検索",
|
||||
"K1da86266": "無効",
|
||||
"Kb147fabc": "新規作成",
|
||||
"K40ca4f2": "更新"
|
||||
}
|
||||
@@ -7,16 +7,19 @@
|
||||
"Kecbb0e45": "系统",
|
||||
"Ka358e23d": "常规",
|
||||
"K449058e9": "API 网关",
|
||||
"K99935e6f": "AI 模型",
|
||||
"K1deaa2dd": "用户",
|
||||
"K631d646f": "Open API",
|
||||
"K1196b104": "APIPark",
|
||||
"Kffd7e274": "无审核:允许所有消费者订阅该服务",
|
||||
"K8a8b13e4": "人工审核:仅允许审核通过的消费者订阅该服务",
|
||||
"Kf1b166e7": "详情",
|
||||
"K7ac2be34": "AI 模型管理",
|
||||
"K18dccc1a": "同步最新模型",
|
||||
"K9bdd8403": "为了安全地调用 API,你需要创建一个消费者以及Token。",
|
||||
"Kc8239422": "团队中包含了人员、消费者和服务,不同团队之间的消费者和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。",
|
||||
"Ka0a8840a": "审核其他消费者的订阅申请,审核通过后的才可发起 API 请求。",
|
||||
"K5cfdd950": "该数据删除后将无法找回,是否删除?",
|
||||
"K28435c5c": "API 详情",
|
||||
"Kb9052305": "搜索用户名、邮箱",
|
||||
"K5ece3bac": "设置团队和成员,然后你可以在团队内创建服务和消费者、订阅API,成员只能看到所属团队内的服务和消费者。",
|
||||
"K1512e983": "消费者调用统计",
|
||||
@@ -28,11 +31,14 @@
|
||||
"K546e46f": "消费者 ID",
|
||||
"K95764d1d": "删除消费者",
|
||||
"K667bbbe7": "添加消费者",
|
||||
"Kbe3e9335": "退出测试",
|
||||
"K8723422e": "接入消费者",
|
||||
"K93d5a66e": "接入消费者数量",
|
||||
"K216a1ac7": "消费者开发者",
|
||||
"K27924db": "消费者管理员",
|
||||
"Kd55c6887": "审核",
|
||||
"K831aa6c0": "申请方-消费者",
|
||||
"K40a89bd8": "输入名称、ID 查找服务"
|
||||
"K40a89bd8": "输入名称、ID 查找服务",
|
||||
"Kb147fabc": "新建",
|
||||
"K40ca4f2": "更新"
|
||||
}
|
||||
@@ -7,16 +7,19 @@
|
||||
"Kecbb0e45": "系統",
|
||||
"Ka358e23d": "常規",
|
||||
"K449058e9": "API 網關",
|
||||
"K99935e6f": "AI 模型",
|
||||
"K1deaa2dd": "用戶",
|
||||
"K631d646f": "Open API",
|
||||
"K1196b104": "APIPark",
|
||||
"Kffd7e274": "無審核:允許所有應用程式訂閱該服務",
|
||||
"K8a8b13e4": "人工審核:僅允許審核通過的應用程式訂閱該服務",
|
||||
"Kf1b166e7": "詳情",
|
||||
"K7ac2be34": "AI 模型管理",
|
||||
"K18dccc1a": "同步最新模型",
|
||||
"K9bdd8403": "為了安全地調用 API,你需要創建一個應用以及Token。",
|
||||
"Kc8239422": "團隊中包含了人員、應用程式和服務,不同團隊之間的應用程式和服務數據是隔離的,可用於管理企業內部不同的部門/項目組/團隊。",
|
||||
"Ka0a8840a": "審核其他應用程式的訂閱申請,審核通過後的才可發起 API 請求。",
|
||||
"K5cfdd950": "該數據刪除後將無法找回,是否刪除?",
|
||||
"K28435c5c": "API 詳情",
|
||||
"Kb9052305": "搜索用戶名、電郵",
|
||||
"K5ece3bac": "設置團隊和成員,然後你可以在團隊內創建服務和應用程式、訂閱API,成員只能看到所屬團隊內的服務和應用程式。",
|
||||
"K1512e983": "應用程式調用統計",
|
||||
@@ -28,11 +31,15 @@
|
||||
"K546e46f": "應用程式 ID",
|
||||
"K95764d1d": "刪除應用程式",
|
||||
"K667bbbe7": "添加應用程式",
|
||||
"Kbe3e9335": "退出測試",
|
||||
"K8723422e": "接入應用程式",
|
||||
"K93d5a66e": "接入應用程式數量",
|
||||
"K216a1ac7": "應用程式開發者",
|
||||
"K27924db": "應用程式管理員",
|
||||
"Kd55c6887": "審核",
|
||||
"K831aa6c0": "申請方-應用程式",
|
||||
"K40a89bd8": "輸入名稱、ID 查找服務"
|
||||
"K40a89bd8": "輸入名稱、ID 查找服務",
|
||||
"K1da86266": "無效",
|
||||
"Kb147fabc": "新建",
|
||||
"K40ca4f2": "更新"
|
||||
}
|
||||
@@ -716,5 +716,46 @@
|
||||
"K1bc5e0a3": "消费者 IP",
|
||||
"K6f39ea21": "鉴权名称",
|
||||
"K8c34c02f": "脱敏前",
|
||||
"K8e3d388d": "脱敏后"
|
||||
}
|
||||
"K8e3d388d": "脱敏后",
|
||||
"K94b48734": "获取 AI providers 失败",
|
||||
"Kf23a8988": "AI 供应商",
|
||||
"K4d81a657": "预览",
|
||||
"K91144ebd": "AI API 列表",
|
||||
"Kf8187c33": "请输入 APIURL 搜索",
|
||||
"Kee4139c2": "拦截接口",
|
||||
"K3e38ea": "开启拦截后,网关会拦截所有该路径的请求。",
|
||||
"Kd752a3a8": "未配置 AI 模型",
|
||||
"K8b7ac871": "前往设置",
|
||||
"Kf97448b3": "已设置",
|
||||
"K30d4d8df": "未设置",
|
||||
"Kc2ee5223": "默认模型",
|
||||
"K608af899": "负载优先级",
|
||||
"K65b7a96": "负载优先级决定在原供应商异常或停用后,优先使用哪一个供应商。优先级数字越小,优先级越高。",
|
||||
"K9eccff16": "优先级必须大于 0",
|
||||
"Kfcf02780": "请输入优先级",
|
||||
"K5c6dcf58": "API Key(默认 Key)",
|
||||
"K59bf8ed9": "LLM 状态管理",
|
||||
"Kedd64e4d": "停用",
|
||||
"K2a3aeb8d": "默认:",
|
||||
"K8b88ef63": "请输入 APIKey",
|
||||
"Kcbd30819": "API Key",
|
||||
"Kcb6e2d3e": "请填写 APIKey",
|
||||
"Ke13e332a": "设置过期时间",
|
||||
"K409aa8ba": "请选择过期时间",
|
||||
"Kba69594c": "超额",
|
||||
"Kb9e7ceda": "过期",
|
||||
"Kac405b50": "错误",
|
||||
"K3fde5b49": "请选择状态",
|
||||
"K434b7e76": "编辑 APIKey",
|
||||
"K28190dbc": "删除成功",
|
||||
"Kb5fcf5b8": "停用成功",
|
||||
"K5940d788": "启用成功",
|
||||
"K8743bccd": "排序成功",
|
||||
"K19590c2c": "调用优先级",
|
||||
"K89f135a7": "已用 Token",
|
||||
"K1acc30b2": "编辑时间",
|
||||
"Kefb03657": "APIKey 资源池",
|
||||
"Kc0352e64": "支持单个 API 模型供应商下创建多个 APIKey APIKey 进行智能负载均衡",
|
||||
"Kd25acba1": "请输入名称搜索",
|
||||
"K6d0388a0": "添加 APIKey"
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,11 +17,11 @@
|
||||
|
||||
import G6, { EdgeConfig } from '@antv/g6'
|
||||
import {
|
||||
SELF_SPACE_CONTENT_COLOR,
|
||||
OUT_SPACE_CONTENT_COLOR,
|
||||
OUT_SPACE_THEME,
|
||||
RELATIVE_PICTURE_NODE_FONTSIZE,
|
||||
SELF_SPACE_THEME,
|
||||
OUT_SPACE_THEME
|
||||
SELF_SPACE_CONTENT_COLOR,
|
||||
SELF_SPACE_THEME
|
||||
} from '@core/const/system-running/const'
|
||||
import { NodeData } from '@core/const/system-running/type'
|
||||
import { TopologyProjectItem, TopologyServiceItem } from '@core/pages/systemRunning/SystemRunning'
|
||||
@@ -144,131 +144,6 @@ export const getNodeSpacing = (num: number, nodes?: unknown) => {
|
||||
return result
|
||||
}
|
||||
|
||||
// const registerEdge = () => {
|
||||
// G6.registerEdge(
|
||||
// 'line-running',
|
||||
// {
|
||||
// options: {
|
||||
// style: EDGE_STYLE
|
||||
// },
|
||||
|
||||
// afterDraw: (cfg, group) => {
|
||||
// const lineDash = [4, 2, 1, 2]
|
||||
// if (!group) return
|
||||
// const shape = group.get('children')[0]
|
||||
// let index = 0
|
||||
// // Define the animation
|
||||
// shape.animate(
|
||||
// () => {
|
||||
// index = index + 0.4
|
||||
// if (index > 1000) {
|
||||
// index = 0
|
||||
// }
|
||||
// const res = {
|
||||
// lineDash,
|
||||
// lineDashOffset: -index
|
||||
// }
|
||||
// return res
|
||||
// },
|
||||
// {
|
||||
// repeat: true,
|
||||
// duration: 5000
|
||||
// }
|
||||
// )
|
||||
// },
|
||||
|
||||
// setState: (name, value, item) => {
|
||||
// if (!item || !name) return
|
||||
// const shape = item.get('keyShape')
|
||||
// const itemStatus = item.getStates()
|
||||
|
||||
// if (
|
||||
// !['edge-success', 'edge-error', 'edge-transparent'].includes(name) &&
|
||||
// itemStatus.some((state) => ['edge-error', 'edge-success', 'edge-transparent'].includes(state))
|
||||
// )
|
||||
// return
|
||||
// const theme = item?._cfg?.model?.style?.stroke || SELF_SPACE_THEME
|
||||
// if (name === 'running') {
|
||||
// if (value) {
|
||||
// shape.attr({
|
||||
// lineWidth: 4,
|
||||
// shadowColor: theme,
|
||||
// shadowBlur: 2
|
||||
// })
|
||||
// } else {
|
||||
// shape.attr(EDGE_STYLE)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// 'quadratic'
|
||||
// )
|
||||
// }
|
||||
|
||||
// private initGraph = (container: ElementRef) => {
|
||||
// const element = container.nativeElement
|
||||
// this.graph = new G6.Graph({
|
||||
// container: container.nativeElement,
|
||||
// plugins: [this.tooltip],
|
||||
// layout: {
|
||||
// type: 'force',
|
||||
// // 稳定系数,初始动画的加载时长(稳定性)=节点数量/稳定系数
|
||||
// alphaDecay: 0.08,
|
||||
// // 因为有分组的存在,整体布局需要往左偏移一点
|
||||
// center: [element.scrollWidth / 2 - 150, element.scrollHeight / 2],
|
||||
// preventOverlap: true,
|
||||
// linkDistance: (d: nodeAny) => {
|
||||
// if (d.source.id === 'node0') {
|
||||
// return 100
|
||||
// }
|
||||
// return 30
|
||||
// },
|
||||
// nodeStrength: (d: nodeAny) => {
|
||||
// if (d.isLeaf) {
|
||||
// return -50
|
||||
// }
|
||||
// return -10
|
||||
// },
|
||||
// edgeStrength: (d: nodeAny) => {
|
||||
// if (d.source.id === 'node1' || d.source.id === 'node2' || d.source.id === 'node3') {
|
||||
// return 0.7
|
||||
// }
|
||||
// return 0.1
|
||||
// }
|
||||
// },
|
||||
// modes: {
|
||||
// default: ['drag-canvas', 'drag-node', 'zoom-canvas']
|
||||
// },
|
||||
// defaultNode: {
|
||||
// size: [24, 24],
|
||||
// style: {
|
||||
// radius: 5,
|
||||
// stroke: '#69c0ff',
|
||||
// lineWidth: 1,
|
||||
// fillOpacity: 1
|
||||
// },
|
||||
// labelCfg: {
|
||||
// style: {
|
||||
// fontSize: RELATIVE_PICTURE_NODE_FONTSIZE,
|
||||
// fill: this.textColor
|
||||
// },
|
||||
// position: 'bottom',
|
||||
// offset: 12
|
||||
// }
|
||||
// },
|
||||
// defaultEdge: {
|
||||
// type: 'line-running',
|
||||
// label: $t('详情',
|
||||
// labelCfg: {
|
||||
// style: {
|
||||
// fill: '5B8FF9',
|
||||
// opacity: 0
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
export class UnionFind {
|
||||
private parent: Record<string, string>
|
||||
private rank: Record<string, number>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { STATUS_CODE } from '@common/const/const'
|
||||
import { useFetch } from '@common/hooks/http'
|
||||
import { $t } from '@common/locales'
|
||||
import { ModelDetailData } from '@core/pages/aiSetting/types'
|
||||
import { Select, Space, message } from 'antd'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
@@ -52,10 +53,10 @@ const AIProviderSelect: React.FC<AIProviderSelectProps> = ({ value, onChange, st
|
||||
const selectedProvider: AIProvider = value ? providers.find((p) => p.id === value) : providers[0]
|
||||
onChange?.(selectedProvider.id, selectedProvider)
|
||||
} else {
|
||||
message.error(msg || t('Failed to fetch AI providers'))
|
||||
message.error(msg || t('获取 AI providers 失败'))
|
||||
}
|
||||
} catch (error) {
|
||||
message.error(t('Failed to fetch AI providers'))
|
||||
message.error(t('获取 AI providers 失败'))
|
||||
} finally {
|
||||
isMounted && setLoading(false)
|
||||
}
|
||||
@@ -70,7 +71,7 @@ const AIProviderSelect: React.FC<AIProviderSelectProps> = ({ value, onChange, st
|
||||
|
||||
return (
|
||||
<Space className="flex items-center">
|
||||
<span>{t('AI 供应商')}:</span>
|
||||
<span>{$t('AI 供应商')}:</span>
|
||||
<Select
|
||||
value={value}
|
||||
onChange={(selectedValue) => {
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
import { Codebox } from '@common/components/postcat/api/Codebox'
|
||||
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
|
||||
import { useFetch } from '@common/hooks/http'
|
||||
import { $t } from '@common/locales'
|
||||
import { AIProvider } from '@core/components/AIProviderSelect'
|
||||
import { App, DatePicker, Form, Input, Switch } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import React, { forwardRef, useEffect, useImperativeHandle, useState } from 'react'
|
||||
import { EditAPIKey } from '../types'
|
||||
|
||||
interface ApiKeyContentProps {
|
||||
provider?: AIProvider
|
||||
entity: EditAPIKey
|
||||
}
|
||||
|
||||
const ApiKeyContent: React.FC<ApiKeyContentProps> = forwardRef(({ provider, entity }, ref) => {
|
||||
const [form] = Form.useForm()
|
||||
const [neverExpire, setNeverExpire] = useState(true)
|
||||
const { fetchData } = useFetch()
|
||||
const { message } = App.useApp()
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
const isNeverExpire = entity.expire_time === 0
|
||||
setNeverExpire(isNeverExpire)
|
||||
form.setFieldsValue({
|
||||
name: entity.name,
|
||||
expire_time: isNeverExpire ? undefined : dayjs(entity.expire_time),
|
||||
config: entity.config
|
||||
})
|
||||
} catch (e) {
|
||||
form.setFieldsValue({
|
||||
name: entity.name,
|
||||
expire_time: undefined,
|
||||
config: ''
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
const values = await form.validateFields()
|
||||
const { expire_time, ...restValues } = values
|
||||
const expireTime = neverExpire ? 0 : expire_time.valueOf()
|
||||
|
||||
const response = await fetchData<BasicResponse<null>>('ai/resource/key', {
|
||||
method: entity.id ? 'PUT' : 'POST',
|
||||
eoParams: { provider: provider?.id, id: entity.id },
|
||||
eoBody: { ...restValues, expire_time: expireTime },
|
||||
eoTransformKeys: ['config']
|
||||
})
|
||||
|
||||
const { code, msg } = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
message.success(msg || $t(RESPONSE_TIPS.success))
|
||||
return true
|
||||
} else {
|
||||
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||
return false
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Validation failed:', error)
|
||||
}
|
||||
}
|
||||
useImperativeHandle(ref, () => ({
|
||||
handleOk
|
||||
}))
|
||||
const handleNeverExpireChange = (checked: boolean) => {
|
||||
setNeverExpire(checked)
|
||||
if (!checked) {
|
||||
form.setFieldsValue({
|
||||
expire_time: dayjs().add(7, 'days')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Form form={form} layout="vertical">
|
||||
<Form.Item name="name" label={$t('名称')} rules={[{ required: true, message: $t('请输入 APIKey') }]}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item label={$t('API Key')} name="config" rules={[{ required: true, message: $t('请填写 APIKey') }]}>
|
||||
<Codebox
|
||||
editorTheme="vs-dark"
|
||||
readOnly={false}
|
||||
width="100%"
|
||||
height="150px"
|
||||
language="json"
|
||||
enableToolbar={false}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label={$t('过期时间')} name="neverExpire" valuePropName="checked">
|
||||
<div className="flex items-center">
|
||||
<Switch onChange={handleNeverExpireChange} checked={neverExpire} />
|
||||
<span className="ml-2">{neverExpire ? $t('永不过期') : $t('设置过期时间')}</span>
|
||||
</div>
|
||||
</Form.Item>
|
||||
{!neverExpire && (
|
||||
<Form.Item
|
||||
name="expire_time"
|
||||
label={$t('过期时间')}
|
||||
rules={[{ required: true, message: $t('请选择过期时间') }]}
|
||||
>
|
||||
<DatePicker style={{ width: '100%' }} showTime />
|
||||
</Form.Item>
|
||||
)}
|
||||
</Form>
|
||||
)
|
||||
})
|
||||
|
||||
export default ApiKeyContent
|
||||
@@ -1,40 +0,0 @@
|
||||
import { $t } from '@common/locales'
|
||||
import { Select, Space, theme } from 'antd'
|
||||
import React from 'react'
|
||||
|
||||
interface StatusFilterProps {
|
||||
value: string[]
|
||||
onChange: (value: string[]) => void
|
||||
}
|
||||
|
||||
const StatusFilter: React.FC<StatusFilterProps> = ({ value, onChange }) => {
|
||||
const { token } = theme.useToken()
|
||||
|
||||
const options = [
|
||||
{ label: $t('Normal'), value: 'normal', color: token.colorSuccess },
|
||||
{ label: $t('Exceeded'), value: 'exceeded', color: token.colorError },
|
||||
{ label: $t('Expired'), value: 'expired', color: token.colorWarning },
|
||||
{ label: $t('Disabled'), value: 'disabled', color: token.colorTextDisabled },
|
||||
{ label: $t('Error'), value: 'error', color: token.colorError }
|
||||
]
|
||||
|
||||
return (
|
||||
<Space>
|
||||
<span>{$t('Status')}:</span>
|
||||
<Select
|
||||
mode="multiple"
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
style={{ width: 300 }}
|
||||
placeholder={$t('Filter by status')}
|
||||
allowClear
|
||||
options={options.map((option) => ({
|
||||
...option,
|
||||
label: <span style={{ color: option.color }}>{option.label}</span>
|
||||
}))}
|
||||
/>
|
||||
</Space>
|
||||
)
|
||||
}
|
||||
|
||||
export default StatusFilter
|
||||
@@ -12,7 +12,7 @@ import { Alert, App, Button, Typography } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import { useNavigate, useSearchParams } from 'react-router-dom'
|
||||
import { APIKey } from './types'
|
||||
import { APIs } from './types'
|
||||
|
||||
const ApiSettings: React.FC = () => {
|
||||
const pageListRef = useRef<ActionType>(null)
|
||||
@@ -35,6 +35,9 @@ const ApiSettings: React.FC = () => {
|
||||
pageListRef.current?.reload()
|
||||
}, [selectedProvider])
|
||||
|
||||
const handlePreview = (record: APIs) => {
|
||||
navigate(`service/${record.team.id}/aiInside/${record.service.id}/route/${record.id}`)
|
||||
}
|
||||
const requestApis = async (params: any) => {
|
||||
if (!selectedProvider) return
|
||||
setQueryBtnLoading(true)
|
||||
@@ -52,7 +55,7 @@ const ApiSettings: React.FC = () => {
|
||||
eoParams.start = startTime
|
||||
eoParams.end = endTime
|
||||
}
|
||||
const response = await fetchData<BasicResponse<{ data: APIKey[] }>>('ai/apis', {
|
||||
const response = await fetchData<BasicResponse<{ data: APIs[] }>>('ai/apis', {
|
||||
method: 'GET',
|
||||
eoParams
|
||||
})
|
||||
@@ -81,28 +84,28 @@ const ApiSettings: React.FC = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const operation: PageProColumns<APIKey>[] = [
|
||||
const operation: PageProColumns<APIs>[] = [
|
||||
{
|
||||
title: '',
|
||||
key: 'option',
|
||||
btnNums: 4,
|
||||
fixed: 'right',
|
||||
valueType: 'option',
|
||||
render: (_: React.ReactNode, entity: APIKey) => [
|
||||
render: (_: React.ReactNode, entity: APIs) => [
|
||||
<TableBtnWithPermission
|
||||
access="system.settings.ai_key_resource.manager"
|
||||
key="edit"
|
||||
btnType="edit"
|
||||
// onClick={() => handleEdit(entity)}
|
||||
btnTitle={$t('编辑')}
|
||||
access="team.service.router.view"
|
||||
key="preview"
|
||||
btnType="view"
|
||||
onClick={() => handlePreview(entity)}
|
||||
btnTitle={$t('预览')}
|
||||
/>
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
const columns: PageProColumns<APIKey>[] = [
|
||||
const columns: PageProColumns<APIs>[] = [
|
||||
{
|
||||
title: 'AI 服务',
|
||||
title: $t('AI 服务'),
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 180
|
||||
@@ -112,10 +115,16 @@ const ApiSettings: React.FC = () => {
|
||||
dataIndex: 'request_path',
|
||||
key: 'request_path',
|
||||
width: 200,
|
||||
ellipsis: true
|
||||
ellipsis: true,
|
||||
render: (text: string, record: APIs) => (
|
||||
<p>
|
||||
<Typography.Text type="success">{record.method}</Typography.Text>
|
||||
<span className="ml-1">{text}</span>
|
||||
</p>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: '模型',
|
||||
title: $t('模型'),
|
||||
dataIndex: ['model', 'name'],
|
||||
key: 'model',
|
||||
width: 150,
|
||||
@@ -125,14 +134,14 @@ const ApiSettings: React.FC = () => {
|
||||
valueEnum: {}
|
||||
},
|
||||
{
|
||||
title: '已用 Token',
|
||||
title: $t('已用 Token'),
|
||||
dataIndex: 'use_token',
|
||||
key: 'use_token',
|
||||
width: 120,
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '是否放行',
|
||||
title: $t('是否放行'),
|
||||
dataIndex: 'disabled',
|
||||
ellipsis: true,
|
||||
filters: true,
|
||||
@@ -144,7 +153,7 @@ const ApiSettings: React.FC = () => {
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '编辑时间',
|
||||
title: $t('编辑时间'),
|
||||
dataIndex: 'update_time',
|
||||
key: 'update_time',
|
||||
width: 200,
|
||||
@@ -165,22 +174,26 @@ const ApiSettings: React.FC = () => {
|
||||
|
||||
const renderProviderBanner = () => {
|
||||
if (!provider) return null
|
||||
|
||||
console.log(provider)
|
||||
if (provider.status === 'disabled' || provider.status === 'abnormal') {
|
||||
const message =
|
||||
provider.status === 'disabled'
|
||||
? $t(`当前供应商异常,以下API均临时调用 ${provider.backupName} 下的 ${provider.backupModel} 模型能力。`)
|
||||
: $t(`当前供应商异常,以下API均临时调用 ${provider.backupName} 下的 ${provider.backupModel} 模型能力。`)
|
||||
|
||||
const type = provider.status === 'disabled' ? 'warning' : 'error'
|
||||
return (
|
||||
<Alert
|
||||
message={message}
|
||||
type="warning"
|
||||
type={type}
|
||||
className="my-4"
|
||||
showIcon
|
||||
action={
|
||||
<Button size="small" type="link" onClick={() => navigate('/aisetting')}>
|
||||
<Button
|
||||
size="small"
|
||||
type="link"
|
||||
onClick={() => {
|
||||
navigate('/aisetting')
|
||||
}}
|
||||
>
|
||||
{$t('查看详情')}
|
||||
</Button>
|
||||
}
|
||||
@@ -192,7 +205,7 @@ const ApiSettings: React.FC = () => {
|
||||
|
||||
return (
|
||||
<InsidePage
|
||||
className="overflow-y-auto gap-4 pb-PAGE_INSIDE_B pr-PAGE_INSIDE_X"
|
||||
className="overflow-y-auto gap-4 pb-PAGE_INSIDE_B"
|
||||
pageTitle={$t('AI API 列表')}
|
||||
description={
|
||||
<>
|
||||
@@ -211,7 +224,7 @@ const ApiSettings: React.FC = () => {
|
||||
showBorder={false}
|
||||
scrollPage={false}
|
||||
>
|
||||
<div className="h-[calc(100%-1rem-36px)]">
|
||||
<div className="h-[calc(100%-1rem-36px)] pr-PAGE_INSIDE_X">
|
||||
<PageList
|
||||
ref={pageListRef}
|
||||
rowKey="id"
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
|
||||
|
||||
export interface APIKey extends EditAPIKey {
|
||||
status: 'normal' | 'exceeded' | 'expired' | 'disabled' | 'error'
|
||||
use_token: number
|
||||
update_time: string
|
||||
can_delete: boolean
|
||||
priority: number
|
||||
}
|
||||
|
||||
export interface EditAPIKey {
|
||||
id?: string
|
||||
name: string
|
||||
config: string
|
||||
expire_time: number
|
||||
}
|
||||
export interface APIs {
|
||||
id: string;
|
||||
name: string;
|
||||
service: {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
team:{
|
||||
id: string;
|
||||
name: string;
|
||||
},
|
||||
method: string;
|
||||
request_path: string;
|
||||
model: string;
|
||||
disabled: boolean;
|
||||
update_time: string;
|
||||
use_token: number;
|
||||
}
|
||||
@@ -25,7 +25,7 @@ const ApiKeyContent: React.FC<ApiKeyContentProps> = forwardRef(({ provider, enti
|
||||
setNeverExpire(isNeverExpire)
|
||||
form.setFieldsValue({
|
||||
name: entity.name,
|
||||
expire_time: isNeverExpire ? undefined : dayjs(entity.expire_time),
|
||||
expire_time: isNeverExpire ? undefined : dayjs(entity.expire_time * 1000),
|
||||
config: entity.config
|
||||
})
|
||||
} catch (e) {
|
||||
@@ -41,7 +41,7 @@ const ApiKeyContent: React.FC<ApiKeyContentProps> = forwardRef(({ provider, enti
|
||||
try {
|
||||
const values = await form.validateFields()
|
||||
const { expire_time, ...restValues } = values
|
||||
const expireTime = neverExpire ? 0 : expire_time.valueOf()
|
||||
const expireTime = neverExpire ? 0 : Math.trunc(expire_time.valueOf() / 1000)
|
||||
|
||||
const response = await fetchData<BasicResponse<null>>('ai/resource/key', {
|
||||
method: entity.id ? 'PUT' : 'POST',
|
||||
|
||||
@@ -11,22 +11,22 @@ const StatusFilter: React.FC<StatusFilterProps> = ({ value, onChange }) => {
|
||||
const { token } = theme.useToken()
|
||||
|
||||
const options = [
|
||||
{ label: $t('Normal'), value: 'normal', color: token.colorSuccess },
|
||||
{ label: $t('Exceeded'), value: 'exceeded', color: token.colorError },
|
||||
{ label: $t('Expired'), value: 'expired', color: token.colorWarning },
|
||||
{ label: $t('Disabled'), value: 'disabled', color: token.colorTextDisabled },
|
||||
{ label: $t('Error'), value: 'error', color: token.colorError }
|
||||
{ label: $t('正常'), value: 'normal', color: token.colorSuccess },
|
||||
{ label: $t('超额'), value: 'exceeded', color: token.colorError },
|
||||
{ label: $t('过期'), value: 'expired', color: token.colorWarning },
|
||||
{ label: $t('停用'), value: 'disabled', color: token.colorTextDisabled },
|
||||
{ label: $t('错误'), value: 'error', color: token.colorError }
|
||||
]
|
||||
|
||||
return (
|
||||
<Space>
|
||||
<span>{$t('Status')}:</span>
|
||||
<span>{$t('状态')}:</span>
|
||||
<Select
|
||||
mode="multiple"
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
style={{ width: 300 }}
|
||||
placeholder={$t('Filter by status')}
|
||||
placeholder={$t('请选择状态')}
|
||||
allowClear
|
||||
options={options.map((option) => ({
|
||||
...option,
|
||||
|
||||
Reference in New Issue
Block a user