st-comp 0.0.61 → 0.0.63
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 +16236 -15786
- package/lib/bundle.umd.cjs +49 -49
- package/lib/style.css +1 -1
- package/package.json +1 -1
- package/packages/Kline/componentsNew/KlineSlide/index.vue +155 -0
- package/packages/Kline/componentsNew/KlineSub/index.vue +282 -0
- package/packages/Kline/componentsNew/KlineTips/index.vue +66 -0
- package/packages/Kline/componentsNew/KlineUtils/index.vue +83 -0
- package/packages/Kline/componentsNew/Tips/index.vue +33 -0
- package/packages/Kline/index.ts +16 -8
- package/packages/VarietySearch/components/CommonIndicator/index.vue +2 -2
- package/packages/VarietySearch/index.vue +8 -8
- package/src/pages/KlineNew/components/KlineBasic/utils.js +15 -2
- package/src/pages/KlineNew/components/KlineNew/index.vue +317 -0
- package/src/pages/KlineNew/components/KlineNew/utils.js +31 -0
- package/src/pages/KlineNew/components/KlineSlideNew/index.vue +430 -0
- package/src/pages/KlineNew/components/KlineSlideNew/utils.js +78 -0
- package/src/pages/KlineNew/index.vue +26 -14
- package/src/pages/VarietySearch/index.vue +12 -0
|
@@ -164,8 +164,8 @@ const formatData = (data) => {
|
|
|
164
164
|
switch (key) {
|
|
165
165
|
// 过期时间
|
|
166
166
|
case "expireDays":
|
|
167
|
-
searchOptionDto.minExpireDays = item.range[0];
|
|
168
|
-
searchOptionDto.maxExpireDays = item.range[1];
|
|
167
|
+
if (!["", null].includes(item.range[0])) searchOptionDto.minExpireDays = item.range[0];
|
|
168
|
+
if (!["", null].includes(item.range[1])) searchOptionDto.maxExpireDays = item.range[1];
|
|
169
169
|
break;
|
|
170
170
|
// 虚实度
|
|
171
171
|
case "virtualRealDegree":
|
|
@@ -184,8 +184,8 @@ const formatData = (data) => {
|
|
|
184
184
|
break;
|
|
185
185
|
// 杠杆率
|
|
186
186
|
case "levelMultiplier":
|
|
187
|
-
searchOptionDto.minLevelMultiplier = item.range[0];
|
|
188
|
-
searchOptionDto.maxLevelMultiplier = item.range[1];
|
|
187
|
+
if (!["", null].includes(item.range[0])) searchOptionDto.minLevelMultiplier = item.range[0];
|
|
188
|
+
if (!["", null].includes(item.range[1])) searchOptionDto.maxLevelMultiplier = item.range[1];
|
|
189
189
|
break;
|
|
190
190
|
// 成交额(期权)
|
|
191
191
|
case "turnover":
|
|
@@ -194,13 +194,13 @@ const formatData = (data) => {
|
|
|
194
194
|
break;
|
|
195
195
|
// 成交量
|
|
196
196
|
case "volume":
|
|
197
|
-
searchOptionDto.minVolume = item.range[0];
|
|
198
|
-
searchOptionDto.maxVolume = item.range[1];
|
|
197
|
+
if (!["", null].includes(item.range[0])) searchOptionDto.minVolume = item.range[0];
|
|
198
|
+
if (!["", null].includes(item.range[1])) searchOptionDto.maxVolume = item.range[1];
|
|
199
199
|
break;
|
|
200
200
|
// 持仓量
|
|
201
201
|
case "openInterest":
|
|
202
|
-
searchOptionDto.minOpenInterest = item.range[0];
|
|
203
|
-
searchOptionDto.maxOpenInterest = item.range[1];
|
|
202
|
+
if (!["", null].includes(item.range[0])) searchOptionDto.minOpenInterest = item.range[0];
|
|
203
|
+
if (!["", null].includes(item.range[1])) searchOptionDto.maxOpenInterest = item.range[1];
|
|
204
204
|
break;
|
|
205
205
|
// 认沽认购
|
|
206
206
|
case "optionsCpType":
|
|
@@ -19,15 +19,28 @@ export const formatConfig = (config) => {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
const getKlineNew = async(params) => {
|
|
23
|
+
const res = await axios({
|
|
24
|
+
method: 'post',
|
|
25
|
+
headers: {
|
|
26
|
+
token: '36cbbea2e76aff9d99f88d50669c009c',
|
|
27
|
+
},
|
|
28
|
+
url: 'http://127.0.0.1:7001/middleLayer/kline/getKline',
|
|
29
|
+
data: params,
|
|
30
|
+
})
|
|
31
|
+
console.log('getKlineNew', res.data.data)
|
|
32
|
+
}
|
|
33
|
+
|
|
22
34
|
// 默认获取k线参数
|
|
23
35
|
export const getKlineDataApi = async(params) => {
|
|
24
36
|
const res = await axios({
|
|
25
37
|
method: 'post',
|
|
26
38
|
headers: {
|
|
27
|
-
token: '
|
|
39
|
+
token: '36cbbea2e76aff9d99f88d50669c009c',
|
|
28
40
|
},
|
|
29
41
|
url: 'http://invest.hzyotoy.com/common/qt/getSingleCycleSingleVariety',
|
|
30
42
|
data: params,
|
|
31
43
|
})
|
|
44
|
+
getKlineNew(params)
|
|
32
45
|
return res.data.body
|
|
33
|
-
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="kline"
|
|
4
|
+
@mousemove="isSelect = true"
|
|
5
|
+
@mouseout="isSelect = false"
|
|
6
|
+
>
|
|
7
|
+
<div class="kline-mainTips">
|
|
8
|
+
<st-kline-tips-new :data="klineData" :activeIndex="activeIndex"/>
|
|
9
|
+
</div>
|
|
10
|
+
<div class="kline-mainChart" ref="mainChartRef"></div>
|
|
11
|
+
<div class="kline-sub">
|
|
12
|
+
<st-kline-sub-new
|
|
13
|
+
ref="klineSubRef"
|
|
14
|
+
v-model="subIndicator"
|
|
15
|
+
:data="klineData"
|
|
16
|
+
:activeIndex="activeIndex"
|
|
17
|
+
:subIndicatorList="subIndicatorList"
|
|
18
|
+
/>
|
|
19
|
+
</div>
|
|
20
|
+
<st-kline-utils-new ref="klineUtilsRef" />
|
|
21
|
+
</div>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script setup>
|
|
25
|
+
import { ref, onMounted, onUnmounted, watch, computed } from "vue"
|
|
26
|
+
import * as echarts from 'echarts'
|
|
27
|
+
import { getKlineDataApi, formatConfig } from './utils'
|
|
28
|
+
import dayjs from "dayjs"
|
|
29
|
+
import { stMath } from 'st-func'
|
|
30
|
+
const { round } = stMath
|
|
31
|
+
|
|
32
|
+
const props = defineProps({
|
|
33
|
+
code: { type: String, required: true }, // 品种代码
|
|
34
|
+
freqId: { type: String, required: true }, // 周期
|
|
35
|
+
freqDict: { type: Object, required: true }, // 周期字典
|
|
36
|
+
mainIndicator: { type: String, required: true }, // 主图指标
|
|
37
|
+
mainIndicatorList: { type: Array, required: true }, // 主图指标列表
|
|
38
|
+
subIndicatorList: { type: Array, required: true }, // 副图指标列表
|
|
39
|
+
config: { type: Object, default: () => ({}) }, // 配置
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
let mainChart
|
|
43
|
+
let mainDataZoomTimer = null // 主图数据缩放定时器
|
|
44
|
+
let isLoadHistory = false // 是否正在加载历史数据
|
|
45
|
+
let isloadAllHistory = false // 是否加载完全部历史数据
|
|
46
|
+
let resizeRo // dom元素监听事件
|
|
47
|
+
let highlightTimer = null // 高亮处理事件的定时器
|
|
48
|
+
const activeIndex = ref(0) // 显示的index
|
|
49
|
+
|
|
50
|
+
const mainChartRef = ref() // 主图
|
|
51
|
+
const klineSubRef = ref() // 副图
|
|
52
|
+
const klineUtilsRef = ref() // k线辅助函数实例
|
|
53
|
+
const isSelect = ref(false) // 是否选中,选中可通过键盘按键操作
|
|
54
|
+
const klineData = ref({}) // 绘图数据
|
|
55
|
+
const subIndicator = ref('VOL') // 副图指标
|
|
56
|
+
|
|
57
|
+
const config = computed(() => formatConfig(props.config))
|
|
58
|
+
|
|
59
|
+
watch(
|
|
60
|
+
() => [props.code, props.freqId, props.mainIndicator, subIndicator],
|
|
61
|
+
async () => {
|
|
62
|
+
initChart()
|
|
63
|
+
},
|
|
64
|
+
{ deep: true }
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
onMounted(async () => {
|
|
68
|
+
// 初始化指标计算方法
|
|
69
|
+
mainChart = echarts.init(mainChartRef.value)
|
|
70
|
+
klineSubRef.value.connect(mainChart)
|
|
71
|
+
addEventListener()
|
|
72
|
+
initChart()
|
|
73
|
+
// 绑定resize事件
|
|
74
|
+
let isFirst = true
|
|
75
|
+
resizeRo = new ResizeObserver(() => {
|
|
76
|
+
if (isFirst) {
|
|
77
|
+
isFirst = null
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
mainChart.resize()
|
|
81
|
+
})
|
|
82
|
+
resizeRo.observe(mainChartRef.value)
|
|
83
|
+
window.addEventListener('keydown', keyDownEvent)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
onUnmounted(() => {
|
|
87
|
+
window.removeEventListener('keydown', keyDownEvent)
|
|
88
|
+
mainChart.off('datazoom')
|
|
89
|
+
mainChart.off('highlight')
|
|
90
|
+
mainChart.off('globalout')
|
|
91
|
+
mainChart.dispose()
|
|
92
|
+
resizeRo.disconnect()
|
|
93
|
+
resizeRo = null
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
// 项目初始化
|
|
97
|
+
const initChart = async () => {
|
|
98
|
+
const { addCount } = config.value
|
|
99
|
+
const res = await getKlineDataApi({
|
|
100
|
+
variety: props.code,
|
|
101
|
+
contractType: 0, // 合约类型 0-主连 1-加权
|
|
102
|
+
right: 1,
|
|
103
|
+
cycle: 5,
|
|
104
|
+
mainIndicator: props.mainIndicator,
|
|
105
|
+
subIndicator: subIndicator.value,
|
|
106
|
+
endTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
|
107
|
+
limit: addCount,
|
|
108
|
+
})
|
|
109
|
+
klineData.value = res
|
|
110
|
+
draw('main', { startValue: res.time.length - 1 - config.value.defaultShowCount, endValue: res.time.length - 1 })
|
|
111
|
+
draw('sub', { startValue: res.time.length - 1 - config.value.defaultShowCount, endValue: res.time.length - 1 })
|
|
112
|
+
activeIndex.value = mainChart.getOption().dataZoom[0].endValue
|
|
113
|
+
}
|
|
114
|
+
// 绑定事件
|
|
115
|
+
const addEventListener = () => {
|
|
116
|
+
mainChart.on('datazoom', (params) => {
|
|
117
|
+
clearTimeout(mainDataZoomTimer)
|
|
118
|
+
mainDataZoomTimer = setTimeout(() => {
|
|
119
|
+
const { loadCheckCount, addCount } = config.value
|
|
120
|
+
const { startValue } = mainChart.getOption().dataZoom[0]
|
|
121
|
+
// 加载数据
|
|
122
|
+
if (startValue < loadCheckCount && isLoadHistory === false && isloadAllHistory === false) {
|
|
123
|
+
// 左侧数据小于1000条,加载左侧数据
|
|
124
|
+
isLoadHistory = true
|
|
125
|
+
getMoreData()
|
|
126
|
+
}
|
|
127
|
+
clearTimeout(mainDataZoomTimer)
|
|
128
|
+
}, 100)
|
|
129
|
+
})
|
|
130
|
+
// 高亮事件
|
|
131
|
+
mainChart.on('highlight', (data) => {
|
|
132
|
+
let index = data.dataIndex || -1
|
|
133
|
+
if (data.batch ) {
|
|
134
|
+
index = typeof data?.batch[0]?.dataIndex === 'number' ? data?.batch[0]?.dataIndex : -1
|
|
135
|
+
}
|
|
136
|
+
clearTimeout(highlightTimer)
|
|
137
|
+
highlightTimer = setTimeout(() => {
|
|
138
|
+
activeIndex.value = index
|
|
139
|
+
clearTimeout(highlightTimer)
|
|
140
|
+
}, 20)
|
|
141
|
+
})
|
|
142
|
+
// 移出图表事件
|
|
143
|
+
mainChart.on('globalout', () => {
|
|
144
|
+
const index = mainChart.getOption().dataZoom[0].endValue
|
|
145
|
+
activeIndex.value = index
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 键盘事件
|
|
150
|
+
const keyDownEvent = e => {
|
|
151
|
+
// 只有选中或者按ctrl才激活按键
|
|
152
|
+
if (!(e.ctrlKey || isSelect.value)) return
|
|
153
|
+
const option = mainChart.getOption()
|
|
154
|
+
let { startValue, endValue } = option.dataZoom[0]
|
|
155
|
+
mainChart.dispatchAction({
|
|
156
|
+
type: 'dataZoom',
|
|
157
|
+
...klineUtilsRef.value.handleKeyDown(e, { startValue, endValue, maxIndex: option.xAxis[0].data.length - 1})
|
|
158
|
+
})
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// 获取更多数据
|
|
162
|
+
const getMoreData = async(params) => {
|
|
163
|
+
const { addCount, maxLoadCount } = config.value
|
|
164
|
+
const res = await getKlineDataApi({
|
|
165
|
+
variety: props.code,
|
|
166
|
+
contractType: 0, // 合约类型 0-主连 1-加权
|
|
167
|
+
right: 1,
|
|
168
|
+
cycle: 5,
|
|
169
|
+
mainIndicator: props.mainIndicator,
|
|
170
|
+
subIndicator: subIndicator.value,
|
|
171
|
+
endTime: klineData.value.time[0],
|
|
172
|
+
limit: addCount,
|
|
173
|
+
})
|
|
174
|
+
klineData.value = klineUtilsRef.value.mergeData(res, klineData.value)
|
|
175
|
+
const { startValue, endValue } = mainChart.getOption().dataZoom[0]
|
|
176
|
+
let dataZoomAddCount = addCount
|
|
177
|
+
if(klineData.value.time.length > maxLoadCount){
|
|
178
|
+
// 超出设置的最长加载数据条数
|
|
179
|
+
isloadAllHistory = true
|
|
180
|
+
} else if (res.time.length < addCount) {
|
|
181
|
+
// 表示历史数据已加载完
|
|
182
|
+
isloadAllHistory = true
|
|
183
|
+
dataZoomAddCount = res.length - 1
|
|
184
|
+
}
|
|
185
|
+
isLoadHistory = false
|
|
186
|
+
draw('main', { startValue: startValue + dataZoomAddCount, endValue: endValue + dataZoomAddCount })
|
|
187
|
+
draw('sub', { startValue: startValue + dataZoomAddCount, endValue: endValue + dataZoomAddCount })
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// 绘制函数
|
|
191
|
+
const draw = (type, params = {}) => {
|
|
192
|
+
const { startValue, endValue, maxValueSpan } = params
|
|
193
|
+
const callBackMap = new Map([
|
|
194
|
+
[ "main", () => {
|
|
195
|
+
const { kline, time } = klineData.value
|
|
196
|
+
const indicatorSeries = klineData.value.mainIndicator.map((item) => {
|
|
197
|
+
return {
|
|
198
|
+
name: item.key,
|
|
199
|
+
type: 'line',
|
|
200
|
+
silent: true,
|
|
201
|
+
symbol: 'none',
|
|
202
|
+
data: item.data,
|
|
203
|
+
lineStyle: {
|
|
204
|
+
width: item.width || 1,
|
|
205
|
+
},
|
|
206
|
+
itemStyle: {
|
|
207
|
+
color: item.color,
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
})
|
|
211
|
+
mainChart.setOption({
|
|
212
|
+
animation: false,
|
|
213
|
+
grid: {
|
|
214
|
+
left: `${config.value.gridLeft}px`,
|
|
215
|
+
top: '20px',
|
|
216
|
+
right: `${config.value.gridRight}px`,
|
|
217
|
+
bottom: '6px',
|
|
218
|
+
},
|
|
219
|
+
dataZoom: [
|
|
220
|
+
{
|
|
221
|
+
type: 'inside',
|
|
222
|
+
startValue,
|
|
223
|
+
endValue,
|
|
224
|
+
maxValueSpan: config.value.maxShowCount,
|
|
225
|
+
}
|
|
226
|
+
],
|
|
227
|
+
tooltip: {
|
|
228
|
+
trigger: 'axis',
|
|
229
|
+
appendToBody: true,
|
|
230
|
+
confine: true,
|
|
231
|
+
axisPointer: {
|
|
232
|
+
type: 'cross',
|
|
233
|
+
label: {
|
|
234
|
+
rich: {},
|
|
235
|
+
formatter: data => {
|
|
236
|
+
const { axisDimension, value } = data
|
|
237
|
+
if(axisDimension === 'x') {
|
|
238
|
+
return ''
|
|
239
|
+
} else {
|
|
240
|
+
return String(round(value))
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
formatter: () => '',
|
|
246
|
+
},
|
|
247
|
+
xAxis: {
|
|
248
|
+
show: false,
|
|
249
|
+
type: 'category',
|
|
250
|
+
data: time,
|
|
251
|
+
splitLine: {
|
|
252
|
+
show: false,
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
yAxis: {
|
|
256
|
+
type: 'value',
|
|
257
|
+
axisLine: {
|
|
258
|
+
show: true,
|
|
259
|
+
},
|
|
260
|
+
splitLine: {
|
|
261
|
+
show: true,
|
|
262
|
+
lineStyle: {
|
|
263
|
+
type: "dotted",
|
|
264
|
+
color: "#333",
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
min: (value) => round(value.min),
|
|
268
|
+
max: (value) => round(value.max),
|
|
269
|
+
},
|
|
270
|
+
series: [
|
|
271
|
+
{
|
|
272
|
+
type: 'candlestick',
|
|
273
|
+
data: kline,
|
|
274
|
+
itemStyle: {
|
|
275
|
+
color: "transparent",
|
|
276
|
+
color0: "#00FFFF",
|
|
277
|
+
borderColor: "#FF0000",
|
|
278
|
+
borderColor0: "#00FFFF",
|
|
279
|
+
borderWidth: 1,
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
...indicatorSeries,
|
|
283
|
+
]
|
|
284
|
+
}, true)
|
|
285
|
+
}],
|
|
286
|
+
[ "sub", () => {
|
|
287
|
+
klineSubRef.value.draw({ startValue, endValue, maxValueSpan }, config.value)
|
|
288
|
+
}],
|
|
289
|
+
]);
|
|
290
|
+
const callBack = callBackMap.get(type);
|
|
291
|
+
if (callBack instanceof Function) {
|
|
292
|
+
callBack();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
</script>
|
|
296
|
+
|
|
297
|
+
<style lang="scss" scoped>
|
|
298
|
+
.kline {
|
|
299
|
+
width: 100%;
|
|
300
|
+
height: 100%;
|
|
301
|
+
background: #000;
|
|
302
|
+
&-mainTips {
|
|
303
|
+
height: 26px;
|
|
304
|
+
}
|
|
305
|
+
&-mainChart {
|
|
306
|
+
width: 100%;
|
|
307
|
+
height: calc(65% - 26px);
|
|
308
|
+
}
|
|
309
|
+
&-subTips {
|
|
310
|
+
height: 16px;
|
|
311
|
+
}
|
|
312
|
+
&-sub {
|
|
313
|
+
width: 100%;
|
|
314
|
+
height: calc(35%);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
</style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import axios from 'axios'
|
|
2
|
+
|
|
3
|
+
const defaultConfig = {
|
|
4
|
+
defaultShowCount: 500, // 默认展示天数
|
|
5
|
+
addCount: 2000, // 首屏加载条数,滚动加载条数
|
|
6
|
+
maxLoadCount: 50000, // 最多加载多少条数据
|
|
7
|
+
maxShowCount: 5000, // 一屏幕最多展示多少条数据
|
|
8
|
+
loadCheckCount: 500, // 加载数据检查条数
|
|
9
|
+
gridLeft: 60, // echarts绘图左侧grid距离
|
|
10
|
+
gridRight: 20, // echarts绘图右侧grid距离
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// 获取配置
|
|
14
|
+
export const formatConfig = (config) => {
|
|
15
|
+
return {
|
|
16
|
+
...defaultConfig,
|
|
17
|
+
...config,
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const getKlineDataApi = async(params) => {
|
|
22
|
+
const res = await axios({
|
|
23
|
+
method: 'post',
|
|
24
|
+
headers: {
|
|
25
|
+
token: '3a9677a2bee56b14179b88d7c62d9db8',
|
|
26
|
+
},
|
|
27
|
+
url: 'http://127.0.0.1:7001/middleLayer/kline/getKline',
|
|
28
|
+
data: params,
|
|
29
|
+
})
|
|
30
|
+
return res.data.body
|
|
31
|
+
}
|