修改页面布局样式
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">
|
<div class="hd">
|
||||||
<h1>PMS 持仓管理<span class="ver">v{{ health.version || '-' }} · {{ health.now || '' }}</span></h1>
|
<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.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.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>
|
<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="openPlan">上游计划</button>
|
||||||
<button class="tbtn" @click="openReport">日报</button>
|
<button class="tbtn" @click="openReport">日报</button>
|
||||||
<button class="tbtn" v-show="mode==='ops'" @click="opsDrawer=true">运维</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>
|
<button class="tbtn pri" :disabled="loading" @click="loadAll">{{ loading ? '刷新中…' : '刷新' }}</button>
|
||||||
</div>
|
</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
|
<el-alert v-if="ov.sector_ready===false" class="banner" type="warning" effect="dark" show-icon
|
||||||
:closable="false"
|
:closable="false"
|
||||||
title="行业划分数据源未配置 —— 行业集中度硬拦截已停用, 行业类命令置灰 (设计 §5)"></el-alert>
|
title="行业划分数据源未配置 —— 行业集中度硬拦截已停用, 行业类命令置灰 (设计 §5)"></el-alert>
|
||||||
<el-alert v-if="ov.price_missing && ov.price_missing.length" class="banner" type="warning"
|
<el-alert v-if="marketOpen && ov.price_missing && ov.price_missing.length" class="banner" type="warning"
|
||||||
effect="dark" show-icon :closable="false"
|
show-icon :closable="false"
|
||||||
:title="'以下持仓取不到实时价, 已用摊薄成本兜底: ' + ov.price_missing.join(', ')"></el-alert>
|
: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
|
<el-alert v-if="health.calendar_degraded" class="banner" type="warning" effect="dark" show-icon
|
||||||
:closable="false" title="交易日历降级: 未安装 chinesecalendar, 节假日不可辨"></el-alert>
|
:closable="false" title="交易日历降级: 未安装 chinesecalendar, 节假日不可辨"></el-alert>
|
||||||
<el-alert v-if="dm.shadow" class="banner" type="info" effect="dark" show-icon :closable="false"
|
<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 showLedger = ref(false); // 「今天发生了什么」默认折叠
|
||||||
const showOpLog = ref(false); // 操作日志默认折叠
|
const showOpLog = ref(false); // 操作日志默认折叠
|
||||||
const showSettings = ref(false); // 设置默认折叠
|
const showSettings = ref(false); // 设置默认折叠
|
||||||
|
const lastRefresh = ref('');
|
||||||
|
const autoRefresh = ref(true);
|
||||||
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,
|
||||||
|
|
@ -1408,6 +1415,16 @@ createApp({
|
||||||
const heldPositions = computed(() => (positions.value || []).filter(p => (p.total_qty || 0) > 0));
|
const heldPositions = computed(() => (positions.value || []).filter(p => (p.total_qty || 0) > 0));
|
||||||
// ---- 今日在办分档 + 候选处置 (2026-08-12 重构新增) ----
|
// ---- 今日在办分档 + 候选处置 (2026-08-12 重构新增) ----
|
||||||
const todayYmd = computed(() => (String(health.value.now || '').slice(0, 10).replace(/-/g, '')) || '');
|
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 _LIVE_INS = ['PROPOSED', 'RULE_PASSED', 'JUDGE_PASSED', 'DISPATCHED'];
|
||||||
const _sameDayIns = r => { const y = todayYmd.value;
|
const _sameDayIns = r => { const y = todayYmd.value;
|
||||||
return !y || String(r.instruction_id || '').indexOf('INS_' + y + '_') === 0; };
|
return !y || String(r.instruction_id || '').indexOf('INS_' + y + '_') === 0; };
|
||||||
|
|
@ -1448,8 +1465,8 @@ createApp({
|
||||||
if (o.buy_halt) out.push('已暂停买入(卖出与止损不受影响)');
|
if (o.buy_halt) out.push('已暂停买入(卖出与止损不受影响)');
|
||||||
if (o.exec_halt) out.push('休假模式:所有自动动作暂停,仅保留对账与日报');
|
if (o.exec_halt) out.push('休假模式:所有自动动作暂停,仅保留对账与日报');
|
||||||
if (o.brake_until) out.push('组合刹车中(解除日 ' + o.brake_until + ')');
|
if (o.brake_until) out.push('组合刹车中(解除日 ' + o.brake_until + ')');
|
||||||
if ((o.price_missing || []).length)
|
if (marketOpen.value && (o.price_missing || []).length)
|
||||||
out.push(o.price_missing.length + ' 只取不到实时价(停牌等),其盈亏与安全垫暂不可用');
|
out.push(o.price_missing.length + ' 只取不到实时价(停牌或行情中断),其盈亏与安全垫暂不可用');
|
||||||
if (o.sector_ready === false) out.push('行业数据未就绪,行业类操作暂不可用');
|
if (o.sector_ready === false) out.push('行业数据未就绪,行业类操作暂不可用');
|
||||||
const j = (dm.value || {}).judge;
|
const j = (dm.value || {}).judge;
|
||||||
if (j && j.available === false) out.push('决策系统暂不可用:补足/加仓/补仓一律降级为需你确认');
|
if (j && j.available === false) out.push('决策系统暂不可用:补足/加仓/补仓一律降级为需你确认');
|
||||||
|
|
@ -1703,6 +1720,7 @@ createApp({
|
||||||
loadPositions(), loadInstructions(), loadLedger(), loadProposals(),
|
loadPositions(), loadInstructions(), loadLedger(), loadProposals(),
|
||||||
loadDispatchMode(), loadWs(), loadStrategies(), loadOpLog(), loadOpenScan()]);
|
loadDispatchMode(), loadWs(), loadStrategies(), loadOpLog(), loadOpenScan()]);
|
||||||
await loadNames();
|
await loadNames();
|
||||||
|
lastRefresh.value = (health.value.now || '').slice(11, 19);
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
wsPollSync();
|
wsPollSync();
|
||||||
}
|
}
|
||||||
|
|
@ -1896,7 +1914,24 @@ createApp({
|
||||||
reportDrawer.value = true;
|
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,
|
return { tab, loading, err, health, ov, params, catalog, commands, plans, plansOf,
|
||||||
positions, lots, lotsOf, instructions, ledger, proposals, report, reportDrawer,
|
positions, lots, lotsOf, instructions, ledger, proposals, report, reportDrawer,
|
||||||
opsDrawer, opsResult, opsLoading, issuing, form, curSpec, dirtyCount, dm,
|
opsDrawer, opsResult, opsLoading, issuing, form, curSpec, dirtyCount, dm,
|
||||||
|
|
@ -1918,7 +1953,7 @@ createApp({
|
||||||
openStrategy, validateStrategy, attachStrategy, setStrategyStatus, stratStateText, resumeBuy,
|
openStrategy, validateStrategy, attachStrategy, setStrategyStatus, stratStateText, resumeBuy,
|
||||||
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 };
|
showOpLog, showSettings, watchCandidates, marketOpen, marketState, lastRefresh, autoRefresh };
|
||||||
}
|
}
|
||||||
}).use(ElementPlus).mount('#app');
|
}).use(ElementPlus).mount('#app');
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue