diff --git a/.claude/README.md b/.claude/README.md new file mode 100644 index 00000000..83719146 --- /dev/null +++ b/.claude/README.md @@ -0,0 +1,18 @@ +# InfoGenie 仓库 — Claude / Cursor 工作区说明 + +本目录用于存放与 **Cursor / Claude Code** 等工具相关的本地配置(如 `settings.local.json`),**不放业务代码**。 + +## 与文档的关系 + +| 文档 | 路径 | 内容 | +|------|------|------| +| Go 后端 | [`infogenie-backend-go/后端文档.md`](../infogenie-backend-go/后端文档.md) | API、MySQL、AI 流式、站点配置、功能卡片统计 | +| React 前端 | [`infogenie-frontend/前端文档.md`](../infogenie-frontend/前端文档.md) | 路由、构建、环境变量、静态 AI 小应用 | + +## 仓库结构(与开发相关) + +- **`infogenie-backend-go/`**:万象口袋 **主后端**(Gin + GORM + MySQL)。生产环境前端默认请求此服务提供的 API。 +- **`infogenie-frontend/`**:**主站 SPA**(Create React App),`public/` 下含大量静态页(`aimodelapp/`、`smallgame/`、`toolbox/` 等)。 +- **`infogenie-backend-java/`**:Java 后端(若部署需与本仓库 Go 文档中的接口约定自行对齐)。 + +给助手或协作者改需求时,优先阅读上表两份 **后端文档 / 前端文档**,再下钻到具体源码路径。 diff --git a/InfoGenie-frontend/.env.development b/InfoGenie-frontend/.env.development index da2550ea..1d89ce1b 100644 --- a/InfoGenie-frontend/.env.development +++ b/InfoGenie-frontend/.env.development @@ -1,7 +1,7 @@ # 复制为 .env.local 后可按需覆盖本地开发值 -REACT_APP_API_URL=http://127.0.0.1:5002 -REACT_APP_AUTH_URL=https://auth.shumengya.top -REACT_APP_AUTH_API_URL=https://auth.api.shumengya.top -REACT_APP_NAME=InfoGenie -REACT_APP_VERSION=1.0.0 -REACT_APP_DEBUG=true +VITE_API_URL=http://127.0.0.1:5002 +VITE_AUTH_URL=https://auth.shumengya.top +VITE_AUTH_API_URL=https://auth.api.shumengya.top +VITE_NAME=InfoGenie +VITE_VERSION=1.0.0 +VITE_DEBUG=true diff --git a/InfoGenie-frontend/.env.production b/InfoGenie-frontend/.env.production index 33b98de6..5b26b406 100644 --- a/InfoGenie-frontend/.env.production +++ b/InfoGenie-frontend/.env.production @@ -1,7 +1,7 @@ # 生产前端环境变量 -REACT_APP_API_URL=https://infogenie.api.shumengya.top -REACT_APP_AUTH_URL=https://auth.shumengya.top -REACT_APP_AUTH_API_URL=https://auth.api.shumengya.top -REACT_APP_NAME=InfoGenie -REACT_APP_VERSION=1.0.0 -REACT_APP_DEBUG=false +VITE_API_URL=https://infogenie.api.shumengya.top +VITE_AUTH_URL=https://auth.shumengya.top +VITE_AUTH_API_URL=https://auth.api.shumengya.top +VITE_NAME=InfoGenie +VITE_VERSION=1.0.0 +VITE_DEBUG=false diff --git a/InfoGenie-frontend/public/index.html b/InfoGenie-frontend/index.html old mode 100755 new mode 100644 similarity index 90% rename from InfoGenie-frontend/public/index.html rename to InfoGenie-frontend/index.html index 55dcd0f0..63191cc8 --- a/InfoGenie-frontend/public/index.html +++ b/InfoGenie-frontend/index.html @@ -15,7 +15,7 @@ - + @@ -28,14 +28,14 @@ - - + + - + - + @@ -183,7 +183,7 @@
- +
@@ -199,6 +199,8 @@
+ + + + + +
+ +
+
+
🖼️
+

PNG ↔ JPG 转换器

+
+

纯浏览器本地转换 • 零上传 • 安全隐私 • 秒级处理

+
+ +
+
+ +
+ +
+ + + +
+

点击或拖拽图片到此区域

+

支持 PNG / JPG 格式,最大 50MB

+
+ + + +
+ + + +
+ +
+ 完全本地运行 • 无需联网 • 图片不会离开您的浏览器 +
+
+ + + + + + diff --git a/InfoGenie-frontend/public/toolbox/图片处理/图片加文字水印/图片加文字水印.html b/InfoGenie-frontend/public/toolbox/图片处理/图片加文字水印/图片加文字水印.html new file mode 100644 index 00000000..8911187b --- /dev/null +++ b/InfoGenie-frontend/public/toolbox/图片处理/图片加文字水印/图片加文字水印.html @@ -0,0 +1,728 @@ + + + + + +水印工具 · WaterMark + + + + + +
+ + + + + WM + +
+
WaterMark
+
图片文字水印工具
+
+
+ +
+ + + +
+
+
+
🖼️
+

上传图片后
在左侧调整参数
即可预览水印效果

+
+
+ 预览 +
+ +
尺寸:  |  文件:
+
+
+ + + + \ No newline at end of file diff --git a/InfoGenie-frontend/public/toolbox/图片处理/图片压缩处理/图片压缩处理.html b/InfoGenie-frontend/public/toolbox/图片处理/图片压缩处理/图片压缩处理.html new file mode 100644 index 00000000..066cec3a --- /dev/null +++ b/InfoGenie-frontend/public/toolbox/图片处理/图片压缩处理/图片压缩处理.html @@ -0,0 +1,359 @@ + + + + + + 在线图片压缩工具 + + + + +
+

图片压缩工具

+ +
+

点击这里或将图片拖拽到此处上传

+

支持 JPG, PNG, WebP 等常见格式

+ +
+ +
+
+ + +
数值越小,体积越小,画质越低
+
+
+ + +
+
+ +
+
+

原图

+
等待上传...
+ +
+
+

压缩后

+
等待处理...
+ +
+
+ + 下载压缩后的图片 +
+ + + + + diff --git a/InfoGenie-frontend/public/toolbox/实用工具/C语言编译器/网页C语言编译器.html b/InfoGenie-frontend/public/toolbox/实用工具/C语言编译器/网页C语言编译器.html new file mode 100644 index 00000000..a525801c --- /dev/null +++ b/InfoGenie-frontend/public/toolbox/实用工具/C语言编译器/网页C语言编译器.html @@ -0,0 +1,46 @@ + + + + + Wasmer Clang in Browser + + +

浏览器里直接编译 C → WASM

+ +
+ +

+
+  
+
+
\ No newline at end of file
diff --git a/InfoGenie-frontend/public/toolbox/实用工具/JavaScript编译器/app.js b/InfoGenie-frontend/public/toolbox/实用工具/JavaScript解释器/app.js
similarity index 100%
rename from InfoGenie-frontend/public/toolbox/实用工具/JavaScript编译器/app.js
rename to InfoGenie-frontend/public/toolbox/实用工具/JavaScript解释器/app.js
diff --git a/InfoGenie-frontend/public/toolbox/实用工具/JavaScript编译器/index.html b/InfoGenie-frontend/public/toolbox/实用工具/JavaScript解释器/index.html
similarity index 100%
rename from InfoGenie-frontend/public/toolbox/实用工具/JavaScript编译器/index.html
rename to InfoGenie-frontend/public/toolbox/实用工具/JavaScript解释器/index.html
diff --git a/InfoGenie-frontend/public/toolbox/实用工具/JavaScript编译器/styles.css b/InfoGenie-frontend/public/toolbox/实用工具/JavaScript解释器/styles.css
similarity index 100%
rename from InfoGenie-frontend/public/toolbox/实用工具/JavaScript编译器/styles.css
rename to InfoGenie-frontend/public/toolbox/实用工具/JavaScript解释器/styles.css
diff --git a/InfoGenie-frontend/src/App.js b/InfoGenie-frontend/src/App.js
index 53d1301f..98bef650 100755
--- a/InfoGenie-frontend/src/App.js
+++ b/InfoGenie-frontend/src/App.js
@@ -1,9 +1,7 @@
 import React from 'react';
 import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
 import { Toaster } from 'react-hot-toast';
-import styled from 'styled-components';
 
-// 页面组件
 import HomePage from './pages/HomePage';
 import LoginPage from './pages/LoginPage';
 import AuthCallbackPage from './pages/AuthCallbackPage';
@@ -15,42 +13,27 @@ import UserProfilePage from './pages/UserProfilePage';
 import AdminPage from './pages/AdminPage';
 import ToolboxPage from './pages/ToolboxPage';
 
-// 公共组件
 import Header from './components/Header';
 import Navigation from './components/Navigation';
 import Footer from './components/Footer';
 import ParticleEffect from './components/ParticleEffect';
+import RandomSiteBackground from './components/RandomSiteBackground';
 import ScrollToTop from './components/ScrollToTop';
 
-// 上下文
 import { UserProvider } from './contexts/UserContext';
 
-// 样式
-import './styles/global.css';
-
-const AppContainer = styled.div`
-  min-height: 100vh;
-  display: flex;
-  flex-direction: column;
-  background: linear-gradient(135deg, #a8e6cf 0%, #dcedc1 50%, #ffd3a5 100%);
-`;
-
-const MainContent = styled.main`
-  flex: 1;
-  padding: 0;
-  margin: 0;
-`;
+import './styles/index.css';
 
 function App() {
   return (
     
       
         
-        
+        
+        
- +
- {/* 主要页面 */} } /> } /> } /> @@ -61,14 +44,12 @@ function App() { } /> } /> } /> - {/* 通配符路由 - 所有未匹配的路径都重定向到首页 */} } /> - +
- - {/* 全局提示组件 */} + - - {/* 全局粒子效果 */} + - +
); diff --git a/InfoGenie-frontend/src/components/Footer.js b/InfoGenie-frontend/src/components/Footer.js index bedce638..66a679e4 100755 --- a/InfoGenie-frontend/src/components/Footer.js +++ b/InfoGenie-frontend/src/components/Footer.js @@ -1,74 +1,33 @@ import React from 'react'; -import styled from 'styled-components'; - -const FooterContainer = styled.footer` - background: linear-gradient(135deg, #81c784 0%, #66bb6a 100%); - color: white; - padding: 40px 0 80px; /* 底部留出导航栏空间 */ - margin-top: 60px; - box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1); - - @media (min-width: 769px) { - padding: 40px 0 20px; - } -`; - -const FooterContent = styled.div` - max-width: 1200px; - margin: 0 auto; - padding: 0 16px; -`; - -const FooterInfo = styled.div` - text-align: center; - margin-bottom: 24px; -`; - -const FooterTitle = styled.h3` - color: white; - margin-bottom: 12px; - font-size: 20px; - font-weight: bold; -`; - -const FooterDivider = styled.div` - height: 1px; - background: rgba(255, 255, 255, 0.2); - margin: 24px 0; -`; - -const FooterBottom = styled.div` - text-align: center; - font-size: 12px; - color: rgba(255, 255, 255, 0.8); - line-height: 1.5; -`; - -const Copyright = styled.p` - margin-bottom: 8px; -`; const Footer = () => { const currentYear = new Date().getFullYear(); return ( - - - - 万象口袋 - +
+
+
+

万象口袋

+
+
- - - - - - 蜀ICP备2025151694号 | Copyright © 2025-{currentYear} - - - - +
+

+ 蜀ICP备2025151694号 | Copyright © 2025-{currentYear} +

+
+
+
); }; diff --git a/InfoGenie-frontend/src/components/FullscreenEmbed.js b/InfoGenie-frontend/src/components/FullscreenEmbed.js index 8c1db4a1..de4463f8 100644 --- a/InfoGenie-frontend/src/components/FullscreenEmbed.js +++ b/InfoGenie-frontend/src/components/FullscreenEmbed.js @@ -1,175 +1,7 @@ import React, { useState, useEffect, useCallback, useRef } from 'react'; import { createPortal } from 'react-dom'; -import styled, { keyframes, css } from 'styled-components'; import { FiArrowLeft, FiRefreshCw, FiAlertCircle } from 'react-icons/fi'; - -const slideUp = keyframes` - from { transform: translateY(100%); opacity: 0; } - to { transform: translateY(0); opacity: 1; } -`; - -const slideDown = keyframes` - from { transform: translateY(0); opacity: 1; } - to { transform: translateY(100%); opacity: 0; } -`; - -const spin = keyframes` - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } -`; - -const fadeIn = keyframes` - from { opacity: 0; } - to { opacity: 1; } -`; - -const Overlay = styled.div` - position: fixed; - inset: 0; - z-index: 999999; - display: flex; - flex-direction: column; - background: #fff; - font-family: inherit; - animation: ${({ $closing }) => $closing ? css`${slideDown} 0.25s ease-in forwards` : css`${slideUp} 0.3s ease-out`}; -`; - -const Header = styled.div` - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 0 16px; - height: 52px; - flex-shrink: 0; - background: ${({ $color }) => $color}; - color: #fff; - box-shadow: 0 2px 8px rgba(0,0,0,0.12); - user-select: none; - -webkit-tap-highlight-color: transparent; -`; - -const HeaderTitle = styled.h1` - flex: 1; - margin: 0; - font-size: 16px; - font-weight: 600; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -`; - -const HeaderBtn = styled.button` - display: flex; - align-items: center; - justify-content: center; - gap: 5px; - height: 34px; - padding: 0 14px; - border: none; - border-radius: 8px; - background: rgba(255,255,255,0.18); - color: #fff; - font-size: 13px; - font-weight: 500; - cursor: pointer; - transition: background 0.2s; - flex-shrink: 0; - &:hover { background: rgba(255,255,255,0.3); } - &:active { background: rgba(255,255,255,0.1); } -`; - -const IframeWrapper = styled.div` - position: relative; - flex: 1; - overflow: hidden; -`; - -const StyledIframe = styled.iframe` - display: block; - width: 100%; - height: 100%; - border: none; - background: #fff; -`; - -const LoadingOverlay = styled.div` - position: absolute; - inset: 0; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 16px; - background: #fff; - animation: ${fadeIn} 0.15s ease-out; - z-index: 2; -`; - -const Spinner = styled.div` - width: 36px; - height: 36px; - border: 3px solid #e5e7eb; - border-top-color: ${({ $color }) => $color}; - border-radius: 50%; - animation: ${spin} 0.7s linear infinite; -`; - -const LoadingText = styled.p` - margin: 0; - font-size: 14px; - color: #9ca3af; -`; - -const ErrorOverlay = styled.div` - position: absolute; - inset: 0; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 16px; - background: #fff; - z-index: 2; - padding: 24px; - text-align: center; -`; - -const ErrorIcon = styled(FiAlertCircle)` - color: #ef4444; - font-size: 48px; -`; - -const ErrorTitle = styled.h2` - margin: 0; - font-size: 18px; - font-weight: 600; - color: #1f2937; -`; - -const ErrorDesc = styled.p` - margin: 0; - font-size: 14px; - color: #6b7280; - max-width: 320px; - line-height: 1.5; -`; - -const RetryButton = styled.button` - display: flex; - align-items: center; - gap: 6px; - padding: 10px 24px; - border: none; - border-radius: 10px; - background: linear-gradient(135deg, #4ade80 0%, #22c55e 100%); - color: #fff; - font-size: 14px; - font-weight: 600; - cursor: pointer; - transition: transform 0.15s, box-shadow 0.15s; - &:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(74,222,128,0.35); } -`; +import clsx from 'clsx'; const LOAD_TIMEOUT_MS = 20000; @@ -255,20 +87,57 @@ const FullscreenEmbed = ({ }, [url, loading]); return createPortal( - -
- +
+ + + {/* Header */} +
+ +

+ {title} +

+
+ +
- - +