diff --git a/stock-html/static/css/auth.css b/stock-html/static/css/auth.css index 2a61f9f..ca61e85 100644 --- a/stock-html/static/css/auth.css +++ b/stock-html/static/css/auth.css @@ -120,14 +120,14 @@ } .login-error { - color: #ff4444; + color: var(--danger); font-size: 13px; margin-bottom: 12px; text-align: center; } .login-success { - color: #00ff88; + color: var(--success); font-size: 13px; margin-bottom: 12px; text-align: center; diff --git a/stock-html/static/css/base.css b/stock-html/static/css/base.css index 3f2f926..910f4e3 100644 --- a/stock-html/static/css/base.css +++ b/stock-html/static/css/base.css @@ -383,7 +383,7 @@ } .scan-source-select option { - background: #1a1a2e; + background: var(--bg-dark); color: var(--text-primary); padding: 10px; } @@ -773,4 +773,46 @@ color: var(--text-muted); line-height: 1.5; } + + /* ===== 内联样式提取的公共 class ===== */ + .cursor-pointer { cursor: pointer; } + .margin-top-sm { margin-top: 8px; } + .margin-top-md { margin-top: 15px; } + .margin-bottom-sm { margin-bottom: 8px; } + .margin-bottom-md { margin-bottom: 12px; } + .margin-left-auto { margin-left: auto; } + .margin-right-sm { margin-right: 6px; } + .text-xs { font-size: 11px; } + .text-sm { font-size: 12px; } + .text-md { font-size: 13px; } + .text-muted-2 { color: var(--text-muted); } + .text-secondary-2 { color: var(--text-secondary); } + .text-danger { color: var(--danger); } + .text-success { color: var(--success); } + .text-warning { color: var(--warning); } + .text-info { color: var(--info); } + .font-weight-600 { font-weight: 600; } + .flex-center { display: flex; align-items: center; gap: 4px; } + .flex-wrap-gap { display: flex; flex-wrap: wrap; gap: 6px; } + .grid-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; } + .hidden { display: none; } + .opacity-70 { opacity: 0.7; } + .padding-y-sm { padding: 8px 0; } + .max-height-scroll { max-height: 300px; overflow-y: auto; } + .icon-sm { width: 16px; height: 16px; vertical-align: -2px; margin-right: 4px; } + .icon-xs { width: 14px; height: 14px; vertical-align: -2px; margin-right: 3px; } + .input-mini { + width: 60px; background: var(--bg-dark); border: 1px solid var(--border-color); + color: var(--text-primary); border-radius: 4px; padding: 2px 6px; + } + .input-mini-wide { + width: 80px; background: var(--bg-dark); border: 1px solid var(--border-color); + color: var(--text-primary); border-radius: 4px; padding: 2px 6px; + } + .badge-mini { + background: var(--bg-dark); padding: 1px 6px; border-radius: 8px; font-size: 10px; + } + .border-top-divider { + margin-top: 10px; border-top: 1px solid var(--border-color); padding-top: 10px; + } diff --git a/stock-html/static/css/components.css b/stock-html/static/css/components.css index 1ba4da7..e409ed5 100644 --- a/stock-html/static/css/components.css +++ b/stock-html/static/css/components.css @@ -438,7 +438,7 @@ } .stoploss-sell-btn:hover { - background: #ff6666; + background: var(--danger); } /* 基本面弹窗样式 */ @@ -502,7 +502,7 @@ } .watch-btn.add:hover { - background: #00cc6a; + background: var(--success); } .watch-btn.remove { @@ -592,7 +592,7 @@ } .signal-chip.triggered { background: rgba(239,68,68,0.12); - color: #ef4444; + color: var(--danger); border: 1px solid rgba(239,68,68,0.25); } .signal-chip.inactive { @@ -606,7 +606,7 @@ border-radius: 50%; display: inline-block; } - .signal-dot.on { background: #ef4444; } + .signal-dot.on { background: var(--danger); } .signal-dot.off { background: var(--text-muted); opacity: 0.4; } .signal-summary { font-size: 12px; @@ -614,7 +614,7 @@ border-radius: 6px; background: var(--bg-secondary); } - .signal-strong { color: #ef4444; font-weight: 600; } + .signal-strong { color: var(--danger); font-weight: 600; } .signal-normal { color: var(--text-secondary); } .signal-none { color: var(--text-muted); } @@ -1826,7 +1826,7 @@ } .alert-price { font-size: 12px; - color: #ffd700; + color: var(--warning); margin-left: auto; font-weight: 500; } @@ -1839,14 +1839,14 @@ font-weight: 500; margin-right: 4px; } - .alert-change.up { color: #ff4444; } - .alert-change.down { color: #00ce9e; } + .alert-change.up { color: var(--up); } + .alert-change.down { color: var(--down); } .alert-sig-tag { font-size: 10px; padding: 1px 6px; border-radius: 3px; background: rgba(0, 206, 158, 0.15); - color: #00ce9e; + color: var(--success); } .refresh-btn { @@ -1932,7 +1932,7 @@ .toast-container.info .toast-icon { background: rgba(100, 150, 255, 0.2); - color: #6496ff; + color: var(--info); } .toast-container.success .toast-icon { diff --git a/stock-html/static/css/pages.css b/stock-html/static/css/pages.css index aa128b0..6f40f6a 100644 --- a/stock-html/static/css/pages.css +++ b/stock-html/static/css/pages.css @@ -89,8 +89,8 @@ .tech-recommend-reason { font-size: 12px; color: var(--text-secondary); margin-top: 6px; } .tech-holding-note { margin-top: 8px; padding: 6px 10px; - background: rgba(255,152,0,0.08); border-radius: 6px; - font-size: 12px; color: #e67e00; line-height: 1.5; + background: rgba(255,170,0,0.08); border-radius: 6px; + font-size: 12px; color: var(--warning); line-height: 1.5; } .tech-indicators { @@ -843,9 +843,9 @@ color: var(--text-secondary); } .step-watch .step-action { color: #748ffc; } -.step-buy .step-action { color: #ff6b6b; } -.step-add .step-action { color: #00ce9e; } -.step-hold .step-action { color: #ffd93d; } +.step-buy .step-action { color: var(--danger); } +.step-add .step-action { color: var(--success); } +.step-hold .step-action { color: var(--warning); } /* 核心信号一句话总结 */ .signal-summary-list { @@ -869,11 +869,11 @@ } .summary-tag.core { background: rgba(255, 107, 107, 0.15); - color: #ff6b6b; + color: var(--danger); } .summary-tag.normal { background: rgba(0, 206, 158, 0.15); - color: #00ce9e; + color: var(--success); } .summary-tag.aux { background: rgba(255,255,255,0.08); @@ -1287,13 +1287,13 @@ flex-shrink: 0; } -.ss-dot.s85 { background: #ff4444; } -.ss-dot.s80 { background: #ff6b35; } -.ss-dot.s75 { background: #4CAF50; } -.ss-dot.s70 { background: #2196F3; } -.ss-dot.s65 { background: #9C27B0; } -.ss-dot.s60 { background: #FF9800; } -.ss-dot.s55 { background: #607D8B; } +.ss-dot.s85 { background: var(--sig-85); } +.ss-dot.s80 { background: var(--sig-80); } +.ss-dot.s75 { background: var(--sig-75); } +.ss-dot.s70 { background: var(--sig-70); } +.ss-dot.s65 { background: var(--sig-65); } +.ss-dot.s60 { background: var(--sig-60); } +.ss-dot.s55 { background: var(--sig-55); } .ss-name { font-weight: 600; @@ -1315,7 +1315,7 @@ .ss-badge.active { background: rgba(0, 200, 83, 0.2); - color: #00c853; + color: var(--down); border: 1px solid rgba(0, 200, 83, 0.4); } @@ -1431,12 +1431,12 @@ .trade-type-tag.buy { background: rgba(76, 175, 80, 0.2); - color: #4caf50; + color: var(--success); } .trade-type-tag.sell, .trade-type-tag.partial_sell { background: rgba(244, 67, 54, 0.2); - color: #f44336; + color: var(--danger); } .trade-stock { @@ -1451,7 +1451,7 @@ } .trade-fee { - color: #ff9800; + color: var(--warning); font-size: 11px; } @@ -1474,22 +1474,22 @@ .result-reason-item.reason-limit { background: rgba(255, 152, 0, 0.1); - border-left: 3px solid #ff9800; + border-left: 3px solid var(--warning); } .result-reason-item.reason-cash { background: rgba(33, 150, 243, 0.1); - border-left: 3px solid #2196f3; + border-left: 3px solid var(--info); } .result-reason-item.reason-sell { background: rgba(244, 67, 54, 0.08); - border-left: 3px solid #f44336; + border-left: 3px solid var(--danger); } .result-reason-item.reason-buy { background: rgba(76, 175, 80, 0.08); - border-left: 3px solid #4caf50; + border-left: 3px solid var(--success); } .result-reason-item.reason-info { diff --git a/stock-html/static/js/app.js b/stock-html/static/js/app.js index ed3c52b..c48df61 100644 --- a/stock-html/static/js/app.js +++ b/stock-html/static/js/app.js @@ -541,10 +541,10 @@ const response = await axios.get('/api/me'); if (response.data.success && response.data.user) { this.currentUser = response.data.user; - console.log('已登录:', this.currentUser.username); + console.debug('已登录:', this.currentUser.username); } } catch (e) { - console.log('未登录'); + console.debug('未登录'); } finally { this.checkingAuth = false; } @@ -791,7 +791,7 @@ return response.data.data.stock_name; } } catch (e) { - console.log('获取股票名称失败'); + console.debug('获取股票名称失败'); } return null; }, @@ -1235,19 +1235,19 @@ // 版本不匹配则强制刷新 if (cacheVer < ALERT_CACHE_VERSION) { - console.log(`缓存版本过旧(v${cacheVer} < v${ALERT_CACHE_VERSION}),强制刷新`); + console.debug(`缓存版本过旧(v${cacheVer} < v${ALERT_CACHE_VERSION}),强制刷新`); } else { this.stockAlerts = cachedAlerts; - console.log(`加载缓存数据: ${cachedAlerts.length}条, 更新时间: ${lastUpdate}, v${cacheVer}`); + console.debug(`加载缓存数据: ${cachedAlerts.length}条, 更新时间: ${lastUpdate}, v${cacheVer}`); if (cacheDate === today) { - console.log('缓存是今天的,无需更新'); + console.debug('缓存是今天的,无需更新'); this.alertsLoading = false; this.updateHoldingPricesFromAlerts(); const cachedCodes = new Set(cachedAlerts.map(a => a.code)); const newStocks = allStocks.filter(s => !cachedCodes.has(s.code)); if (newStocks.length > 0) { - console.log(`发现${newStocks.length}只新股票,增量更新`); + console.debug(`发现${newStocks.length}只新股票,增量更新`); await this.analyzeNewStocks(newStocks, today); } return; @@ -1255,7 +1255,7 @@ } } } catch (err) { - console.log('加载缓存失败,将重新分析:', err); + console.debug('加载缓存失败,将重新分析:', err); } } @@ -1264,7 +1264,7 @@ this.alertsProgress = { current: 0, total: allStocks.length }; try { - console.log(`开始信号分析 ${allStocks.length} 只股票...`); + console.debug(`开始信号分析 ${allStocks.length} 只股票...`); const startTime = Date.now(); const response = await axios.post('/api/signal_alerts', { @@ -1273,14 +1273,14 @@ }); const elapsed = ((Date.now() - startTime) / 1000).toFixed(1); - console.log(`信号分析完成,耗时 ${elapsed}s`); + console.debug(`信号分析完成,耗时 ${elapsed}s`); if (response.data.success) { const results = response.data.results || []; this.alertsProgress.current = allStocks.length; this.stockAlerts = [...results]; - console.log(`成功: ${response.data.success_count}`); + console.debug(`成功: ${response.data.success_count}`); // 3. 保存到缓存 this.saveAlertsCache(this.stockAlerts); @@ -1296,7 +1296,7 @@ } catch (err) { console.error('批量分析请求失败:', err); // 回退到逐个分析 - console.log('回退到逐个分析模式...'); + console.debug('回退到逐个分析模式...'); await this.analyzeStocksOneByOne(allStocks, today, forceRefresh); } @@ -1445,7 +1445,7 @@ lastUpdate: new Date().toISOString().replace('T', ' ').split('.')[0], version: ALERT_CACHE_VERSION }); - console.log('分析结果已保存到缓存'); + console.debug('分析结果已保存到缓存'); } catch (err) { console.error('保存缓存失败:', err); } @@ -1562,6 +1562,7 @@ await this.loadAvailableCash(); } catch (err) { console.error('加载交易记录失败:', err); + this.showToast('加载交易记录失败', 'error'); } }, @@ -1752,6 +1753,7 @@ } } catch (error) { console.error('检查止损失败:', error); + this.showToast('检查止损失败,请稍后重试', 'error'); } }, @@ -2161,6 +2163,7 @@ } } catch (err) { console.error('技术信号检测失败:', err); + this.showToast('技术信号检测失败,请稍后重试', 'error'); } finally { this.techLoading = false; } @@ -2187,6 +2190,7 @@ } } catch (err) { console.error('批量技术信号检测失败:', err); + this.showToast('批量检测失败,请稍后重试', 'error'); } finally { this.techLoading = false; } @@ -2241,6 +2245,7 @@ } } catch (err) { console.error('获取扫描结果失败:', err); + this.showToast('获取扫描结果失败,请稍后重试', 'error'); } finally { this.fullScanLoading = false; } diff --git a/stock-html/templates/index.html b/stock-html/templates/index.html index 07ef1b7..d0e95f2 100644 --- a/stock-html/templates/index.html +++ b/stock-html/templates/index.html @@ -21,10 +21,10 @@ - - - - + + + + @@ -193,7 +193,7 @@