diff --git a/docs/security/admin-models-react-error-425-fix.md b/docs/security/admin-models-react-error-425-fix.md
new file mode 100644
index 0000000..9c66a20
--- /dev/null
+++ b/docs/security/admin-models-react-error-425-fix.md
@@ -0,0 +1,82 @@
+# /admin/models 空白页 - React #425 hydration mismatch 修复 (#961)
+
+## 用户截图 DevTools Console 错误
+
+AT ÃüÁîÒÑÆúÓá£Çë¸ÄÓà schtasks.exe¡£
+
+ÎÞЧµÄÃüÁ
+
+AT ÃüÁÅÅÔÚÌض¨ÈÕÆںÍʱ¼äÔËÐÐÃüÁîºͳÌÐ
+ҪʹÓà AT ÃüÁ¼ƻ®·þÎñ±ØÐëÒÑÔÚÔËÐÐÖС£
+
+AT [\computername] [ [id] [/DELETE] | /DELETE [/YES]]
+AT [\computername] time [/INTERACTIVE]
+ [ /EVERY:date[,...] | /NEXT:date[,...]] "command"
+
+\computername ָ¶¨Զ³̼ÆËã»ú¡£Èç¹ûʡÂÔÕâ¸ö²ÎÊý£¬
+ »á¼ƻ®Ôڱ¾µؼÆËã»úÉÏÔËÐÐÃüÁ
+id ָ¶¨¸øÒѼƻ®ÃüÁîµÄʶ±ðºš£
+/delete ɾ³ýij¸öÒѼƻ®µÄÃüÁÈç¹ûʡÂÔ id£¬
+ ¼ÆËã»úÉÏËùÓÐÒѼƻ®µÄÃüÁ»ᱻɾ³ý¡£
+/yes ²»ÐèҪ½øһ²½ȷÈÏʱ£¬¸úɾ³ýËùÓÐ×÷ҵ
+ µÄÃüÁîһÆðʹÓá£
+time ָ¶¨ÔËÐÐÃüÁîµÄʱ¼䡣
+/interactive ÔÊÐí×÷ҵÔÚÔËÐÐʱ£¬Ó뵱ʱµÇ¼µÄÓû§
+ ×ÀÃæ½øÐн»»¥¡£
+/every:date[,...] ָ¶¨ÔÚÿÖܻòÿÔµÄÌض¨ÈÕÆÚÔËÐÐÃüÁ
+ Èç¹ûʡÂÔÈÕÆڣ¬ÔòĬÈÏΪÔÚÿÔµÄ
+ ±¾ÈÕÔËÐС£
+/next:date[,...] ָ¶¨ÔÚÏÂһ¸öָ¶¨ÈÕÆÚ(È磬ÏÂÖÜËÄ)ÔË
+ ÐÐÃüÁÈç¹ûʡÂÔÈÕÆڣ¬ÔòĬÈÏΪÔÚÿ
+ Ôµı¾ÈÕÔËÐС£
+"command" ±¸ÔËÐеÄ Windows NT ÃüÁî»òÅú´¦Àí
+ ³ÌÐ
+
+**React error #425** = "Text content does not match server-rendered HTML"
+(https://react.dev/errors/425)
+
+## 根因分析
+
+1. **诊断面板输出**显示 React mount 失败 (#root.children.length = 0)
+2. **Console error #425** 是 hydration mismatch 错误
+3. 但项目**没有 SSR** 配置(vite.config.ts 只有 plugin-react,无 ssr 选项)
+4. 真正的 root cause:**React 18.3.1 createRoot 在某些边缘情况下会自动尝试 hydrate**
+
+## 修复
+
+**main.tsx 增强**:
+
+1. **强制清空 #root 避免 hydration** — 在 createRoot 之前:
+
+
+2. **全局错误监听** — 把所有未捕获错误打印到 console:
+
+
+3. **try-catch 包裹 createRoot** — 如果 mount 失败,在 #root 显示错误:
+
+
+## 验证
+
+- dist 已 rebuild,index.html 544 bytes(标准)
+- main.tsx 现在有完整错误处理链
+- HTTPS serve 200 OK
+
+## 用户操作
+
+**Ctrl + Shift + R 硬刷新** https://ai.qihuyun.com/admin/models
+
+如果 React mount 仍然失败,现在页面会显示具体错误信息(因为 rootEl.innerHTML = 错误信息),而不再完全空白。
+
+## 调试教训
+
+- React error #425 在 production build 中是 minified,完整描述要去 https://react.dev/errors/425
+- 即使没有 SSR,React 18 createRoot 也会检测 #root 内容,可能触发 hydration
+- **生产环境的 SPA 错误总是被 minified**,需要全局 error handler 才能看到完整信息
+- vite build 后的 bundle 用 命名(虽然是 production 内容)——这是 Vite/Rollup 的默认行为
+
+## 历史
+
+- #957 (2026-08-11 08:55): 修 nginx server 级 root
+- #959 (2026-08-11 09:18): 加 no-store 头
+- #961 (2026-08-11 12:36): 加 main.tsx 错误处理 + #root 清空 + try-catch
+
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx
index 43c906c..5e90fa4 100644
--- a/frontend/src/main.tsx
+++ b/frontend/src/main.tsx
@@ -4,10 +4,32 @@ import { BrowserRouter } from 'react-router-dom';
import App from './App';
import './styles/global.css';
-ReactDOM.createRoot(document.getElementById('root')!).render(
-
React mount failed: ' + String(err) + ''; +} + +