@363045841yyt/klinechart 0.8.0 → 0.8.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/KLineChart.vue.d.ts.map +1 -1
- package/dist/components/SymbolSelector.vue.d.ts +20 -0
- package/dist/components/SymbolSelector.vue.d.ts.map +1 -0
- package/dist/components/TopToolbar.vue.d.ts +7 -0
- package/dist/components/TopToolbar.vue.d.ts.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.css +1 -1
- package/dist/index.js +717 -431
- package/package.json +1 -1
- package/src/components/KLineChart.vue +72 -88
- package/src/components/SymbolSelector.vue +478 -0
- package/src/components/TopToolbar.vue +62 -84
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div ref="chartWrapperRef" class="chart-wrapper" :data-theme="chartTheme" :style="themeCssVars">
|
|
3
|
-
<TopToolbar
|
|
4
|
-
:symbol="
|
|
3
|
+
<TopToolbar
|
|
4
|
+
:symbol="currentSymbol"
|
|
5
5
|
:k-line-level="kLineLevel"
|
|
6
|
+
:symbol-loading="symbolLoading"
|
|
7
|
+
:symbol-error="symbolError"
|
|
6
8
|
@add-overlay-symbol="$emit('addOverlaySymbol')"
|
|
7
9
|
@k-line-level-change="onKLineLevelChange"
|
|
8
10
|
@toggle-indicator="onToggleIndicator"
|
|
11
|
+
@symbol-change="onSymbolChange"
|
|
9
12
|
/>
|
|
10
13
|
<div
|
|
11
14
|
class="chart-stage"
|
|
@@ -120,7 +123,6 @@
|
|
|
120
123
|
import { ref, computed, onMounted, onUnmounted, watch, nextTick, shallowRef } from 'vue'
|
|
121
124
|
import {
|
|
122
125
|
SemanticChartController,
|
|
123
|
-
__setDataFetcher,
|
|
124
126
|
type SemanticChartConfig,
|
|
125
127
|
type DataFetcher,
|
|
126
128
|
} from '@363045841yyt/klinechart-core/semantic'
|
|
@@ -149,9 +151,15 @@ import {
|
|
|
149
151
|
} from '@363045841yyt/klinechart-core/indicators'
|
|
150
152
|
import type { DrawingObject, DrawingStyle } from '@363045841yyt/klinechart-core/plugin'
|
|
151
153
|
import type { ChartSettings } from '@363045841yyt/klinechart-core/config'
|
|
152
|
-
import {
|
|
154
|
+
import {
|
|
155
|
+
resolveThemeColors,
|
|
156
|
+
themeToCssVars,
|
|
157
|
+
lightTheme,
|
|
158
|
+
darkTheme,
|
|
159
|
+
type ColorPresetSettings,
|
|
160
|
+
} from '@363045841yyt/klinechart-core'
|
|
153
161
|
import LeftToolbar from './LeftToolbar.vue'
|
|
154
|
-
import TopToolbar from './TopToolbar.vue'
|
|
162
|
+
import TopToolbar, { type SymbolItem } from './TopToolbar.vue'
|
|
155
163
|
|
|
156
164
|
const props = withDefaults(
|
|
157
165
|
defineProps<{
|
|
@@ -195,17 +203,37 @@ const emit = defineEmits<{
|
|
|
195
203
|
(e: 'zoomLevelChange', level: number, kWidth: number): void
|
|
196
204
|
(e: 'toggleFullscreen'): void
|
|
197
205
|
(e: 'themeChange', theme: 'light' | 'dark'): void
|
|
198
|
-
(e: 'addOverlaySymbol'): void
|
|
206
|
+
(e: 'addOverlaySymbol'): void
|
|
199
207
|
(e: 'kLineLevelChange', level: string): void
|
|
200
208
|
}>()
|
|
201
209
|
|
|
202
210
|
const kLineLevel = ref(props.semanticConfig.data.period)
|
|
211
|
+
const currentSymbol = ref('选择商品')
|
|
212
|
+
const symbolLoading = ref(false)
|
|
213
|
+
const symbolError = ref(false)
|
|
203
214
|
|
|
204
215
|
function onKLineLevelChange(level: string) {
|
|
205
216
|
kLineLevel.value = level as typeof kLineLevel.value
|
|
206
217
|
emit('kLineLevelChange', level)
|
|
207
218
|
}
|
|
208
219
|
|
|
220
|
+
function onSymbolChange(item: SymbolItem) {
|
|
221
|
+
symbolLoading.value = true
|
|
222
|
+
symbolError.value = false
|
|
223
|
+
currentSymbol.value = item.code
|
|
224
|
+
controller.value?.setSymbols([
|
|
225
|
+
{
|
|
226
|
+
symbol: item.code,
|
|
227
|
+
exchange: item.exchange,
|
|
228
|
+
period: kLineLevel.value,
|
|
229
|
+
source: item.source,
|
|
230
|
+
startDate: props.semanticConfig.data.startDate,
|
|
231
|
+
endDate: props.semanticConfig.data.endDate,
|
|
232
|
+
adjust: props.semanticConfig.data.adjust,
|
|
233
|
+
},
|
|
234
|
+
])
|
|
235
|
+
}
|
|
236
|
+
|
|
209
237
|
const containerRef = ref<HTMLDivElement | null>(null)
|
|
210
238
|
const chartMainRef = ref<HTMLDivElement | null>(null)
|
|
211
239
|
const chartWrapperRef = ref<HTMLDivElement | null>(null)
|
|
@@ -258,7 +286,9 @@ const tooltipColors = computed(() => {
|
|
|
258
286
|
|
|
259
287
|
const themeCssVars = computed(() => {
|
|
260
288
|
const theme = chartTheme.value === 'dark' ? darkTheme : lightTheme
|
|
261
|
-
const overrides = (chartSettings.value.colorPresetSettings as ColorPresetSettings | undefined)?.[
|
|
289
|
+
const overrides = (chartSettings.value.colorPresetSettings as ColorPresetSettings | undefined)?.[
|
|
290
|
+
chartTheme.value
|
|
291
|
+
]
|
|
262
292
|
if (overrides && Object.keys(overrides).length > 0) {
|
|
263
293
|
return themeToCssVars({ ...theme, colors: { ...theme.colors, ...overrides } })
|
|
264
294
|
}
|
|
@@ -299,55 +329,10 @@ function handleSettingsChange(settings: ChartSettings) {
|
|
|
299
329
|
applyThemeFromSettings(controller.value, settings.theme as string)
|
|
300
330
|
controller.value?.updateSettingsFacade(settings)
|
|
301
331
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
controller.value?.updateData(testData)
|
|
306
|
-
console.timeEnd('updateData-10k')
|
|
307
|
-
dataLength.value = testData.length
|
|
308
|
-
dataVersion.value++
|
|
309
|
-
} else {
|
|
310
|
-
if (semanticController.value && controller.value?.getData()?.length === 10000) {
|
|
311
|
-
semanticController.value.applyConfig(props.semanticConfig)
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
// 生成1万条K线测试数据
|
|
317
|
-
function generate10kKLineData() {
|
|
318
|
-
const data: KLineData[] = []
|
|
319
|
-
const startTime = new Date('2020-01-01').getTime()
|
|
320
|
-
const dayMs = 24 * 60 * 60 * 1000
|
|
321
|
-
|
|
322
|
-
let lastClose = 3000 // 起始价格
|
|
323
|
-
|
|
324
|
-
for (let i = 0; i < 10000; i++) {
|
|
325
|
-
const timestamp = startTime + i * dayMs
|
|
326
|
-
|
|
327
|
-
// 生成随机波动
|
|
328
|
-
const volatility = 0.02 // 2%日波动率
|
|
329
|
-
const trend = 0.0001 // 轻微上涨趋势
|
|
330
|
-
const change = (Math.random() - 0.5) * 2 * volatility + trend
|
|
331
|
-
|
|
332
|
-
const open = lastClose
|
|
333
|
-
const close = open * (1 + change)
|
|
334
|
-
const high = Math.max(open, close) * (1 + Math.random() * 0.01)
|
|
335
|
-
const low = Math.min(open, close) * (1 - Math.random() * 0.01)
|
|
336
|
-
const volume = Math.floor(1000000 + Math.random() * 5000000)
|
|
337
|
-
|
|
338
|
-
data.push({
|
|
339
|
-
timestamp,
|
|
340
|
-
open: parseFloat(open.toFixed(2)),
|
|
341
|
-
high: parseFloat(high.toFixed(2)),
|
|
342
|
-
low: parseFloat(low.toFixed(2)),
|
|
343
|
-
close: parseFloat(close.toFixed(2)),
|
|
344
|
-
volume,
|
|
345
|
-
})
|
|
346
|
-
|
|
347
|
-
lastClose = close
|
|
332
|
+
controller.value?.setDataFetcher(props.dataFetcher)
|
|
333
|
+
if (semanticController.value && props.semanticConfig) {
|
|
334
|
+
semanticController.value.applyConfig(props.semanticConfig)
|
|
348
335
|
}
|
|
349
|
-
|
|
350
|
-
return data
|
|
351
336
|
}
|
|
352
337
|
|
|
353
338
|
function measureTooltipSize(el: HTMLDivElement, minWidth: number, minHeight: number) {
|
|
@@ -736,9 +721,24 @@ function handleIndicatorToggle(indicatorId: string, active: boolean) {
|
|
|
736
721
|
if (!c) return
|
|
737
722
|
|
|
738
723
|
const mainIndicatorIds = [
|
|
739
|
-
'MA',
|
|
740
|
-
'
|
|
741
|
-
'
|
|
724
|
+
'MA',
|
|
725
|
+
'BOLL',
|
|
726
|
+
'EXPMA',
|
|
727
|
+
'ENE',
|
|
728
|
+
'WMA',
|
|
729
|
+
'DEMA',
|
|
730
|
+
'TEMA',
|
|
731
|
+
'HMA',
|
|
732
|
+
'KAMA',
|
|
733
|
+
'SAR',
|
|
734
|
+
'SUPERTREND',
|
|
735
|
+
'KELTNER',
|
|
736
|
+
'DONCHIAN',
|
|
737
|
+
'ICHIMOKU',
|
|
738
|
+
'PIVOT',
|
|
739
|
+
'FIB',
|
|
740
|
+
'STRUCTURE',
|
|
741
|
+
'ZONES',
|
|
742
742
|
]
|
|
743
743
|
if (mainIndicatorIds.includes(indicatorId)) {
|
|
744
744
|
const existingIndicator = mainActiveIndicators.value.find((id) => id === indicatorId)
|
|
@@ -772,8 +772,10 @@ function handleIndicatorToggle(indicatorId: string, active: boolean) {
|
|
|
772
772
|
|
|
773
773
|
function handleUpdateParams(indicatorId: string, params: Record<string, unknown>) {
|
|
774
774
|
if (
|
|
775
|
-
indicatorId === 'MA' ||
|
|
776
|
-
indicatorId === '
|
|
775
|
+
indicatorId === 'MA' ||
|
|
776
|
+
indicatorId === 'BOLL' ||
|
|
777
|
+
indicatorId === 'EXPMA' ||
|
|
778
|
+
indicatorId === 'ENE'
|
|
777
779
|
) {
|
|
778
780
|
controller.value?.updateIndicatorParams(indicatorId, params)
|
|
779
781
|
return
|
|
@@ -942,11 +944,7 @@ function setupChartCallbacks(ctrl: ChartController): void {
|
|
|
942
944
|
if (viewWidth.value !== vp.plotWidth) {
|
|
943
945
|
viewWidth.value = vp.plotWidth
|
|
944
946
|
}
|
|
945
|
-
if (
|
|
946
|
-
zoomLevel.value !== vp.zoomLevel ||
|
|
947
|
-
kWidth.value !== vp.kWidth ||
|
|
948
|
-
kGap.value !== vp.kGap
|
|
949
|
-
) {
|
|
947
|
+
if (zoomLevel.value !== vp.zoomLevel || kWidth.value !== vp.kWidth || kGap.value !== vp.kGap) {
|
|
950
948
|
zoomLevel.value = vp.zoomLevel
|
|
951
949
|
kWidth.value = vp.kWidth
|
|
952
950
|
kGap.value = vp.kGap
|
|
@@ -970,6 +968,8 @@ function setupChartCallbacks(ctrl: ChartController): void {
|
|
|
970
968
|
const data = ctrl.data.peek()
|
|
971
969
|
dataLength.value = data.length
|
|
972
970
|
dataVersion.value++
|
|
971
|
+
symbolLoading.value = false
|
|
972
|
+
symbolError.value = data.length === 0
|
|
973
973
|
})
|
|
974
974
|
|
|
975
975
|
const unsubscribeTheme = ctrl.theme.subscribe(() => {
|
|
@@ -1048,13 +1048,6 @@ function applyInitialSettings(ctrl: ChartController): void {
|
|
|
1048
1048
|
chartSettings.value = initialSettings
|
|
1049
1049
|
applyThemeFromSettings(ctrl, initialSettings.theme as string)
|
|
1050
1050
|
ctrl.updateSettingsFacade(initialSettings)
|
|
1051
|
-
|
|
1052
|
-
if (initialSettings.performanceTest10kKlines) {
|
|
1053
|
-
const testData = generate10kKLineData()
|
|
1054
|
-
console.time('updateData-10k')
|
|
1055
|
-
ctrl.updateData(testData)
|
|
1056
|
-
console.timeEnd('updateData-10k')
|
|
1057
|
-
}
|
|
1058
1051
|
}
|
|
1059
1052
|
|
|
1060
1053
|
function setupDrawingController(ctrl: ChartController): void {
|
|
@@ -1082,7 +1075,7 @@ function setupInteractionCallbacks(ctrl: ChartController): void {
|
|
|
1082
1075
|
}
|
|
1083
1076
|
|
|
1084
1077
|
function setupSemanticController(ctrl: ChartController): void {
|
|
1085
|
-
|
|
1078
|
+
ctrl.setDataFetcher(props.dataFetcher)
|
|
1086
1079
|
semanticController.value = new SemanticChartController(ctrl)
|
|
1087
1080
|
|
|
1088
1081
|
semanticController.value.on('config:error', (error) => {
|
|
@@ -1095,21 +1088,12 @@ function setupSemanticController(ctrl: ChartController): void {
|
|
|
1095
1088
|
syncSubPanesFromChart()
|
|
1096
1089
|
nextTick(() => scrollToRight())
|
|
1097
1090
|
})
|
|
1098
|
-
//
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
console.error('Semantic config apply failed:', result.errors)
|
|
1105
|
-
}
|
|
1106
|
-
} else {
|
|
1107
|
-
semanticController.value.applyConfig(props.semanticConfig).then((result) => {
|
|
1108
|
-
if (result && !result.success) {
|
|
1109
|
-
console.error('Semantic config apply failed:', result.errors)
|
|
1110
|
-
}
|
|
1111
|
-
})
|
|
1112
|
-
}
|
|
1091
|
+
// 暂时断开语义化配置加载,由搜索结果驱动
|
|
1092
|
+
// semanticController.value.applyConfig(props.semanticConfig).then((result) => {
|
|
1093
|
+
// if (result && !result.success) {
|
|
1094
|
+
// console.error('Semantic config apply failed:', result.errors)
|
|
1095
|
+
// }
|
|
1096
|
+
// })
|
|
1113
1097
|
}
|
|
1114
1098
|
|
|
1115
1099
|
onMounted(() => {
|