修改页面布局样式
This commit is contained in:
parent
7b7eef674d
commit
abfeff22cb
|
|
@ -113,7 +113,7 @@ pre.json{background:var(--surface-2);border:1px solid var(--hair);border-radius:
|
|||
|
||||
<div class="hd">
|
||||
<h1>PMS 持仓管理<span class="ver">v{{ health.version || '-' }} · {{ health.now || '' }}</span></h1>
|
||||
<span class="chip" :class="health.trade_day?'ok':'idle'"><span class="dot"></span>{{ health.trade_day ? '交易日':'非交易日' }}</span>
|
||||
<span class="chip" :class="marketOpen?'ok':'idle'"><span class="dot"></span>{{ marketState }}</span>
|
||||
<span class="chip" :class="ov.buy_halt?'warn':'ok'"><span class="dot"></span>买入 {{ ov.buy_halt ? '已暂停':'正常' }}</span>
|
||||
<span class="chip" :class="ov.exec_halt?'warn':'ok'"><span class="dot"></span>执行 {{ ov.exec_halt ? '已暂停':'正常' }}</span>
|
||||
<span class="chip" :class="ov.autonomy==='off'?'warn':'ok'"><span class="dot"></span>自主 {{ tx('autonomy', ov.autonomy) }}<span class="help" data-tip="系统自己出手的程度:全自动=闸门通过就执行;只提议=等你在『等我拍板』确认;暂停=不自动动作。">?</span></span>
|
||||
|
|
@ -127,6 +127,8 @@ pre.json{background:var(--surface-2);border:1px solid var(--hair);border-radius:
|
|||
<button class="tbtn" @click="openPlan">上游计划</button>
|
||||
<button class="tbtn" @click="openReport">日报</button>
|
||||
<button class="tbtn" v-show="mode==='ops'" @click="opsDrawer=true">运维</button>
|
||||
<span class="muted" style="font-size:11.5px;cursor:pointer" @click="autoRefresh=!autoRefresh"
|
||||
:title="autoRefresh?'自动刷新开,点此关闭':'自动刷新关,点此开启'">{{ autoRefresh ? '自动' : '手动' }}<span v-if="lastRefresh"> · {{ lastRefresh }}</span></span>
|
||||
<button class="tbtn pri" :disabled="loading" @click="loadAll">{{ loading ? '刷新中…' : '刷新' }}</button>
|
||||
</div>
|
||||
|
||||
|
|
@ -139,9 +141,12 @@ pre.json{background:var(--surface-2);border:1px solid var(--hair);border-radius:
|
|||
<el-alert v-if="ov.sector_ready===false" class="banner" type="warning" effect="dark" show-icon
|
||||
:closable="false"
|
||||
title="行业划分数据源未配置 —— 行业集中度硬拦截已停用, 行业类命令置灰 (设计 §5)"></el-alert>
|
||||
<el-alert v-if="ov.price_missing && ov.price_missing.length" class="banner" type="warning"
|
||||
effect="dark" show-icon :closable="false"
|
||||
:title="'以下持仓取不到实时价, 已用摊薄成本兜底: ' + ov.price_missing.join(', ')"></el-alert>
|
||||
<el-alert v-if="marketOpen && ov.price_missing && ov.price_missing.length" class="banner" type="warning"
|
||||
show-icon :closable="false"
|
||||
:title="'以下持仓取不到实时价(停牌或行情中断),已用摊薄成本兜底: ' + ov.price_missing.join(', ')"></el-alert>
|
||||
<el-alert v-if="!marketOpen && ov.price_missing && ov.price_missing.length" class="banner" type="info"
|
||||
show-icon :closable="false"
|
||||
:title="'现在' + marketState + ',行情未刷新;持仓盈亏与安全垫按最近收盘价/成本估算,不是实时。'"></el-alert>
|
||||
<el-alert v-if="health.calendar_degraded" class="banner" type="warning" effect="dark" show-icon
|
||||
:closable="false" title="交易日历降级: 未安装 chinesecalendar, 节假日不可辨"></el-alert>
|
||||
<el-alert v-if="dm.shadow" class="banner" type="info" effect="dark" show-icon :closable="false"
|
||||
|
|
@ -1252,6 +1257,8 @@ createApp({
|
|||
const showLedger = ref(false); // 「今天发生了什么」默认折叠
|
||||
const showOpLog = ref(false); // 操作日志默认折叠
|
||||
const showSettings = ref(false); // 设置默认折叠
|
||||
const lastRefresh = ref('');
|
||||
const autoRefresh = ref(true);
|
||||
const openScan = ref({ by_code: {}, notes: [] });
|
||||
const insTab = ref('live');
|
||||
const stratDlg = reactive({ visible:false, busy:false, reasons:[], ts_code:'', price:0,
|
||||
|
|
@ -1408,6 +1415,16 @@ createApp({
|
|||
const heldPositions = computed(() => (positions.value || []).filter(p => (p.total_qty || 0) > 0));
|
||||
// ---- 今日在办分档 + 候选处置 (2026-08-12 重构新增) ----
|
||||
const todayYmd = computed(() => (String(health.value.now || '').slice(0, 10).replace(/-/g, '')) || '');
|
||||
// 是否处于连续交易时段 (09:30-11:30 / 13:00-15:00 的交易日)。缺实时价在盘中才是问题,
|
||||
// 休市/非交易日本就没有实时行情, 不该报警 —— 2026-08-12 用户提。
|
||||
const marketOpen = computed(() => {
|
||||
if (!health.value.trade_day) return false;
|
||||
const t = (health.value.now || '').slice(11, 16);
|
||||
if (!t) return false;
|
||||
return (t >= '09:30' && t <= '11:30') || (t >= '13:00' && t <= '15:00');
|
||||
});
|
||||
const marketState = computed(() =>
|
||||
!health.value.trade_day ? '非交易日' : (marketOpen.value ? '盘中' : '休市'));
|
||||
const _LIVE_INS = ['PROPOSED', 'RULE_PASSED', 'JUDGE_PASSED', 'DISPATCHED'];
|
||||
const _sameDayIns = r => { const y = todayYmd.value;
|
||||
return !y || String(r.instruction_id || '').indexOf('INS_' + y + '_') === 0; };
|
||||
|
|
@ -1448,8 +1465,8 @@ createApp({
|
|||
if (o.buy_halt) out.push('已暂停买入(卖出与止损不受影响)');
|
||||
if (o.exec_halt) out.push('休假模式:所有自动动作暂停,仅保留对账与日报');
|
||||
if (o.brake_until) out.push('组合刹车中(解除日 ' + o.brake_until + ')');
|
||||
if ((o.price_missing || []).length)
|
||||
out.push(o.price_missing.length + ' 只取不到实时价(停牌等),其盈亏与安全垫暂不可用');
|
||||
if (marketOpen.value && (o.price_missing || []).length)
|
||||
out.push(o.price_missing.length + ' 只取不到实时价(停牌或行情中断),其盈亏与安全垫暂不可用');
|
||||
if (o.sector_ready === false) out.push('行业数据未就绪,行业类操作暂不可用');
|
||||
const j = (dm.value || {}).judge;
|
||||
if (j && j.available === false) out.push('决策系统暂不可用:补足/加仓/补仓一律降级为需你确认');
|
||||
|
|
@ -1703,6 +1720,7 @@ createApp({
|
|||
loadPositions(), loadInstructions(), loadLedger(), loadProposals(),
|
||||
loadDispatchMode(), loadWs(), loadStrategies(), loadOpLog(), loadOpenScan()]);
|
||||
await loadNames();
|
||||
lastRefresh.value = (health.value.now || '').slice(11, 19);
|
||||
loading.value = false;
|
||||
wsPollSync();
|
||||
}
|
||||
|
|
@ -1896,7 +1914,24 @@ createApp({
|
|||
reportDrawer.value = true;
|
||||
}
|
||||
|
||||
onMounted(() => { loadAll(); loadPlan(); }); // 计划状态并行拉, 不阻塞首屏
|
||||
// —— 自动刷新: 盘中 30s、休市 5min; 只拉快变数据, 不动 params(免得冲掉设置里在改的输入) ——
|
||||
let refreshTimer = null, refreshTick = 0;
|
||||
async function refreshLive() {
|
||||
await Promise.all([loadOverview(), loadPositions(), loadInstructions(), loadLedger(),
|
||||
loadProposals(), loadStrategies(), loadOpLog(), loadOpenScan()]);
|
||||
await loadNames();
|
||||
lastRefresh.value = (health.value.now || '').slice(11, 19);
|
||||
}
|
||||
function startAutoRefresh() {
|
||||
if (refreshTimer) return;
|
||||
refreshTimer = setInterval(() => {
|
||||
if (!autoRefresh.value) return;
|
||||
refreshTick++;
|
||||
if (marketOpen.value || refreshTick % 10 === 0) refreshLive();
|
||||
}, 30000);
|
||||
}
|
||||
onUnmounted(() => { if (refreshTimer) clearInterval(refreshTimer); });
|
||||
onMounted(() => { loadAll(); loadPlan(); startAutoRefresh(); }); // 首屏 + 启动自动刷新
|
||||
return { tab, loading, err, health, ov, params, catalog, commands, plans, plansOf,
|
||||
positions, lots, lotsOf, instructions, ledger, proposals, report, reportDrawer,
|
||||
opsDrawer, opsResult, opsLoading, issuing, form, curSpec, dirtyCount, dm,
|
||||
|
|
@ -1918,7 +1953,7 @@ createApp({
|
|||
openStrategy, validateStrategy, attachStrategy, setStrategyStatus, stratStateText, resumeBuy,
|
||||
showLedger, onPosExpand,
|
||||
openScan, insTab, todayYmd, insLive, insDone, insEnd, dispOf, loadOpenScan, denyToday,
|
||||
showOpLog, showSettings, watchCandidates };
|
||||
showOpLog, showSettings, watchCandidates, marketOpen, marketState, lastRefresh, autoRefresh };
|
||||
}
|
||||
}).use(ElementPlus).mount('#app');
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in New Issue