diff --git a/dashboards/g_force/index.html b/dashboards/g_force/index.html
new file mode 100644
index 0000000..ef7d2e4
--- /dev/null
+++ b/dashboards/g_force/index.html
@@ -0,0 +1,90 @@
+
+
+
+
+
+TurboSu - G力
+
+
+
+
+
+
+
diff --git a/dashboards/g_force/manifest.json b/dashboards/g_force/manifest.json
new file mode 100644
index 0000000..e0809c4
--- /dev/null
+++ b/dashboards/g_force/manifest.json
@@ -0,0 +1,14 @@
+{
+ "id": "g_force",
+ "name": "G 力圆图",
+ "category": "physics",
+ "description": "加速度向量实时可视化,圆心偏移表示纵向/横向G力方向和大小",
+ "author": "Yei.J. (AskaEth)",
+ "version": "1.0.0",
+ "supported_games": "all",
+ "config": {
+ "icon": "🎯",
+ "aspect_ratio": "1:1",
+ "render_mode": "contain"
+ }
+}
diff --git a/server/api.py b/server/api.py
index 9e59282..b9e2d2b 100644
--- a/server/api.py
+++ b/server/api.py
@@ -469,3 +469,23 @@ async def api_start_playback(data: dict):
async def api_stop_playback():
_get_player().stop()
return {"ok": True, "playing": False}
+
+
+@router.get("/recording/{filename}/export")
+async def api_export_recording(filename: str):
+ from fastapi.responses import FileResponse
+ from server.recorder import RECORDINGS_DIR
+ path = RECORDINGS_DIR / filename
+ if not path.exists():
+ raise HTTPException(404, "Recording not found")
+ return FileResponse(path, media_type="application/octet-stream", filename=filename)
+
+
+@router.post("/recording/import")
+async def api_import_recording(file: UploadFile = File(...)):
+ from server.recorder import RECORDINGS_DIR
+ if not file.filename or not file.filename.endswith('.tsr'):
+ raise HTTPException(400, "Only .tsr files are accepted")
+ dest = RECORDINGS_DIR / file.filename
+ dest.write_bytes(await file.read())
+ return {"ok": True}