提交
This commit is contained in:
@@ -11,7 +11,8 @@ import {
|
||||
threeWaves, triangle, xabcd,
|
||||
} from '@klinecharts/extension';
|
||||
import { useSettingsStore, TOOLTIP_FIELDS, DEFAULT_TOOLTIP_FIELDS } from '@/stores/settings';
|
||||
import { registerCustomIndicators, computeZhixingSeries, DKX_PERIODS, ZHIXING_NAME, CHIPS_NAME, CHIPS_COL_PX, type ChipsExt } from '@/indicators';
|
||||
import { darkStyles as sharedDarkStyles } from '@/chartStyles';
|
||||
import { registerCustomIndicators, computeZhixingSeries, DKX_PERIODS, ZHIXING_NAME } from '@/indicators';
|
||||
import type { Candle, TooltipField } from '@/api/types';
|
||||
|
||||
// 通达信导入的自定义主图指标注册表;知行序列走 PV 管道按时间戳取预计算值。
|
||||
@@ -95,10 +96,6 @@ const props = defineProps<{
|
||||
showZhixing: boolean;
|
||||
/** 知行指标图例行的板块文本(通达信 HYBLOCK+DYBLOCK 的近似,行业+地域) */
|
||||
zhixingBlocks?: string;
|
||||
/** 主图是否叠加筹码峰(cyq 截面横向直方图,纯 draw 绘制) */
|
||||
showChips: boolean;
|
||||
/** 筹码峰截面数据(父组件按 当前窗口末根/十字线 所在周期取数;null=暂无) */
|
||||
chips?: ChipsExt | null;
|
||||
/** K线周期标签(仅用于 MA 指标名缓存 key) */
|
||||
timeframe: string;
|
||||
/** 浮层显示的指标(可选;缺省=目录全开,空数组=仅日期头) */
|
||||
@@ -114,8 +111,6 @@ const props = defineProps<{
|
||||
const emit = defineEmits<{
|
||||
/** 日期跳转锚点在本次数据窗口里找不到(早于上市/晚于最后一根):请父组件回退到最新行情并提示 */
|
||||
(e: 'centerMiss', ts: number): void;
|
||||
/** 十字线落在某根K线上(开启筹码峰时逐根上报,父组件防抖后取该周期筹码截面) */
|
||||
(e: 'crosshairDate', ts: number): void;
|
||||
}>();
|
||||
|
||||
// A股语义色(黑底高对比);UP/DOWN 跟随设置中的涨跌配色
|
||||
@@ -327,35 +322,9 @@ function maybePrefetch(myEpoch: number) {
|
||||
}
|
||||
|
||||
function darkStyles() {
|
||||
return {
|
||||
grid: { horizontal: { color: '#1C1E24' }, vertical: { color: '#1C1E24' } },
|
||||
// 内建 VOL 等指标柱的涨跌色缺省是库默认绿涨红跌,与全站语义相反;
|
||||
// bars[0] 与库默认项深合并(init 时 merge 到 getDefaultStyles),只覆盖三个颜色键,
|
||||
// UP/DOWN 在 build() 里随 settings 刷新,故切「绿涨红跌」重建后同样生效
|
||||
indicator: { bars: [{ upColor: UP, downColor: DOWN, noChangeColor: '#7A818C' }] },
|
||||
candle: {
|
||||
bar: {
|
||||
upColor: UP, downColor: DOWN,
|
||||
upBorderColor: UP, downBorderColor: DOWN,
|
||||
upWickColor: UP, downWickColor: DOWN,
|
||||
},
|
||||
priceMark: {
|
||||
high: { color: '#9AA0AA' }, low: { color: '#9AA0AA' },
|
||||
last: { upColor: UP, downColor: DOWN },
|
||||
},
|
||||
},
|
||||
xAxis: { axisLine: { color: '#2A2D34' }, tickText: { color: '#9AA0AA', size: 12 }, tickLine: { color: '#2A2D34' } },
|
||||
yAxis: { axisLine: { color: '#2A2D34' }, tickText: { color: '#9AA0AA', size: 12 }, tickLine: { color: '#2A2D34' } },
|
||||
crosshair: {
|
||||
horizontal: { text: { backgroundColor: '#333A45' } },
|
||||
vertical: { text: { backgroundColor: '#333A45' } },
|
||||
},
|
||||
separator: {
|
||||
color: '#23252B',
|
||||
// 悬停/拖拽分隔条时的底色(库默认 8% 蓝在纯黑底上不可见,加重为可感知的拖拽提示)
|
||||
activeBackgroundColor: 'rgba(37, 99, 235, 0.30)',
|
||||
},
|
||||
};
|
||||
// 共享暗色主题(chartStyles.ts);UP/DOWN 在 build() 里随 settings 刷新,
|
||||
// 故切「绿涨红跌」重建后同样生效
|
||||
return sharedDarkStyles(UP, DOWN);
|
||||
}
|
||||
|
||||
// 副图默认高度
|
||||
@@ -437,8 +406,6 @@ function bindCrosshair(ch: Chart) {
|
||||
const idx = ts != null ? idxOfTs(ts) : -1; // 全量数组与指标序列按索引对齐
|
||||
if (idx < 0) { hover.value = null; return; }
|
||||
const k = allData[idx];
|
||||
// 筹码峰跟随:十字线逐根上报(父组件防抖取截面);不开启时不上报,避免无谓事件
|
||||
if (props.showChips) emit('crosshairDate', k.timestamp);
|
||||
const prev = idx > 0 ? allData[idx - 1] : null;
|
||||
const diff = prev ? k.close - prev.close : null;
|
||||
const chg = prev ? (diff! / prev.close) * 100 : null;
|
||||
@@ -662,70 +629,8 @@ function placeTradeTip(px: number, py: number, rowCount: number): { x: number; y
|
||||
return { x, y };
|
||||
}
|
||||
|
||||
// ---------- 筹码峰指标同步(不重建图表:createIndicator 不支持原地改 extendData,
|
||||
// 先删后建即可;数据/开关变化走这里,保留滚动位置与用户画线) ----------
|
||||
function syncChipsIndicator() {
|
||||
if (!chart) return;
|
||||
const exists = chart.getIndicators().some((i) => i.name === CHIPS_NAME);
|
||||
const want = props.showChips && !!props.chips;
|
||||
if (want) {
|
||||
if (exists) chart.removeIndicator({ name: CHIPS_NAME });
|
||||
chart.createIndicator({ name: CHIPS_NAME, paneId: 'candle_pane', extendData: props.chips ?? undefined });
|
||||
syncRightOffset(); // 开关即扩留白(不等数据),数据到达时列直接落在已预留的空白里
|
||||
} else if (exists) {
|
||||
chart.removeIndicator({ name: CHIPS_NAME });
|
||||
restoreRightOffset();
|
||||
} else {
|
||||
restoreRightOffset(); // 数据未到即关:同样要还原已扩出去的留白
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- 筹码峰竖列的右侧留白管理 ----------
|
||||
// klinecharts 滚动状态唯一变量是 diff(最后一根K距绘图区右缘的 bar 数),
|
||||
// setOffsetRightDistance(px) 会把 diff 直接重置为 px/barSpace 并 relayout——等价于
|
||||
// “视口拽回实时位并留 px 空白”。因此只在「右区」(末根K在视野内,getVisibleRange().to
|
||||
// 达到 data 长度)时调用;用户在看历史时绝不调,滚回右区后由 onScroll 防抖补一次吸附
|
||||
// (同花顺松手吸附同款)。绝不调 setMaxOffsetRightDistance:会把滚动限制切到
|
||||
// 'distance' 模式,默认钳到 50px 且改变滚动边缘行为。
|
||||
// 右侧固定留白(价格轴与末根K之间的呼吸空间;scrollToRealTime 以它为锚点)
|
||||
const BASE_RIGHT_PX = 28;
|
||||
let syncingRightOffset = false; // 重入守卫:set 会同步派发 onVisibleRangeChange
|
||||
let scrollReanchorTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
let managedRightPx = 0; // 筹码开启期间我们 set 过的目标值(关筹码时判断“是否还归我们管”)
|
||||
|
||||
/** 目标右侧留白:开筹码 = 列宽 + 一根K线 + 余量(bar 最宽 50px → 峰值 ~182px) */
|
||||
function targetRightPx(): number {
|
||||
if (!props.showChips) return BASE_RIGHT_PX;
|
||||
const bar = chart?.getBarSpace().bar || 10;
|
||||
return Math.round(CHIPS_COL_PX + bar + 12);
|
||||
}
|
||||
|
||||
/** 开筹码期间保证留白盖住竖列:只扩不缩(用户自己拖出的更大留白不动) */
|
||||
function syncRightOffset(): void {
|
||||
if (!chart || syncingRightOffset || !props.showChips) return;
|
||||
const list = chart.getDataList();
|
||||
if (!list.length || chart.getVisibleRange().to < list.length) return; // 右区守卫
|
||||
const target = targetRightPx();
|
||||
if (chart.getOffsetRightDistance() >= target - 2) return; // 阈值防循环 + 只扩不缩
|
||||
syncingRightOffset = true;
|
||||
try {
|
||||
chart.setOffsetRightDistance(target);
|
||||
managedRightPx = target;
|
||||
} finally {
|
||||
syncingRightOffset = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** 关筹码时一次性还原 28px:仅当留白仍在我们管理范围内(用户没手动拖大过) */
|
||||
function restoreRightOffset(): void {
|
||||
if (!chart || managedRightPx === 0) return;
|
||||
const list = chart.getDataList();
|
||||
const cur = chart.getOffsetRightDistance();
|
||||
if (list.length && chart.getVisibleRange().to >= list.length
|
||||
&& cur > BASE_RIGHT_PX + 2 && cur <= managedRightPx + 2) {
|
||||
chart.setOffsetRightDistance(BASE_RIGHT_PX);
|
||||
}
|
||||
managedRightPx = 0;
|
||||
}
|
||||
|
||||
function build() {
|
||||
if (!container.value || props.candles.length === 0) return;
|
||||
@@ -819,7 +724,6 @@ function build() {
|
||||
calcParams: DKX_PERIODS, extendData: { blocks: props.zhixingBlocks },
|
||||
});
|
||||
}
|
||||
if (props.showChips) syncChipsIndicator(); // 筹码峰(数据未到时 draw 直接空转,到货后由 watch 补建)
|
||||
|
||||
// 副图按用户顺序创建,并设置用户高度;主图吃剩余高度。
|
||||
// minHeight 交给库在分隔条拖拽时强制执行(与 subH 的 40px 下限一致)
|
||||
@@ -852,23 +756,8 @@ function build() {
|
||||
const from = (payload as { data?: { from?: unknown } }).data?.from;
|
||||
if (typeof from === 'number' && from < 200) maybePrefetch(myEpoch);
|
||||
});
|
||||
// 右侧留白:开筹码时按竖列宽度预留(scrollToRealTime 以它为锚点,先后顺序不能换)
|
||||
ch.setOffsetRightDistance(props.showChips ? targetRightPx() : BASE_RIGHT_PX);
|
||||
// 筹码竖列的留白跟随:缩放后 barSpace 变化(onZoom 触发时新值已生效)立即补扩;
|
||||
// 拖拽期间 onScroll 逐帧触发、且拖拽每帧从手势起点快照重算 diff,逐帧同步会与拖拽
|
||||
// “互搏”(从实时位拖向历史会被逐帧拽回),故防抖 150ms 只在手势结束后补一次
|
||||
ch.subscribeAction('onZoom', () => {
|
||||
if (myEpoch !== epoch) return;
|
||||
syncRightOffset();
|
||||
});
|
||||
ch.subscribeAction('onScroll', () => {
|
||||
if (myEpoch !== epoch) return;
|
||||
if (scrollReanchorTimer) clearTimeout(scrollReanchorTimer);
|
||||
scrollReanchorTimer = setTimeout(() => {
|
||||
scrollReanchorTimer = null;
|
||||
if (myEpoch === epoch) syncRightOffset();
|
||||
}, 150);
|
||||
});
|
||||
// 右侧留白(scrollToRealTime 以它为锚点,先后顺序不能换)
|
||||
ch.setOffsetRightDistance(BASE_RIGHT_PX);
|
||||
ch.scrollToRealTime();
|
||||
// 日期跳转:build 尾部的 scrollToRealTime 会把视口重置到最新一根,居中必须放在它之后
|
||||
//(init 数据在 setPeriod 时已同步落入图表,这里可直接定位)。
|
||||
@@ -881,8 +770,6 @@ function build() {
|
||||
|
||||
function teardown() {
|
||||
if (subHTimer) { clearTimeout(subHTimer); subHTimer = null; }
|
||||
if (scrollReanchorTimer) { clearTimeout(scrollReanchorTimer); scrollReanchorTimer = null; }
|
||||
managedRightPx = 0;
|
||||
if (container.value) dispose(container.value);
|
||||
chart = null;
|
||||
hover.value = null;
|
||||
@@ -893,9 +780,6 @@ function teardown() {
|
||||
onMounted(build);
|
||||
onBeforeUnmount(teardown);
|
||||
watch(() => [props.candles, props.indicators, props.subPanes, props.showBoll, props.showZhixing, props.zhixingBlocks, props.maPeriods, props.timeframe], () => { teardown(); build(); }, { deep: true });
|
||||
// 筹码峰开关/截面变化:只同步该指标,不重建图表(保留滚动位置与用户画线;
|
||||
// 十字线跟随会高频更新截面,重建会闪 + 丢状态)
|
||||
watch(() => [props.showChips, props.chips], syncChipsIndicator, { deep: true });
|
||||
// 买卖点数据变化(导入/清空/开关显示):只重画标记,不重建图表(保留滚动位置与用户画线)
|
||||
watch(() => props.tradeMarkers, renderTradeMarkers, { deep: true });
|
||||
// 涨跌配色切换:重建图表以应用新颜色
|
||||
|
||||
@@ -5,6 +5,7 @@ import { getMarketOverview } from '@/api/client';
|
||||
import type { IndexQuote, MarketOverview as Overview } from '@/api/types';
|
||||
|
||||
import AmountHistoryChart from '@/components/AmountHistoryChart.vue';
|
||||
import IndexKLine from '@/components/IndexKLine.vue';
|
||||
|
||||
// 主页大盘总览:A 股 + 港美指数最近收盘(收盘口径,标注交易日),沪深两市市值/成交统计。
|
||||
// 数据为 EOD 口径,进页面拉一次 + 手动刷新即可,不做轮询。
|
||||
@@ -226,6 +227,9 @@ function hoverText(it: IndexQuote): string {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 上证指数 K 线(日/周/月/年,周期随用户偏好持久化) -->
|
||||
<IndexKLine class="mt-4" />
|
||||
|
||||
<!-- 两市统计:daily_info 沪 SH_MARKET(主板A+科创+B) + 深 SZ_MARKET 汇总 -->
|
||||
<div
|
||||
v-if="overview.stats"
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
||||
import {
|
||||
addWatchlist, clearTrades, getStockChips, getStockPreview, getTrades, getWatchlist as getWatchlistApi,
|
||||
addWatchlist, clearTrades, getStockPreview, getTrades, getWatchlist as getWatchlistApi,
|
||||
importTrades, removeWatchlist,
|
||||
} from '@/api/client';
|
||||
import type {
|
||||
ChartLayoutPrefs, ChipsResponse, PreviewResponse, ScreenerItemOut, Timeframe, TooltipField,
|
||||
ChartLayoutPrefs, PreviewResponse, ScreenerItemOut, Timeframe, TooltipField,
|
||||
TradesImportResponse, UserTrade,
|
||||
} from '@/api/types';
|
||||
import { useSettingsStore, DEFAULT_TOOLTIP_FIELDS, TOOLTIP_FIELDS, type PriceAdjust } from '@/stores/settings';
|
||||
import type { ChipsExt } from '@/indicators';
|
||||
import DetailKLine from './DetailKLine.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -67,8 +66,11 @@ const subPanes = computed<string[]>(() => layout.value.subPanes);
|
||||
const maPeriods = computed<number[]>(() => layout.value.maPeriods);
|
||||
const subHeights = computed(() => layout.value.subHeights);
|
||||
const tooltipFields = computed<TooltipField[]>(() => layout.value.tooltipFields ?? DEFAULT_TOOLTIP_FIELDS);
|
||||
const showBoll = ref(false);
|
||||
const showZhixing = ref(false);
|
||||
// 主图可选叠加(BOLL / 知行):随用户偏好持久化,跨会话/跨设备记忆开关
|
||||
const showBoll = computed<boolean>(() => layout.value.showBoll === true);
|
||||
const showZhixing = computed<boolean>(() => layout.value.showZhixing === true);
|
||||
function toggleBoll() { settings.setChartLayout({ showBoll: !showBoll.value }); }
|
||||
function toggleZhixing() { settings.setChartLayout({ showZhixing: !showZhixing.value }); }
|
||||
// 知行指标图例行的板块文本(通达信 HYBLOCK+' '+DYBLOCK 的近似;GNBLOCK 概念板块无数据源)
|
||||
const zhixingBlocks = computed(() => {
|
||||
const info = data.value?.info;
|
||||
@@ -76,84 +78,6 @@ const zhixingBlocks = computed(() => {
|
||||
return [info.industry, info.area].filter(Boolean).join(' ') || undefined;
|
||||
});
|
||||
|
||||
// ---------- 筹码峰(cyq 截面,跟随 日/周/月K 的当前周期 + 十字线) ----------
|
||||
const showChips = ref(false);
|
||||
const chipsExt = ref<ChipsExt | null>(null);
|
||||
let chipsToken = 0; // 请求序号:切股/切口径瞬间乱序返回的旧截面不能回填
|
||||
let chipsKey = ''; // 已请求去重键(code|adjust|参考日)
|
||||
|
||||
function toChipsExt(res: ChipsResponse, refClose: number): ChipsExt {
|
||||
return {
|
||||
rows: res.rows.map((r) => ({ price: r.price, percent: r.percent })),
|
||||
date: res.trade_date ?? undefined,
|
||||
refClose,
|
||||
winner: res.winner_rate,
|
||||
avg: res.weight_avg,
|
||||
costLow: res.cost_5pct,
|
||||
costHigh: res.cost_95pct,
|
||||
error: res.error ?? undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/** 筹码锚点(同花顺式):返回 参考日 + 锚定 bar 收盘价(获利/套牢的分界价)。
|
||||
* 日K=bar 当日;周/月/年K 的 bar ts 是周期首日,参考日=下一根 bar 首日的前一天
|
||||
* (最后一根=今天,后端再吸附到 <=参考日 的最近有数据交易日)。
|
||||
* idx 缺省=窗口最后一根(跟随当前可视周期);十字线跟随时传落点下标。
|
||||
* 注:翻页前插的更早 bar 不在 data.candles 里,十字线落到那些 bar 上时沿用上一截面。 */
|
||||
function chipsAnchor(idx?: number): { ref: string; close: number } | undefined {
|
||||
const bars = data.value?.candles;
|
||||
if (!bars?.length) return undefined;
|
||||
const i = idx != null && idx >= 0 && idx < bars.length ? idx : bars.length - 1;
|
||||
if (timeframe.value === '1d') return { ref: bars[i].ts.slice(0, 10), close: bars[i].close };
|
||||
const nextTs = i + 1 < bars.length ? new Date(bars[i + 1].ts).getTime() - 86400000 : Date.now();
|
||||
return { ref: fmtDashDate(Math.min(nextTs, Date.now())), close: bars[i].close };
|
||||
}
|
||||
|
||||
async function loadChips(anchorIdx?: number) {
|
||||
if (!showChips.value) return;
|
||||
const anchor = chipsAnchor(anchorIdx);
|
||||
if (!anchor) return;
|
||||
const key = `${active.value}|${adjust.value}|${anchor.ref}`;
|
||||
if (key === chipsKey) return; // 同股同口径同参考日不重复请求(后端有 Redis 缓存,前端也省一次往返)
|
||||
chipsKey = key;
|
||||
const token = ++chipsToken;
|
||||
try {
|
||||
const res = await getStockChips(active.value, { date: anchor.ref, adjust: adjust.value });
|
||||
if (token === chipsToken) chipsExt.value = toChipsExt(res, anchor.close);
|
||||
} catch {
|
||||
if (token === chipsToken) chipsExt.value = { rows: [], refClose: anchor.close, error: '筹码数据获取失败' };
|
||||
}
|
||||
}
|
||||
|
||||
/** K线数据就绪/切换(切股、复权、周期、日期跳转都经 load() 换 data):筹码重置到新窗口末根 */
|
||||
watch(data, () => {
|
||||
chipsKey = '';
|
||||
chipHoverTs = null;
|
||||
chipsExt.value = null;
|
||||
void loadChips();
|
||||
});
|
||||
|
||||
/** 十字线跟随(防抖 350ms):落在哪根K线就取那个周期的截面;离开图表保留最后截面(通达信同款) */
|
||||
let chipHoverTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
let chipHoverTs: number | null = null;
|
||||
function onCrosshairDate(ts: number) {
|
||||
if (!showChips.value || chipHoverTs === ts) return;
|
||||
chipHoverTs = ts;
|
||||
if (chipHoverTimer) clearTimeout(chipHoverTimer);
|
||||
chipHoverTimer = setTimeout(() => {
|
||||
chipHoverTimer = null;
|
||||
const bars = data.value?.candles;
|
||||
if (!bars) return;
|
||||
const idx = bars.findIndex((b) => new Date(b.ts).getTime() === ts);
|
||||
if (idx >= 0) void loadChips(idx);
|
||||
}, 350);
|
||||
}
|
||||
|
||||
function toggleChips() {
|
||||
showChips.value = !showChips.value;
|
||||
if (showChips.value) { chipsKey = ''; chipHoverTs = null; void loadChips(); }
|
||||
}
|
||||
|
||||
function toggleSub(key: string) {
|
||||
const cur = subPanes.value;
|
||||
settings.setChartLayout({
|
||||
@@ -664,7 +588,7 @@ const fmtListDate = (s?: string | null) => (s && s.length === 8 ? `${s.slice(0,
|
||||
class="rounded-md border px-2.5 py-1 text-[13px] transition-colors"
|
||||
:class="showBoll ? 'border-purple-500 bg-purple-500 text-white' : 'border-[#26272E] bg-[#101014] text-[#9BA3AE]'"
|
||||
title="主图叠加布林带"
|
||||
@click="showBoll = !showBoll"
|
||||
@click="toggleBoll"
|
||||
>BOLL</button>
|
||||
<!-- 知行:通达信导入的自定义主图指标(趋势线+多空线) -->
|
||||
<button
|
||||
@@ -672,16 +596,8 @@ const fmtListDate = (s?: string | null) => (s && s.length === 8 ? `${s.slice(0,
|
||||
class="rounded-md border px-2.5 py-1 text-[13px] transition-colors"
|
||||
:class="showZhixing ? 'border-[#E61851] bg-[#E61851] text-white' : 'border-[#26272E] bg-[#101014] text-[#9BA3AE]'"
|
||||
title="知行指标:短期趋势线 EMA(EMA(C,10),10) + 多空线 (MA14+MA28+MA57+MA114)/4"
|
||||
@click="showZhixing = !showZhixing"
|
||||
@click="toggleZhixing"
|
||||
>知行</button>
|
||||
<!-- 筹码峰:右侧横向线状直方图(选中K线下方获利盘红/上方套牢盘蓝+平均成本虚线) -->
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-md border px-2.5 py-1 text-[13px] transition-colors"
|
||||
:class="showChips ? 'border-cyan-400 bg-cyan-400 text-black' : 'border-[#26272E] bg-[#101014] text-[#9BA3AE]'"
|
||||
title="筹码峰:各价位持仓占比(选中K线分界:下方获利盘红/上方套牢盘蓝),随日/周/月K与十字线切换截面"
|
||||
@click="toggleChips"
|
||||
>筹码峰</button>
|
||||
<!-- 实盘交易点:交割单导入的买卖标记 -->
|
||||
<button
|
||||
type="button"
|
||||
@@ -812,9 +728,6 @@ const fmtListDate = (s?: string | null) => (s && s.length === 8 ? `${s.slice(0,
|
||||
:show-boll="showBoll"
|
||||
:show-zhixing="showZhixing"
|
||||
:zhixing-blocks="zhixingBlocks"
|
||||
:show-chips="showChips"
|
||||
:chips="chipsExt"
|
||||
@crosshair-date="onCrosshairDate"
|
||||
:timeframe="timeframe"
|
||||
:tooltip-fields="tooltipFields"
|
||||
:center-ts="jumpTs"
|
||||
|
||||
Reference in New Issue
Block a user