@363045841yyt/klinechart 0.8.1 → 0.8.2
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/README.md +6 -2
- package/dist/components/KLineAdjustmentDropdown.vue.d.ts +13 -0
- package/dist/components/KLineAdjustmentDropdown.vue.d.ts.map +1 -0
- package/dist/components/KLineChart.vue.d.ts +7 -2
- package/dist/components/KLineChart.vue.d.ts.map +1 -1
- package/dist/components/KLineLevelDropdown.vue.d.ts +1 -1
- package/dist/components/KLineLevelDropdown.vue.d.ts.map +1 -1
- package/dist/components/KLineTooltip.vue.d.ts +6 -0
- package/dist/components/KLineTooltip.vue.d.ts.map +1 -1
- package/dist/components/SymbolSelector.vue.d.ts.map +1 -1
- package/dist/components/TopToolbar.vue.d.ts +3 -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 +699 -653
- package/dist/web-component.d.ts +2 -1
- package/dist/web-component.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/KLineAdjustmentDropdown.vue +32 -0
- package/src/components/KLineChart.vue +23 -7
- package/src/components/KLineLevelDropdown.vue +2 -0
- package/src/components/KLineTooltip.vue +16 -9
- package/src/components/SymbolSelector.vue +2 -0
- package/src/components/TopToolbar.vue +22 -17
package/dist/web-component.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SemanticChartConfig, DataFetcher } from '@363045841yyt/klinechart-core/semantic';
|
|
2
2
|
declare const KLineChartElement: import('vue').VueElementConstructor<{
|
|
3
|
-
semanticConfig
|
|
3
|
+
semanticConfig?: SemanticChartConfig;
|
|
4
4
|
dataFetcher: DataFetcher;
|
|
5
5
|
yPaddingPx?: number;
|
|
6
6
|
minKWidth?: number;
|
|
@@ -11,6 +11,7 @@ declare const KLineChartElement: import('vue').VueElementConstructor<{
|
|
|
11
11
|
zoomLevels?: number;
|
|
12
12
|
initialZoomLevel?: number;
|
|
13
13
|
isFullscreen?: boolean;
|
|
14
|
+
timezone?: string;
|
|
14
15
|
}>;
|
|
15
16
|
export { KLineChartElement };
|
|
16
17
|
export default KLineChartElement;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-component.d.ts","sourceRoot":"","sources":["../src/web-component.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAE9F,QAAA,MAAM,iBAAiB
|
|
1
|
+
{"version":3,"file":"web-component.d.ts","sourceRoot":"","sources":["../src/web-component.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAE9F,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;EAErB,CAAA;AAIF,OAAO,EAAE,iBAAiB,EAAE,CAAA;AAC5B,eAAe,iBAAiB,CAAA;AAEhC,YAAY,EAAE,mBAAmB,EAAE,WAAW,EAAE,CAAA"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Dropdown
|
|
3
|
+
:model-value="modelValue"
|
|
4
|
+
:options="adjustmentOptions"
|
|
5
|
+
label="复权"
|
|
6
|
+
title="复权方式"
|
|
7
|
+
size="md"
|
|
8
|
+
@update:model-value="emit('update:modelValue', $event as KLineAdjustment)"
|
|
9
|
+
/>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup lang="ts">
|
|
13
|
+
import Dropdown from './Dropdown.vue'
|
|
14
|
+
import type { AdjustType } from '@363045841yyt/klinechart-core/semantic'
|
|
15
|
+
|
|
16
|
+
export type KLineAdjustment = AdjustType
|
|
17
|
+
|
|
18
|
+
const adjustmentOptions: Array<{ label: string; value: KLineAdjustment }> = [
|
|
19
|
+
{ label: '前复权', value: 'qfq' },
|
|
20
|
+
{ label: '后复权', value: 'hfq' },
|
|
21
|
+
{ label: '仅拆股', value: 'splits' },
|
|
22
|
+
{ label: '不复权', value: 'none' },
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
defineProps<{
|
|
26
|
+
modelValue?: string
|
|
27
|
+
}>()
|
|
28
|
+
|
|
29
|
+
const emit = defineEmits<{
|
|
30
|
+
(e: 'update:modelValue', adjust: KLineAdjustment): void
|
|
31
|
+
}>()
|
|
32
|
+
</script>
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
<TopToolbar
|
|
4
4
|
:symbol="currentSymbol"
|
|
5
5
|
:k-line-level="kLineLevel"
|
|
6
|
+
:k-line-adjust="kLineAdjust"
|
|
6
7
|
:symbol-loading="symbolLoading"
|
|
7
8
|
:symbol-error="symbolError"
|
|
8
9
|
:overlay-symbols="overlaySymbols"
|
|
@@ -11,6 +12,7 @@
|
|
|
11
12
|
@add-overlay-symbol="onAddOverlaySymbol"
|
|
12
13
|
@remove-overlay-symbol="onRemoveOverlaySymbol"
|
|
13
14
|
@k-line-level-change="onKLineLevelChange"
|
|
15
|
+
@k-line-adjust-change="onKLineAdjustChange"
|
|
14
16
|
@toggle-indicator="onToggleIndicator"
|
|
15
17
|
@symbol-change="onSymbolChange"
|
|
16
18
|
/>
|
|
@@ -91,6 +93,8 @@
|
|
|
91
93
|
:anchor-placement="tooltipAnchorPlacement"
|
|
92
94
|
:up-color="tooltipColors.upColor"
|
|
93
95
|
:down-color="tooltipColors.downColor"
|
|
96
|
+
:timezone="props.timezone"
|
|
97
|
+
:show-time="isIntraday"
|
|
94
98
|
/>
|
|
95
99
|
<MarkerTooltip
|
|
96
100
|
v-if="hoveredMarker || hoveredCustomMarker"
|
|
@@ -168,8 +172,8 @@ import TopToolbar, { type SymbolItem } from './TopToolbar.vue'
|
|
|
168
172
|
|
|
169
173
|
const props = withDefaults(
|
|
170
174
|
defineProps<{
|
|
171
|
-
/**
|
|
172
|
-
semanticConfig
|
|
175
|
+
/** 语义化配置(可选,唯一控制源) */
|
|
176
|
+
semanticConfig?: SemanticChartConfig
|
|
173
177
|
|
|
174
178
|
/** 数据获取函数(必需)。框架不绑定数据源,由使用者注入。 */
|
|
175
179
|
dataFetcher: DataFetcher
|
|
@@ -190,6 +194,8 @@ const props = withDefaults(
|
|
|
190
194
|
initialZoomLevel?: number
|
|
191
195
|
/** 是否全屏 */
|
|
192
196
|
isFullscreen?: boolean
|
|
197
|
+
/** 时区,默认 Asia/Shanghai */
|
|
198
|
+
timezone?: string
|
|
193
199
|
}>(),
|
|
194
200
|
{
|
|
195
201
|
yPaddingPx: 20,
|
|
@@ -201,6 +207,7 @@ const props = withDefaults(
|
|
|
201
207
|
zoomLevels: 20,
|
|
202
208
|
initialZoomLevel: 3,
|
|
203
209
|
isFullscreen: false,
|
|
210
|
+
timezone: 'Asia/Shanghai',
|
|
204
211
|
},
|
|
205
212
|
)
|
|
206
213
|
|
|
@@ -209,9 +216,12 @@ const emit = defineEmits<{
|
|
|
209
216
|
(e: 'toggleFullscreen'): void
|
|
210
217
|
(e: 'themeChange', theme: 'light' | 'dark'): void
|
|
211
218
|
(e: 'kLineLevelChange', level: string): void
|
|
219
|
+
(e: 'kLineAdjustChange', adjust: 'qfq' | 'hfq' | 'splits' | 'none'): void
|
|
212
220
|
}>()
|
|
213
221
|
|
|
214
|
-
const kLineLevel = ref(props.semanticConfig
|
|
222
|
+
const kLineLevel = ref(props.semanticConfig?.data?.period ?? 'daily')
|
|
223
|
+
const kLineAdjust = ref(props.semanticConfig?.data?.adjust ?? 'none')
|
|
224
|
+
const isIntraday = computed(() => kLineLevel.value.includes('min'))
|
|
215
225
|
const currentSymbol = ref('选择商品')
|
|
216
226
|
const currentSymbolItem = ref<SymbolItem | null>(null)
|
|
217
227
|
const symbolLoading = ref(false)
|
|
@@ -225,6 +235,12 @@ function onKLineLevelChange(level: string) {
|
|
|
225
235
|
syncSymbolsToController()
|
|
226
236
|
}
|
|
227
237
|
|
|
238
|
+
function onKLineAdjustChange(adjust: 'qfq' | 'hfq' | 'splits' | 'none') {
|
|
239
|
+
kLineAdjust.value = adjust
|
|
240
|
+
emit('kLineAdjustChange', adjust)
|
|
241
|
+
syncSymbolsToController()
|
|
242
|
+
}
|
|
243
|
+
|
|
228
244
|
function onSymbolChange(item: SymbolItem) {
|
|
229
245
|
symbolError.value = false
|
|
230
246
|
currentSymbol.value = item.code
|
|
@@ -253,9 +269,9 @@ function toSymbolSpec(item: SymbolItem): SymbolSpec {
|
|
|
253
269
|
exchange: item.exchange,
|
|
254
270
|
period: kLineLevel.value,
|
|
255
271
|
source: item.source,
|
|
256
|
-
startDate: props.semanticConfig
|
|
257
|
-
endDate: props.semanticConfig
|
|
258
|
-
adjust:
|
|
272
|
+
startDate: props.semanticConfig?.data?.startDate ?? '',
|
|
273
|
+
endDate: props.semanticConfig?.data?.endDate ?? '',
|
|
274
|
+
adjust: kLineAdjust.value,
|
|
259
275
|
}
|
|
260
276
|
}
|
|
261
277
|
|
|
@@ -706,7 +722,7 @@ function clearAllSubPanes(): void {
|
|
|
706
722
|
function initIndicatorsFromConfig(): void {
|
|
707
723
|
const config = props.semanticConfig
|
|
708
724
|
const c = controller.value
|
|
709
|
-
if (!c) return
|
|
725
|
+
if (!config || !c) return
|
|
710
726
|
|
|
711
727
|
const mainIndicators = config.indicators?.main
|
|
712
728
|
if (mainIndicators) {
|
|
@@ -18,12 +18,14 @@ export type KLineLevel =
|
|
|
18
18
|
| '15min'
|
|
19
19
|
| '30min'
|
|
20
20
|
| '60min'
|
|
21
|
+
| 'daily'
|
|
21
22
|
| 'weekly'
|
|
22
23
|
| 'monthly'
|
|
23
24
|
| 'quarterly'
|
|
24
25
|
| 'yearly'
|
|
25
26
|
|
|
26
27
|
const kLineLevelOptions: Array<{ label: string; value: KLineLevel }> = [
|
|
28
|
+
{ label: '1day', value: 'daily' },
|
|
27
29
|
{ label: '1min', value: '1min' },
|
|
28
30
|
{ label: '5min', value: '5min' },
|
|
29
31
|
{ label: '15min', value: '15min' },
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
>
|
|
9
9
|
<div class="kline-tooltip__title">
|
|
10
10
|
<span v-if="k.stockCode">{{ k.stockCode }}</span>
|
|
11
|
-
<span>{{
|
|
11
|
+
<span>{{ formattedDate }}</span>
|
|
12
12
|
</div>
|
|
13
13
|
<div class="kline-tooltip__grid">
|
|
14
14
|
<div class="row">
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
<script setup lang="ts">
|
|
52
52
|
import { computed } from 'vue'
|
|
53
53
|
import type { ComponentPublicInstance } from 'vue'
|
|
54
|
+
import { formatTimestamp } from '@363045841yyt/klinechart-core'
|
|
54
55
|
|
|
55
56
|
export interface KLineData {
|
|
56
57
|
timestamp: number
|
|
@@ -79,9 +80,23 @@ const props = withDefaults(defineProps<{
|
|
|
79
80
|
upColor?: string
|
|
80
81
|
/** 跌的颜色(默认绿跌) */
|
|
81
82
|
downColor?: string
|
|
83
|
+
/** 时区,默认 Asia/Shanghai */
|
|
84
|
+
timezone?: string
|
|
85
|
+
/** 是否显示时分,默认 false */
|
|
86
|
+
showTime?: boolean
|
|
82
87
|
}>(), {
|
|
83
88
|
upColor: '#ef4444',
|
|
84
89
|
downColor: '#22c55e',
|
|
90
|
+
timezone: 'Asia/Shanghai',
|
|
91
|
+
showTime: false,
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
const formattedDate = computed(() => {
|
|
95
|
+
if (!props.k) return ''
|
|
96
|
+
return formatTimestamp(props.k.timestamp, {
|
|
97
|
+
timeZone: props.timezone,
|
|
98
|
+
showTime: props.showTime,
|
|
99
|
+
})
|
|
85
100
|
})
|
|
86
101
|
|
|
87
102
|
const useAnchor = computed(() => props.useAnchor === true)
|
|
@@ -93,14 +108,6 @@ function onRef(el: Element | ComponentPublicInstance | null) {
|
|
|
93
108
|
props.setEl?.(el as HTMLDivElement | null)
|
|
94
109
|
}
|
|
95
110
|
|
|
96
|
-
function formatDate(ts: number): string {
|
|
97
|
-
const d = new Date(ts)
|
|
98
|
-
const y = d.getFullYear()
|
|
99
|
-
const m = String(d.getMonth() + 1).padStart(2, '0')
|
|
100
|
-
const day = String(d.getDate()).padStart(2, '0')
|
|
101
|
-
return `${y}-${m}-${day}`
|
|
102
|
-
}
|
|
103
|
-
|
|
104
111
|
function formatVolume(v: number): string {
|
|
105
112
|
if (v >= 1e8) return (v / 1e8).toFixed(2) + '亿'
|
|
106
113
|
if (v >= 1e4) return (v / 1e4).toFixed(2) + '万'
|
|
@@ -20,6 +20,10 @@
|
|
|
20
20
|
:model-value="kLineLevel"
|
|
21
21
|
@update:model-value="emit('kLineLevelChange', $event)"
|
|
22
22
|
/>
|
|
23
|
+
<KLineAdjustmentDropdown
|
|
24
|
+
:model-value="kLineAdjust"
|
|
25
|
+
@update:model-value="emit('kLineAdjustChange', $event)"
|
|
26
|
+
/>
|
|
23
27
|
<button
|
|
24
28
|
type="button"
|
|
25
29
|
class="indicator-button"
|
|
@@ -36,6 +40,7 @@
|
|
|
36
40
|
<script setup lang="ts">
|
|
37
41
|
import { computed } from 'vue'
|
|
38
42
|
import KLineLevelDropdown, { type KLineLevel } from './KLineLevelDropdown.vue'
|
|
43
|
+
import KLineAdjustmentDropdown, { type KLineAdjustment } from './KLineAdjustmentDropdown.vue'
|
|
39
44
|
import SymbolSelector from './SymbolSelector.vue'
|
|
40
45
|
import CompareSymbolSelector from './CompareSymbolSelector.vue'
|
|
41
46
|
import type { SymbolItem } from './SymbolSelector.vue'
|
|
@@ -45,6 +50,7 @@ export type { SymbolItem }
|
|
|
45
50
|
const props = defineProps<{
|
|
46
51
|
symbol?: string
|
|
47
52
|
kLineLevel?: string
|
|
53
|
+
kLineAdjust?: string
|
|
48
54
|
symbols?: SymbolItem[]
|
|
49
55
|
symbolLoading?: boolean
|
|
50
56
|
symbolError?: boolean
|
|
@@ -57,30 +63,29 @@ const emit = defineEmits<{
|
|
|
57
63
|
(e: 'addOverlaySymbol', item: SymbolItem): void
|
|
58
64
|
(e: 'removeOverlaySymbol', code: string): void
|
|
59
65
|
(e: 'kLineLevelChange', level: KLineLevel): void
|
|
66
|
+
(e: 'kLineAdjustChange', adjust: KLineAdjustment): void
|
|
60
67
|
(e: 'toggleIndicator'): void
|
|
61
68
|
(e: 'symbolChange', symbol: SymbolItem): void
|
|
62
69
|
}>()
|
|
63
70
|
|
|
64
71
|
const MOCK_SYMBOLS: SymbolItem[] = [
|
|
65
72
|
// ── TradingView 全球品种 ──
|
|
66
|
-
{ code: 'XAUUSD',
|
|
67
|
-
{ code: 'BTCUSDT', description: 'Bitcoin / Tether',
|
|
68
|
-
{ code: 'ETHUSDT', description: 'Ethereum / Tether',
|
|
69
|
-
{ code: 'EURUSD',
|
|
70
|
-
{ code: 'SPX',
|
|
71
|
-
{ code: 'AAPL',
|
|
72
|
-
{ code: 'TSLA',
|
|
73
|
-
{ code: '
|
|
74
|
-
|
|
75
|
-
{ code: '
|
|
76
|
-
|
|
77
|
-
{ code: '
|
|
78
|
-
{ code: '
|
|
79
|
-
{ code: '000858', description: '五 粮 液', exchange: 'SZSE', source: 'baostock' },
|
|
80
|
-
{ code: '000001', description: '平安银行', exchange: 'SZSE', source: 'baostock' },
|
|
73
|
+
{ code: 'XAUUSD', description: '现货黄金', exchange: 'OANDA', source: 'tradingview' },
|
|
74
|
+
{ code: 'BTCUSDT', description: 'Bitcoin / Tether', exchange: 'BINANCE', source: 'tradingview' },
|
|
75
|
+
{ code: 'ETHUSDT', description: 'Ethereum / Tether', exchange: 'BINANCE', source: 'tradingview' },
|
|
76
|
+
{ code: 'EURUSD', description: '欧元/美元', exchange: 'OANDA', source: 'tradingview' },
|
|
77
|
+
{ code: 'SPX', description: '标普 500 指数', exchange: 'SP', source: 'tradingview' },
|
|
78
|
+
{ code: 'AAPL', description: 'Apple Inc.', exchange: 'NASDAQ', source: 'tradingview' },
|
|
79
|
+
{ code: 'TSLA', description: 'Tesla, Inc.', exchange: 'NASDAQ', source: 'tradingview' },
|
|
80
|
+
{ code: '1810', description: '小米集团', exchange: 'HKEX', source: 'tradingview' },
|
|
81
|
+
// ── gotdx A 股 ──
|
|
82
|
+
{ code: '600519', description: '贵州茅台', exchange: 'SSE', source: 'gotdx' },
|
|
83
|
+
{ code: '601360', description: '三六零', exchange: 'SSE', source: 'gotdx' },
|
|
84
|
+
{ code: '000858', description: '五 粮 液', exchange: 'SZSE', source: 'gotdx' },
|
|
85
|
+
{ code: '000001', description: '平安银行', exchange: 'SZSE', source: 'gotdx' },
|
|
81
86
|
// ── Mock ──
|
|
82
|
-
{ code: 'MOCK-100',
|
|
83
|
-
{ code: 'MOCK-10000', description: 'Mock 10000 条',
|
|
87
|
+
{ code: 'MOCK-100', description: 'Mock 100 条', exchange: 'MOCK', source: 'mock-100' },
|
|
88
|
+
{ code: 'MOCK-10000', description: 'Mock 10000 条', exchange: 'MOCK', source: 'mock-10000' },
|
|
84
89
|
]
|
|
85
90
|
|
|
86
91
|
const displaySymbol = computed(() => props.symbol?.trim() ?? '')
|