跳到主要内容

配置

导出​

名称类型说明
WidgetIccandle组件扫描器浮层(宿主负责结果 iframe)
WidgetIccandleProps类型WidgetIccandle 的 props
WidgetChartMaskColors类型chartMaskColors 的 { light?: string; dark?: string }
WidgetLanguage类型支持的语言代码
withPlayChart函数包装 TradingView datafeed(或工厂函数)以注入回放 K 线
getCustomIndicators函数返回 iC Candle 自定义指标(生成 K 线)
GeneratedCandlesTheme类型getCustomIndicators 的 "light" | "dark"
handleResultIframeLoad函数在 iframe 加载时向结果 iframe 发送 parent-origin / payment-success
useICCandleAuth组合式函数宿主侧会话:来自 iccandle_token 的 { isAuthenticated, idToken }
ICCandleAuth类型useICCandleAuth 的返回类型
WIDGET_RESULT_URL常量"https://embed-iccandle-app.iccandle.ai"
OPEN_PRICING_MESSAGE_TYPE常量"open-pricing" postMessage 类型
postOpenPricingToEmbed函数请求结果 iframe 打开定价。无 contentWindow 时返回 false。
postOpenPricingToParent函数当本组件自身被嵌入时,将定价请求转发到 window.parent。
postOpenPricingToWindow函数向任意 Window 发送 open-pricing 消息。
OpenPricingMessage类型{ type, theme?, language? }

WidgetIccandle props​

Prop类型必需说明
chartWidgetIChartingLibraryWidget | null是实时 TradingView widget(就绪前为 null)。模板::chart-widget。
submitCallback(iframeSrc: string) => void是扫描、新闻导航或定价回退需要更新结果 iframe 时调用。将 iframe 的 src 设为该 URL(可选追加 header=false)。模板::submit-callback。
theme"light" | "dark" | "system"否扫描器与 iframe 主题。"system" 跟随 prefers-color-scheme。默认 "light"。
chartMaskColorsWidgetChartMaskColors否按主题隐藏尚未揭示的预测 K 线的颜色。必须与图表面板背景一致。默认:{ light: "#ffffff", dark: "#0F0F0F" }。模板::chart-mask-colors。
bg_darkstring否深色主题下的嵌入页背景。十六进制,# 可选。省略则不附加 bg_dark 查询参数。模板:bg_dark。
bg_lightstring否浅色主题下的嵌入页背景。十六进制,# 可选。省略则不附加 bg_light 查询参数。模板:bg_light。
languageWidgetLanguage否UI 与 iframe 语言。可选:en、zh、vi、th、ko、ja、mn、ru。默认 en。
onCloseResult() => void否嵌入端发送 selector.closeResult 时调用。模板::on-close-result(prop 回调,不是 emit)。
iframeLoadedboolean否为 false 时,在结果 iframe 就绪前禁用扫描 / 追踪操作。默认 true。模板::iframe-loaded。
resultIframeRef{ current: HTMLIFrameElement | null } | null否结果 iframe 盒子(不是 Vue ref)。用于接收 open-pricing 与 chart-resolution postMessage。模板::result-iframe-ref。
isShowScanButtonboolean否在弹窗中显示扫描。默认 true。模板::is-show-scan-button。
isShowTrackerButtonboolean否在弹窗中显示形态追踪。默认 true。模板::is-show-tracker-button。
isShowScannerPopupboolean否显示扫描器弹窗。默认 true。模板::is-show-scanner-popup。
availableIntervalsstring[]否从嵌入端选择形态时允许绘制日期范围的周期。模板::available-intervals。
onScanClick() => void否用户点击扫描时触发,发生在登录 / 配置 / 扫描逻辑之前。模板::on-scan-click。

默认插槽:把图表 UI 作为 WidgetIccandle 的子节点。插槽还会收到 { chartRefs }(高亮 K 线 + 生成 K 线指标 id)。同一 chartRefs 对象也可通过组件实例访问。

IChartingLibraryWidget 必须从你的 Charting Library 类型定义导入 — 本包不重新导出 TradingView 类型。

submitCallback​

必需。宿主负责结果 iframe。用户执行扫描、从新闻标记打开相似事件,或(在无 iframe ref / 父窗口时)请求定价时,WidgetIccandle 会构建完整嵌入 URL 并传给 submitCallback。请用该值更新 iframe 的 src。

常见 URL 形态:

https://embed-iccandle-app.iccandle.ai/{locale}?symbol=…&res=…&ref_res=…&cid=…&tk=…&from=…&to=…&theme=light
https://embed-iccandle-app.iccandle.ai/{locale}/news/similar-events/{id}?symbol=…&theme=light
https://embed-iccandle-app.iccandle.ai/{locale}?pricing=true&theme=light

可选扫描筛选也可能追加:fs(品种筛选)、period、model(light / standard / plus / pro)、temp(0.5 / 1 / 1.5)。设置了 bg_dark / bg_light 时,这些颜色也会追加到同一批 URL 上。

<script setup lang="ts">
import { ref, watch } from "vue";
import {
WidgetIccandle,
handleResultIframeLoad,
WIDGET_RESULT_URL,
} from "@iccandle/vuejs-widget";

const iframeSrc = ref(`${WIDGET_RESULT_URL}/zh?theme=light&header=false`);
const iframeLoaded = ref(false);
const resultIframeRef = ref<HTMLIFrameElement | null>(null);
const resultIframeBox = { current: null as HTMLIFrameElement | null };

watch(
resultIframeRef,
(el) => {
resultIframeBox.current = el;
},
{ immediate: true },
);

const submitCallback = (nextSrc: string) => {
const url = new URL(nextSrc);
url.searchParams.set("header", "false");
const next = url.toString();
if (iframeSrc.value !== next) {
iframeSrc.value = next;
}
};

const handleIframeLoad = () => {
iframeLoaded.value = true;
handleResultIframeLoad(resultIframeRef.value);
};
</script>

<template>
<WidgetIccandle
:chart-widget="chartWidget"
:submit-callback="submitCallback"
theme="light"
language="zh"
:iframe-loaded="iframeLoaded"
:result-iframe-ref="resultIframeBox"
>
<!-- 图表 -->
</WidgetIccandle>
<iframe
ref="resultIframeRef"
:src="iframeSrc"
title="iC Candle results"
@load="handleIframeLoad"
/>
</template>

result-iframe-ref 是可变的 { current } 盒子,不是 Vue 的 ref。请按上面示例从 iframe 元素同步。

header=false​

在嵌入 URL(初始 src 以及 submitCallback 内)追加 header=false,可在宿主已提供导航时隐藏嵌入应用顶栏。页脚与页内 UI 仍会渲染;顶栏标签触发的 nav.click 消息不会发出。

扫描器生成的 URL 会包含扫描参数与 theme,但不会自动添加 header=false — 需要时由宿主自行设置。

完整查询参数说明见 搜索参数 → header。

handleResultIframeLoad(iframe)​

在结果 iframe 的 @load 中调用。它会向嵌入端发送宿主 origin(用于 Stripe 返回,并使 auth.signIn 指向正确宿主);当父页面 URL 带有 ?payment=success 时,还会发送 payment-success 以刷新订阅状态。

parent-origin 会在 0 / 300 / 1000 / 2500 ms 重试,因为嵌入端没有消息缓冲 — 必须先挂上监听器再收到消息。

import { handleResultIframeLoad } from "@iccandle/vuejs-widget";

handleResultIframeLoad(resultIframeRef.value);

useICCandleAuth()​

宿主侧用于判断结果 iframe 是否已经登录。读取 iccandle_token,在 JWT exp 前 60 秒视为过期,并在 auth.signIn / auth.signOut 时更新。

import { useICCandleAuth } from "@iccandle/vuejs-widget";

const { isAuthenticated, idToken } = useICCandleAuth();
字段类型说明
isAuthenticatedRef<boolean>存在且未过期的 iccandle_token 时为 true
idTokenRef<string | null>当前身份令牌;未登录时为 null

企业合作伙伴:先监听 isAuthenticated,仅在其为 false 时调用 get-user-token。见 无缝认证示例。

withPlayChart(datafeed)​

图表回放 / 预测所必需。包装 TradingView datafeed 的 subscribeBars,使组件可以:

  1. 注入回放 K 线 — 当嵌入端发送 chart.play、chart.stop 或回放载荷时,写入实时 tick 流。
  2. 阻止实时 tick — 回放期间屏蔽实盘更新,避免覆盖预测 K 线。

签名​

withPlayChart(datafeed: IBasicDataFeed): IBasicDataFeed
参数类型说明
datafeedIBasicDataFeed已就绪的 datafeed 实例(须提供 onReady)。
factory, ...args函数重载可选:传入工厂函数及其参数;withPlayChart 会调用并包装返回值。

用法​

import { withPlayChart } from "@iccandle/vuejs-widget";

datafeed: withPlayChart(myDatafeed),
// 或: withPlayChart(createDatafeed, arg1, arg2)

说明​

  • 返回值仍是普通 datafeed;仅包装了 subscribeBars。可选的 getTimescaleMarks 等方法保持不变。
  • 需与 getCustomIndicators 一起使用 — 缺一不可,否则回放 / 预测叠加无法生效。

getCustomIndicators(theme?)​

注册 iC Candle 自定义指标,用于在主系列上绘制生成 / 预测 K 线。返回 TradingView CustomIndicator[] 的 Promise,供 custom_indicators_getter 使用。

签名​

getCustomIndicators(theme?: "light" | "dark"): Promise<readonly CustomIndicator[]>
参数类型默认说明
theme"light" | "dark""light"面板遮罩颜色,用于在预测时间点盖住底层 K 线。须与图表主题一致。

返回的指标​

指标名称作用
Generated Candles Background - By iC Candle隐藏的遮罩层,在预测时间戳处覆盖真实 K 线。
Generated Candles - By iC Candle可见 OHLC 叠加(上涨 #00dfb9 / 下跌 #ffb84d),绘制预测 K 线。

当嵌入端发送回放 / 预测数据时,WidgetIccandle 会创建并驱动这些指标。

用法​

import { getCustomIndicators } from "@iccandle/vuejs-widget";

const options: ChartingLibraryWidgetOptions = {
// ...
datafeed: withPlayChart(yourDatafeed),
custom_indicators_getter: () => getCustomIndicators("light"),
};

保持 getCustomIndicators(theme) 与图表主题一致(并尽量与 WidgetIccandle 的 theme prop 一致)。指标创建后,WidgetIccandle 会用 chartMaskColors 覆盖背景指标颜色,使尚未揭示的预测 K 线与面板背景一致。

与 withPlayChart 配合​

辅助函数作用
withPlayChart允许组件向 datafeed 推送 K 线,并在回放期间屏蔽实时 tick。
getCustomIndicators以自定义指标绘制预测 K 线视觉效果(遮罩 + 彩色 OHLC)。

结果 iframe 的回放 / 预测功能需要两者同时配置。

chartMaskColors​

回放 / 预测时,组件会绘制生成 K 线,并用实心遮罩色盖住尚未揭示的 K 线。该颜色必须与 TradingView 图表面板背景(paneProperties.background)一致;否则未揭示的 K 线会在回放光标前方显示为色块。

深色图表面板上盖住尚未揭示预测 K 线的遮罩

键默认使用时机
light#fffffftheme="light",或 theme="system" 且系统为浅色
dark#0F0F0Ftheme="dark",或 theme="system" 且系统为深色

仅当前主题对应的值会生效。每个键都是可选的 — 省略则使用默认值。图表库接受的任意 CSS 颜色字符串均可;不要使用透明色,否则真实系列会透出来。

若图表面板不是默认的白色 / #0F0F0F,请传入匹配的值:

<WidgetIccandle
:chart-widget="chartWidget"
:submit-callback="submitCallback"
theme="dark"
:chart-mask-colors="{ dark: '#2F2F2F', light: '#ffffff' }"
>
<!-- 图表 -->
</WidgetIccandle>

WidgetIccandle 会将该颜色作为 Generated Candles Background 指标的覆盖色。更改 chartMaskColors 或 theme 会重建这些指标,因此宿主可在图表背景变化时同步更新。

这不是扫描窗口(date_range)的填充色 — 那由 .iccandle-selector-widget 上的 --iccandle-primary 控制。

bg_dark 与 bg_light​

可选的十六进制颜色,用于结果 iframe 的页面背景。组件会在它构建的嵌入 URL 上追加 bg_dark 与 bg_light 查询参数:扫描结果、新闻详情,以及定价回退。

Prop查询参数生效时机
bg_darkbg_dark嵌入主题解析为深色
bg_lightbg_light嵌入主题解析为浅色

开头的 # 可省略(#131722 与 131722 相同)。接受 3、6、8 位十六进制。空值或非十六进制会被丢弃,对应参数不会追加。省略某个 prop 时,该主题使用嵌入端默认背景。两个都省略时,组件不追加任何 bg_* 参数。

初始 iframe src 由宿主负责。请在那里带上相同参数,这样首次加载就一致。嵌入端收到有效颜色后会保存它,之后省略 bg_* 的导航仍沿用该颜色。

<script setup lang="ts">
import { ref } from "vue";
import { WIDGET_RESULT_URL } from "@iccandle/vuejs-widget";

const iframeSrc = ref(
`${WIDGET_RESULT_URL}/zh?theme=dark&header=false&bg_dark=131722&bg_light=ffffff`,
);
</script>

<template>
<WidgetIccandle
:chart-widget="chartWidget"
:submit-callback="submitCallback"
theme="dark"
bg_dark="#131722"
bg_light="#ffffff"
>
<!-- 图表 -->
</WidgetIccandle>
</template>

这些 prop 设置的是嵌入页背景。图表上的回放遮罩仍由 chartMaskColors 控制。

详见 搜索参数 → bg_dark 与 bg_light。

定价辅助函数​

用户在扫描器设置中点击升级时,组件会向结果 iframe(resultIframeRef)发送 open-pricing,然后转发到 window.parent,最后回退为带 ?pricing=true 的 submitCallback。

你也可以自行触发定价:

import { postOpenPricingToEmbed } from "@iccandle/vuejs-widget";

postOpenPricingToEmbed(resultIframeRef.value, {
theme: "light",
language: "zh",
});

认证与存储​

使用 useICCandleAuth() 在宿主侧读取当前会话。企业合作伙伴应先监听 isAuthenticated,再调用 get-user-token — 见 无缝认证示例。

键用途
iccandle_token扫描缓存、形态追踪及相关 API 的 Bearer 令牌。由嵌入端通过 auth.signIn 写入;auth.signOut 时清除。
search-filter持久化的扫描器高级选项(symbols、top_k、period、model、temperature)。
search-filter-session用户不持久化时的会话级筛选副本。
scanner-always-show扫描器是否保持可见("true" / 未设置)。
tv:selected-news-events用作时间轴标记的新闻事件 JSON 数组。
tv:clicked-news-event最近点击的日历事件,用于标记高亮。
tv:latest-symbol最近的图表品种(演示应用 / 回退使用)。

postMessage 桥接​

仅接受来自结果源(https://embed-iccandle-app.iccandle.ai)的消息。嵌入 → 父页面载荷使用 { name, data } 结构。

方向Name效果
嵌入 → 父页面chart.play / chart.stop在图表上注入 / 清除回放 K 线
嵌入 → 父页面selector.loading切换扫描器加载 UI
嵌入 → 父页面auth.signIn从 data.idToken 持久化 iccandle_token
嵌入 → 父页面auth.signOut移除 iccandle_token
嵌入 → 父页面selector.closeResult清除回放状态;调用 onCloseResult
嵌入 → 父页面pattern.classicPatternSelected / pattern.custom_pattern_selected为对比形态绘制日期范围
嵌入 → 父页面pattern.clearClassicPatternSelected / pattern.clear_custom_pattern_selected移除形态日期范围
嵌入 → 父页面news.eventClicked居中图表、绘制事件线、显示标记
嵌入 → 父页面news.back / news.backToSimilarEvents清除事件线 / 回放
嵌入 → 父页面nav.click在 /news 路由上清除日期范围
嵌入 → 父页面chart.requestResolution向 iframe 重新发送当前图表周期
父页面 → 嵌入parent-originStripe 返回用的宿主 origin
父页面 → 嵌入payment-success结账后刷新订阅状态
父页面 → 嵌入open-pricing请求嵌入端打开定价(需要 resultIframeRef)
父页面 → 嵌入chart-resolution当前图表周期(iframeLoaded 变为 true 时发送)

宿主 → 嵌入辅助函数使用 { type: "parent-origin" | "payment-success" | "open-pricing" | "chart-resolution", ... }。

可选:时间轴标记(新闻/事件)​

时间轴上的新闻标记是可选的。WidgetIccandle 不会自动添加它们。若要在图表上显示日历 / 经济事件,请在你自己的 datafeed(传给 withPlayChart 的对象)上实现 TradingView 的 getTimescaleMarks。withPlayChart 只包装 subscribeBars,因此你的 getTimescaleMarks 会原样生效。

时间轴上带货币图标与竖线的新闻事件标记

请在 datafeed 的 onReady 配置中声明支持(supports_timescale_marks: true),否则图表库不会调用 getTimescaleMarks。

组件会将事件写入 localStorage。你的实现应读取这些键并返回标记:

键值标记
tv:clicked-news-event单个事件 JSON蓝色标记,富文本提示(实际 / 预测 / 前值)
tv:selected-news-events事件数组 JSON绿色标记

事件的 timestamp 为 unix 毫秒;TradingView 标记使用 unix 秒(time: timestamp / 1000)。事件结构见 NewsEvent。

import type {
GetMarksCallback,
LibrarySymbolInfo,
TimescaleMark,
} from "charting_library/charting_library";

type NewsEventType = {
id: string;
timestamp: number; // unix ms
event_name: string;
currency?: string;
actual?: string;
forecast?: string;
previous?: string;
};

const yourDatafeed = {
// ...onReady, resolveSymbol, getBars, subscribeBars, ...
getTimescaleMarks: async (
_symbolInfo: LibrarySymbolInfo,
_from: number,
_to: number,
onResult: GetMarksCallback<TimescaleMark>,
) => {
const marks: TimescaleMark[] = [];

const pushEventMark = (
event: NewsEventType,
options?: { color?: TimescaleMark["color"]; richTooltip?: boolean },
) => {
const { id, timestamp, event_name, currency, actual, forecast, previous } =
event;
if (!id || !Number.isFinite(timestamp) || timestamp <= 0) return;
if (marks.some((m) => String(m.id) === String(id))) return;

const tooltip = options?.richTooltip
? [
event_name,
currency ? `Currency: ${currency}` : null,
actual ? `Actual: ${actual}` : null,
forecast ? `Forecast: ${forecast}` : null,
previous ? `Previous: ${previous}` : null,
].filter((line): line is string => Boolean(line))
: [event_name];

marks.push({
id,
time: timestamp / 1000,
color: options?.color ?? "green",
label: event_name.slice(0, 1) || "N",
tooltip,
...(currency
? {
imageUrl: `https://cdn.backprop.services/symbols/${currency}.svg`,
}
: {}),
showLabelWhenImageLoaded: true,
});
};

try {
const clickedEvent = JSON.parse(
localStorage.getItem("tv:clicked-news-event") || "null",
) as NewsEventType | null;
if (clickedEvent) {
pushEventMark(clickedEvent, { color: "blue", richTooltip: true });
}
} catch {
// no-op
}

try {
const allNewsEvents = JSON.parse(
localStorage.getItem("tv:selected-news-events") || "[]",
) as NewsEventType[];
allNewsEvents?.forEach((event) => pushEventMark(event));
} catch {
// no-op
}

onResult(marks);
},
};

然后照常包装:datafeed: withPlayChart(yourDatafeed)。

主题​

扫描器 UI 在 .iccandle-selector-widget 上使用 CSS 变量:

  • --iccandle-primary
  • --iccandle-primary-gradient-end
  • --iccandle-background
  • --iccandle-border
  • --iccandle-text
  • --iccandle-secondary
  • --iccandle-font

浅色与深色默认值在打包样式表中。theme prop 会切换 .iccandle-dark 类,并通过 submitCallback 转发到 iframe URL。传入 bg_dark 与 bg_light 可设置嵌入页背景。

回放遮罩色不是 CSS 变量:请用 chartMaskColors 与 paneProperties.background 对齐。

布局辅助类​

打包样式包含演示应用使用的分栏类:

类名作用
.iccandle-selector-widget__container横向 flex(小于 1024px 时纵向堆叠)。--chart-pane-size 默认 60%。
.iccandle-selector-widget__chart-pane图表面板。
.iccandle-selector-widget__resize-handle拖动手柄;堆叠布局加 --stacked。
.iccandle-selector-widget__iframe结果面板。

行为摘要​

  • 订阅图表就绪、周期、品种变更、可见范围、绘图事件与时间轴标记点击。
  • 管理 date_range 多点绘图,供用户调整 K 线窗口(默认:25 根)。
  • 将 K 线提交到 https://scan-service.iccandle.ai/cacheCandle,再通过 submitCallback 传入嵌入 URL(symbol、res、ref_res、cid、tk、from、to、筛选、theme,以及已设置时的 bg_dark / bg_light)。
  • 与宿主持有的结果 iframe(https://embed-iccandle-app.iccandle.ai)通过 postMessage 同步。