@363045841yyt/klinechart 0.7.12 → 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/ChartSettingsDialog.vue.d.ts.map +1 -1
- package/dist/components/DrawingStyleToolbar.vue.d.ts.map +1 -1
- package/dist/components/Dropdown.vue.d.ts +29 -0
- package/dist/components/Dropdown.vue.d.ts.map +1 -0
- package/dist/components/IndicatorSelector.vue.d.ts +5 -1
- package/dist/components/IndicatorSelector.vue.d.ts.map +1 -1
- package/dist/components/KLineChart.vue.d.ts +4 -0
- package/dist/components/KLineChart.vue.d.ts.map +1 -1
- package/dist/components/KLineLevelDropdown.vue.d.ts +12 -0
- package/dist/components/KLineLevelDropdown.vue.d.ts.map +1 -0
- 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 +24 -0
- package/dist/components/TopToolbar.vue.d.ts.map +1 -0
- package/dist/index.cjs +2 -2
- package/dist/index.css +1 -1
- package/dist/index.js +1328 -913
- package/package.json +9 -9
- package/src/components/ChartSettingsDialog.vue +15 -39
- package/src/components/DrawingStyleToolbar.vue +27 -36
- package/src/components/Dropdown.vue +291 -0
- package/src/components/IndicatorSelector.vue +21 -357
- package/src/components/KLineChart.vue +127 -98
- package/src/components/KLineLevelDropdown.vue +45 -0
- package/src/components/LeftToolbar.vue +4 -4
- package/src/components/SymbolSelector.vue +478 -0
- package/src/components/TopToolbar.vue +210 -0
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div ref="chartWrapperRef" class="chart-wrapper" :data-theme="chartTheme" :style="themeCssVars">
|
|
3
|
+
<TopToolbar
|
|
4
|
+
:symbol="currentSymbol"
|
|
5
|
+
:k-line-level="kLineLevel"
|
|
6
|
+
:symbol-loading="symbolLoading"
|
|
7
|
+
:symbol-error="symbolError"
|
|
8
|
+
@add-overlay-symbol="$emit('addOverlaySymbol')"
|
|
9
|
+
@k-line-level-change="onKLineLevelChange"
|
|
10
|
+
@toggle-indicator="onToggleIndicator"
|
|
11
|
+
@symbol-change="onSymbolChange"
|
|
12
|
+
/>
|
|
3
13
|
<div
|
|
4
14
|
class="chart-stage"
|
|
5
15
|
:class="{
|
|
@@ -99,6 +109,7 @@
|
|
|
99
109
|
</div>
|
|
100
110
|
</div>
|
|
101
111
|
<IndicatorSelector
|
|
112
|
+
ref="indicatorSelectorRef"
|
|
102
113
|
:active-indicators="activeIndicators"
|
|
103
114
|
:indicator-params="indicatorParams"
|
|
104
115
|
@toggle="handleIndicatorToggle"
|
|
@@ -112,7 +123,6 @@
|
|
|
112
123
|
import { ref, computed, onMounted, onUnmounted, watch, nextTick, shallowRef } from 'vue'
|
|
113
124
|
import {
|
|
114
125
|
SemanticChartController,
|
|
115
|
-
__setDataFetcher,
|
|
116
126
|
type SemanticChartConfig,
|
|
117
127
|
type DataFetcher,
|
|
118
128
|
} from '@363045841yyt/klinechart-core/semantic'
|
|
@@ -133,14 +143,23 @@ import {
|
|
|
133
143
|
zoomLevelToKWidth,
|
|
134
144
|
kGapFromKWidth,
|
|
135
145
|
getPhysicalKLineConfig,
|
|
136
|
-
SUB_PANE_INDICATOR_CONFIGS,
|
|
137
|
-
SUB_PANE_INDICATORS,
|
|
138
146
|
DrawingInteractionController,
|
|
139
147
|
} from '@363045841yyt/klinechart-core/controllers'
|
|
148
|
+
import {
|
|
149
|
+
getRegisteredIndicatorDefinition,
|
|
150
|
+
getRegisteredIndicatorDefinitions,
|
|
151
|
+
} from '@363045841yyt/klinechart-core/indicators'
|
|
140
152
|
import type { DrawingObject, DrawingStyle } from '@363045841yyt/klinechart-core/plugin'
|
|
141
153
|
import type { ChartSettings } from '@363045841yyt/klinechart-core/config'
|
|
142
|
-
import {
|
|
154
|
+
import {
|
|
155
|
+
resolveThemeColors,
|
|
156
|
+
themeToCssVars,
|
|
157
|
+
lightTheme,
|
|
158
|
+
darkTheme,
|
|
159
|
+
type ColorPresetSettings,
|
|
160
|
+
} from '@363045841yyt/klinechart-core'
|
|
143
161
|
import LeftToolbar from './LeftToolbar.vue'
|
|
162
|
+
import TopToolbar, { type SymbolItem } from './TopToolbar.vue'
|
|
144
163
|
|
|
145
164
|
const props = withDefaults(
|
|
146
165
|
defineProps<{
|
|
@@ -184,13 +203,43 @@ const emit = defineEmits<{
|
|
|
184
203
|
(e: 'zoomLevelChange', level: number, kWidth: number): void
|
|
185
204
|
(e: 'toggleFullscreen'): void
|
|
186
205
|
(e: 'themeChange', theme: 'light' | 'dark'): void
|
|
206
|
+
(e: 'addOverlaySymbol'): void
|
|
207
|
+
(e: 'kLineLevelChange', level: string): void
|
|
187
208
|
}>()
|
|
188
209
|
|
|
210
|
+
const kLineLevel = ref(props.semanticConfig.data.period)
|
|
211
|
+
const currentSymbol = ref('选择商品')
|
|
212
|
+
const symbolLoading = ref(false)
|
|
213
|
+
const symbolError = ref(false)
|
|
214
|
+
|
|
215
|
+
function onKLineLevelChange(level: string) {
|
|
216
|
+
kLineLevel.value = level as typeof kLineLevel.value
|
|
217
|
+
emit('kLineLevelChange', level)
|
|
218
|
+
}
|
|
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
|
+
|
|
189
237
|
const containerRef = ref<HTMLDivElement | null>(null)
|
|
190
238
|
const chartMainRef = ref<HTMLDivElement | null>(null)
|
|
191
239
|
const chartWrapperRef = ref<HTMLDivElement | null>(null)
|
|
192
240
|
const tooltipLayerRef = ref<HTMLDivElement | null>(null)
|
|
193
241
|
const toolbarRef = ref<InstanceType<typeof LeftToolbar> | null>(null)
|
|
242
|
+
const indicatorSelectorRef = ref<InstanceType<typeof IndicatorSelector> | null>(null)
|
|
194
243
|
provideFullscreenTeleportTarget(chartWrapperRef)
|
|
195
244
|
|
|
196
245
|
/* ========== 图表控制器 ========== */
|
|
@@ -237,7 +286,9 @@ const tooltipColors = computed(() => {
|
|
|
237
286
|
|
|
238
287
|
const themeCssVars = computed(() => {
|
|
239
288
|
const theme = chartTheme.value === 'dark' ? darkTheme : lightTheme
|
|
240
|
-
const overrides = (chartSettings.value.colorPresetSettings as ColorPresetSettings | undefined)?.[
|
|
289
|
+
const overrides = (chartSettings.value.colorPresetSettings as ColorPresetSettings | undefined)?.[
|
|
290
|
+
chartTheme.value
|
|
291
|
+
]
|
|
241
292
|
if (overrides && Object.keys(overrides).length > 0) {
|
|
242
293
|
return themeToCssVars({ ...theme, colors: { ...theme.colors, ...overrides } })
|
|
243
294
|
}
|
|
@@ -278,57 +329,12 @@ function handleSettingsChange(settings: ChartSettings) {
|
|
|
278
329
|
applyThemeFromSettings(controller.value, settings.theme as string)
|
|
279
330
|
controller.value?.updateSettingsFacade(settings)
|
|
280
331
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
controller.value?.updateData(testData)
|
|
285
|
-
console.timeEnd('updateData-10k')
|
|
286
|
-
dataLength.value = testData.length
|
|
287
|
-
dataVersion.value++
|
|
288
|
-
} else {
|
|
289
|
-
if (semanticController.value && controller.value?.getData()?.length === 10000) {
|
|
290
|
-
semanticController.value.applyConfig(props.semanticConfig)
|
|
291
|
-
}
|
|
332
|
+
controller.value?.setDataFetcher(props.dataFetcher)
|
|
333
|
+
if (semanticController.value && props.semanticConfig) {
|
|
334
|
+
semanticController.value.applyConfig(props.semanticConfig)
|
|
292
335
|
}
|
|
293
336
|
}
|
|
294
337
|
|
|
295
|
-
// 生成1万条K线测试数据
|
|
296
|
-
function generate10kKLineData() {
|
|
297
|
-
const data: KLineData[] = []
|
|
298
|
-
const startTime = new Date('2020-01-01').getTime()
|
|
299
|
-
const dayMs = 24 * 60 * 60 * 1000
|
|
300
|
-
|
|
301
|
-
let lastClose = 3000 // 起始价格
|
|
302
|
-
|
|
303
|
-
for (let i = 0; i < 10000; i++) {
|
|
304
|
-
const timestamp = startTime + i * dayMs
|
|
305
|
-
|
|
306
|
-
// 生成随机波动
|
|
307
|
-
const volatility = 0.02 // 2%日波动率
|
|
308
|
-
const trend = 0.0001 // 轻微上涨趋势
|
|
309
|
-
const change = (Math.random() - 0.5) * 2 * volatility + trend
|
|
310
|
-
|
|
311
|
-
const open = lastClose
|
|
312
|
-
const close = open * (1 + change)
|
|
313
|
-
const high = Math.max(open, close) * (1 + Math.random() * 0.01)
|
|
314
|
-
const low = Math.min(open, close) * (1 - Math.random() * 0.01)
|
|
315
|
-
const volume = Math.floor(1000000 + Math.random() * 5000000)
|
|
316
|
-
|
|
317
|
-
data.push({
|
|
318
|
-
timestamp,
|
|
319
|
-
open: parseFloat(open.toFixed(2)),
|
|
320
|
-
high: parseFloat(high.toFixed(2)),
|
|
321
|
-
low: parseFloat(low.toFixed(2)),
|
|
322
|
-
close: parseFloat(close.toFixed(2)),
|
|
323
|
-
volume,
|
|
324
|
-
})
|
|
325
|
-
|
|
326
|
-
lastClose = close
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
return data
|
|
330
|
-
}
|
|
331
|
-
|
|
332
338
|
function measureTooltipSize(el: HTMLDivElement, minWidth: number, minHeight: number) {
|
|
333
339
|
const r = el.getBoundingClientRect()
|
|
334
340
|
return {
|
|
@@ -475,10 +481,15 @@ function handleSelectTool(toolId: string) {
|
|
|
475
481
|
drawingController.value?.setTool(toolId as DrawingToolId)
|
|
476
482
|
}
|
|
477
483
|
|
|
484
|
+
function onToggleIndicator() {
|
|
485
|
+
indicatorSelectorRef.value?.toggleMenu()
|
|
486
|
+
}
|
|
487
|
+
|
|
478
488
|
function onUpdateDrawingStyle(style: Partial<DrawingStyle>) {
|
|
479
489
|
const d = selectedDrawing.value
|
|
480
490
|
if (!d || !drawingController.value) return
|
|
481
491
|
drawingController.value.updateDrawingStyle(d.id, style)
|
|
492
|
+
drawings.value = drawingController.value.getDrawings()
|
|
482
493
|
}
|
|
483
494
|
|
|
484
495
|
function onDeleteDrawing() {
|
|
@@ -614,7 +625,19 @@ function buildPaneLayoutIntent(): PaneSpec[] {
|
|
|
614
625
|
function getDefaultParams(
|
|
615
626
|
indicatorId: SubIndicatorType,
|
|
616
627
|
): Record<string, number | boolean | string> {
|
|
617
|
-
return {
|
|
628
|
+
if (indicatorId === 'VOLUME') return {}
|
|
629
|
+
const meta = getRegisteredIndicatorDefinition(indicatorId)
|
|
630
|
+
if (meta?.runtime?.defaultConfig) {
|
|
631
|
+
return { ...meta.runtime.defaultConfig } as Record<string, number | boolean | string>
|
|
632
|
+
}
|
|
633
|
+
return {}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// 副图指标判定(基于 registry category + VOLUME 特例)
|
|
637
|
+
function isSubPaneIndicator(id: string): boolean {
|
|
638
|
+
if (id === 'VOLUME') return true
|
|
639
|
+
const def = getRegisteredIndicatorDefinition(id)
|
|
640
|
+
return !!def && def.category !== 'main'
|
|
618
641
|
}
|
|
619
642
|
|
|
620
643
|
// 副图实例计数器:用于生成 'RSI_0', 'MACD_0' 这样的 paneId
|
|
@@ -698,9 +721,24 @@ function handleIndicatorToggle(indicatorId: string, active: boolean) {
|
|
|
698
721
|
if (!c) return
|
|
699
722
|
|
|
700
723
|
const mainIndicatorIds = [
|
|
701
|
-
'MA',
|
|
702
|
-
'
|
|
703
|
-
'
|
|
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',
|
|
704
742
|
]
|
|
705
743
|
if (mainIndicatorIds.includes(indicatorId)) {
|
|
706
744
|
const existingIndicator = mainActiveIndicators.value.find((id) => id === indicatorId)
|
|
@@ -712,7 +750,7 @@ function handleIndicatorToggle(indicatorId: string, active: boolean) {
|
|
|
712
750
|
return
|
|
713
751
|
}
|
|
714
752
|
|
|
715
|
-
if (
|
|
753
|
+
if (isSubPaneIndicator(indicatorId)) {
|
|
716
754
|
if (active) {
|
|
717
755
|
const existingPane = subPanes.value.find((p) => p.indicatorId === indicatorId)
|
|
718
756
|
if (existingPane) return
|
|
@@ -734,13 +772,15 @@ function handleIndicatorToggle(indicatorId: string, active: boolean) {
|
|
|
734
772
|
|
|
735
773
|
function handleUpdateParams(indicatorId: string, params: Record<string, unknown>) {
|
|
736
774
|
if (
|
|
737
|
-
indicatorId === 'MA' ||
|
|
738
|
-
indicatorId === '
|
|
775
|
+
indicatorId === 'MA' ||
|
|
776
|
+
indicatorId === 'BOLL' ||
|
|
777
|
+
indicatorId === 'EXPMA' ||
|
|
778
|
+
indicatorId === 'ENE'
|
|
739
779
|
) {
|
|
740
780
|
controller.value?.updateIndicatorParams(indicatorId, params)
|
|
741
781
|
return
|
|
742
782
|
}
|
|
743
|
-
if (
|
|
783
|
+
if (isSubPaneIndicator(indicatorId)) {
|
|
744
784
|
subPanes.value
|
|
745
785
|
.filter((p) => p.indicatorId === indicatorId)
|
|
746
786
|
.forEach((pane) => {
|
|
@@ -753,7 +793,7 @@ function handleReorderSubIndicators(orderedIndicatorIds: string[]) {
|
|
|
753
793
|
if (!orderedIndicatorIds.length || subPanes.value.length <= 1) return
|
|
754
794
|
|
|
755
795
|
const validOrder = orderedIndicatorIds.filter((id): id is SubIndicatorType =>
|
|
756
|
-
|
|
796
|
+
isSubPaneIndicator(id),
|
|
757
797
|
)
|
|
758
798
|
if (!validOrder.length) return
|
|
759
799
|
|
|
@@ -904,11 +944,7 @@ function setupChartCallbacks(ctrl: ChartController): void {
|
|
|
904
944
|
if (viewWidth.value !== vp.plotWidth) {
|
|
905
945
|
viewWidth.value = vp.plotWidth
|
|
906
946
|
}
|
|
907
|
-
if (
|
|
908
|
-
zoomLevel.value !== vp.zoomLevel ||
|
|
909
|
-
kWidth.value !== vp.kWidth ||
|
|
910
|
-
kGap.value !== vp.kGap
|
|
911
|
-
) {
|
|
947
|
+
if (zoomLevel.value !== vp.zoomLevel || kWidth.value !== vp.kWidth || kGap.value !== vp.kGap) {
|
|
912
948
|
zoomLevel.value = vp.zoomLevel
|
|
913
949
|
kWidth.value = vp.kWidth
|
|
914
950
|
kGap.value = vp.kGap
|
|
@@ -932,6 +968,8 @@ function setupChartCallbacks(ctrl: ChartController): void {
|
|
|
932
968
|
const data = ctrl.data.peek()
|
|
933
969
|
dataLength.value = data.length
|
|
934
970
|
dataVersion.value++
|
|
971
|
+
symbolLoading.value = false
|
|
972
|
+
symbolError.value = data.length === 0
|
|
935
973
|
})
|
|
936
974
|
|
|
937
975
|
const unsubscribeTheme = ctrl.theme.subscribe(() => {
|
|
@@ -1010,13 +1048,6 @@ function applyInitialSettings(ctrl: ChartController): void {
|
|
|
1010
1048
|
chartSettings.value = initialSettings
|
|
1011
1049
|
applyThemeFromSettings(ctrl, initialSettings.theme as string)
|
|
1012
1050
|
ctrl.updateSettingsFacade(initialSettings)
|
|
1013
|
-
|
|
1014
|
-
if (initialSettings.performanceTest10kKlines) {
|
|
1015
|
-
const testData = generate10kKLineData()
|
|
1016
|
-
console.time('updateData-10k')
|
|
1017
|
-
ctrl.updateData(testData)
|
|
1018
|
-
console.timeEnd('updateData-10k')
|
|
1019
|
-
}
|
|
1020
1051
|
}
|
|
1021
1052
|
|
|
1022
1053
|
function setupDrawingController(ctrl: ChartController): void {
|
|
@@ -1044,7 +1075,7 @@ function setupInteractionCallbacks(ctrl: ChartController): void {
|
|
|
1044
1075
|
}
|
|
1045
1076
|
|
|
1046
1077
|
function setupSemanticController(ctrl: ChartController): void {
|
|
1047
|
-
|
|
1078
|
+
ctrl.setDataFetcher(props.dataFetcher)
|
|
1048
1079
|
semanticController.value = new SemanticChartController(ctrl)
|
|
1049
1080
|
|
|
1050
1081
|
semanticController.value.on('config:error', (error) => {
|
|
@@ -1057,21 +1088,12 @@ function setupSemanticController(ctrl: ChartController): void {
|
|
|
1057
1088
|
syncSubPanesFromChart()
|
|
1058
1089
|
nextTick(() => scrollToRight())
|
|
1059
1090
|
})
|
|
1060
|
-
//
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
console.error('Semantic config apply failed:', result.errors)
|
|
1067
|
-
}
|
|
1068
|
-
} else {
|
|
1069
|
-
semanticController.value.applyConfig(props.semanticConfig).then((result) => {
|
|
1070
|
-
if (result && !result.success) {
|
|
1071
|
-
console.error('Semantic config apply failed:', result.errors)
|
|
1072
|
-
}
|
|
1073
|
-
})
|
|
1074
|
-
}
|
|
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
|
+
// })
|
|
1075
1097
|
}
|
|
1076
1098
|
|
|
1077
1099
|
onMounted(() => {
|
|
@@ -1161,20 +1183,23 @@ watch(
|
|
|
1161
1183
|
|
|
1162
1184
|
display: flex;
|
|
1163
1185
|
align-items: center;
|
|
1164
|
-
justify-content: center;
|
|
1165
1186
|
width: var(--kmap-width);
|
|
1166
|
-
height: var(--kmap-height);
|
|
1187
|
+
height: calc(var(--kmap-height) - 32px);
|
|
1167
1188
|
min-height: 300px;
|
|
1168
1189
|
flex-direction: column;
|
|
1190
|
+
margin: 16px 0;
|
|
1191
|
+
padding: 0;
|
|
1192
|
+
box-sizing: border-box;
|
|
1193
|
+
gap: 4px;
|
|
1169
1194
|
}
|
|
1170
1195
|
|
|
1171
1196
|
.chart-stage {
|
|
1172
1197
|
width: 95%;
|
|
1173
|
-
|
|
1198
|
+
flex: 1;
|
|
1174
1199
|
min-height: 255px;
|
|
1175
1200
|
display: flex;
|
|
1176
1201
|
align-items: stretch;
|
|
1177
|
-
gap:
|
|
1202
|
+
gap: 4px;
|
|
1178
1203
|
}
|
|
1179
1204
|
|
|
1180
1205
|
.chart-main {
|
|
@@ -1243,7 +1268,7 @@ watch(
|
|
|
1243
1268
|
-ms-overflow-style: none;
|
|
1244
1269
|
border: 1px solid var(--chart-border);
|
|
1245
1270
|
border-right: 0;
|
|
1246
|
-
border-radius:
|
|
1271
|
+
border-radius: 3px 0 0 3px;
|
|
1247
1272
|
box-sizing: border-box;
|
|
1248
1273
|
background: var(--chart-bg);
|
|
1249
1274
|
|
|
@@ -1266,8 +1291,8 @@ watch(
|
|
|
1266
1291
|
background: var(--chart-bg);
|
|
1267
1292
|
overflow: visible;
|
|
1268
1293
|
border: 1px solid var(--chart-border);
|
|
1269
|
-
border-top-right-radius:
|
|
1270
|
-
border-bottom-right-radius:
|
|
1294
|
+
border-top-right-radius: 3px;
|
|
1295
|
+
border-bottom-right-radius: 3px;
|
|
1271
1296
|
|
|
1272
1297
|
-webkit-touch-callout: none;
|
|
1273
1298
|
-webkit-user-select: none;
|
|
@@ -1311,8 +1336,12 @@ watch(
|
|
|
1311
1336
|
}
|
|
1312
1337
|
|
|
1313
1338
|
@media (max-width: 768px), (max-height: 640px) {
|
|
1339
|
+
.chart-wrapper {
|
|
1340
|
+
gap: 4px;
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1314
1343
|
.chart-stage {
|
|
1315
|
-
gap:
|
|
1344
|
+
gap: 4px;
|
|
1316
1345
|
}
|
|
1317
1346
|
}
|
|
1318
1347
|
</style>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Dropdown
|
|
3
|
+
:model-value="modelValue"
|
|
4
|
+
:options="kLineLevelOptions"
|
|
5
|
+
label="级别"
|
|
6
|
+
title="K线级别"
|
|
7
|
+
size="md"
|
|
8
|
+
@update:model-value="emit('update:modelValue', $event as KLineLevel)"
|
|
9
|
+
/>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup lang="ts">
|
|
13
|
+
import Dropdown from './Dropdown.vue'
|
|
14
|
+
|
|
15
|
+
export type KLineLevel =
|
|
16
|
+
| '1min'
|
|
17
|
+
| '5min'
|
|
18
|
+
| '15min'
|
|
19
|
+
| '30min'
|
|
20
|
+
| '60min'
|
|
21
|
+
| 'weekly'
|
|
22
|
+
| 'monthly'
|
|
23
|
+
| 'quarterly'
|
|
24
|
+
| 'yearly'
|
|
25
|
+
|
|
26
|
+
const kLineLevelOptions: Array<{ label: string; value: KLineLevel }> = [
|
|
27
|
+
{ label: '1min', value: '1min' },
|
|
28
|
+
{ label: '5min', value: '5min' },
|
|
29
|
+
{ label: '15min', value: '15min' },
|
|
30
|
+
{ label: '30min', value: '30min' },
|
|
31
|
+
{ label: '1小时', value: '60min' },
|
|
32
|
+
{ label: '1周', value: 'weekly' },
|
|
33
|
+
{ label: '1月', value: 'monthly' },
|
|
34
|
+
{ label: '3月', value: 'quarterly' },
|
|
35
|
+
{ label: '12月', value: 'yearly' },
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
defineProps<{
|
|
39
|
+
modelValue?: string
|
|
40
|
+
}>()
|
|
41
|
+
|
|
42
|
+
const emit = defineEmits<{
|
|
43
|
+
(e: 'update:modelValue', level: KLineLevel): void
|
|
44
|
+
}>()
|
|
45
|
+
</script>
|
|
@@ -307,7 +307,7 @@ onUnmounted(() => {
|
|
|
307
307
|
gap: 6px;
|
|
308
308
|
padding: 8px 5px;
|
|
309
309
|
border: 1px solid var(--klc-color-border-chart);
|
|
310
|
-
border-radius:
|
|
310
|
+
border-radius: 3px;
|
|
311
311
|
background: var(--klc-color-background);
|
|
312
312
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
|
|
313
313
|
box-sizing: border-box;
|
|
@@ -333,7 +333,7 @@ onUnmounted(() => {
|
|
|
333
333
|
height: 28px;
|
|
334
334
|
padding: 0;
|
|
335
335
|
border: 1px solid transparent;
|
|
336
|
-
border-radius:
|
|
336
|
+
border-radius: 3px;
|
|
337
337
|
background: transparent;
|
|
338
338
|
color: var(--klc-color-axis-text);
|
|
339
339
|
cursor: pointer;
|
|
@@ -420,7 +420,7 @@ onUnmounted(() => {
|
|
|
420
420
|
backdrop-filter: blur(8px);
|
|
421
421
|
-webkit-backdrop-filter: blur(8px);
|
|
422
422
|
border: 1px solid var(--klc-color-border-chart);
|
|
423
|
-
border-radius:
|
|
423
|
+
border-radius: 3px;
|
|
424
424
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
|
|
425
425
|
box-sizing: border-box;
|
|
426
426
|
z-index: 100;
|
|
@@ -451,7 +451,7 @@ onUnmounted(() => {
|
|
|
451
451
|
flex-basis: 36px;
|
|
452
452
|
padding: 6px 4px;
|
|
453
453
|
gap: 5px;
|
|
454
|
-
border-radius:
|
|
454
|
+
border-radius: 3px;
|
|
455
455
|
}
|
|
456
456
|
|
|
457
457
|
.left-toolbar__group {
|