]> acesimba.cloud Git - words.git/commitdiff
feat(v2): 建立 v2 隔离分支基线 — /v2 路径部署、独立 DB(bcd_v2.db)、独立 IndexedDB/token/SW 作用域
authorroot <root@localhost.localdomain>
Thu, 20 Aug 2026 04:24:45 +0000 (12:24 +0800)
committerroot <root@localhost.localdomain>
Thu, 20 Aug 2026 04:24:45 +0000 (12:24 +0800)
.gitignore
backend/main.py
frontend/.env.production
frontend/src/App.js
frontend/src/api.js
frontend/src/auth.js
frontend/src/db.js
frontend/src/index.js

index aabb8b3d6a17d7bb0631102a48c5e12bc99ac6db..27c2004fc71968184024837b9e7d88a2bfe6649f 100644 (file)
@@ -20,3 +20,7 @@ backend/db/tts_cache/
 
 # certbot 一次性 DNS 挑战值(临时文件,不入库)
 deploy/dns-txt-value.txt
+
+# v2 隔离部署产物(不入库)
+frontend/build-v2/
+backend/db/bcd_v2.db
index 46463396c758f4ce482b2f3d840b090affd65cfd..346102ecd63e37d5d945a9194fd44926d4a2998e 100644 (file)
@@ -38,9 +38,12 @@ async def auth_guard(request: Request, call_next):
 
 # --- 路径自动修复逻辑 ---
 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
-DATABASE_PATH = os.path.join(BASE_DIR, "a", "bcd.db")
-if not os.path.exists(DATABASE_PATH):
-    DATABASE_PATH = os.path.join(BASE_DIR, "db", "bcd.db")
+# v2 等隔离部署可通过环境变量 WORDS_DB_PATH 指向独立数据库文件
+DATABASE_PATH = os.environ.get("WORDS_DB_PATH")
+if not DATABASE_PATH:
+    DATABASE_PATH = os.path.join(BASE_DIR, "a", "bcd.db")
+    if not os.path.exists(DATABASE_PATH):
+        DATABASE_PATH = os.path.join(BASE_DIR, "db", "bcd.db")
 
 # --- 简单登录鉴权(单用户;账密可用环境变量覆盖,默认 Simba / Simba+0322)---
 # 前端登录后持 token;所有 /api/*(除登录接口)必须带有效 token,否则 401。
index d72a60202299c8472a62aa60caacdcaff2872713..82f5e3b749d20289672ec62018f8fbd84d2802d3 100644 (file)
@@ -1 +1 @@
-REACT_APP_API_BASE=
+REACT_APP_API_BASE=/v2
index d17f71d61c8d51e393c2b1111f8c5f9b452c15bd..94a6c4eaa2321c65d0051c7bc7ffec39c79edcb2 100644 (file)
@@ -15,7 +15,7 @@ function App() {
     return (
         <div className="app-shell">
             {loggedIn ? (
-                <Router>
+                <Router basename="/v2">
                     <SyncNotifications />
                     <Routes>
                         <Route path="/" element={<Home />} />
index 911d1dd67fa11fce7c082f3d33617d835af073de..0f4656b2b3307091dd5fc8c8ae24a6d330da3594 100644 (file)
@@ -24,7 +24,7 @@ http.interceptors.response.use(
     (err) => {
         if (err.response && err.response.status === 401) {
             clearToken();
-            window.location.href = '/';
+            window.location.href = '/v2/';
         }
         return Promise.reject(err);
     }
index 4a4bcf03b14cfd1bfaf5cc837a2afb736ced9e94..1470cf4be8463a445351a9857d06185bf2fbe702 100644 (file)
@@ -2,7 +2,7 @@
 // 后端在 main.py 校验账密并签发 HMAC token;所有 /api/* 需携带该 token。
 import { API_BASE } from './api';
 
-const TOKEN_KEY = 'words_auth_token';
+const TOKEN_KEY = 'words_auth_token_v2';
 
 export function getToken() {
     return localStorage.getItem(TOKEN_KEY) || '';
index a3603ecf9d085ed913f8f6622d5024899098fba9..163f44d55b03864a42e924f7c6dd7e4db925e798 100644 (file)
@@ -4,7 +4,7 @@
 //   - progress: 离线进度, keyPath=`${group_id}:${op_type}`, {key, group_id, op_type, completed_at, dirty}
 //   - meta:     元数据, keyPath=key (lastSyncAt, learnableGroups[])
 
-const DB_NAME = 'words-pwa';
+const DB_NAME = 'words-pwa-v2';
 const DB_VERSION = 1;
 
 let dbPromise = null;
index 2b8b867011101e8e0e8d7430702c49f28db9010b..0417c4aa9669dc56c81c93078ab96aa1069fefa6 100644 (file)
@@ -20,7 +20,7 @@ reportWebVitals();
 // 注册 Service Worker (PWA 离线支持)
 if ('serviceWorker' in navigator) {
   window.addEventListener('load', () => {
-    navigator.serviceWorker.register('/sw.js').catch(err => console.error('SW registration failed:', err));
+    navigator.serviceWorker.register('/v2/sw.js').catch(err => console.error('SW registration failed:', err));
     // SW 接管页面后, 再触发一次同步+预取, 确保预取请求被 SW 拦截并写入缓存
     navigator.serviceWorker.ready.then(() => {
       if (isLoggedIn()) {