mirror of
https://ghfast.top/https://github.com/aeroxw/tick-stock-panel.git
synced 2026-09-12 17:54:15 +08:00
feat(v0.2): 市场阶段与主线识别 + 因子挖掘全链路 + 数据层完善
- 市场环境: 新增情绪周期6阶段(冰点/启动/主升/高潮/退潮/修复, 连板梯队驱动, EMA平滑+2日确认+弱档否决, 平均段长9.7天)与概念/行业主线排名(涨停梯队聚合, 可配置宽基/风格标签过滤); 市场环境页重构, regime 透明加列, 与5档state并存 - 挖掘: 因子与策略挖掘全链路(API/worker/进程锁/候选库/前端工作台/文档), 周度调度默认关闭且永不自动发布 - 回测: 财务快照因子(点时口径), 批量回测预计算共享下期收益, 信号路径矩阵列依赖展开修复(consecutive_limit_ups 缺列报错) - 数据/性能: enriched 生成与预热治理, 重任务限流, 行情/K线缓存复用, 时区修复 - 测试: 后端全量 914 通过; GUI 黑盒验证截图存证 gui-test-screenshots/
This commit is contained in:
@@ -25,6 +25,7 @@ import {
|
||||
Star,
|
||||
ScanSearch,
|
||||
History,
|
||||
Pickaxe,
|
||||
FileText,
|
||||
Settings,
|
||||
Key,
|
||||
@@ -79,6 +80,7 @@ const nav = [
|
||||
{ to: '/watchlist', label: '自选', icon: Star },
|
||||
{ to: '/screener', label: '策略', icon: ScanSearch },
|
||||
{ to: '/backtest', label: '回测', icon: History },
|
||||
{ to: '/mining', label: '挖掘', icon: Pickaxe },
|
||||
{ to: '/stock-analysis', label: '个股分析', icon: TrendingUp },
|
||||
{ to: '/limit-ladder', label: '连板梯队', icon: Flame },
|
||||
{ to: '/concept-analysis', label: '概念分析', icon: Layers3 },
|
||||
@@ -424,12 +426,11 @@ export function Layout() {
|
||||
: (dataSources?.custom?.find(s => s.name === activeProvider)?.display_name || activeProvider)
|
||||
const isCustomActive = activeProvider !== 'tickflow'
|
||||
|
||||
// 轮询触发记录总数 → 更新监控中心徽标 (每 15 秒)
|
||||
// 轮询触发记录总数 → 更新监控中心徽标 (每 15 秒; 后台标签页由 SSE 事件驱动, 不轮询)
|
||||
const alertsTotalQuery = useQuery({
|
||||
queryKey: ['alerts-total'],
|
||||
queryFn: () => api.alertsList({ days: 7, limit: 1 }),
|
||||
refetchInterval: 15000,
|
||||
refetchIntervalInBackground: true,
|
||||
select: (data) => data.total,
|
||||
})
|
||||
// 只在拿到真实总数时同步徽标 (避免 data=undefined 时传 0 重置 lastSeen)
|
||||
@@ -456,11 +457,27 @@ export function Layout() {
|
||||
const navItems = savedOrder.length > 0
|
||||
? (() => {
|
||||
const byTo = new Map(allNav.map(n => [n.to, n]))
|
||||
const ordered = savedOrder
|
||||
const ordered = (savedOrder
|
||||
.map(id => byTo.get(id) ?? byTo.get(`/analysis/${id}`))
|
||||
.filter(Boolean)
|
||||
const seen = new Set(ordered.map(n => n!.to))
|
||||
return [...ordered as typeof allNav, ...allNav.filter(n => !seen.has(n.to))]
|
||||
.filter(Boolean)) as typeof allNav
|
||||
const seen = new Set(ordered.map(n => n.to))
|
||||
const merged = [...ordered]
|
||||
for (const item of allNav) {
|
||||
if (seen.has(item.to)) continue
|
||||
// 未保存过排序的新条目: 内置页插回默认位置(排在已保存的默认前驱之后),
|
||||
// 分析/扩展菜单仍追加到末尾
|
||||
const defaultIndex = nav.findIndex(n => n.to === item.to)
|
||||
let anchor = -1
|
||||
if (defaultIndex > 0) {
|
||||
for (let i = defaultIndex - 1; i >= 0 && anchor < 0; i -= 1) {
|
||||
anchor = merged.findIndex(n => n.to === nav[i].to)
|
||||
}
|
||||
}
|
||||
if (anchor >= 0) merged.splice(anchor + 1, 0, item)
|
||||
else if (defaultIndex >= 0) merged.unshift(item)
|
||||
else merged.push(item)
|
||||
}
|
||||
return merged
|
||||
})()
|
||||
: allNav
|
||||
|
||||
|
||||
Reference in New Issue
Block a user