diff --git a/install-and-run.bat b/install-and-run.bat index a0b9356..30fd4a2 100644 --- a/install-and-run.bat +++ b/install-and-run.bat @@ -88,14 +88,4 @@ echo ⏹️ 按 Ctrl+C 停止服务器 echo. :: 启动服务器 -node src\api-server.js - -:: 如果启动失败 -if !errorlevel! neq 0 ( - echo. - echo ❌ 服务器异常 - pause - exit /b 1 -) - -pause \ No newline at end of file +node src\api-server.js \ No newline at end of file diff --git a/install-and-run.sh b/install-and-run.sh index d3a41c5..fb9e2ed 100644 --- a/install-and-run.sh +++ b/install-and-run.sh @@ -91,12 +91,4 @@ echo "⏹️ 按 Ctrl+C 停止服务器" echo # 启动服务器 -node src/api-server.js - -# 如果启动失败 -if [ $? -ne 0 ]; then - echo - echo "❌ 服务器异常" - echo "请检查错误信息并重试" - exit 1 -fi \ No newline at end of file +node src/api-server.js \ No newline at end of file diff --git a/src/ui-manager.js b/src/ui-manager.js index f3f2ec6..bfe1d23 100644 --- a/src/ui-manager.js +++ b/src/ui-manager.js @@ -8,8 +8,38 @@ import { CONFIG } from './config-manager.js'; import { serviceInstances } from './adapter.js'; import { initApiService } from './service-manager.js'; -// Token存储在内存中(生产环境建议使用Redis) -const tokenStore = new Map(); +// Token存储到本地文件中 +const TOKEN_STORE_FILE = 'token-store.json'; + +/** + * 读取token存储文件 + */ +async function readTokenStore() { + try { + if (existsSync(TOKEN_STORE_FILE)) { + const content = await fs.readFile(TOKEN_STORE_FILE, 'utf8'); + return JSON.parse(content); + } else { + // 如果文件不存在,创建一个默认的token store + await writeTokenStore({ tokens: {} }); + return { tokens: {} }; + } + } catch (error) { + console.error('读取token存储文件失败:', error); + return { tokens: {} }; + } +} + +/** + * 写入token存储文件 + */ +async function writeTokenStore(tokenStore) { + try { + await fs.writeFile(TOKEN_STORE_FILE, JSON.stringify(tokenStore, null, 2), 'utf8'); + } catch (error) { + console.error('写入token存储文件失败:', error); + } +} /** * 生成简单的token @@ -30,31 +60,60 @@ function getExpiryTime() { /** * 验证简单token */ -function verifyToken(token) { - const tokenInfo = tokenStore.get(token); +async function verifyToken(token) { + const tokenStore = await readTokenStore(); + const tokenInfo = tokenStore.tokens[token]; if (!tokenInfo) { return null; } // 检查是否过期 if (Date.now() > tokenInfo.expiryTime) { - tokenStore.delete(token); + await deleteToken(token); return null; } return tokenInfo; } +/** + * 保存token到本地文件 + */ +async function saveToken(token, tokenInfo) { + const tokenStore = await readTokenStore(); + tokenStore.tokens[token] = tokenInfo; + await writeTokenStore(tokenStore); +} + +/** + * 删除token + */ +async function deleteToken(token) { + const tokenStore = await readTokenStore(); + if (tokenStore.tokens[token]) { + delete tokenStore.tokens[token]; + await writeTokenStore(tokenStore); + } +} + /** * 清理过期的token */ -function cleanupExpiredTokens() { +async function cleanupExpiredTokens() { + const tokenStore = await readTokenStore(); const now = Date.now(); - for (const [token, info] of tokenStore.entries()) { - if (now > info.expiryTime) { - tokenStore.delete(token); + let hasChanges = false; + + for (const token in tokenStore.tokens) { + if (now > tokenStore.tokens[token].expiryTime) { + delete tokenStore.tokens[token]; + hasChanges = true; } } + + if (hasChanges) { + await writeTokenStore(tokenStore); + } } /** @@ -105,7 +164,7 @@ function parseRequestBody(req) { /** * 检查token验证 */ -function checkAuth(req) { +async function checkAuth(req) { const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { @@ -113,7 +172,7 @@ function checkAuth(req) { } const token = authHeader.substring(7); - const tokenInfo = verifyToken(token); + const tokenInfo = await verifyToken(token); return tokenInfo !== null; } @@ -145,8 +204,8 @@ async function handleLoginRequest(req, res) { const token = generateToken(); const expiryTime = getExpiryTime(); - // 存储token信息 - tokenStore.set(token, { + // 存储token信息到本地文件 + await saveToken(token, { username: 'admin', loginTime: Date.now(), expiryTime @@ -301,7 +360,8 @@ export async function handleUIApiRequests(method, pathParam, req, res, currentCo // Handle UI management API requests (需要token验证,除了登录接口、健康检查和Events接口) if (pathParam.startsWith('/api/') && pathParam !== '/api/login' && pathParam !== '/api/health' && pathParam !== '/api/events') { // 检查token验证 - if (!checkAuth(req)) { + const isAuth = await checkAuth(req); + if (!isAuth) { res.writeHead(401, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', diff --git a/static/app/styles.css b/static/app/styles.css index 86fb09a..a4a03c9 100644 --- a/static/app/styles.css +++ b/static/app/styles.css @@ -120,6 +120,33 @@ body { font-size: 14px; } +/* 高亮说明样式 */ +.highlight-note { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 1rem; + background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); + border: 1px solid #fbbf24; + border-radius: 0.5rem; + margin-bottom: 1.5rem; + color: #92400e; + font-weight: 500; + width: 100%; + box-sizing: border-box; +} + +.highlight-note i { + color: #f59e0b; + font-size: 1.25rem; + flex-shrink: 0; +} + +.highlight-note span { + flex: 1; + text-align: center; +} + @keyframes pulse { 0%, 100% { opacity: 1; @@ -2956,4 +2983,5 @@ input:checked + .toggle-slider:before { .contact-section h3 i { color: var(--primary-color); } + } diff --git a/static/index.html b/static/index.html index 67b94bb..1b58b3d 100644 --- a/static/index.html +++ b/static/index.html @@ -625,7 +625,7 @@
- 配置了提供商池后,可在提供商池管理中查看详细信息 + 配置了提供商池后,默认使用提供商池的配置,提供商池配置失效降级到默认配置
@@ -708,6 +708,12 @@

提供商池管理

+
+
+ + 配置了提供商池后,默认使用提供商池的配置,提供商池配置失效降级到默认配置 +
+