Refine monitor 2x2 slots and drop tablet CSS.
Add options target column, reserve pos/monitor rows, equal columns, and remove hub-tablet densify path. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,6 +4,33 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 2026-07-16 · 监控区 2×2 细化(目标监控列/预留行/去平板专属)
|
||||||
|
|
||||||
|
### 修改原因
|
||||||
|
|
||||||
|
四卡对齐后需:左右等宽;期权表改目标监控列;去掉打开期权页与永续卡「期权 N仓」;合约卡预留仓位+监控位两行并统一全屏提示;多仓时同行左右一起长高;平板改用浏览器 80% 缩放,去掉 hub-tablet 专属样式(手机 UI 不动)。
|
||||||
|
|
||||||
|
### 修改的地方
|
||||||
|
|
||||||
|
| 文件 | 改动摘要 |
|
||||||
|
|------|----------|
|
||||||
|
| `manual_trading_hub/static/app.js` | 平铺 `monitor-split-2x2`;期权表删指数/到期平衡/平掉回本,加目标监控列(有=绿/无=`—`);去打开期权页;永续卡隐藏期权徽章;预留仓位/监控位槽;去掉 `isTabletLayout` |
|
||||||
|
| `manual_trading_hub/static/app.css` | 左右 1:1;`minmax(min-content,1fr)` 同行同高可外扩;删除全部 `hub-tablet` 规则 |
|
||||||
|
| `manual_trading_hub/static/index.html` | 缓存 `20260716-hub-2x2-slots` |
|
||||||
|
|
||||||
|
### 达成的目标
|
||||||
|
|
||||||
|
桌面监控区四卡等宽对齐;期权看目标监控列;永续卡结构为仓位行+监控位行+提示行;≥2 仓左右一起加高;平板不再走单独 CSS。
|
||||||
|
|
||||||
|
### 交付之后的验收
|
||||||
|
|
||||||
|
1. 左右列等宽;永续卡无「期权 1仓」、无「打开期权页」。
|
||||||
|
2. 期权表有「目标监控」列,有监控绿色、无则 `—`;无指数/到期平衡/平掉回本。
|
||||||
|
3. 永续/币安卡可见预留仓位行、监控位行与完整全屏提示文案。
|
||||||
|
4. 多开仓后该行变高且左右同高;`body` 无 `hub-tablet`;手机布局未改。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 2026-07-16 · OKX 拆成永续/期权双卡(2×2 对齐)
|
## 2026-07-16 · OKX 拆成永续/期权双卡(2×2 对齐)
|
||||||
|
|
||||||
### 修改原因
|
### 修改原因
|
||||||
|
|||||||
@@ -1271,6 +1271,30 @@ html[data-theme="light"] .host-metric-bar {
|
|||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 四卡平铺 2×2:左右等宽;同行同高;多仓时该行 min-content 变高,左右一起长 */
|
||||||
|
.monitor-split-body.monitor-split-2x2 {
|
||||||
|
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
||||||
|
grid-template-rows: minmax(min-content, 1fr) minmax(min-content, 1fr);
|
||||||
|
gap: 12px;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.monitor-split-2x2 > .card {
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 0;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.monitor-split-2x2 > .card-monitor-placeholder {
|
||||||
|
visibility: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
.monitor-split-left,
|
.monitor-split-left,
|
||||||
.monitor-split-right {
|
.monitor-split-right {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
@@ -1305,10 +1329,27 @@ html[data-theme="light"] .host-metric-bar {
|
|||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hub-slot-pos,
|
||||||
|
.hub-slot-monitor {
|
||||||
|
min-height: 2.4em;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hub-slot-pos[data-pos-count="0"] .empty-hint,
|
||||||
|
.hub-slot-monitor[data-key-count="0"] .empty-hint {
|
||||||
|
margin: 0;
|
||||||
|
padding: 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hub-opt-target-cell.is-on {
|
||||||
|
color: var(--green);
|
||||||
|
font-weight: 600;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|
||||||
.hub-inner-cards {
|
.hub-inner-cards {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: grid;
|
display: grid;
|
||||||
/* 永续按内容高度,期权吃剩余 —— 避免「无持仓」半屏空洞 */
|
|
||||||
grid-template-rows: auto minmax(0, 1fr);
|
grid-template-rows: auto minmax(0, 1fr);
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
@@ -1364,8 +1405,10 @@ html[data-theme="light"] .host-metric-bar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 960px) {
|
@media (max-width: 960px) {
|
||||||
.monitor-split-body {
|
.monitor-split-body,
|
||||||
|
.monitor-split-body.monitor-split-2x2 {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-rows: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.monitor-split-left,
|
.monitor-split-left,
|
||||||
@@ -9789,7 +9832,7 @@ html[data-theme="light"] .hub-logs-card-hint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── 一屏适配:桌面 1080p + 平板 CSS 视口(2560×1600@2x≈1280×800) ── */
|
/* ── 一屏适配:桌面(含用户自行缩放的平板视口);手机端 .hub-phone 另走 ── */
|
||||||
@media (min-width: 721px) and (min-height: 650px) {
|
@media (min-width: 721px) and (min-height: 650px) {
|
||||||
body.hub-page-monitor:not(.hub-phone) .app-shell,
|
body.hub-page-monitor:not(.hub-phone) .app-shell,
|
||||||
body.hub-page-market:not(.hub-phone) .app-shell,
|
body.hub-page-market:not(.hub-phone) .app-shell,
|
||||||
@@ -9801,7 +9844,8 @@ html[data-theme="light"] .hub-logs-card-hint {
|
|||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.hub-page-monitor:not(.hub-phone) .app-header,
|
body.hub-page-monitor:not(.hub-phone) .app-header,
|
||||||
@@ -9818,7 +9862,7 @@ html[data-theme="light"] .hub-logs-card-hint {
|
|||||||
min-height: 0;
|
min-height: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.hub-page-monitor:not(.hub-phone) #page-monitor > .page-head {
|
body.hub-page-monitor:not(.hub-phone) #page-monitor > .page-head {
|
||||||
@@ -9858,7 +9902,7 @@ html[data-theme="light"] .hub-logs-card-hint {
|
|||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
overflow: hidden;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.hub-page-monitor:not(.hub-phone) .grid-monitor.grid-monitor-options-split {
|
body.hub-page-monitor:not(.hub-phone) .grid-monitor.grid-monitor-options-split {
|
||||||
@@ -9893,6 +9937,12 @@ html[data-theme="light"] .hub-logs-card-hint {
|
|||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.hub-page-monitor:not(.hub-phone) .monitor-split-body.monitor-split-2x2 {
|
||||||
|
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
||||||
|
grid-template-rows: minmax(min-content, 1fr) minmax(min-content, 1fr);
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
body.hub-page-monitor:not(.hub-phone) .monitor-split-left,
|
body.hub-page-monitor:not(.hub-phone) .monitor-split-left,
|
||||||
body.hub-page-monitor:not(.hub-phone) .monitor-split-right {
|
body.hub-page-monitor:not(.hub-phone) .monitor-split-right {
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
@@ -9902,7 +9952,8 @@ html[data-theme="light"] .hub-logs-card-hint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body.hub-page-monitor:not(.hub-phone) .monitor-split-left > .card,
|
body.hub-page-monitor:not(.hub-phone) .monitor-split-left > .card,
|
||||||
body.hub-page-monitor:not(.hub-phone) .monitor-split-right > .card {
|
body.hub-page-monitor:not(.hub-phone) .monitor-split-right > .card,
|
||||||
|
body.hub-page-monitor:not(.hub-phone) .monitor-split-2x2 > .card {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
@@ -9971,13 +10022,6 @@ html[data-theme="light"] .hub-logs-card-hint {
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 1080p 短屏:左侧略宽,把横向空间给 OKX 期权表 */
|
|
||||||
@media (max-height: 1100px) {
|
|
||||||
body.hub-page-monitor:not(.hub-phone) .grid-monitor-options-split .monitor-split-body {
|
|
||||||
grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* —— 行情区 —— */
|
/* —— 行情区 —— */
|
||||||
body.hub-page-market:not(.hub-phone) #page-market {
|
body.hub-page-market:not(.hub-phone) #page-market {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
@@ -10109,425 +10153,3 @@ html[data-theme="light"] .hub-logs-card-hint {
|
|||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 平板(hub-tablet):一屏 + 提密度 + 不裁切正文。
|
|
||||||
* 典型 CSS 视口 ~1280×800 横 / ~800×1280 竖。
|
|
||||||
* 外壳锁 100dvh;字号/间距压缩让常规内容装下;
|
|
||||||
* 持仓很多时仅表体内滚,不把卡片文字拦腰切掉。
|
|
||||||
*/
|
|
||||||
body.hub-tablet:not(.hub-phone).hub-page-monitor .app-shell,
|
|
||||||
body.hub-tablet:not(.hub-phone).hub-page-funds .app-shell,
|
|
||||||
body.hub-tablet:not(.hub-phone).hub-page-market .app-shell {
|
|
||||||
height: 100dvh;
|
|
||||||
max-height: 100dvh;
|
|
||||||
overflow: hidden;
|
|
||||||
padding-top: 0;
|
|
||||||
padding-bottom: max(6px, env(safe-area-inset-bottom));
|
|
||||||
padding-left: max(10px, env(safe-area-inset-left));
|
|
||||||
padding-right: max(10px, env(safe-area-inset-right));
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet:not(.hub-phone).hub-page-monitor .app-header,
|
|
||||||
body.hub-tablet:not(.hub-phone).hub-page-funds .app-header,
|
|
||||||
body.hub-tablet:not(.hub-phone).hub-page-market .app-header {
|
|
||||||
padding: 6px 0 4px;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet:not(.hub-phone) .brand-sub {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet:not(.hub-phone) .brand-title {
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet:not(.hub-phone) .top-nav a {
|
|
||||||
font-size: 11px;
|
|
||||||
padding: 4px 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* —— 监控区:一屏 flex + 密度 —— */
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) #page-monitor {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
min-height: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) #page-monitor > .page-head {
|
|
||||||
margin: 4px 0 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) #page-monitor > .page-head h1 {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) #page-monitor .page-desc {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) #page-monitor .grid-monitor {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
min-height: 0;
|
|
||||||
gap: 6px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .grid-monitor.grid-monitor-options-split {
|
|
||||||
height: 100%;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .grid-monitor-options-split .monitor-stats-card {
|
|
||||||
padding: 4px 8px;
|
|
||||||
gap: 8px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .grid-monitor-options-split .monitor-stat-label {
|
|
||||||
font-size: 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .grid-monitor-options-split .monitor-stat-value {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .grid-monitor-options-split .monitor-stat-sub {
|
|
||||||
font-size: 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .grid-monitor-options-split .monitor-split-body {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
min-height: 0;
|
|
||||||
height: auto;
|
|
||||||
gap: 6px;
|
|
||||||
align-items: stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .monitor-split-left > .card,
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .monitor-split-right > .card {
|
|
||||||
height: 100%;
|
|
||||||
min-height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .monitor-split-left,
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .monitor-split-right {
|
|
||||||
grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
|
|
||||||
align-content: stretch;
|
|
||||||
gap: 6px;
|
|
||||||
min-height: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 竖屏(<960)叠成 OKX 两卡在上 + Gate/币安并排 */
|
|
||||||
@media (max-width: 960px) {
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .monitor-split-body {
|
|
||||||
grid-template-rows: minmax(0, 1.35fr) minmax(0, 1fr);
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .monitor-split-left {
|
|
||||||
grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .monitor-split-right {
|
|
||||||
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
||||||
grid-template-rows: minmax(0, 1fr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .card-monitor-okx-split,
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .card-monitor-split-side {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .card-monitor-okx-split .card-head,
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .card-monitor-split-side .card-head {
|
|
||||||
padding: 5px 8px;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .card-title {
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .card-sub {
|
|
||||||
font-size: 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .card-actions {
|
|
||||||
gap: 4px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
max-width: 46%;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .card-actions .btn-link,
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .card-actions button {
|
|
||||||
font-size: 10px;
|
|
||||||
padding: 3px 6px;
|
|
||||||
min-height: 0;
|
|
||||||
line-height: 1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .card-monitor-okx-split .card-body,
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .card-monitor-split-side .card-body {
|
|
||||||
padding: 6px 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
min-height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .hub-inner-cards {
|
|
||||||
grid-template-rows: auto minmax(0, 1fr);
|
|
||||||
gap: 5px;
|
|
||||||
min-height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .hub-inner-card {
|
|
||||||
overflow: hidden;
|
|
||||||
min-height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .hub-inner-card-head {
|
|
||||||
padding: 4px 6px;
|
|
||||||
font-size: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .hub-inner-card-body {
|
|
||||||
padding: 5px 6px;
|
|
||||||
overflow: auto;
|
|
||||||
min-height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .stat-row {
|
|
||||||
gap: 6px;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .stat-box {
|
|
||||||
padding: 5px 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .stat-label {
|
|
||||||
font-size: 9px;
|
|
||||||
margin-bottom: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .stat-value {
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .stat-value small {
|
|
||||||
font-size: 10px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .section-title {
|
|
||||||
margin: 4px 0 3px;
|
|
||||||
padding-bottom: 3px;
|
|
||||||
font-size: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .empty-hint {
|
|
||||||
padding: 4px 0;
|
|
||||||
font-size: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .grid-monitor-options-split .hub-options-table-wrap,
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .grid-monitor-options-split .pos-table-wrap,
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .grid-monitor-options-split .table-scroll {
|
|
||||||
overflow: auto;
|
|
||||||
max-height: 100%;
|
|
||||||
min-height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .data-table th,
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .data-table td {
|
|
||||||
padding: 3px 4px;
|
|
||||||
font-size: 10px;
|
|
||||||
line-height: 1.25;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-monitor:not(.hub-phone) .data-table th {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* —— 资金概况:一屏 + 曲线让位给分户卡片 —— */
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) #page-funds,
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-stage,
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-stage-inner {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
min-height: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-stage-inner {
|
|
||||||
padding: 6px 8px 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-head {
|
|
||||||
margin-bottom: 2px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-head h1 {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-desc-fold {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-toolbar {
|
|
||||||
margin-bottom: 4px;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-pnl-banner {
|
|
||||||
padding: 6px 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-pnl-value {
|
|
||||||
font-size: 1.05rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-summary {
|
|
||||||
margin-bottom: 4px;
|
|
||||||
gap: 6px;
|
|
||||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-stat-card {
|
|
||||||
padding: 6px 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-stat-label {
|
|
||||||
font-size: 0.55rem;
|
|
||||||
margin-bottom: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-stat-value {
|
|
||||||
font-size: 0.98rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-stat-card-primary .funds-stat-value {
|
|
||||||
font-size: 1.08rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-stat-sub {
|
|
||||||
font-size: 0.62rem;
|
|
||||||
margin-top: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-meta {
|
|
||||||
margin: 0 0 4px;
|
|
||||||
padding: 3px 6px;
|
|
||||||
font-size: 0.68rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-chart-panel {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
min-height: 90px;
|
|
||||||
max-height: 26vh;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-chart-head {
|
|
||||||
padding: 4px 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-chart-tag {
|
|
||||||
font-size: 0.58rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-chart-host {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
height: auto;
|
|
||||||
min-height: 70px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-section-head {
|
|
||||||
margin-bottom: 4px;
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-accounts {
|
|
||||||
flex: 0 1 auto;
|
|
||||||
min-height: 0;
|
|
||||||
max-height: 34vh;
|
|
||||||
overflow: auto;
|
|
||||||
gap: 6px;
|
|
||||||
padding: 0;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-ac-card {
|
|
||||||
padding: 7px 9px;
|
|
||||||
gap: 5px;
|
|
||||||
overflow: visible;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-ac-name {
|
|
||||||
font-size: 0.72rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-ac-badge {
|
|
||||||
font-size: 0.58rem;
|
|
||||||
padding: 1px 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-ac-total {
|
|
||||||
padding: 5px 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-ac-total .k {
|
|
||||||
font-size: 0.62rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-ac-total .v {
|
|
||||||
font-size: 0.92rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-ac-stats {
|
|
||||||
gap: 4px 8px;
|
|
||||||
font-size: 0.68rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-ac-stats .k {
|
|
||||||
font-size: 0.58rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-ac-foot {
|
|
||||||
padding-top: 5px;
|
|
||||||
font-size: 0.62rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 960px) {
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-summary {
|
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-chart-panel {
|
|
||||||
max-height: 22vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-funds:not(.hub-phone) .funds-accounts {
|
|
||||||
max-height: 38vh;
|
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* —— 行情:一屏图表 —— */
|
|
||||||
body.hub-tablet.hub-page-market:not(.hub-phone) #page-market > .page-head h1 {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.hub-tablet.hub-page-market:not(.hub-phone) #page-market .market-ohlcv-bar {
|
|
||||||
padding: 5px 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -72,30 +72,14 @@
|
|||||||
|
|
||||||
const HUB_PHONE_PRIMARY = { monitor: 1, market: 1, calculator: 1, ai: 1 };
|
const HUB_PHONE_PRIMARY = { monitor: 1, market: 1, calculator: 1, ai: 1 };
|
||||||
|
|
||||||
/** 窄屏布局:仅按视口宽度,监控区/行情等共用 */
|
/** 窄屏布局:仅按视口宽度,监控区/行情等共用;手机端 UI 不改 */
|
||||||
function isMobileLayout() {
|
function isMobileLayout() {
|
||||||
return window.matchMedia("(max-width: 720px)").matches;
|
return window.matchMedia("(max-width: 720px)").matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 平板 CSS 视口(如 2560×1600@2x≈1280×800, 竖屏≈800×1280)。
|
|
||||||
* 禁止「仅按高度」判断:1080p 电脑开任务栏/浏览器栏时 innerHeight 常 ≤920,
|
|
||||||
* 会误加 hub-tablet,字号被压到 ~10px,看起来发糊。
|
|
||||||
*/
|
|
||||||
function isTabletLayout() {
|
|
||||||
if (isMobileLayout()) return false;
|
|
||||||
const w = window.innerWidth || 0;
|
|
||||||
const h = window.innerHeight || 0;
|
|
||||||
// 横屏平板:中等宽度 + 偏矮
|
|
||||||
if (w >= 721 && w <= 1366 && h > 0 && h <= 900) return true;
|
|
||||||
// 竖屏平板:偏窄 + 偏高
|
|
||||||
if (w >= 721 && w <= 920 && h >= 900) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function syncHubPhoneShellClass() {
|
function syncHubPhoneShellClass() {
|
||||||
document.body.classList.toggle("hub-phone", isMobileLayout());
|
document.body.classList.toggle("hub-phone", isMobileLayout());
|
||||||
document.body.classList.toggle("hub-tablet", isTabletLayout());
|
document.body.classList.remove("hub-tablet");
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeHubMobileMore() {
|
function closeHubMobileMore() {
|
||||||
@@ -2434,17 +2418,19 @@
|
|||||||
if (optionsSplit) {
|
if (optionsSplit) {
|
||||||
const okxRow = displayRows.find((r) => rowHasOptionsLayout(r));
|
const okxRow = displayRows.find((r) => rowHasOptionsLayout(r));
|
||||||
const otherRows = displayRows.filter((r) => !rowHasOptionsLayout(r));
|
const otherRows = displayRows.filter((r) => !rowHasOptionsLayout(r));
|
||||||
/* OKX 拆成永续+期权两张独立卡,与右侧两所组成 2×2 对齐 */
|
const ph =
|
||||||
const leftHtml = okxRow
|
'<div class="card card-monitor-split-side card-monitor-placeholder" aria-hidden="true"></div>';
|
||||||
? renderMonitorCard(okxRow, { okxPart: "perp", splitSide: true }) +
|
/* 平铺 2×2 顺序:永续|币安 / 期权|Gate —— 同行左右同高,多仓时该行一起长高 */
|
||||||
renderMonitorCard(okxRow, { okxPart: "options", splitSide: true })
|
const cells = [
|
||||||
: "";
|
okxRow ? renderMonitorCard(okxRow, { okxPart: "perp", splitSide: true }) : ph,
|
||||||
const rightHtml = otherRows.map((r) => renderMonitorCard(r, { splitSide: true })).join("");
|
otherRows[0] ? renderMonitorCard(otherRows[0], { splitSide: true }) : ph,
|
||||||
cardsHtml =
|
okxRow ? renderMonitorCard(okxRow, { okxPart: "options", splitSide: true }) : ph,
|
||||||
`<div class="monitor-split-body">` +
|
otherRows[1] ? renderMonitorCard(otherRows[1], { splitSide: true }) : ph,
|
||||||
`<div class="monitor-split-left">${leftHtml}</div>` +
|
];
|
||||||
`<div class="monitor-split-right">${rightHtml}</div>` +
|
for (let i = 2; i < otherRows.length; i++) {
|
||||||
`</div>`;
|
cells.push(renderMonitorCard(otherRows[i], { splitSide: true }));
|
||||||
|
}
|
||||||
|
cardsHtml = `<div class="monitor-split-body monitor-split-2x2">${cells.join("")}</div>`;
|
||||||
} else {
|
} else {
|
||||||
cardsHtml =
|
cardsHtml =
|
||||||
displayRows
|
displayRows
|
||||||
@@ -3609,11 +3595,12 @@
|
|||||||
return counts;
|
return counts;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderCardStrategyStats(row, hm, flaskOk) {
|
function renderCardStrategyStats(row, hm, flaskOk, opts) {
|
||||||
|
const options = opts || {};
|
||||||
const caps = row.capabilities || [];
|
const caps = row.capabilities || [];
|
||||||
const chips = [];
|
const chips = [];
|
||||||
if (flaskOk && hm && typeof hm === "object") {
|
if (flaskOk && hm && typeof hm === "object") {
|
||||||
if (caps.includes("key")) {
|
if (caps.includes("key") && !options.hideKeyChips) {
|
||||||
const kc = countKeyMonitorsByBucket(hm.keys || []);
|
const kc = countKeyMonitorsByBucket(hm.keys || []);
|
||||||
if (kc.breakout > 0) chips.push({ kind: "key-breakout", label: `突破 ${kc.breakout}` });
|
if (kc.breakout > 0) chips.push({ kind: "key-breakout", label: `突破 ${kc.breakout}` });
|
||||||
if (kc.fib > 0) chips.push({ kind: "key-breakout", label: `斐波 ${kc.fib}` });
|
if (kc.fib > 0) chips.push({ kind: "key-breakout", label: `斐波 ${kc.fib}` });
|
||||||
@@ -3626,8 +3613,8 @@
|
|||||||
const rollN = Array.isArray(hm.rolls) ? hm.rolls.length : 0;
|
const rollN = Array.isArray(hm.rolls) ? hm.rolls.length : 0;
|
||||||
if (rollN > 0) chips.push({ kind: "roll", label: `顺势加仓 ${rollN}` });
|
if (rollN > 0) chips.push({ kind: "roll", label: `顺势加仓 ${rollN}` });
|
||||||
}
|
}
|
||||||
// OKX/已勾选期权能力:磁贴始终展示期权入口态(含 0 仓)
|
// 永续独立卡不再显示「期权 N仓」(期权只看期权卡);手机磁贴仍可显示
|
||||||
if (caps.includes("options") || rowHasOptionsLayout(row)) {
|
if (!options.hideOptions && (caps.includes("options") || rowHasOptionsLayout(row))) {
|
||||||
const opt = row.options || {};
|
const opt = row.options || {};
|
||||||
if (opt.enabled === false) {
|
if (opt.enabled === false) {
|
||||||
chips.push({ kind: "options", label: "期权 · 未启用" });
|
chips.push({ kind: "options", label: "期权 · 未启用" });
|
||||||
@@ -3722,13 +3709,37 @@
|
|||||||
return `<span class="opt-expiry-cd" data-opt-exp-ms="${esc(ms)}">—</span>`;
|
return `<span class="opt-expiry-cd" data-opt-exp-ms="${esc(ms)}">—</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderOptionsPositionsTable(pos) {
|
function findOptionsTargetForInst(targets, instId) {
|
||||||
if (!pos.length) return '<div class="empty-hint">暂无期权持仓</div>';
|
const want = String(instId || "").trim();
|
||||||
|
if (!want) return null;
|
||||||
|
const list = Array.isArray(targets) ? targets : [];
|
||||||
|
return (
|
||||||
|
list.find((t) => String((t && t.inst_id) || "").trim() === want) ||
|
||||||
|
list.find((t) => String((t && t.instId) || "").trim() === want) ||
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderOptionsTargetCell(target) {
|
||||||
|
if (!target) return "<td>—</td>";
|
||||||
|
const side = String(target.opt_type || "").toUpperCase() === "P" ? "Put≤" : "Call≥";
|
||||||
|
const px = target.target_index != null ? fmt(target.target_index, 1) : "—";
|
||||||
|
return `<td class="hub-opt-target-cell is-on" title="目标监控">${esc(side)} ${esc(px)}</td>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderOptionsPositionsTable(pos, targets) {
|
||||||
|
if (!pos.length) return '<div class="empty-hint hub-slot-pos">暂无期权持仓</div>';
|
||||||
let html = '<div class="table-wrap hub-options-table-wrap"><table class="hub-options-table"><thead><tr>';
|
let html = '<div class="table-wrap hub-options-table-wrap"><table class="hub-options-table"><thead><tr>';
|
||||||
html += "<th>合约</th><th>类型</th><th>张数</th><th>到期倒计时</th><th>指数</th><th>到期平衡</th><th>平掉回本</th><th>净盈亏</th><th>收益率</th>";
|
html +=
|
||||||
|
"<th>合约</th><th>类型</th><th>张数</th><th>到期倒计时</th><th>目标监控</th><th>净盈亏</th><th>收益率</th>";
|
||||||
html += "</tr></thead><tbody>";
|
html += "</tr></thead><tbody>";
|
||||||
pos.forEach((p) => {
|
pos.forEach((p) => {
|
||||||
const optType = (p.opt_type || "").toUpperCase() === "C" ? "Call" : (p.opt_type || "").toUpperCase() === "P" ? "Put" : (p.opt_type || "—");
|
const optType =
|
||||||
|
(p.opt_type || "").toUpperCase() === "C"
|
||||||
|
? "Call"
|
||||||
|
: (p.opt_type || "").toUpperCase() === "P"
|
||||||
|
? "Put"
|
||||||
|
: p.opt_type || "—";
|
||||||
const preview = p.close_preview || {};
|
const preview = p.close_preview || {};
|
||||||
let net = preview.estimated_pnl;
|
let net = preview.estimated_pnl;
|
||||||
if (net == null && preview.total_received != null && p.premium_paid != null) {
|
if (net == null && preview.total_received != null && p.premium_paid != null) {
|
||||||
@@ -3738,14 +3749,13 @@
|
|||||||
if (roi == null && net != null && Number(p.premium_paid) > 0) {
|
if (roi == null && net != null && Number(p.premium_paid) > 0) {
|
||||||
roi = (Number(net) / Number(p.premium_paid)) * 100;
|
roi = (Number(net) / Number(p.premium_paid)) * 100;
|
||||||
}
|
}
|
||||||
|
const target = findOptionsTargetForInst(targets, p.inst_id);
|
||||||
html += `<tr>
|
html += `<tr>
|
||||||
<td><code class="hub-options-inst" title="${esc(p.inst_id || "")}">${esc(shortOptionsInst(p.inst_id))}</code></td>
|
<td><code class="hub-options-inst" title="${esc(p.inst_id || "")}">${esc(shortOptionsInst(p.inst_id))}</code></td>
|
||||||
<td>${esc(optType)}</td>
|
<td>${esc(optType)}</td>
|
||||||
<td>${esc(p.pos)}</td>
|
<td>${esc(p.pos)}</td>
|
||||||
<td>${optionsExpiryCdHtml(p.exp_time_ms != null ? p.exp_time_ms : p.exp_time)}</td>
|
<td>${optionsExpiryCdHtml(p.exp_time_ms != null ? p.exp_time_ms : p.exp_time)}</td>
|
||||||
<td>${p.idx_px != null ? fmt(p.idx_px, 0) : "—"}</td>
|
${renderOptionsTargetCell(target)}
|
||||||
<td>${p.expiry_be_px != null ? fmt(p.expiry_be_px, 0) : "—"}</td>
|
|
||||||
<td>${p.close_be_px != null ? fmt(p.close_be_px, 0) : "—"}</td>
|
|
||||||
<td class="${pnlCls(net)}">${net == null ? "—" : fmt(net, 2)}</td>
|
<td class="${pnlCls(net)}">${net == null ? "—" : fmt(net, 2)}</td>
|
||||||
<td class="${pnlCls(net)}">${roi == null ? "—" : esc(Number(roi).toFixed(2)) + "%"}</td>
|
<td class="${pnlCls(net)}">${roi == null ? "—" : esc(Number(roi).toFixed(2)) + "%"}</td>
|
||||||
</tr>`;
|
</tr>`;
|
||||||
@@ -3801,20 +3811,11 @@
|
|||||||
const targets = Array.isArray(opt.target_monitors) ? opt.target_monitors : [];
|
const targets = Array.isArray(opt.target_monitors) ? opt.target_monitors : [];
|
||||||
const bal = optionsBalanceFields(opt);
|
const bal = optionsBalanceFields(opt);
|
||||||
html += renderStatRow(bal.funding, bal.trading, bal.upl);
|
html += renderStatRow(bal.funding, bal.trading, bal.upl);
|
||||||
if (targets.length) {
|
|
||||||
html += `<div class="section-title hub-options-title">目标监控 · ${targets.length}</div>`;
|
|
||||||
html += '<div class="hub-opt-target-list">';
|
|
||||||
targets.forEach((t) => {
|
|
||||||
const side = String(t.opt_type || "").toUpperCase() === "P" ? "Put ≤" : "Call ≥";
|
|
||||||
html += `<div class="hub-opt-target-item"><code title="${esc(t.inst_id || "")}">${esc(shortOptionsInst(t.inst_id))}</code> <span>${side} ${esc(fmt(t.target_index, 1))}</span></div>`;
|
|
||||||
});
|
|
||||||
html += "</div>";
|
|
||||||
}
|
|
||||||
html += `<div class="section-title hub-options-title">期权持仓 · ${pos.length} 仓</div>`;
|
html += `<div class="section-title hub-options-title">期权持仓 · ${pos.length} 仓</div>`;
|
||||||
html += layout === "cards" ? renderOptionsPositionsCards(pos) : renderOptionsPositionsTable(pos);
|
html +=
|
||||||
if (row.flask_url_browser || row.flask_url) {
|
layout === "cards"
|
||||||
html += `<div class="hub-options-actions"><a class="btn-link btn-open-instance" href="#" data-ex-id="${esc(row.id)}" data-next="/options">打开期权页</a></div>`;
|
? renderOptionsPositionsCards(pos)
|
||||||
}
|
: renderOptionsPositionsTable(pos, targets);
|
||||||
}
|
}
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
@@ -3838,9 +3839,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderPerpetualPositionsSection(row, ag, pos, orders, trends, tickMap, intraday) {
|
function renderPerpetualPositionsSection(row, ag, pos, orders, trends, tickMap, intraday) {
|
||||||
|
const n = Array.isArray(pos) ? pos.length : 0;
|
||||||
let html = "";
|
let html = "";
|
||||||
html += `<div class="section-title">交易所持仓 · ${pos.length} 仓</div>`;
|
html += `<div class="section-title">交易所持仓 · ${n} 仓</div>`;
|
||||||
if (pos.length) {
|
html += `<div class="hub-slot-pos" data-pos-count="${n}">`;
|
||||||
|
if (n) {
|
||||||
html += renderGridPositionsTable(
|
html += renderGridPositionsTable(
|
||||||
row.id,
|
row.id,
|
||||||
row.key || row.id,
|
row.key || row.id,
|
||||||
@@ -3853,29 +3856,66 @@
|
|||||||
} else {
|
} else {
|
||||||
html += '<div class="empty-hint">无持仓</div>';
|
html += '<div class="empty-hint">无持仓</div>';
|
||||||
}
|
}
|
||||||
|
html += "</div>";
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderPerpetualKeyMonitorSlot(keys, kmap) {
|
||||||
|
const list = Array.isArray(keys) ? keys : [];
|
||||||
|
let html = `<div class="section-title">监控位 · ${list.length}</div>`;
|
||||||
|
html += `<div class="hub-slot-monitor" data-key-count="${list.length}">`;
|
||||||
|
if (list.length) {
|
||||||
|
const first = list.slice(0, 1);
|
||||||
|
html += renderKeySection(first, kmap || {});
|
||||||
|
if (list.length > 1) {
|
||||||
|
html += `<div class="empty-hint hub-slot-more">另有 ${list.length - 1} 个监控位 · 点标题全屏查看</div>`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
html += '<div class="empty-hint">无监控位</div>';
|
||||||
|
}
|
||||||
|
html += "</div>";
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
const HUB_EXPAND_HINT =
|
||||||
|
"点击标题栏进入全屏 · 委托 / 关键位 / 下单监控 / 趋势回调 / 顺势加仓";
|
||||||
|
|
||||||
function renderGridBody(row, ag, pos, hm, flaskOk, keys, orders, trends, rolls, kmap, layoutOpts) {
|
function renderGridBody(row, ag, pos, hm, flaskOk, keys, orders, trends, rolls, kmap, layoutOpts) {
|
||||||
const layout = layoutOpts || {};
|
const layout = layoutOpts || {};
|
||||||
const tickMap = buildPriceTickMap(row);
|
const tickMap = buildPriceTickMap(row);
|
||||||
const intraday = isIntradayDisciplineRow(row);
|
const intraday = isIntradayDisciplineRow(row);
|
||||||
|
const expandHint = `<div class="card-expand-hint">${esc(HUB_EXPAND_HINT)}</div>`;
|
||||||
let inner = "";
|
let inner = "";
|
||||||
if (layout.okxPart === "perp") {
|
if (layout.okxPart === "perp" || layout.splitSide) {
|
||||||
inner += renderAccountStatRow(row, ag);
|
/* 桌面分栏永续/分所卡:预留仓位行+监控位行+全屏提示;不显示期权 N仓 */
|
||||||
inner += renderPerpetualPositionsSection(row, ag, pos, orders, trends, tickMap, intraday);
|
if (layout.okxPart === "options") {
|
||||||
inner += renderCardStrategyStats(row, hm, flaskOk);
|
inner += renderOptionsSectionBody(row);
|
||||||
inner += `<div class="card-expand-hint">点击标题栏进入全屏</div>`;
|
inner += expandHint;
|
||||||
return inner;
|
return inner;
|
||||||
|
}
|
||||||
|
if (layout.okxPart === "perp" || !rowHasOptionsLayout(row)) {
|
||||||
|
inner += renderAccountStatRow(row, ag);
|
||||||
|
inner += renderPerpetualPositionsSection(row, ag, pos, orders, trends, tickMap, intraday);
|
||||||
|
inner += renderPerpetualKeyMonitorSlot(flaskOk ? keys : [], kmap || {});
|
||||||
|
inner += renderCardStrategyStats(row, hm, flaskOk, {
|
||||||
|
hideOptions: true,
|
||||||
|
hideKeyChips: true,
|
||||||
|
});
|
||||||
|
if (intraday) {
|
||||||
|
inner += `<div class="card-expand-hint">日内纪律:禁手动平仓/改委托 · 整点强制清仓${row.force_close && row.force_close.enabled ? " · " + esc(row.force_close.label || "强制清仓") : ""}</div>`;
|
||||||
|
} else {
|
||||||
|
inner += expandHint;
|
||||||
|
}
|
||||||
|
return inner;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (layout.okxPart === "options") {
|
if (layout.okxPart === "options") {
|
||||||
inner += renderOptionsSectionBody(row);
|
inner += renderOptionsSectionBody(row);
|
||||||
inner += `<div class="card-expand-hint">点击标题栏进入全屏 · 期权专页可下单</div>`;
|
inner += expandHint;
|
||||||
return inner;
|
return inner;
|
||||||
}
|
}
|
||||||
if (rowHasOptionsLayout(row)) {
|
if (rowHasOptionsLayout(row)) {
|
||||||
if (monitorGridOptionsSplit) {
|
if (monitorGridOptionsSplit) {
|
||||||
/* 兼容旧单卡内嵌;正常分栏已走 okxPart 双卡 */
|
|
||||||
inner += '<div class="hub-inner-cards">';
|
inner += '<div class="hub-inner-cards">';
|
||||||
inner += renderPerpetualInnerCard(row, ag, pos, orders, trends, tickMap, intraday);
|
inner += renderPerpetualInnerCard(row, ag, pos, orders, trends, tickMap, intraday);
|
||||||
inner += renderOptionsInnerCard(row);
|
inner += renderOptionsInnerCard(row);
|
||||||
@@ -3895,7 +3935,7 @@
|
|||||||
inner += renderCardStrategyStats(row, hm, flaskOk);
|
inner += renderCardStrategyStats(row, hm, flaskOk);
|
||||||
inner += intraday
|
inner += intraday
|
||||||
? `<div class="card-expand-hint">日内纪律:禁手动平仓/改委托 · 整点强制清仓${row.force_close && row.force_close.enabled ? " · " + esc(row.force_close.label || "强制清仓") : ""}</div>`
|
? `<div class="card-expand-hint">日内纪律:禁手动平仓/改委托 · 整点强制清仓${row.force_close && row.force_close.enabled ? " · " + esc(row.force_close.label || "强制清仓") : ""}</div>`
|
||||||
: `<div class="card-expand-hint">点击标题栏进入全屏 · 委托 / 关键位 / 下单监控 / 趋势回调 / 顺势加仓</div>`;
|
: expandHint;
|
||||||
return inner;
|
return inner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" media="print" onload="this.media='all'" />
|
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" media="print" onload="this.media='all'" />
|
||||||
<noscript><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" /></noscript>
|
<noscript><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" /></noscript>
|
||||||
<link rel="stylesheet" href="/assets/app.css?v=20260716-hub-okx-2x2" />
|
<link rel="stylesheet" href="/assets/app.css?v=20260716-hub-2x2-slots" />
|
||||||
<link rel="stylesheet" href="/assets/trade_stats_calendar.css?v=4" />
|
<link rel="stylesheet" href="/assets/trade_stats_calendar.css?v=4" />
|
||||||
<link rel="stylesheet" href="/assets/account_risk_badge.css?v=4" />
|
<link rel="stylesheet" href="/assets/account_risk_badge.css?v=4" />
|
||||||
<script src="/assets/account_risk_badge.js?v=4"></script>
|
<script src="/assets/account_risk_badge.js?v=4"></script>
|
||||||
@@ -1327,6 +1327,6 @@
|
|||||||
<script src="/assets/options_expiry_countdown.js?v=1"></script>
|
<script src="/assets/options_expiry_countdown.js?v=1"></script>
|
||||||
<script src="/assets/options_position_cards.js?v=1"></script>
|
<script src="/assets/options_position_cards.js?v=1"></script>
|
||||||
<script src="/assets/backup.js?v=1"></script>
|
<script src="/assets/backup.js?v=1"></script>
|
||||||
<script src="/assets/app.js?v=20260716-hub-okx-2x2"></script>
|
<script src="/assets/app.js?v=20260716-hub-2x2-slots"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user