From 3f0ec3bbf262e46a6875c83747bf409d9e340f6f Mon Sep 17 00:00:00 2001 From: root Date: Sat, 15 Aug 2026 18:17:28 +0800 Subject: [PATCH] =?utf8?q?fix:=20TTS=20=E6=94=AF=E6=8C=81=E5=90=AB?= =?utf8?q?=E6=96=9C=E6=9D=A0=E7=9F=AD=E8=AF=AD=20+=20=E6=8F=90=E4=BA=A4?= =?utf8?q?=E5=AD=A6=E4=B9=A0=E8=BF=9B=E5=BA=A6=20+=20=E4=BF=AE=E6=AD=A3=20?= =?utf8?q?gitignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 1. 后端 /api/tts 新增 ?w= 查询参数路由:词内字面 "/"(如 "in the/a form of")不再与 URL 路径分隔符冲突导致 404; 原 /api/tts/{word} 路径路由保留向后兼容。 2. 前端 ttsUrl 改为 /api/tts?w= 形式(api.js 一处改动覆盖 StudyMode/TestMode/离线预取所有调用点)。 3. SW 缓存规则改为匹配 /api/tts(无尾斜杠),保证新形式 音频仍走 cache-first,离线可用。 4. frontend/.gitignore 修正为 build-https/(原 frontend/build-https/ 无效),构建产物不再误入库。 5. 提交今日 iPad 离线学习进度(db/bcd.db)。 已验证端到端:含斜杠短语经 :8443 → :1060 均返回 200 音频。 --- backend/db/bcd.db | Bin 9461760 -> 9461760 bytes backend/main.py | 14 ++++++++++++-- frontend/.gitignore | 2 +- frontend/public/sw.js | 3 ++- frontend/src/api.js | 3 ++- 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/backend/db/bcd.db b/backend/db/bcd.db index fb865f0a7cfdccd74152fa291f359330b0131a53..ca3a2be4b0d82bf8187196f8c8869c7ee3ebc78f 100644 GIT binary patch delta 1595 zcmZwDTW}Lq9LMpVvm2ANw1BjUZ4eR^1hukfcaydWUMhl$mx8Ugax2;*)LS71MA{_H zHWne#Aj9ko!?O=O$uMJHb)3-|opA|$9>8X7!Gm}R52F{4U@HtLn6O|Yi4^+Kj{&5S z!8SaK$M86wz#yK)c07e0*omj{44%ar7Nr$>RLJb~iSg66nD5YILLQ$u zd355GvV`MVnx-gvmX;E8%`TQGcuL9?dC$@^M9#A`m6&Z`+S3v<3n{ByOIej4w`rH; zm0EDB5*8b@U4fPQU)rzQxcpcDOh2O;@(=Ah?F;#XmeacBb$R9bV0=>KBLUHskam3* z(=b!LMt`qLic&NnqI|wRmgoC?cR<7v()xcwPsM3e%tpoZREmv?YE&#wWiArP*LSyk zyW67R>!q51*dpJk7|VOvBIny>X@6VHHfFK>v)E#${>Q@QYz3dxE@wZT{6$NI;%;zv zb!%tq&el-)`*1nDC%h)~bI1+t4aK>zo59unPN2O-bgd8ZgcDYa?cNxzMm8p!r%c8T zmA34()i>biM5CVQwS(o(&Gj4hr_E&Av@?!II@U~E?uE0J$eq$EZL5qUeQDD@w!hlF z{1_^gP7Y)o;fpHw#_$~*D~_T1ofgtd^I47g?BxU$k_AM<63d0%7m_KAC#Z+Tj! zlc`KG=T7abcDlEQE34{bEeo-`ZDxwIzLu&nmM1#GOoqWbP@EyUbi0;Yzul<6@rW`T L=~{8LnhX2~Rn!d8 delta 692 zcmWmANmo*F0EY2%`ClMVp-FLyXdcW2DY7Id$|edMRVoDsET>c|DH0JRG%kuQxaagK z^t8BJUA6NQbWW}K1T9?pwD_%_cl9Q>cjP1rb&_GD-X|HhLYaURPnQDOQb2+Z0y6Y4 zz=#7d!HhDLqXHIKaS(@a7)Njvm8gOZ)u=%&>QIkku;Vx!IDwNmh0{2Lvp9$IxPXgj zz$G-|GMeCo3(auj3a-L~YiPlB+(0Y5xQRBjqXV7jf)BTF8{N2rySRt@cmO{h;t~FT z*MrA+f~RTK#sCHpLKs6B#t23c!5H4)Eygi{NlalH?=XW|%pr>R z_<)a?M+~3v8F75U0uoq65=%%Sjb&u;6BAB2)hxBvhE diff --git a/backend/main.py b/backend/main.py index 49f93c5..3c2c7c0 100644 --- a/backend/main.py +++ b/backend/main.py @@ -252,8 +252,7 @@ async def get_picture(pic_id: int): TTS_CACHE_DIR = os.path.join(BASE_DIR, "db", "tts_cache") os.makedirs(TTS_CACHE_DIR, exist_ok=True) -@app.get("/api/tts/{word}") -async def get_tts(word: str): +def _build_tts_response(word: str): word = word.strip() if not word: raise HTTPException(status_code=400, detail="empty word") @@ -304,6 +303,17 @@ async def get_tts(word: str): return Response(content=data, media_type="audio/mpeg") + +@app.get("/api/tts/{word}") +async def get_tts(word: str): + return _build_tts_response(word) + + +@app.get("/api/tts") +async def get_tts_query(w: str = ""): + # 含 / 的短语(如 "in the/a form of")走查询参数,避免与 URL 路径分隔符冲突 + return _build_tts_response(w) + @app.post("/api/progress/update") async def update_progress(data: ProgressUpdate): try: diff --git a/frontend/.gitignore b/frontend/.gitignore index bc2c3eb..ad91416 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -23,4 +23,4 @@ yarn-debug.log* yarn-error.log* # HTTPS 同源构建产物(由 REACT_APP_API_BASE="" BUILD_PATH=build-https 生成,不入库) -frontend/build-https/ +build-https/ diff --git a/frontend/public/sw.js b/frontend/public/sw.js index 4888e89..beef00e 100644 --- a/frontend/public/sw.js +++ b/frontend/public/sw.js @@ -31,7 +31,8 @@ self.addEventListener('fetch', (event) => { const path = url.pathname; // 图片与 TTS 音频: cache-first (含跨域, 后端已开 CORS) - if (path.startsWith('/api/picture/') || path.startsWith('/api/tts/')) { + // 注意 TTS 现用查询参数形式 /api/tts?w=,pathname 为 /api/tts(无尾斜杠),故不加尾斜杠匹配 + if (path.startsWith('/api/picture') || path.startsWith('/api/tts')) { event.respondWith(cacheFirst(req)); return; } diff --git a/frontend/src/api.js b/frontend/src/api.js index 0982fde..6e735fd 100644 --- a/frontend/src/api.js +++ b/frontend/src/api.js @@ -27,5 +27,6 @@ export const api = { }), // 图片与 TTS 走 /new Audio(),不走 axios;SW 仍能拦截缓存 pictureUrl: (picId) => `${API_BASE}/api/picture/${picId}`, - ttsUrl: (word) => `${API_BASE}/api/tts/${encodeURIComponent(word)}`, + // 走查询参数 w=,避免词内字面 "/"(如 "in the/a form of")与 URL 路径分隔符冲突导致 404 + ttsUrl: (word) => `${API_BASE}/api/tts?w=${encodeURIComponent(word)}`, }; -- 2.43.0