M1.1 收尾: - 24项 P0/P1/P2 bug 修复 (Rust 107 tests + Flutter 15 tests) - Flutter App v0.3: cupertino_icons 修复, 单元测试, 调试面板, APK 52.6MB - 示例插件完善: manifest.json + 请求/响应示范 + 7个测试 - API 文档重写 (以 routes.rs 为唯一权威) - MILESTONES.md 更新至 100% M1.2 启动: - P0: 插件管理 API 闭环 (handle_manager_message Custom 分支 + broadcast_plugin_states) - ServiceManager 集成测试 8/8 (tests/m1_2_service_manager.rs) - M1.2 测试计划 (docs/M1.2_TEST_PLAN.md, 18个E2E场景) - 动态插件系统: auto_rollback + version_manager GC + 路径穿越防护 总计: Rust 115/115 测试, Flutter 15/15 测试, 零 warning Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
25 KiB
25 KiB
ShowenV2 HTTP API
基础信息
- Base URL:
http://<device-ip>:8080 - API 前缀:
/api - 编码:
UTF-8 - 认证: 当前版本局域网无认证,后续版本预留
- 权威实现:
src/plugins/http/routes.rs
响应约定
成功响应
写操作接口统一返回:
{
"status": "ok",
"message": "开始播放"
}
错误响应
除文件下载接口外,错误统一返回:
{
"status": "error",
"message": "错误描述"
}
查询接口直接返回业务 JSON,不包裹 status 字段。
典型错误码
400 Bad Request: 参数、JSON、文件名或配置内容非法403 Forbidden: 文件管理路径越界或目标目录不合法404 Not Found: 文件、目录、插件或配置不存在409 Conflict: 文件移动目标已存在413 Payload Too Large: 单文件超过 100 MB500 Internal Server Error: 内部发送消息失败、文件操作失败502 Bad Gateway: WiFi 插件返回无效 JSON504 Gateway Timeout: 等待 WiFi 插件响应超时
Web UI
GET /
- Method:
GET - Path:
/ - Request Body: 无
- Response Example:
<!doctype html>
<html lang="zh-CN">
<head><title>Showen 控制台</title></head>
<body>...</body>
</html>
- Error Response: 标准 HTTP 错误页面,无 JSON 包装
GET /index.html
- Method:
GET - Path:
/index.html - Request Body: 无
- Response Example:
<!doctype html>
<html lang="zh-CN">
<head><title>Showen 控制台</title></head>
<body>...</body>
</html>
- Error Response: 标准 HTTP 错误页面,无 JSON 包装
WebSocket
GET /ws
- Method:
GET(Upgrade to WebSocket) - Path:
/ws - Request Body: 无
- Response Example: 连接建立后服务端会先推送当前快照,再持续推送事件
- Error Response: WebSocket 握手失败时返回标准 HTTP 错误
服务端事件
status_update
{
"type": "status_update",
"data": {
"running": true,
"paused": false,
"in_transition": false,
"current_index": 0,
"playlist_length": 3,
"current_video": "intro"
}
}
state_update
{
"type": "state_update",
"data": {
"old_state": "rest",
"new_state": "interact"
}
}
config_update
{
"type": "config_update",
"data": {
"display": {
"fullscreen": true,
"window_title": "Hologram Player - Cat",
"rotation": 0,
"flip_horizontal": true,
"flip_vertical": true,
"offset_x": 0,
"offset_y": 0,
"prevent_screen_lock": true,
"render_width": 1280,
"render_height": 800,
"output_width": null,
"output_height": null,
"scale_mode": "stretch",
"allow_upscale": true,
"perspective_correction": {
"enabled": false,
"points": [[0, 0], [1280, 0], [1280, 800], [0, 800]]
},
"chroma_key": {
"enabled": false,
"hsv_min": [0, 0, 200],
"hsv_max": [180, 30, 255],
"invert": false,
"feather": 3
},
"brightness_adjust": {
"enabled": true,
"subject_boost": 1.5,
"background_suppress": 0.3,
"threshold": 30
}
},
"playlist": [
{
"id": "anim_0",
"path": "videos/intro.mp4",
"duration": null,
"loop_count": 1,
"random_loop_range": null
}
],
"transition": {
"enabled": true,
"type": "fade",
"duration": 0.5
},
"playback": {
"loop_playlist": true,
"auto_start": true
},
"scenes": {
"rest": [],
"active": [],
"sleep": [],
"interact": [],
"state_machine": null
},
"remote_control": {
"enabled": true,
"host": "0.0.0.0",
"port": 8080
},
"ble": {
"enabled": true,
"device_name": "Showen"
},
"source_path": "/home/showen/Showen/ShowenV2/configs/cat_state_machine.json",
"source_dir": "/home/showen/Showen/ShowenV2/configs"
}
}
wifi_update
{
"type": "wifi_update",
"data": {
"ok": true,
"networks": [
{
"ssid": "OfficeWiFi",
"signal": 78,
"security": "WPA2"
}
]
}
}
说明:该事件直接转发 WiFi 插件返回的 JSON,字段随具体命令而变。
ble_update
{
"type": "ble_update",
"data": {
"ready": true
}
}
客户端可发送命令
WebSocket 文本消息需为 JSON;成功响应格式不是 HTTP API 的 { "status": "ok" },而是 WebSocket 专用格式:
{
"ok": true,
"cmd": "play"
}
错误示例:
{
"ok": false,
"cmd": "goto",
"error": "missing index"
}
已支持命令示例:
{"cmd":"play"}
{"cmd":"pause"}
{"cmd":"next"}
{"cmd":"previous"}
{"cmd":"goto","index":3}
{"cmd":"scene","name":"rest"}
{"cmd":"trigger","name":"voice","value":"name"}
{"cmd":"connect","ssid":"OfficeWiFi","password":"secret"}
{"cmd":"ap_start","ssid":"showen","password":"12345678"}
播放控制
GET /api/status
- Method:
GET - Path:
/api/status - Request Body: 无
- Response Example:
{
"running": true,
"paused": false,
"in_transition": false,
"current_index": 0,
"playlist_length": 3,
"current_video": "intro"
}
- Error Response:
404/405由路由层处理;无业务级错误 JSON
POST /api/play
- Method:
POST - Path:
/api/play - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "开始播放"
}
- Error Response:
{ "status": "error", "message": "发送命令失败: ..." }
POST /api/pause
- Method:
POST - Path:
/api/pause - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "已暂停"
}
- Error Response:
{ "status": "error", "message": "发送命令失败: ..." }
POST /api/next
- Method:
POST - Path:
/api/next - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "切换到下一个视频"
}
- Error Response:
{ "status": "error", "message": "发送命令失败: ..." }
POST /api/previous
- Method:
POST - Path:
/api/previous - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "切换到上一个视频"
}
- Error Response:
{ "status": "error", "message": "发送命令失败: ..." }
POST /api/goto/:index
- Method:
POST - Path:
/api/goto/:index - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "跳转到视频 2"
}
- Error Response:
{ "status": "error", "message": "无效的视频索引" }或{ "status": "error", "message": "发送命令失败: ..." }
GET /api/playlist
- Method:
GET - Path:
/api/playlist - Request Body: 无
- Response Example:
{
"playlist": [
{
"id": "anim_0",
"path": "videos/intro.mp4",
"duration": null,
"loop_count": 1,
"random_loop_range": null
},
{
"id": "anim_1",
"path": "videos/idle.mp4",
"duration": 12.5,
"loop_count": 2,
"random_loop_range": null
}
],
"current_index": 0
}
- Error Response:
404/405由路由层处理;无业务级错误 JSON
POST /api/scene/:name
- Method:
POST - Path:
/api/scene/:name - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "切换到场景: rest"
}
- Error Response:
{ "status": "error", "message": "发送命令失败: ..." }
POST /api/trigger/:name
- Method:
POST - Path:
/api/trigger/:name - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "触发器 'voice' 已发送"
}
- Error Response:
{ "status": "error", "message": "发送命令失败: ..." }
POST /api/trigger/:name/:value
- Method:
POST - Path:
/api/trigger/:name/:value - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "触发器 'voice' 已发送,值: name"
}
- Error Response:
{ "status": "error", "message": "发送命令失败: ..." }
配置管理
GET /api/config
- Method:
GET - Path:
/api/config - Request Body: 无
- Response Example:
{
"display": {
"fullscreen": true,
"window_title": "Hologram Player - Cat",
"rotation": 0,
"flip_horizontal": true,
"flip_vertical": true,
"offset_x": 0,
"offset_y": 0,
"prevent_screen_lock": true,
"render_width": 1280,
"render_height": 800,
"output_width": null,
"output_height": null,
"scale_mode": "stretch",
"allow_upscale": true,
"perspective_correction": {
"enabled": false,
"points": [[0, 0], [1280, 0], [1280, 800], [0, 800]]
},
"chroma_key": {
"enabled": false,
"hsv_min": [0, 0, 200],
"hsv_max": [180, 30, 255],
"invert": false,
"feather": 3
},
"brightness_adjust": {
"enabled": true,
"subject_boost": 1.5,
"background_suppress": 0.3,
"threshold": 30
}
},
"playlist": [
{
"id": "anim_0",
"path": "videos/intro.mp4",
"duration": null,
"loop_count": 1,
"random_loop_range": null
}
],
"transition": {
"enabled": true,
"type": "fade",
"duration": 0.5
},
"playback": {
"loop_playlist": true,
"auto_start": true
},
"scenes": {
"rest": [],
"active": [],
"sleep": [],
"interact": [],
"state_machine": null
},
"remote_control": {
"enabled": true,
"host": "0.0.0.0",
"port": 8080
},
"ble": {
"enabled": true,
"device_name": "Showen"
},
"source_path": "/home/showen/Showen/ShowenV2/configs/cat_state_machine.json",
"source_dir": "/home/showen/Showen/ShowenV2/configs"
}
- Error Response:
404/405由路由层处理;无业务级错误 JSON
GET /api/config/display
- Method:
GET - Path:
/api/config/display - Request Body: 无
- Response Example:
{
"fullscreen": true,
"window_title": "Hologram Player - Cat",
"rotation": 0,
"flip_horizontal": true,
"flip_vertical": true,
"offset_x": 0,
"offset_y": 0,
"prevent_screen_lock": true,
"render_width": 1280,
"render_height": 800,
"output_width": null,
"output_height": null,
"scale_mode": "stretch",
"allow_upscale": true,
"perspective_correction": {
"enabled": false,
"points": [[0, 0], [1280, 0], [1280, 800], [0, 800]]
},
"chroma_key": {
"enabled": false,
"hsv_min": [0, 0, 200],
"hsv_max": [180, 30, 255],
"invert": false,
"feather": 3
},
"brightness_adjust": {
"enabled": true,
"subject_boost": 1.5,
"background_suppress": 0.3,
"threshold": 30
}
}
- Error Response:
404/405由路由层处理;无业务级错误 JSON
POST /api/config
- Method:
POST - Path:
/api/config - Request Body Example:
{
"display": {
"fullscreen": true,
"window_title": "Showen",
"rotation": 0,
"flip_horizontal": false,
"flip_vertical": false,
"offset_x": 0,
"offset_y": 0,
"prevent_screen_lock": true,
"render_width": 1280,
"render_height": 800,
"output_width": null,
"output_height": null,
"scale_mode": "fit",
"allow_upscale": true,
"perspective_correction": {
"enabled": false,
"points": []
},
"chroma_key": {
"enabled": false,
"hsv_min": [0, 0, 200],
"hsv_max": [180, 30, 255],
"invert": false,
"feather": 0
},
"brightness_adjust": {
"enabled": false,
"subject_boost": 1.5,
"background_suppress": 0.3,
"threshold": 30
}
},
"playlist": [
{
"id": "intro",
"path": "videos/intro.mp4",
"duration": null,
"loop_count": 1,
"random_loop_range": null
}
],
"transition": {
"enabled": true,
"type": "fade",
"duration": 0.5
},
"playback": {
"loop_playlist": true,
"auto_start": true
},
"scenes": {
"rest": [],
"active": [],
"sleep": [],
"interact": [],
"state_machine": null
},
"remote_control": {
"enabled": true,
"host": "0.0.0.0",
"port": 8080
},
"ble": {
"enabled": true,
"device_name": "Showen"
}
}
- Response Example:
{
"status": "ok",
"message": "配置已保存,热重载将自动生效"
}
- Error Response:
{ "status": "error", "message": "请求体不是有效的 UTF-8" }、{ "status": "error", "message": "配置验证失败: ..." }、{ "status": "error", "message": "写入配置文件失败: ..." }
GET /api/config/available
- Method:
GET - Path:
/api/config/available - Request Body: 无
- Response Example:
{
"configs": [
"cat_state_machine.json",
"dog_state_machine.json"
],
"active": "cat_state_machine.json"
}
- Error Response:
404/405由路由层处理;无业务级错误 JSON
POST /api/config/switch
- Method:
POST - Path:
/api/config/switch - Request Body Example:
{
"filename": "dog_state_machine.json"
}
- Response Example:
{
"status": "ok",
"message": "已切换到配置: dog_state_machine.json"
}
- Error Response:
{ "status": "error", "message": "文件名不合法" }、{ "status": "error", "message": "只支持 .json 配置文件" }、{ "status": "error", "message": "配置文件不存在" }、{ "status": "error", "message": "配置验证失败: ..." }
视频管理
GET /api/videos
- Method:
GET - Path:
/api/videos - Request Body: 无
- Response Example:
[
{
"name": "intro.mp4",
"size": 1048576
},
{
"name": "subdir/idle.mp4",
"size": 2097152
}
]
- Error Response:
404/405由路由层处理;无业务级错误 JSON
POST /api/videos/upload
- Method:
POST - Path:
/api/videos/upload - Request Body Example:
multipart/form-data,一个或多个file字段 - Response Example:
{
"status": "ok",
"message": "已上传 2 个文件: intro.mp4, idle.mp4"
}
- Error Response:
{ "status": "error", "message": "未找到上传文件" }、{ "status": "error", "message": "文件大小超过限制: 单文件最大 100 MB" }、{ "status": "error", "message": "保存文件失败: ..." }
DELETE /api/videos/:filename
- Method:
DELETE - Path:
/api/videos/:filename - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "已删除: intro.mp4"
}
- Error Response:
{ "status": "error", "message": "无效的文件名" }、{ "status": "error", "message": "文件不存在" }、{ "status": "error", "message": "删除失败: ..." }
WiFi
GET /api/wifi/status
- Method:
GET - Path:
/api/wifi/status - Request Body: 无
- Response Example:
{
"connected": true,
"ssid": "OfficeWiFi",
"ip": "192.168.1.23"
}
- Error Response:
{ "status": "error", "message": "等待 WiFi 响应超时" }、{ "status": "error", "message": "WiFi 返回了无效 JSON: ..." }、{ "status": "error", "message": "WiFi 操作失败" }
GET /api/wifi/scan
- Method:
GET - Path:
/api/wifi/scan - Request Body: 无
- Response Example:
[
{
"ssid": "OfficeWiFi",
"signal": 78,
"security": "WPA2"
},
{
"ssid": "Guest",
"signal": 42,
"security": "open"
}
]
- Error Response:
{ "status": "error", "message": "等待 WiFi 响应超时" }、{ "status": "error", "message": "WiFi 返回了无效 JSON: ..." }
POST /api/wifi/scan
- Method:
POST - Path:
/api/wifi/scan - Request Body: 无
- Response Example:
[
{
"ssid": "OfficeWiFi",
"signal": 78,
"security": "WPA2"
}
]
- Error Response: 与
GET /api/wifi/scan相同
POST /api/wifi/connect
- Method:
POST - Path:
/api/wifi/connect - Request Body Example:
{
"ssid": "OfficeWiFi",
"password": "secret123"
}
- Response Example:
{
"status": "ok",
"message": "WiFi 连接成功: OfficeWiFi"
}
- Error Response:
{ "status": "error", "message": "等待 WiFi 响应超时" }、{ "status": "error", "message": "WiFi 操作失败" }
POST /api/wifi/ap/start
- Method:
POST - Path:
/api/wifi/ap/start - Request Body Example:
{
"ssid": "showen",
"password": "12345678"
}
- Response Example:
{
"status": "ok",
"message": "AP 热点已启动: SSID=showen"
}
- Error Response:
{ "status": "error", "message": "JSON 格式错误: ..." }、{ "status": "error", "message": "等待 WiFi 响应超时" }
说明:请求体可省略;默认 ssid=showen、password=12345678。
POST /api/wifi/hotspot/start
- Method:
POST - Path:
/api/wifi/hotspot/start - Request Body Example:
{
"ssid": "showen",
"password": "12345678"
}
- Response Example:
{
"status": "ok",
"message": "AP 热点已启动: SSID=showen"
}
- Error Response: 与
POST /api/wifi/ap/start相同
说明:这是 POST /api/wifi/ap/start 的兼容别名。
POST /api/wifi/ap/stop
- Method:
POST - Path:
/api/wifi/ap/stop - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "AP 热点已关闭"
}
- Error Response:
{ "status": "error", "message": "等待 WiFi 响应超时" }、{ "status": "error", "message": "WiFi 操作失败" }
POST /api/wifi/hotspot/stop
- Method:
POST - Path:
/api/wifi/hotspot/stop - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "AP 热点已关闭"
}
- Error Response: 与
POST /api/wifi/ap/stop相同
说明:这是 POST /api/wifi/ap/stop 的兼容别名。
BLE
POST /api/ble/start
- Method:
POST - Path:
/api/ble/start - Request Body Example:
{
"device_name": "Showen"
}
- Response Example:
{
"status": "ok",
"message": "BLE 配网服务已内嵌运行中,设备名: Showen"
}
- Error Response:
{ "status": "error", "message": "JSON 格式错误: ..." }
说明:请求体可省略;未传时使用当前配置中的 ble.device_name。
POST /api/ble/stop
- Method:
POST - Path:
/api/ble/stop - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "BLE 配网服务随主进程运行,无需手动停止"
}
- Error Response: 无业务级错误 JSON
GET /api/ble/status
- Method:
GET - Path:
/api/ble/status - Request Body: 无
- Response Example:
{
"running": true,
"embedded": true,
"device_name": "Showen"
}
- Error Response:
404/405由路由层处理;无业务级错误 JSON
App 下载
GET /api/app/info
- Method:
GET - Path:
/api/app/info - Request Body: 无
- Response Example:
{
"version": "0.1.0",
"apk_available": true,
"apk_size": 18432000,
"download_url": "/download/showen-app.apk"
}
- Error Response:
404/405由路由层处理;无业务级错误 JSON
GET /download/:filename
- Method:
GET - Path:
/download/:filename - Request Body: 无
- Response Example: 二进制附件下载,响应头包含:
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="showen-app.apk"
- Error Response Example:
HTTP 400/404/500
text/html; charset=utf-8
无效的文件名
说明:该接口错误响应不是 JSON。
插件管理
GET /api/plugins
- Method:
GET - Path:
/api/plugins - Request Body: 无
- Response Example:
[
{
"id": "wifi",
"info": {
"name": "WiFi Plugin",
"version": "0.1.0",
"description": "Manage WiFi via nmcli",
"platform": "LinuxArm64"
},
"is_dynamic": false,
"error_policy": "auto_rollback",
"error_count": 0,
"max_errors": 5,
"enabled": true,
"test_results": [
{
"capability": "wifi_scan",
"passed": true,
"message": "no test defined"
}
],
"capabilities": ["wifi_scan", "wifi_connect"],
"needs_rollback": false
}
]
- Error Response:
404/405由路由层处理;无业务级错误 JSON
GET /api/plugins/:id
- Method:
GET - Path:
/api/plugins/:id - Request Body: 无
- Response Example:
{
"id": "wifi",
"info": {
"name": "WiFi Plugin",
"version": "0.1.0",
"description": "Manage WiFi via nmcli",
"platform": "LinuxArm64"
},
"is_dynamic": false,
"error_policy": "auto_rollback",
"error_count": 0,
"max_errors": 5,
"enabled": true,
"test_results": [],
"capabilities": ["wifi_scan", "wifi_connect"],
"needs_rollback": false
}
- Error Response:
{ "status": "error", "message": "plugin 'wifi' not found" }
POST /api/plugins/:id/enable
- Method:
POST - Path:
/api/plugins/:id/enable - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "plugin_enable 命令已发送"
}
- Error Response:
{ "status": "error", "message": "发送失败: ..." }
POST /api/plugins/:id/disable
- Method:
POST - Path:
/api/plugins/:id/disable - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "plugin_disable 命令已发送"
}
- Error Response:
{ "status": "error", "message": "发送失败: ..." }
POST /api/plugins/:id/rollback
- Method:
POST - Path:
/api/plugins/:id/rollback - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "plugin_rollback 命令已发送"
}
- Error Response:
{ "status": "error", "message": "发送失败: ..." }
POST /api/plugins/:id/switch
- Method:
POST - Path:
/api/plugins/:id/switch - Request Body Example:
{
"version": "1.2.3"
}
- Response Example:
{
"status": "ok",
"message": "版本切换请求已发送: wifi -> v1.2.3"
}
- Error Response:
{ "status": "error", "message": "发送失败: ..." }
POST /api/plugins/install
- Method:
POST - Path:
/api/plugins/install - Request Body Example:
{
"id": "weather",
"version": "0.3.0"
}
- Response Example:
{
"status": "ok",
"message": "安装请求已发送: weather"
}
- Error Response:
{ "status": "error", "message": "发送失败: ..." }
说明:version 可省略,省略时请求体仍需提供 id。
POST /api/plugins/check-updates
- Method:
POST - Path:
/api/plugins/check-updates - Request Body: 无
- Response Example:
{
"status": "ok",
"message": "plugin_check_updates 命令已发送"
}
- Error Response:
{ "status": "error", "message": "发送失败: ..." }
文件管理
目录参数 :dir 仅支持:videos、configs、plugins。
GET /api/files/:dir
- Method:
GET - Path:
/api/files/:dir?path=<subdir> - Request Body: 无
- Response Example:
[
{
"name": "subdir",
"is_dir": true,
"size": 0
},
{
"name": "intro.mp4",
"is_dir": false,
"size": 1048576
}
]
- Error Response:
{ "status": "error", "message": "不支持的目录: logs(仅支持 videos/configs/plugins)" }、{ "status": "error", "message": "路径不合法" }、{ "status": "error", "message": "目录不存在" }
POST /api/files/:dir/upload
- Method:
POST - Path:
/api/files/:dir/upload?path=<subdir> - Request Body Example:
multipart/form-data,一个或多个file字段 - Response Example:
{
"status": "ok",
"message": "已上传 1 个文件: intro.mp4"
}
- Error Response:
{ "status": "error", "message": "不支持的目录" }、{ "status": "error", "message": "目标目录不合法" }、{ "status": "error", "message": "未找到上传文件" }、{ "status": "error", "message": "文件大小超过限制: 单文件最大 100 MB" }
GET /api/files/:dir/download
- Method:
GET - Path:
/api/files/:dir/download?path=<file> - Request Body: 无
- Response Example: 二进制附件下载,响应头包含:
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="intro.mp4"
- Error Response Example:
HTTP 400/403/404
text/html; charset=utf-8
缺少 path 参数
说明:该接口错误响应不是 JSON。
POST /api/files/:dir/delete
- Method:
POST - Path:
/api/files/:dir/delete - Request Body Example:
{
"path": "subdir/intro.mp4"
}
- Response Example:
{
"status": "ok",
"message": "已删除: subdir/intro.mp4"
}
- Error Response:
{ "status": "error", "message": "不支持的目录" }、{ "status": "error", "message": "缺少 path" }、{ "status": "error", "message": "路径不合法" }、{ "status": "error", "message": "文件不存在" }
POST /api/files/move
- Method:
POST - Path:
/api/files/move - Request Body Example:
{
"from_dir": "videos",
"from_path": "intro.mp4",
"to_dir": "videos",
"to_path": "archive/intro.mp4"
}
- Response Example:
{
"status": "ok",
"message": "已移动: intro.mp4 → archive/intro.mp4"
}
- Error Response:
{ "status": "error", "message": "源目录不支持" }、{ "status": "error", "message": "目标目录不支持" }、{ "status": "error", "message": "源路径不合法" }、{ "status": "error", "message": "目标路径已存在" }
POST /api/files/:dir/mkdir
- Method:
POST - Path:
/api/files/:dir/mkdir - Request Body Example:
{
"path": "archive"
}
- Response Example:
{
"status": "ok",
"message": "已创建目录: archive"
}
- Error Response:
{ "status": "error", "message": "不支持的目录" }、{ "status": "error", "message": "缺少 path" }、{ "status": "error", "message": "路径不合法" }、{ "status": "error", "message": "创建失败: ..." }
已移除的旧文档端点
以下端点当前实现中不存在,不应再使用:
/api/stop/api/wifi/disconnect