修改页面布局样式

This commit is contained in:
zlt 2026-08-13 11:25:34 +08:00
parent cd9c90dee0
commit 7bd9dcd998
1 changed files with 57 additions and 12 deletions

View File

@ -113,6 +113,21 @@ pre.json{background:var(--surface-2);border:1px solid var(--hair);border-radius:
.mr-two{display:grid;grid-template-columns:1fr 1fr;gap:16px;font-size:12.5px;} .mr-two{display:grid;grid-template-columns:1fr 1fr;gap:16px;font-size:12.5px;}
.mr-row{padding:3px 0;border-bottom:1px solid var(--hair);} .mr-row{padding:3px 0;border-bottom:1px solid var(--hair);}
.mr-row:last-child{border-bottom:none;} .mr-row:last-child{border-bottom:none;}
/* 顶部风控告警条 (系统状态色: 琥珀/橙/灰, 不用红绿; 红绿只留给方向看涨看跌) */
.alert-bar{display:flex;align-items:center;gap:9px;background:var(--surface);border:1px solid var(--hair);
border-left:3px solid var(--hair);border-radius:12px;padding:9px 14px;margin:16px 0 8px;box-shadow:var(--shadow);}
.alert-bar.lv-danger{border-left-color:var(--stop);}
.alert-bar.lv-warn{border-left-color:var(--warn);}
.alert-bar .ab-title{font-weight:640;font-size:13px;color:var(--ink-2);white-space:nowrap;display:flex;align-items:center;gap:6px;}
.alert-bar .ab-badge{font-size:11px;font-weight:600;padding:1px 8px;border-radius:999px;background:rgba(138,136,130,.16);color:var(--ink-2);}
.alert-bar.lv-danger .ab-badge{background:var(--stop-weak);color:var(--stop);}
.alert-bar.lv-warn .ab-badge{background:var(--warn-weak);color:var(--warn);}
.alert-bar .ab-latest{flex:1;min-width:0;font-size:13px;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.alert-bar .ab-toggle{flex:none;color:var(--accent);font-size:12.5px;font-weight:560;cursor:pointer;background:none;border:0;padding:4px 4px;}
.alert-bar .ab-empty{flex:1;color:var(--muted);font-size:12.5px;}
.alert-dot{width:7px;height:7px;border-radius:50%;flex:none;background:var(--muted);}
.alert-dot.lv-danger{background:var(--stop);} .alert-dot.lv-warn{background:var(--warn);}
.alert-panel{margin-top:0;}
</style> </style>
</head> </head>
<body> <body>
@ -165,6 +180,37 @@ pre.json{background:var(--surface-2);border:1px solid var(--hair);border-radius:
<!-- ==================== 交易员视图 ==================== --> <!-- ==================== 交易员视图 ==================== -->
<div v-show="mode==='trader'"> <div v-show="mode==='trader'">
<!-- 0) 顶部风控告警条 (默认折叠; 条上常驻最新一条, 展开看全部) -->
<div class="alert-bar" :class="'lv-'+alertLevelClass">
<span class="ab-title"><span class="alert-dot" :class="'lv-'+alertLevelClass"></span>风控告警</span>
<template v-if="alertItems.length">
<span class="ab-badge">{{ alertItems.length }} 条</span>
<span class="ab-latest">最新 ·
<b>{{ nm(alertLatest.ts_code) }}</b> <span class="muted mono">{{ alertLatest.ts_code }}</span>
<span :class="alertLatest.direction==='看涨'?'clr-up':(alertLatest.direction==='看跌'?'clr-down':'muted')">{{ alertLatest.direction }}</span>
<span class="disp" :class="alertLatest.level==='DANGER'?'deny':(alertLatest.level==='WARNING'?'queue':'wait')" style="padding:1px 7px">{{ alertLatest.level }}</span>
<span class="muted">{{ alertLatest.source }} · {{ alertLatest.time }}</span>
</span>
<button class="ab-toggle" @click="showAlerts=!showAlerts">{{ showAlerts?'收起 ▲':'展开全部 ▼' }}</button>
</template>
<template v-else-if="usrc('alerts') && usrc('alerts').ok===false">
<span class="ab-empty">· 读取失败:{{ usrc('alerts').error }}</span>
</template>
<template v-else>
<span class="ab-empty">· 暂无风控告警</span>
</template>
</div>
<div class="panel tblk alert-panel" v-if="showAlerts && alertItems.length">
<el-table :data="alertItems.slice(0,30)" size="small" max-height="340">
<el-table-column label="股票" min-width="150"><template #default="s"><b>{{ nm(s.row.ts_code) }}</b> <span class="muted mono">{{ s.row.ts_code }}</span></template></el-table-column>
<el-table-column label="方向" width="70"><template #default="s"><span :class="s.row.direction==='看涨'?'clr-up':(s.row.direction==='看跌'?'clr-down':'muted')">{{ s.row.direction }}</span></template></el-table-column>
<el-table-column label="级别" width="96"><template #default="s"><span class="disp" :class="s.row.level==='DANGER'?'deny':(s.row.level==='WARNING'?'queue':'wait')">{{ s.row.level }}</span></template></el-table-column>
<el-table-column label="来源" min-width="170"><template #default="s"><span class="muted" style="font-size:11.5px">{{ s.row.source }}</span></template></el-table-column>
<el-table-column label="时间" width="64" align="right"><template #default="s"><span class="mono muted">{{ s.row.time }}</span></template></el-table-column>
</el-table>
</div>
<!-- 1) 今日一览 + 需要注意 --> <!-- 1) 今日一览 + 需要注意 -->
<div class="metrics"> <div class="metrics">
<div class="m"><div class="k">账户总资产</div><div class="v">{{ money(ov.total_asset) }}</div></div> <div class="m"><div class="k">账户总资产</div><div class="v">{{ money(ov.total_asset) }}</div></div>
@ -597,17 +643,6 @@ pre.json{background:var(--surface-2);border:1px solid var(--hair);border-radius:
</el-table> </el-table>
</div> </div>
<div class="up-cell">
<div class="up-h">双向风控告警<span class="src-err" v-if="usrc('alerts') && usrc('alerts').ok===false"> · 读取失败</span></div>
<el-table :data="((usrc('alerts')||{}).items||[]).slice(0,8)" size="small" max-height="200" empty-text="暂无">
<el-table-column label="股票" min-width="118"><template #default="s"><b>{{ nm(s.row.ts_code) }}</b></template></el-table-column>
<el-table-column label="方向" width="60"><template #default="s"><span :class="s.row.direction==='看涨'?'clr-up':(s.row.direction==='看跌'?'clr-down':'muted')">{{ s.row.direction }}</span></template></el-table-column>
<el-table-column label="级别" width="86"><template #default="s"><span class="disp" :class="s.row.level==='DANGER'?'deny':(s.row.level==='WARNING'?'queue':'wait')">{{ s.row.level }}</span></template></el-table-column>
<el-table-column label="来源" min-width="140"><template #default="s"><span class="muted" style="font-size:11px">{{ s.row.source }}</span></template></el-table-column>
<el-table-column label="时间" width="56" align="right"><template #default="s"><span class="mono muted">{{ s.row.time }}</span></template></el-table-column>
</el-table>
</div>
<div class="up-cell"> <div class="up-cell">
<div class="up-h">mtf 资金异动<span class="src-err" v-if="usrc('metrics') && usrc('metrics').ok===false"> · 读取失败</span></div> <div class="up-h">mtf 资金异动<span class="src-err" v-if="usrc('metrics') && usrc('metrics').ok===false"> · 读取失败</span></div>
<el-table :data="((usrc('metrics')||{}).items||[]).slice(0,8)" size="small" max-height="200" empty-text="暂无"> <el-table :data="((usrc('metrics')||{}).items||[]).slice(0,8)" size="small" max-height="200" empty-text="暂无">
@ -1345,6 +1380,7 @@ createApp({
const autoRefresh = ref(true); const autoRefresh = ref(true);
const upstream = ref({ sources: {} }); const upstream = ref({ sources: {} });
const showUpstream = ref(true); const showUpstream = ref(true);
const showAlerts = ref(false);
const openScan = ref({ by_code: {}, notes: [] }); const openScan = ref({ by_code: {}, notes: [] });
const insTab = ref('live'); const insTab = ref('live');
const stratDlg = reactive({ visible:false, busy:false, reasons:[], ts_code:'', price:0, const stratDlg = reactive({ visible:false, busy:false, reasons:[], ts_code:'', price:0,
@ -1771,6 +1807,14 @@ createApp({
openScan.value = (d && d.by_code) ? d : { by_code: {}, notes: [] }; openScan.value = (d && d.by_code) ? d : { by_code: {}, notes: [] };
} }
const usrc = k => (upstream.value.sources || {})[k]; const usrc = k => (upstream.value.sources || {})[k];
const alertItems = computed(() => { const a = usrc('alerts'); return (a && Array.isArray(a.items)) ? a.items : []; });
const alertLatest = computed(() => alertItems.value[0] || {});
const alertLevelClass = computed(() => {
const it = alertItems.value;
if (it.some(x => x.level === 'DANGER')) return 'danger';
if (it.some(x => x.level === 'WARNING')) return 'warn';
return 'none';
});
async function loadUpstream() { async function loadUpstream() {
const d = await call('get', '/api/upstream-signals'); const d = await call('get', '/api/upstream-signals');
upstream.value = (d && d.sources) ? d : { sources: {} }; upstream.value = (d && d.sources) ? d : { sources: {} };
@ -2045,7 +2089,8 @@ createApp({
showLedger, onPosExpand, showLedger, onPosExpand,
openScan, insTab, todayYmd, insLive, insDone, insEnd, dispOf, loadOpenScan, denyToday, openScan, insTab, todayYmd, insLive, insDone, insEnd, dispOf, loadOpenScan, denyToday,
showOpLog, showSettings, watchCandidates, marketOpen, marketState, lastRefresh, autoRefresh, showOpLog, showSettings, watchCandidates, marketOpen, marketState, lastRefresh, autoRefresh,
upstream, showUpstream, usrc, loadUpstream }; upstream, showUpstream, usrc, loadUpstream,
showAlerts, alertItems, alertLatest, alertLevelClass };
} }
}).use(ElementPlus).mount('#app'); }).use(ElementPlus).mount('#app');
</script> </script>