🐛 Bug: Fix the bug where the front-end sheet table can only display one key when there are multiple API keys.
Browse files
main.py
CHANGED
@@ -1051,7 +1051,7 @@ from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
|
|
1051 |
from fastapi.security import APIKeyHeader
|
1052 |
from typing import Optional, List
|
1053 |
|
1054 |
-
from xue import HTML, Head, Body, Div, xue_initialize, Script
|
1055 |
from xue.components.menubar import (
|
1056 |
Menubar, MenubarMenu, MenubarTrigger, MenubarContent,
|
1057 |
MenubarItem, MenubarSeparator
|
@@ -1069,7 +1069,6 @@ yaml = YAML()
|
|
1069 |
yaml.preserve_quotes = True
|
1070 |
yaml.indent(mapping=2, sequence=4, offset=2)
|
1071 |
|
1072 |
-
|
1073 |
frontend_router = APIRouter()
|
1074 |
|
1075 |
API_KEY_NAME = "X-API-Key"
|
@@ -1262,7 +1261,7 @@ async def get_columns_menu(menu_id: str, row_id: str):
|
|
1262 |
"hx-delete": f"/delete/{row_id}",
|
1263 |
"hx-target": "body",
|
1264 |
"hx-swap": "outerHTML",
|
1265 |
-
"hx-confirm": "
|
1266 |
},
|
1267 |
]
|
1268 |
result = dropdown.dropdown_menu_content(menu_id, columns).render()
|
@@ -1291,6 +1290,36 @@ async def add_model():
|
|
1291 |
new_model = model_config_row(new_model_id).render()
|
1292 |
return new_model
|
1293 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1294 |
@frontend_router.get("/edit-sheet/{row_id}", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
1295 |
async def get_edit_sheet(row_id: str, x_api_key: str = Depends(get_api_key)):
|
1296 |
row_data = get_row_data(row_id)
|
@@ -1305,6 +1334,10 @@ async def get_edit_sheet(row_id: str, x_api_key: str = Depends(get_api_key)):
|
|
1305 |
key, value = list(model.items())[0]
|
1306 |
model_list.append(model_config_row(f"model{index}", key, value, True))
|
1307 |
|
|
|
|
|
|
|
|
|
1308 |
sheet_id = "edit-sheet"
|
1309 |
edit_sheet_content = sheet.SheetContent(
|
1310 |
sheet.SheetHeader(
|
@@ -1316,7 +1349,19 @@ async def get_edit_sheet(row_id: str, x_api_key: str = Depends(get_api_key)):
|
|
1316 |
form.Form(
|
1317 |
form.FormField("Provider", "provider", value=row_data["provider"], placeholder="Enter provider name", required=True),
|
1318 |
form.FormField("Base URL", "base_url", value=row_data["base_url"], placeholder="Enter base URL", required=True),
|
1319 |
-
form.FormField("API Key", "api_key", value=row_data["api"], type="text", placeholder="Enter API key"),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1320 |
Div(
|
1321 |
Div("Models", class_="text-lg font-semibold mb-2"),
|
1322 |
Div(
|
@@ -1363,6 +1408,27 @@ async def get_edit_sheet(row_id: str, x_api_key: str = Depends(get_api_key)):
|
|
1363 |
).render()
|
1364 |
return result
|
1365 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1366 |
@frontend_router.get("/add-provider-sheet", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
1367 |
async def get_add_provider_sheet():
|
1368 |
sheet_id = "add-provider-sheet"
|
@@ -1427,11 +1493,10 @@ def update_row_data(row_id, updated_data):
|
|
1427 |
print(row_id, updated_data)
|
1428 |
index = int(row_id)
|
1429 |
app.state.config["providers"][index] = updated_data
|
1430 |
-
save_api_yaml()
|
1431 |
|
1432 |
def save_api_yaml():
|
1433 |
with open(API_YAML_PATH, "w", encoding="utf-8") as f:
|
1434 |
-
yaml.
|
1435 |
|
1436 |
@frontend_router.post("/submit/{row_id}", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
1437 |
async def submit_form(
|
@@ -1439,13 +1504,15 @@ async def submit_form(
|
|
1439 |
request: Request,
|
1440 |
provider: str = FastapiForm(...),
|
1441 |
base_url: str = FastapiForm(...),
|
1442 |
-
api_key: Optional[str] = FastapiForm(None),
|
1443 |
tools: Optional[str] = FastapiForm(None),
|
1444 |
notes: Optional[str] = FastapiForm(None),
|
1445 |
x_api_key: str = Depends(get_api_key)
|
1446 |
):
|
1447 |
form_data = await request.form()
|
1448 |
|
|
|
|
|
1449 |
# 收集模型数据
|
1450 |
models = []
|
1451 |
for key, value in form_data.items():
|
@@ -1462,7 +1529,7 @@ async def submit_form(
|
|
1462 |
updated_data = {
|
1463 |
"provider": provider,
|
1464 |
"base_url": base_url,
|
1465 |
-
"api":
|
1466 |
"model": models,
|
1467 |
"tools": tools == "on",
|
1468 |
"notes": notes,
|
|
|
1051 |
from fastapi.security import APIKeyHeader
|
1052 |
from typing import Optional, List
|
1053 |
|
1054 |
+
from xue import HTML, Head, Body, Div, xue_initialize, Script, Ul, Li
|
1055 |
from xue.components.menubar import (
|
1056 |
Menubar, MenubarMenu, MenubarTrigger, MenubarContent,
|
1057 |
MenubarItem, MenubarSeparator
|
|
|
1069 |
yaml.preserve_quotes = True
|
1070 |
yaml.indent(mapping=2, sequence=4, offset=2)
|
1071 |
|
|
|
1072 |
frontend_router = APIRouter()
|
1073 |
|
1074 |
API_KEY_NAME = "X-API-Key"
|
|
|
1261 |
"hx-delete": f"/delete/{row_id}",
|
1262 |
"hx-target": "body",
|
1263 |
"hx-swap": "outerHTML",
|
1264 |
+
"hx-confirm": "Are you sure you want to delete this configuration?"
|
1265 |
},
|
1266 |
]
|
1267 |
result = dropdown.dropdown_menu_content(menu_id, columns).render()
|
|
|
1290 |
new_model = model_config_row(new_model_id).render()
|
1291 |
return new_model
|
1292 |
|
1293 |
+
def render_api_keys(row_id, api_keys):
|
1294 |
+
return Ul(
|
1295 |
+
*[Li(
|
1296 |
+
Div(
|
1297 |
+
Div(
|
1298 |
+
input.input(
|
1299 |
+
type="text",
|
1300 |
+
placeholder="Enter API key",
|
1301 |
+
value=api_key,
|
1302 |
+
name=f"api_key_{i}",
|
1303 |
+
class_="flex-grow w-full"
|
1304 |
+
),
|
1305 |
+
class_="flex-grow"
|
1306 |
+
),
|
1307 |
+
button.button(
|
1308 |
+
"Delete",
|
1309 |
+
variant="outline",
|
1310 |
+
type="button",
|
1311 |
+
class_="ml-2",
|
1312 |
+
hx_delete=f"/delete-api-key/{row_id}/{i}",
|
1313 |
+
hx_target="#api-keys-container",
|
1314 |
+
hx_swap="outerHTML"
|
1315 |
+
),
|
1316 |
+
class_="flex items-center mb-2 w-full"
|
1317 |
+
)
|
1318 |
+
) for i, api_key in enumerate(api_keys)],
|
1319 |
+
id="api-keys-container",
|
1320 |
+
class_="space-y-2 w-full"
|
1321 |
+
)
|
1322 |
+
|
1323 |
@frontend_router.get("/edit-sheet/{row_id}", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
1324 |
async def get_edit_sheet(row_id: str, x_api_key: str = Depends(get_api_key)):
|
1325 |
row_data = get_row_data(row_id)
|
|
|
1334 |
key, value = list(model.items())[0]
|
1335 |
model_list.append(model_config_row(f"model{index}", key, value, True))
|
1336 |
|
1337 |
+
# 处理多个 API keys
|
1338 |
+
api_keys = row_data["api"] if isinstance(row_data["api"], list) else [row_data["api"]]
|
1339 |
+
api_key_inputs = render_api_keys(row_id, api_keys)
|
1340 |
+
|
1341 |
sheet_id = "edit-sheet"
|
1342 |
edit_sheet_content = sheet.SheetContent(
|
1343 |
sheet.SheetHeader(
|
|
|
1349 |
form.Form(
|
1350 |
form.FormField("Provider", "provider", value=row_data["provider"], placeholder="Enter provider name", required=True),
|
1351 |
form.FormField("Base URL", "base_url", value=row_data["base_url"], placeholder="Enter base URL", required=True),
|
1352 |
+
# form.FormField("API Key", "api_key", value=row_data["api"], type="text", placeholder="Enter API key"),
|
1353 |
+
Div(
|
1354 |
+
Div("API Keys", class_="text-lg font-semibold mb-2"),
|
1355 |
+
api_key_inputs,
|
1356 |
+
button.button(
|
1357 |
+
"Add API Key",
|
1358 |
+
class_="mt-2",
|
1359 |
+
hx_post=f"/add-api-key/{row_id}",
|
1360 |
+
hx_target="#api-keys-container",
|
1361 |
+
hx_swap="outerHTML"
|
1362 |
+
),
|
1363 |
+
class_="mb-4"
|
1364 |
+
),
|
1365 |
Div(
|
1366 |
Div("Models", class_="text-lg font-semibold mb-2"),
|
1367 |
Div(
|
|
|
1408 |
).render()
|
1409 |
return result
|
1410 |
|
1411 |
+
@frontend_router.post("/add-api-key/{row_id}", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
1412 |
+
async def add_api_key(row_id: str):
|
1413 |
+
row_data = get_row_data(row_id)
|
1414 |
+
api_keys = row_data["api"] if isinstance(row_data["api"], list) else [row_data["api"]]
|
1415 |
+
api_keys.append("") # 添加一个空的API key
|
1416 |
+
|
1417 |
+
api_key_inputs = render_api_keys(row_id, api_keys)
|
1418 |
+
|
1419 |
+
return api_key_inputs.render()
|
1420 |
+
|
1421 |
+
@frontend_router.delete("/delete-api-key/{row_id}/{index}", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
1422 |
+
async def delete_api_key(row_id: str, index: int):
|
1423 |
+
row_data = get_row_data(row_id)
|
1424 |
+
api_keys = row_data["api"] if isinstance(row_data["api"], list) else [row_data["api"]]
|
1425 |
+
if len(api_keys) > 1:
|
1426 |
+
del api_keys[index]
|
1427 |
+
|
1428 |
+
api_key_inputs = render_api_keys(row_id, api_keys)
|
1429 |
+
|
1430 |
+
return api_key_inputs.render()
|
1431 |
+
|
1432 |
@frontend_router.get("/add-provider-sheet", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
1433 |
async def get_add_provider_sheet():
|
1434 |
sheet_id = "add-provider-sheet"
|
|
|
1493 |
print(row_id, updated_data)
|
1494 |
index = int(row_id)
|
1495 |
app.state.config["providers"][index] = updated_data
|
|
|
1496 |
|
1497 |
def save_api_yaml():
|
1498 |
with open(API_YAML_PATH, "w", encoding="utf-8") as f:
|
1499 |
+
yaml.dump(app.state.config, f)
|
1500 |
|
1501 |
@frontend_router.post("/submit/{row_id}", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
1502 |
async def submit_form(
|
|
|
1504 |
request: Request,
|
1505 |
provider: str = FastapiForm(...),
|
1506 |
base_url: str = FastapiForm(...),
|
1507 |
+
# api_key: Optional[str] = FastapiForm(None),
|
1508 |
tools: Optional[str] = FastapiForm(None),
|
1509 |
notes: Optional[str] = FastapiForm(None),
|
1510 |
x_api_key: str = Depends(get_api_key)
|
1511 |
):
|
1512 |
form_data = await request.form()
|
1513 |
|
1514 |
+
api_keys = [value for key, value in form_data.items() if key.startswith("api_key_") and value]
|
1515 |
+
|
1516 |
# 收集模型数据
|
1517 |
models = []
|
1518 |
for key, value in form_data.items():
|
|
|
1529 |
updated_data = {
|
1530 |
"provider": provider,
|
1531 |
"base_url": base_url,
|
1532 |
+
"api": api_keys[0] if len(api_keys) == 1 else api_keys, # 如果只有一个 API key,就不使用列表
|
1533 |
"model": models,
|
1534 |
"tools": tools == "on",
|
1535 |
"notes": notes,
|