st-comp 0.0.44 → 0.0.46
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/lib/bundle.js +134165 -135341
- package/lib/bundle.umd.cjs +62 -66
- package/lib/style.css +1 -1
- package/package.json +3 -3
- package/packages/Kline/index.vue +201 -7
- package/packages/Kline/option.ts +169 -8
- package/packages/Kline/type.d.ts +1 -0
- package/packages/KlineNew/components/KlineSlide/index.vue +150 -0
- package/packages/KlineNew/components/KlineSub/index.vue +320 -0
- package/packages/KlineNew/components/KlineTips/index.vue +61 -0
- package/packages/KlineNew/components/KlineUtils/index.vue +304 -0
- package/packages/KlineNew/components/Tips/index.vue +33 -0
- package/packages/KlineNew/index.ts +8 -2
- package/src/pages/Kline/api.ts +81 -39
- package/src/pages/Kline/components/SingleCycleSingleVariety.vue +155 -78
- package/src/pages/KlineNew/components/KlineAction/components/ContextMenu/index.vue +91 -0
- package/src/pages/KlineNew/components/KlineAction/components/YearChart/index.vue +532 -0
- package/src/pages/KlineNew/components/KlineAction/images/pen.png +0 -0
- package/src/pages/KlineNew/components/KlineAction/index.vue +716 -0
- package/src/pages/KlineNew/components/KlineAction/mockApi/index.js +13 -0
- package/src/pages/KlineNew/components/KlineAction/utils.js +571 -0
- package/src/pages/KlineNew/components/KlineBasic/index.vue +336 -0
- package/src/pages/KlineNew/components/KlineBasic/utils.js +33 -0
- package/src/pages/KlineNew/components/KlineSlide/index.vue +446 -0
- package/src/pages/KlineNew/components/KlineSlide/utils.js +78 -0
- package/src/pages/KlineNew/index.vue +73 -5
- package/vite.config.ts +1 -1
- package/vitePlugins/createExportFile.ts +2 -1
- package/packages/KlineNew/index.vue +0 -310
- package/packages/KlineNew/option.ts +0 -150
- package/packages/KlineNew/utils.ts +0 -13
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="kline"
|
|
4
|
+
@mousemove="isSelect = true"
|
|
5
|
+
@mouseout="isSelect = false"
|
|
6
|
+
>
|
|
7
|
+
<div class="kline-mainTips">
|
|
8
|
+
<st-klineTips :drawData="drawData" :activeIndex="activeIndex"/>
|
|
9
|
+
</div>
|
|
10
|
+
<div class="kline-mainChart" ref="mainChartRef"></div>
|
|
11
|
+
<div class="kline-sub">
|
|
12
|
+
<st-klineSub ref="klineSubRef" v-model="subIndicator" :config="config" :drawData="drawData" :activeIndex="activeIndex" :subIndicatorList="subIndicatorList" />
|
|
13
|
+
</div>
|
|
14
|
+
<st-klineSlide ref="slideChartRef" :data="slideData" @change="slideChange" />
|
|
15
|
+
<st-klineUtils ref="klineUtilsRef" />
|
|
16
|
+
</div>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script setup>
|
|
20
|
+
import { ref, onMounted, onUnmounted, watch, computed } from "vue"
|
|
21
|
+
import * as echarts from 'echarts'
|
|
22
|
+
import { getKlineDataApi, formatConfig } from './utils'
|
|
23
|
+
import dayjs from "dayjs"
|
|
24
|
+
import { stMath } from 'st-func'
|
|
25
|
+
const { round } = stMath
|
|
26
|
+
|
|
27
|
+
const props = defineProps({
|
|
28
|
+
code: { type: String, required: true }, // 品种代码
|
|
29
|
+
freqId: { type: String, required: true }, // 周期
|
|
30
|
+
freqDict: { type: Object, required: true }, // 周期字典
|
|
31
|
+
mainIndicator: { type: String, required: true }, // 主图指标
|
|
32
|
+
mainIndicatorList: { type: Array, required: true }, // 主图指标列表
|
|
33
|
+
subIndicatorList: { type: Array, required: true }, // 副图指标列表
|
|
34
|
+
config: { type: Object, default: () => ({}) }, // 配置
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
let mainChart
|
|
38
|
+
let mainDataZoomTimer = null // 主图数据缩放定时器
|
|
39
|
+
let isLoadHistory = false // 是否正在加载历史数据
|
|
40
|
+
let isloadAllHistory = false // 是否加载完全部历史数据
|
|
41
|
+
let isLoadNew = false // 是否正在加载新数据
|
|
42
|
+
let isloadAllNew = false // 是否加载完全部新数据
|
|
43
|
+
let resizeRo // dom元素监听事件
|
|
44
|
+
let highlightTimer = null // 高亮处理事件的定时器
|
|
45
|
+
|
|
46
|
+
const mainChartRef = ref() // 主图
|
|
47
|
+
const klineSubRef = ref() // 副图
|
|
48
|
+
const slideChartRef = ref() // 拖动轴
|
|
49
|
+
const klineUtilsRef = ref() // k线辅助函数实例
|
|
50
|
+
const isSelect = ref(false) // 是否选中,选中可通过键盘按键操作
|
|
51
|
+
const drawData = ref({}) // 绘图数据
|
|
52
|
+
const slideData = ref([])
|
|
53
|
+
const activeIndex = ref(0) // 显示的index
|
|
54
|
+
const subIndicator = ref('VOL') // 副图指标
|
|
55
|
+
|
|
56
|
+
const config = computed(() => {
|
|
57
|
+
const freqName = props.freqDict.find((item) => item.value === props.freqId).label
|
|
58
|
+
return formatConfig(props.config, freqName)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
watch(
|
|
62
|
+
() => props.code,
|
|
63
|
+
async() => {
|
|
64
|
+
isLoadHistory = false
|
|
65
|
+
isloadAllHistory = false
|
|
66
|
+
isLoadNew = false
|
|
67
|
+
isloadAllNew = false
|
|
68
|
+
const res = await getKlineData({
|
|
69
|
+
queryType: '0',
|
|
70
|
+
startTime: `${dayjs().subtract(defaultShowYears, 'year').format("YYYY-MM-DD")} 00:00:00`,
|
|
71
|
+
endTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
|
72
|
+
cycle: '6',
|
|
73
|
+
})
|
|
74
|
+
slideData.value = res.map(i => [i[0], i[4]])
|
|
75
|
+
getMainData(
|
|
76
|
+
`${slideData.value[slideData.value.length - 1 - defaultShowDays][0].split(' ')[0]} 00:00:00`,
|
|
77
|
+
`${slideData.value[slideData.value.length - 1][0].split(' ')[0]} 24:00:00`
|
|
78
|
+
)
|
|
79
|
+
},
|
|
80
|
+
{ deep: true }
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
watch(
|
|
84
|
+
() => [props.freqId, props.mainIndicator, subIndicator],
|
|
85
|
+
() => {
|
|
86
|
+
const { defaultShowDays } = config.value
|
|
87
|
+
isLoadHistory = false
|
|
88
|
+
isloadAllHistory = false
|
|
89
|
+
isLoadNew = false
|
|
90
|
+
isloadAllNew = false
|
|
91
|
+
getMainData(
|
|
92
|
+
`${slideData.value[slideData.value.length - 1 - defaultShowDays][0].split(' ')[0]} 00:00:00`,
|
|
93
|
+
`${slideData.value[slideData.value.length - 1][0].split(' ')[0]} 24:00:00`
|
|
94
|
+
)
|
|
95
|
+
},
|
|
96
|
+
{ deep: true }
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
onMounted(async () => {
|
|
100
|
+
const { defaultShowYears, defaultShowDays } = config.value
|
|
101
|
+
// 初始化指标计算方法
|
|
102
|
+
await klineUtilsRef.value.initTalib()
|
|
103
|
+
mainChart = echarts.init(mainChartRef.value)
|
|
104
|
+
klineSubRef.value.connect(mainChart)
|
|
105
|
+
addEventListener()
|
|
106
|
+
// 请求滚动条数据
|
|
107
|
+
const res = await getKlineData({
|
|
108
|
+
queryType: '0',
|
|
109
|
+
startTime: `${dayjs().subtract(defaultShowYears, 'year').format("YYYY-MM-DD")} 00:00:00`,
|
|
110
|
+
endTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
|
111
|
+
cycle: '6',
|
|
112
|
+
})
|
|
113
|
+
slideData.value = res.map(i => [i[0], i[4]])
|
|
114
|
+
await getMainData(
|
|
115
|
+
`${slideData.value[slideData.value.length - 1 - defaultShowDays][0].split(' ')[0]} 00:00:00`,
|
|
116
|
+
`${slideData.value[slideData.value.length - 1][0].split(' ')[0]} 24:00:00`
|
|
117
|
+
)
|
|
118
|
+
// 绑定resize事件
|
|
119
|
+
let isFirst = true
|
|
120
|
+
resizeRo = new ResizeObserver(() => {
|
|
121
|
+
if (isFirst) {
|
|
122
|
+
isFirst = null
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
mainChart.resize()
|
|
126
|
+
})
|
|
127
|
+
resizeRo.observe(mainChartRef.value)
|
|
128
|
+
window.addEventListener('keydown', keyDownEvent)
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
onUnmounted(() => {
|
|
132
|
+
window.removeEventListener('keydown', keyDownEvent)
|
|
133
|
+
mainChart.off('datazoom')
|
|
134
|
+
mainChart.off('highlight')
|
|
135
|
+
mainChart.off('globalout')
|
|
136
|
+
mainChart.dispose()
|
|
137
|
+
resizeRo.disconnect()
|
|
138
|
+
resizeRo = null
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
// 绑定事件
|
|
142
|
+
const addEventListener = () => {
|
|
143
|
+
mainChart.on('datazoom', (params) => {
|
|
144
|
+
clearTimeout(mainDataZoomTimer)
|
|
145
|
+
mainDataZoomTimer = setTimeout(() => {
|
|
146
|
+
const { loadCheckCount, loadAddCount, preLoadCount } = config.value
|
|
147
|
+
const { startValue, endValue } = mainChart.getOption().dataZoom[0]
|
|
148
|
+
const klineDataTime = mainChart.getOption().xAxis[0].data
|
|
149
|
+
const startTime = klineDataTime[startValue].split(' ')[0]
|
|
150
|
+
const endTime = klineDataTime[endValue].split(' ')[0]
|
|
151
|
+
// 加载数据
|
|
152
|
+
if (startValue < loadCheckCount && isLoadHistory === false && isloadAllHistory === false) {
|
|
153
|
+
// 左侧数据小于1000条,加载左侧数据
|
|
154
|
+
isLoadHistory = true
|
|
155
|
+
getMoreData({
|
|
156
|
+
queryType: '1',
|
|
157
|
+
endTime: drawData.value.startTime,
|
|
158
|
+
cycle: props.freqId,
|
|
159
|
+
limit: loadAddCount + preLoadCount,
|
|
160
|
+
})
|
|
161
|
+
}
|
|
162
|
+
if (endValue > drawData.value.length - loadCheckCount && isLoadNew === false && isloadAllNew === false) {
|
|
163
|
+
// 右侧数据小于1000条,加载右侧数据
|
|
164
|
+
isLoadNew = true
|
|
165
|
+
getMoreData({
|
|
166
|
+
queryType: '2',
|
|
167
|
+
startTime: drawData.value.endTime,
|
|
168
|
+
cycle: props.freqId,
|
|
169
|
+
limit: loadAddCount,
|
|
170
|
+
preLimit: preLoadCount, // 向前多查询数量
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
// 重置滚动条
|
|
174
|
+
slideChartRef.value.resetSlide(startTime, endTime, config.value.maxShowDays)
|
|
175
|
+
clearTimeout(mainDataZoomTimer)
|
|
176
|
+
}, 100)
|
|
177
|
+
})
|
|
178
|
+
// 高亮事件
|
|
179
|
+
mainChart.on('highlight', (data) => {
|
|
180
|
+
let index = data.dataIndex || -1
|
|
181
|
+
if (data.batch ) {
|
|
182
|
+
index = typeof data?.batch[0]?.dataIndex === 'number' ? data?.batch[0]?.dataIndex : -1
|
|
183
|
+
}
|
|
184
|
+
clearTimeout(highlightTimer)
|
|
185
|
+
highlightTimer = setTimeout(() => {
|
|
186
|
+
activeIndex.value = index
|
|
187
|
+
clearTimeout(highlightTimer)
|
|
188
|
+
}, 20)
|
|
189
|
+
})
|
|
190
|
+
// 移出图表事件
|
|
191
|
+
mainChart.on('globalout', () => {
|
|
192
|
+
const index = mainChart.getOption().dataZoom[0].endValue
|
|
193
|
+
activeIndex.value = index
|
|
194
|
+
})
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// 键盘事件
|
|
198
|
+
const keyDownEvent = e => {
|
|
199
|
+
// 只有选中或者按ctrl才激活按键
|
|
200
|
+
if (!(e.ctrlKey || isSelect.value)) return
|
|
201
|
+
const option = mainChart.getOption()
|
|
202
|
+
const { startValue, endValue } = option.dataZoom[0]
|
|
203
|
+
mainChart.dispatchAction({
|
|
204
|
+
type: 'dataZoom',
|
|
205
|
+
...klineUtilsRef.value.handleKeyDown(e, { startValue, endValue, maxIndex: option.xAxis[0].data.length - 1})
|
|
206
|
+
})
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// 拖动轴发生变化
|
|
210
|
+
const slideChange = async({ startTime, endTime }) => {
|
|
211
|
+
isLoadHistory = false
|
|
212
|
+
isloadAllHistory = false
|
|
213
|
+
isLoadNew = false
|
|
214
|
+
isloadAllNew = false
|
|
215
|
+
getMainData(startTime, endTime)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// 获取首屏K线数据
|
|
219
|
+
const getMainData = async(startTime, endTime) => {
|
|
220
|
+
const { preLoadCount, maxShowDays, preLoadDays } = config.value
|
|
221
|
+
let startIndex = -1
|
|
222
|
+
let endIndex = -1
|
|
223
|
+
slideData.value.forEach((item, index) => {
|
|
224
|
+
if (item[0].split(' ')[0] === startTime.split(' ')[0]) {
|
|
225
|
+
startIndex = index
|
|
226
|
+
}
|
|
227
|
+
if (item[0].split(' ')[0] === endTime.split(' ')[0]) {
|
|
228
|
+
endIndex = index
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
const loadStartTime = `${slideData.value[startIndex - preLoadDays < 0 ? 0 : startIndex - preLoadDays][0].split(' ')[0]} 00:00:00`
|
|
232
|
+
const loadEndTime = `${slideData.value[endIndex + preLoadDays > slideData.value.length ? slideData.value.length - 1 : endIndex + preLoadDays][0].split(' ')[0]} 24:00:00`
|
|
233
|
+
const params = {
|
|
234
|
+
queryType: '0',
|
|
235
|
+
startTime: loadStartTime,
|
|
236
|
+
endTime: loadEndTime,
|
|
237
|
+
preLimit: preLoadCount, // 向前多查询数量
|
|
238
|
+
cycle: props.freqId,
|
|
239
|
+
}
|
|
240
|
+
const res = await getKlineData(params)
|
|
241
|
+
drawData.value = klineUtilsRef.value.formatDataBySlide({
|
|
242
|
+
originDrawData: drawData.value,
|
|
243
|
+
addData: res,
|
|
244
|
+
startTime: params.startTime,
|
|
245
|
+
endTime: params.endTime,
|
|
246
|
+
mainIndicator: props.mainIndicator,
|
|
247
|
+
mainIndicatorList: props.mainIndicatorList,
|
|
248
|
+
subIndicator: subIndicator.value,
|
|
249
|
+
subIndicatorList: props.subIndicatorList,
|
|
250
|
+
config: config.value,
|
|
251
|
+
timeRange: [slideData.value[0][0], slideData.value[slideData.value.length - 1][0]],
|
|
252
|
+
})
|
|
253
|
+
const dataZoomInfo = klineUtilsRef.value.getDataZoomInfoByTime({
|
|
254
|
+
showStartTime: startTime,
|
|
255
|
+
showEndTime: endTime,
|
|
256
|
+
xAxisData: drawData.value.xAxisData,
|
|
257
|
+
maxShowDays
|
|
258
|
+
})
|
|
259
|
+
draw('main', { ...dataZoomInfo })
|
|
260
|
+
draw('sub', { ...dataZoomInfo })
|
|
261
|
+
activeIndex.value = mainChart.getOption().dataZoom[0].endValue
|
|
262
|
+
slideChartRef.value.resetSlide(startTime, endTime, config.value.maxShowDays)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// 获取更多数据
|
|
266
|
+
const getMoreData = async(params) => {
|
|
267
|
+
const { preLoadCount, maxShowDays } = config.value
|
|
268
|
+
const res = await getKlineData(params)
|
|
269
|
+
drawData.value = klineUtilsRef.value.formatDataBySlide({
|
|
270
|
+
originDrawData: drawData.value,
|
|
271
|
+
addData: params.queryType === '1' ? res.slice(0, res.length - 1) : res.slice(1),
|
|
272
|
+
startTime: params.startTime,
|
|
273
|
+
endTime: params.endTime,
|
|
274
|
+
mainIndicator: props.mainIndicator,
|
|
275
|
+
mainIndicatorList: props.mainIndicatorList,
|
|
276
|
+
subIndicator: subIndicator.value,
|
|
277
|
+
subIndicatorList: props.subIndicatorList,
|
|
278
|
+
config: config.value,
|
|
279
|
+
timeRange: [slideData.value[0][0], slideData.value[slideData.value.length - 1][0]],
|
|
280
|
+
})
|
|
281
|
+
const { startValue, endValue } = mainChart.getOption().dataZoom[0]
|
|
282
|
+
const klineDataTime = mainChart.getOption().xAxis[0].data
|
|
283
|
+
const showStartTime = klineDataTime[startValue]
|
|
284
|
+
const showEndTime = klineDataTime[endValue]
|
|
285
|
+
if (params.queryType === '1') {
|
|
286
|
+
// 加载历史数据
|
|
287
|
+
if (new Date(slideData.value[0][0]) > new Date(res[0][0])) {
|
|
288
|
+
// 表示历史数据已加载完
|
|
289
|
+
isloadAllHistory = true
|
|
290
|
+
}
|
|
291
|
+
isLoadHistory = false
|
|
292
|
+
} else {
|
|
293
|
+
// 加载新数据
|
|
294
|
+
if (res.length < 1 + preLoadCount) {
|
|
295
|
+
// 表示已经加载完全部新数据
|
|
296
|
+
isloadAllNew = true
|
|
297
|
+
isLoadNew = false
|
|
298
|
+
return
|
|
299
|
+
}
|
|
300
|
+
isLoadNew = false
|
|
301
|
+
}
|
|
302
|
+
const dataZoomInfo = klineUtilsRef.value.getDataZoomInfoByTime({ showStartTime, showEndTime, xAxisData: drawData.value.xAxisData, maxShowDays })
|
|
303
|
+
draw('main', { ...dataZoomInfo })
|
|
304
|
+
draw('sub', { ...dataZoomInfo })
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// 获取k线数据
|
|
308
|
+
const getKlineData = async(params) => {
|
|
309
|
+
const apiParams = {
|
|
310
|
+
contractType: 0, // 合约类型 0-主连 1-加权
|
|
311
|
+
variety: props.code, // 品种
|
|
312
|
+
right: 1, // 0-不复权 1-前复权 2-后复权
|
|
313
|
+
...params,
|
|
314
|
+
}
|
|
315
|
+
const res = await getKlineDataApi(apiParams)
|
|
316
|
+
return res
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// 绘制函数
|
|
320
|
+
const draw = (type, params = {}) => {
|
|
321
|
+
const { startValue, endValue, maxValueSpan } = params
|
|
322
|
+
const callBackMap = new Map([
|
|
323
|
+
[ "main", () => {
|
|
324
|
+
const { xAxisData, candlestickData, mainIndicatorData } = drawData.value
|
|
325
|
+
const indicatorSeries = mainIndicatorData.map((item) => {
|
|
326
|
+
return {
|
|
327
|
+
name: item.key,
|
|
328
|
+
type: 'line',
|
|
329
|
+
silent: true,
|
|
330
|
+
symbol: 'none',
|
|
331
|
+
data: item.data,
|
|
332
|
+
lineStyle: {
|
|
333
|
+
width: item.width || 1,
|
|
334
|
+
},
|
|
335
|
+
itemStyle: {
|
|
336
|
+
color: item.color,
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
})
|
|
340
|
+
mainChart.setOption({
|
|
341
|
+
animation: false,
|
|
342
|
+
grid: {
|
|
343
|
+
left: `${config.value.gridLeft}px`,
|
|
344
|
+
top: '20px',
|
|
345
|
+
right: `${config.value.gridRight}px`,
|
|
346
|
+
bottom: '6px',
|
|
347
|
+
},
|
|
348
|
+
dataZoom: [
|
|
349
|
+
{
|
|
350
|
+
type: 'inside',
|
|
351
|
+
startValue,
|
|
352
|
+
endValue,
|
|
353
|
+
maxValueSpan,
|
|
354
|
+
}
|
|
355
|
+
],
|
|
356
|
+
tooltip: {
|
|
357
|
+
trigger: 'axis',
|
|
358
|
+
appendToBody: true,
|
|
359
|
+
confine: true,
|
|
360
|
+
axisPointer: {
|
|
361
|
+
type: 'cross',
|
|
362
|
+
label: {
|
|
363
|
+
rich: {},
|
|
364
|
+
formatter: data => {
|
|
365
|
+
const { axisDimension, value } = data
|
|
366
|
+
if(axisDimension === 'x') {
|
|
367
|
+
return ''
|
|
368
|
+
} else {
|
|
369
|
+
return String(round(value))
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
formatter: () => '',
|
|
375
|
+
},
|
|
376
|
+
xAxis: {
|
|
377
|
+
show: false,
|
|
378
|
+
type: 'category',
|
|
379
|
+
data: xAxisData,
|
|
380
|
+
splitLine: {
|
|
381
|
+
show: false,
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
yAxis: {
|
|
385
|
+
type: 'value',
|
|
386
|
+
axisLine: {
|
|
387
|
+
show: true,
|
|
388
|
+
},
|
|
389
|
+
splitLine: {
|
|
390
|
+
show: true,
|
|
391
|
+
lineStyle: {
|
|
392
|
+
type: "dotted",
|
|
393
|
+
color: "#333",
|
|
394
|
+
},
|
|
395
|
+
},
|
|
396
|
+
min: (value) => round(value.min),
|
|
397
|
+
max: (value) => round(value.max),
|
|
398
|
+
},
|
|
399
|
+
series: [
|
|
400
|
+
{
|
|
401
|
+
type: 'candlestick',
|
|
402
|
+
data: candlestickData,
|
|
403
|
+
itemStyle: {
|
|
404
|
+
color: "transparent",
|
|
405
|
+
color0: "#00FFFF",
|
|
406
|
+
borderColor: "#FF0000",
|
|
407
|
+
borderColor0: "#00FFFF",
|
|
408
|
+
borderWidth: 1,
|
|
409
|
+
},
|
|
410
|
+
},
|
|
411
|
+
...indicatorSeries,
|
|
412
|
+
]
|
|
413
|
+
}, true)
|
|
414
|
+
}],
|
|
415
|
+
[ "sub", () => {
|
|
416
|
+
klineSubRef.value.draw({ startValue, endValue, maxValueSpan })
|
|
417
|
+
}],
|
|
418
|
+
]);
|
|
419
|
+
const callBack = callBackMap.get(type);
|
|
420
|
+
if (callBack instanceof Function) {
|
|
421
|
+
callBack();
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
</script>
|
|
425
|
+
|
|
426
|
+
<style lang="scss" scoped>
|
|
427
|
+
.kline {
|
|
428
|
+
width: 100%;
|
|
429
|
+
height: 100%;
|
|
430
|
+
background: #000;
|
|
431
|
+
&-mainTips {
|
|
432
|
+
height: 26px;
|
|
433
|
+
}
|
|
434
|
+
&-mainChart {
|
|
435
|
+
width: 100%;
|
|
436
|
+
height: calc(65% - 26px);
|
|
437
|
+
}
|
|
438
|
+
&-subTips {
|
|
439
|
+
height: 16px;
|
|
440
|
+
}
|
|
441
|
+
&-sub {
|
|
442
|
+
width: 100%;
|
|
443
|
+
height: calc(35% - 50px - 16px);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
</style>
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import axios from 'axios'
|
|
2
|
+
|
|
3
|
+
const defaultConfig = {
|
|
4
|
+
defaultShowDays: 50, // 默认展示天数,会根据不同周期进行赋值
|
|
5
|
+
preLoadDays: 50, // 预加载天数,会分局不同周期进行赋值
|
|
6
|
+
maxShowDays: 500, // 最大展示天数,会分局不同周期进行赋值
|
|
7
|
+
defaultShowYears: 10, // 默认展示多少年数据
|
|
8
|
+
preLoadCount: 800, // 预加载数据条数(用于计算指标线)
|
|
9
|
+
loadCheckCount: 500, // 加载数据检查条数
|
|
10
|
+
loadAddCount: 2000, // 加载数据条数
|
|
11
|
+
gridLeft: 60, // echarts绘图左侧grid距离
|
|
12
|
+
gridRight: 20, // echarts绘图右侧grid距离
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const freqConfig = {
|
|
16
|
+
'1m': {
|
|
17
|
+
defaultShowDays: 2, // 默认展示天数
|
|
18
|
+
preLoadDays: 4, // 预加载天数
|
|
19
|
+
maxShowDays: 20, // 最大展示天数
|
|
20
|
+
},
|
|
21
|
+
'5m': {
|
|
22
|
+
defaultShowDays: 4, // 默认展示天数
|
|
23
|
+
preLoadDays: 10, // 预加载天数
|
|
24
|
+
maxShowDays: 20, // 最大展示天数
|
|
25
|
+
},
|
|
26
|
+
'15m': {
|
|
27
|
+
defaultShowDays: 12, // 默认展示天数
|
|
28
|
+
preLoadDays: 24, // 预加载天数
|
|
29
|
+
maxShowDays: 50, // 最大展示天数
|
|
30
|
+
},
|
|
31
|
+
'30m': {
|
|
32
|
+
defaultShowDays: 25, // 默认展示天数
|
|
33
|
+
preLoadDays: 50, // 预加载天数
|
|
34
|
+
maxShowDays: 100, // 最大展示天数
|
|
35
|
+
},
|
|
36
|
+
'60m': {
|
|
37
|
+
defaultShowDays: 50, // 默认展示天数
|
|
38
|
+
preLoadDays: 100, // 预加载天数
|
|
39
|
+
maxShowDays: 200, // 最大展示天数
|
|
40
|
+
},
|
|
41
|
+
'1d': {
|
|
42
|
+
defaultShowDays: 200, // 默认展示天数
|
|
43
|
+
preLoadDays: 400, // 预加载天数
|
|
44
|
+
maxShowDays: 800, // 最大展示天数
|
|
45
|
+
},
|
|
46
|
+
'1w': {
|
|
47
|
+
defaultShowDays: 1000, // 默认展示天数
|
|
48
|
+
preLoadDays: 2000, // 预加载天数
|
|
49
|
+
maxShowDays: 4000, // 最大展示天数
|
|
50
|
+
},
|
|
51
|
+
'1mon': {
|
|
52
|
+
defaultShowDays: 4000, // 默认展示天数
|
|
53
|
+
preLoadDays: 8000, // 预加载天数
|
|
54
|
+
maxShowDays: 16000, // 最大展示天数
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// 获取配置
|
|
59
|
+
export const formatConfig = (config, freqName) => {
|
|
60
|
+
return {
|
|
61
|
+
...defaultConfig,
|
|
62
|
+
...freqConfig[freqName],
|
|
63
|
+
...config,
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 默认获取k线参数
|
|
68
|
+
export const getKlineDataApi = async(params) => {
|
|
69
|
+
const res = await axios({
|
|
70
|
+
method: 'post',
|
|
71
|
+
headers: {
|
|
72
|
+
token: '041fd377d5d5efc7e08e2ed5b61b0c8d',
|
|
73
|
+
},
|
|
74
|
+
url: 'http://invest.hzyotoy.com/common/qt/getSingleCycleSingleVariety',
|
|
75
|
+
data: params,
|
|
76
|
+
})
|
|
77
|
+
return res.data.body
|
|
78
|
+
}
|
|
@@ -1,12 +1,80 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div style="width: 100
|
|
3
|
-
<
|
|
2
|
+
<div style="width: 100%">
|
|
3
|
+
<el-select v-model="freqId" :style="{ width: '120px', marginRight: '12px' }">
|
|
4
|
+
<el-option v-for="item in freqOption" :key="item.value" :label="item.label" :value="item.value" />
|
|
5
|
+
</el-select>
|
|
6
|
+
<el-select v-model="mainIndicator" :style="{ width: '120px', marginRight: '12px' }">
|
|
7
|
+
<el-option v-for="item in mainIndicatorList" :key="item.value" :label="item.label" :value="item.value" />
|
|
8
|
+
</el-select>
|
|
9
|
+
<el-select v-model="chartMode" :style="{ width: '200px', marginRight: '12px' }">
|
|
10
|
+
<el-option v-for="item in chartModeList" :key="item" :label="item" :value="item" />
|
|
11
|
+
</el-select>
|
|
4
12
|
</div>
|
|
13
|
+
<el-tabs v-model="activeName" class="demo-tabs">
|
|
14
|
+
<el-tab-pane v-for="(item, index) in tabsList" :key="item.name" :label="item.label" :name="item.name">
|
|
15
|
+
<div style="height: calc(100vh - 64px - 40px - 40px - 40px - 16px - 32px)">
|
|
16
|
+
<component
|
|
17
|
+
:is="item.component"
|
|
18
|
+
:code="'RU'"
|
|
19
|
+
:freqId="freqId"
|
|
20
|
+
:freqDict="freqOption"
|
|
21
|
+
:mainIndicator="mainIndicator"
|
|
22
|
+
:mainIndicatorList="mainIndicatorList"
|
|
23
|
+
:subIndicatorList="subIndicatorList"
|
|
24
|
+
:chartMode="chartMode"
|
|
25
|
+
></component>
|
|
26
|
+
</div>
|
|
27
|
+
</el-tab-pane>
|
|
28
|
+
</el-tabs>
|
|
5
29
|
</template>
|
|
6
30
|
|
|
7
|
-
<script setup
|
|
8
|
-
|
|
31
|
+
<script setup>
|
|
32
|
+
import { ref } from "vue";
|
|
33
|
+
import KlineSlide from "./components/KlineSlide/index.vue";
|
|
34
|
+
import KlineBasic from "./components/KlineBasic/index.vue";
|
|
35
|
+
import KlineAction from "./components/KlineAction/index.vue";
|
|
36
|
+
import { mainIndicatorList, subIndicatorList } from "st-func";
|
|
37
|
+
|
|
38
|
+
const freqOption = [
|
|
39
|
+
{ value: "1", label: "1m" },
|
|
40
|
+
{ value: "2", label: "5m" },
|
|
41
|
+
{ value: "3", label: "15m" },
|
|
42
|
+
{ value: "4", label: "30m" },
|
|
43
|
+
{ value: "5", label: "60m" },
|
|
44
|
+
{ value: "6", label: "1d" },
|
|
45
|
+
{ value: "7", label: "1w" },
|
|
46
|
+
{ value: "8", label: "1mon" },
|
|
47
|
+
];
|
|
48
|
+
const freqId = ref("5");
|
|
49
|
+
const mainIndicator = ref("DKX_EMA");
|
|
9
50
|
|
|
10
|
-
|
|
51
|
+
const chartMode = ref("价差分布图");
|
|
52
|
+
const chartModeList = ["二腿价格走势图", "二腿价格走势百分比图", "二腿相关度", "价差周期性", "价差分布图"];
|
|
53
|
+
|
|
54
|
+
const tabsList = [
|
|
55
|
+
{
|
|
56
|
+
label: "基础K线组件(条数限制)",
|
|
57
|
+
name: "KlineBasic",
|
|
58
|
+
component: KlineBasic,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
label: "带拖拽的K线组件",
|
|
62
|
+
name: "KlineSlide",
|
|
63
|
+
component: KlineSlide,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
label: "带操作的K线组件",
|
|
67
|
+
name: "KlineAction",
|
|
68
|
+
component: KlineAction,
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
const activeName = ref("KlineAction");
|
|
72
|
+
</script>
|
|
11
73
|
|
|
74
|
+
<style lang="scss">
|
|
75
|
+
.klineDemoDialog {
|
|
76
|
+
.el-dialog__body {
|
|
77
|
+
height: calc(100% - 54px - 60px);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
12
80
|
</style>
|
package/vite.config.ts
CHANGED
|
@@ -7,7 +7,7 @@ const toFirstLowerCase = (word) => {
|
|
|
7
7
|
return `${word[0].toLowerCase()}${word.substr(1)}`
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export default () => {
|
|
10
|
+
export default ({ external }) => {
|
|
11
11
|
return {
|
|
12
12
|
name: 'createExport',
|
|
13
13
|
buildStart() {
|
|
@@ -22,6 +22,7 @@ export default () => {
|
|
|
22
22
|
const filterFiles = files.filter(fileName => !fileName.includes('.'))
|
|
23
23
|
// 生成每个组件的导出文件
|
|
24
24
|
filterFiles.forEach(fileName => {
|
|
25
|
+
if (external.includes(fileName)) return
|
|
25
26
|
const content = `import { App } from "vue";
|
|
26
27
|
import St${fileName} from "./index.vue";
|
|
27
28
|
|