st-comp 0.0.45 → 0.0.47
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 +25409 -27447
- package/lib/bundle.umd.cjs +61 -65
- package/lib/style.css +1 -1
- package/package.json +3 -3
- package/packages/KlineNew/components/KlineSlide/index.vue +19 -43
- package/packages/KlineNew/components/KlineSub/index.vue +143 -154
- package/packages/KlineNew/components/{MainTips → KlineTips}/index.vue +9 -9
- package/packages/KlineNew/components/KlineUtils/index.vue +304 -0
- package/packages/KlineNew/index.ts +8 -2
- 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 +60 -32
- package/vitePlugins/createExportFile.ts +2 -1
- package/packages/KlineNew/index.vue +0 -363
- package/packages/KlineNew/klineConfig.ts +0 -44
- package/packages/KlineNew/option.ts +0 -111
- package/packages/KlineNew/utils.ts +0 -156
- package/vite.config.ts +0 -61
|
@@ -0,0 +1,716 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="kline">
|
|
3
|
+
<ContextMenu :class="openPenMode ? 'kline-mainChart penMode' : 'kline-mainChart'" @closeMenuCallBack="closeMenu">
|
|
4
|
+
<!-- 主图 -->
|
|
5
|
+
<div ref="mainChartRef" class="chart" />
|
|
6
|
+
<!-- 右键菜单 -->
|
|
7
|
+
<template #popover>
|
|
8
|
+
<el-menu class="menu">
|
|
9
|
+
<el-menu-item
|
|
10
|
+
class="menu-item"
|
|
11
|
+
v-for="item in menuData"
|
|
12
|
+
:key="item.label"
|
|
13
|
+
:index="item.label"
|
|
14
|
+
@click="clickMenuItem(item)"
|
|
15
|
+
>
|
|
16
|
+
{{ item.label }}
|
|
17
|
+
</el-menu-item>
|
|
18
|
+
</el-menu>
|
|
19
|
+
</template>
|
|
20
|
+
</ContextMenu>
|
|
21
|
+
<YearChart class="year-chart" v-if="props.chartMode === '价差周期性'" :data="yearChartData" />
|
|
22
|
+
<!-- 图表工具库 -->
|
|
23
|
+
<st-klineUtils ref="klineUtilsRef" />
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script setup>
|
|
28
|
+
import dayjs from "dayjs";
|
|
29
|
+
import { stMath } from "st-func";
|
|
30
|
+
import * as echarts from "echarts";
|
|
31
|
+
import { getKlineDataApi } from "./mockApi";
|
|
32
|
+
import {
|
|
33
|
+
debounce,
|
|
34
|
+
formatConfig,
|
|
35
|
+
resizeListener,
|
|
36
|
+
getWarningLineGraphic,
|
|
37
|
+
getPositionLineGraphic,
|
|
38
|
+
getConditionLineGraphic,
|
|
39
|
+
getRelevanceLineSeries,
|
|
40
|
+
getDistributionLineGraphic,
|
|
41
|
+
} from "./utils";
|
|
42
|
+
import { ref, onMounted, onUnmounted, watch, computed, nextTick } from "vue";
|
|
43
|
+
import ContextMenu from "./components/ContextMenu/index.vue";
|
|
44
|
+
import YearChart from "./components/YearChart/index.vue";
|
|
45
|
+
|
|
46
|
+
const { round } = stMath;
|
|
47
|
+
|
|
48
|
+
const props = defineProps({
|
|
49
|
+
code: { type: String, required: true }, // 品种代码
|
|
50
|
+
freqId: { type: String, required: true }, // 周期
|
|
51
|
+
freqDict: { type: Object, required: true }, // 周期字典
|
|
52
|
+
mainIndicator: { type: String, required: true }, // 主图指标
|
|
53
|
+
mainIndicatorList: { type: Array, required: true }, // 主图指标列表
|
|
54
|
+
subIndicatorList: { type: Array, required: true }, // 副图指标列表
|
|
55
|
+
config: { type: Object, default: () => ({}) }, // 配置
|
|
56
|
+
chartMode: { type: String, default: () => "" }, // 价差五种图
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// 主图实例
|
|
60
|
+
let mainChart;
|
|
61
|
+
// 主图Dom监听实例
|
|
62
|
+
let resizeRo;
|
|
63
|
+
// 主图Ref
|
|
64
|
+
const mainChartRef = ref();
|
|
65
|
+
// 主图工具库Ref
|
|
66
|
+
const klineUtilsRef = ref();
|
|
67
|
+
// 主图绘图数据
|
|
68
|
+
const drawData = ref({});
|
|
69
|
+
// 主图配置项
|
|
70
|
+
const config = computed(() => formatConfig(props.config));
|
|
71
|
+
|
|
72
|
+
// 右键菜单数据
|
|
73
|
+
const defaultMenuData = [
|
|
74
|
+
{
|
|
75
|
+
label: "画线预警",
|
|
76
|
+
callBack: () => drawLineWarning(),
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
label: "自定义菜单项二",
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
label: "自定义菜单项三",
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
const menuData = ref([]);
|
|
86
|
+
|
|
87
|
+
// ------额外画线------
|
|
88
|
+
const openPenMode = ref(false);
|
|
89
|
+
const lineData = ref([]);
|
|
90
|
+
|
|
91
|
+
// ------价差五图------
|
|
92
|
+
const relevanceData = ref([]); // 二腿相关度数据
|
|
93
|
+
const yearChartData = ref([]); // 价差周期性数据
|
|
94
|
+
|
|
95
|
+
onMounted(async () => {
|
|
96
|
+
// 1.初始化指标计算方法
|
|
97
|
+
await klineUtilsRef.value.initTalib();
|
|
98
|
+
// 2.初始化主图DOM
|
|
99
|
+
mainChart = echarts.init(mainChartRef.value);
|
|
100
|
+
// 3.绑定resize事件
|
|
101
|
+
resizeRo = resizeListener(mainChartRef.value, () => {
|
|
102
|
+
mainChart.resize();
|
|
103
|
+
handleChartMode();
|
|
104
|
+
});
|
|
105
|
+
// 4.绑定主图事件
|
|
106
|
+
bindMainChartEvent();
|
|
107
|
+
// 5.获取主图数据 + 渲染
|
|
108
|
+
await getMainChartData();
|
|
109
|
+
const params = {
|
|
110
|
+
startValue: drawData.value.length - config.value.defaultShowCount,
|
|
111
|
+
endValue: drawData.value.length - 1,
|
|
112
|
+
};
|
|
113
|
+
draw("main", params);
|
|
114
|
+
// 7.获取额外画线数据 + 渲染
|
|
115
|
+
await getLineData();
|
|
116
|
+
draw("line");
|
|
117
|
+
// 8.初始化右键菜单
|
|
118
|
+
menuData.value = defaultMenuData;
|
|
119
|
+
// 9.根据传入图表模式,进行额外渲染
|
|
120
|
+
handleChartMode();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// 监控: props.code 重绘[主图, 额外画线] - 缩放重置
|
|
124
|
+
watch(
|
|
125
|
+
() => props.code,
|
|
126
|
+
async () => {
|
|
127
|
+
await getMainChartData();
|
|
128
|
+
const params = {
|
|
129
|
+
startValue: drawData.value.length - config.value.defaultShowCount,
|
|
130
|
+
endValue: drawData.value.length - 1,
|
|
131
|
+
};
|
|
132
|
+
draw("main", params);
|
|
133
|
+
await getLineData();
|
|
134
|
+
draw("line");
|
|
135
|
+
},
|
|
136
|
+
{ deep: true }
|
|
137
|
+
);
|
|
138
|
+
// 监控: props.freqId, props.mainIndicator 重绘[主图] - 缩放不重置
|
|
139
|
+
watch(
|
|
140
|
+
() => [props.freqId, props.mainIndicator],
|
|
141
|
+
async () => {
|
|
142
|
+
await getMainChartData();
|
|
143
|
+
const { startValue, endValue } = mainChart.getOption().dataZoom[0];
|
|
144
|
+
const params = {
|
|
145
|
+
startValue,
|
|
146
|
+
endValue,
|
|
147
|
+
};
|
|
148
|
+
draw("main", params);
|
|
149
|
+
},
|
|
150
|
+
{ deep: true }
|
|
151
|
+
);
|
|
152
|
+
// 监控: props.chartMode 重绘[价差五图]
|
|
153
|
+
watch(
|
|
154
|
+
() => props.chartMode,
|
|
155
|
+
async () => {
|
|
156
|
+
handleChartMode();
|
|
157
|
+
},
|
|
158
|
+
{ deep: true }
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
onUnmounted(() => {
|
|
162
|
+
unbindMainChartEvent();
|
|
163
|
+
mainChart.dispose();
|
|
164
|
+
resizeRo.dispose();
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// 获取主图绘制数据
|
|
168
|
+
const getMainChartData = async () => {
|
|
169
|
+
const { addCount, preLoadCount } = config.value;
|
|
170
|
+
const res = await getKlineData({
|
|
171
|
+
queryType: "1",
|
|
172
|
+
endTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
|
173
|
+
cycle: props.freqId,
|
|
174
|
+
limit: addCount + preLoadCount,
|
|
175
|
+
});
|
|
176
|
+
drawData.value = klineUtilsRef.value.formatDataByCount({
|
|
177
|
+
originDrawData: {},
|
|
178
|
+
addData: res,
|
|
179
|
+
mainIndicator: props.mainIndicator,
|
|
180
|
+
mainIndicatorList: props.mainIndicatorList,
|
|
181
|
+
config: config.value,
|
|
182
|
+
});
|
|
183
|
+
console.log(drawData.value);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// 价差五种图的判断渲染函数
|
|
187
|
+
const handleChartMode = debounce(async () => {
|
|
188
|
+
// 因为在DOM变化的时候,这一块也需要重新执行,不然会出现额外图表元素定位不精准的问题
|
|
189
|
+
// resize没用,nextTick也没用
|
|
190
|
+
const { chartMode } = props;
|
|
191
|
+
// 避免之前的绘图模式残留影响,重绘[主图, 额外画线] - 缩放不重置
|
|
192
|
+
const { startValue, endValue } = mainChart.getOption().dataZoom[0];
|
|
193
|
+
const params = {
|
|
194
|
+
startValue,
|
|
195
|
+
endValue,
|
|
196
|
+
};
|
|
197
|
+
draw("main", params);
|
|
198
|
+
draw("line");
|
|
199
|
+
// 二腿相关度
|
|
200
|
+
if (chartMode === "二腿相关度") {
|
|
201
|
+
await getRelevanceData();
|
|
202
|
+
draw("relevance");
|
|
203
|
+
}
|
|
204
|
+
// 价差分布图
|
|
205
|
+
if (chartMode === "价差周期性") {
|
|
206
|
+
await getYearChartData();
|
|
207
|
+
}
|
|
208
|
+
// 价差分布图
|
|
209
|
+
if (chartMode === "价差分布图") {
|
|
210
|
+
draw("distribution");
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// 绘制函数
|
|
215
|
+
const draw = (type, params = {}) => {
|
|
216
|
+
const callBackMap = new Map([
|
|
217
|
+
// [主图]绘制
|
|
218
|
+
[
|
|
219
|
+
"main",
|
|
220
|
+
() => {
|
|
221
|
+
const { startValue, endValue } = params;
|
|
222
|
+
const { xAxisData, candlestickData, mainIndicatorData } = drawData.value;
|
|
223
|
+
const indicatorSeries = mainIndicatorData.map((item) => {
|
|
224
|
+
return {
|
|
225
|
+
name: item.key,
|
|
226
|
+
type: "line",
|
|
227
|
+
silent: true,
|
|
228
|
+
symbol: "none",
|
|
229
|
+
data: item.data,
|
|
230
|
+
lineStyle: {
|
|
231
|
+
width: item.width || 1,
|
|
232
|
+
},
|
|
233
|
+
itemStyle: {
|
|
234
|
+
color: item.color,
|
|
235
|
+
},
|
|
236
|
+
};
|
|
237
|
+
});
|
|
238
|
+
mainChart.setOption(
|
|
239
|
+
{
|
|
240
|
+
animation: false,
|
|
241
|
+
grid: {
|
|
242
|
+
left: `${config.value.gridLeft}px`,
|
|
243
|
+
top: "20px",
|
|
244
|
+
right: `${config.value.gridRight}px`,
|
|
245
|
+
bottom: "30px",
|
|
246
|
+
},
|
|
247
|
+
tooltip: {
|
|
248
|
+
trigger: "axis",
|
|
249
|
+
appendToBody: true,
|
|
250
|
+
confine: true,
|
|
251
|
+
axisPointer: {
|
|
252
|
+
type: "cross",
|
|
253
|
+
label: {
|
|
254
|
+
rich: {},
|
|
255
|
+
formatter: (data) => {
|
|
256
|
+
const { axisDimension, value } = data;
|
|
257
|
+
if (axisDimension === "x") {
|
|
258
|
+
return value;
|
|
259
|
+
} else {
|
|
260
|
+
return String(round(value));
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
formatter: () => "",
|
|
266
|
+
},
|
|
267
|
+
xAxis: {
|
|
268
|
+
show: true,
|
|
269
|
+
type: "category",
|
|
270
|
+
data: xAxisData,
|
|
271
|
+
splitLine: {
|
|
272
|
+
show: false,
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
yAxis: [
|
|
276
|
+
{
|
|
277
|
+
type: "value",
|
|
278
|
+
axisLine: {
|
|
279
|
+
show: true,
|
|
280
|
+
},
|
|
281
|
+
splitLine: {
|
|
282
|
+
show: true,
|
|
283
|
+
lineStyle: {
|
|
284
|
+
type: "dotted",
|
|
285
|
+
color: "#333",
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
min: (value) => round(value.min),
|
|
289
|
+
max: (value) => round(value.max),
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
show: false,
|
|
293
|
+
min: (value) => {
|
|
294
|
+
const { min, max } = value;
|
|
295
|
+
const interval = Math.abs((max - min) / 10);
|
|
296
|
+
return min - interval;
|
|
297
|
+
},
|
|
298
|
+
max: (value) => {
|
|
299
|
+
const { min, max } = value;
|
|
300
|
+
const interval = Math.abs((max - min) / 10);
|
|
301
|
+
return max + interval;
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
],
|
|
305
|
+
series: [
|
|
306
|
+
{
|
|
307
|
+
type: "candlestick",
|
|
308
|
+
data: candlestickData,
|
|
309
|
+
itemStyle: {
|
|
310
|
+
color: "transparent",
|
|
311
|
+
color0: "#00FFFF",
|
|
312
|
+
borderColor: "#FF0000",
|
|
313
|
+
borderColor0: "#00FFFF",
|
|
314
|
+
borderWidth: 1,
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
...indicatorSeries,
|
|
318
|
+
],
|
|
319
|
+
dataZoom: [
|
|
320
|
+
{
|
|
321
|
+
type: "inside",
|
|
322
|
+
startValue,
|
|
323
|
+
endValue,
|
|
324
|
+
maxValueSpan: config.value.maxShowCount,
|
|
325
|
+
},
|
|
326
|
+
],
|
|
327
|
+
},
|
|
328
|
+
true
|
|
329
|
+
);
|
|
330
|
+
},
|
|
331
|
+
],
|
|
332
|
+
// [预警线,持仓线,条件单线]绘制
|
|
333
|
+
[
|
|
334
|
+
"line",
|
|
335
|
+
() => {
|
|
336
|
+
// 1.获取主图当前配置项
|
|
337
|
+
const mainChartOption = mainChart.getOption();
|
|
338
|
+
// 2.生成新的graphic配置项
|
|
339
|
+
const graphic = [];
|
|
340
|
+
lineData.value.forEach((line) => {
|
|
341
|
+
const { name, data } = line;
|
|
342
|
+
// 预警线配置项处理
|
|
343
|
+
if (name === "warningLine") {
|
|
344
|
+
graphic.push(...getWarningLineGraphic(data, mainChart));
|
|
345
|
+
}
|
|
346
|
+
// 持仓线配置项处理
|
|
347
|
+
if (name === "positionLine") {
|
|
348
|
+
graphic.push(...getPositionLineGraphic(data, mainChart));
|
|
349
|
+
}
|
|
350
|
+
// 条件单线配置项处理
|
|
351
|
+
if (name === "conditionLine") {
|
|
352
|
+
graphic.push(...getConditionLineGraphic(data, mainChart));
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
// 3.渲染
|
|
356
|
+
mainChart.setOption(
|
|
357
|
+
{
|
|
358
|
+
...mainChartOption,
|
|
359
|
+
graphic,
|
|
360
|
+
},
|
|
361
|
+
true
|
|
362
|
+
);
|
|
363
|
+
},
|
|
364
|
+
],
|
|
365
|
+
// [二腿相关度]绘制
|
|
366
|
+
[
|
|
367
|
+
"relevance",
|
|
368
|
+
() => {
|
|
369
|
+
// 1.获取主图当前配置项
|
|
370
|
+
const mainChartOption = mainChart.getOption();
|
|
371
|
+
// 2.生成新的series配置项
|
|
372
|
+
const oldSeries = mainChartOption.series.filter((item) => {
|
|
373
|
+
return item.name !== "relevance";
|
|
374
|
+
});
|
|
375
|
+
const series = [...oldSeries, getRelevanceLineSeries(relevanceData.value)];
|
|
376
|
+
// 3.渲染
|
|
377
|
+
mainChart.setOption(
|
|
378
|
+
{
|
|
379
|
+
...mainChartOption,
|
|
380
|
+
series,
|
|
381
|
+
},
|
|
382
|
+
true
|
|
383
|
+
);
|
|
384
|
+
},
|
|
385
|
+
],
|
|
386
|
+
// [价差分布图]绘制
|
|
387
|
+
[
|
|
388
|
+
"distribution",
|
|
389
|
+
() => {
|
|
390
|
+
// 1.获取主图当前配置项
|
|
391
|
+
const mainChartOption = mainChart.getOption();
|
|
392
|
+
// 2.生成新的graphic配置项
|
|
393
|
+
let graphic = [];
|
|
394
|
+
const elements = getDistributionLineGraphic(drawData.value.originData, mainChart);
|
|
395
|
+
// (1).如果先前有graphic配置项
|
|
396
|
+
if (mainChartOption.graphic) {
|
|
397
|
+
const oldGraphic = mainChartOption.graphic[0].elements.filter((item) => {
|
|
398
|
+
return item.name !== "distribution";
|
|
399
|
+
});
|
|
400
|
+
graphic = [...oldGraphic, elements];
|
|
401
|
+
}
|
|
402
|
+
// (2).如果先前没有graphic配置项
|
|
403
|
+
if (!mainChartOption.graphic) {
|
|
404
|
+
graphic = [elements];
|
|
405
|
+
}
|
|
406
|
+
// 5.渲染
|
|
407
|
+
mainChart.setOption(
|
|
408
|
+
{
|
|
409
|
+
...mainChartOption,
|
|
410
|
+
graphic,
|
|
411
|
+
},
|
|
412
|
+
true
|
|
413
|
+
);
|
|
414
|
+
},
|
|
415
|
+
],
|
|
416
|
+
]);
|
|
417
|
+
const callBack = callBackMap.get(type);
|
|
418
|
+
callBack instanceof Function && callBack();
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
// ------------------自定义右键菜单函数------------------
|
|
422
|
+
// 关闭菜单
|
|
423
|
+
const closeMenu = () => {
|
|
424
|
+
menuData.value = defaultMenuData;
|
|
425
|
+
};
|
|
426
|
+
// 点击菜单项
|
|
427
|
+
const clickMenuItem = (item) => {
|
|
428
|
+
const { callBack } = item;
|
|
429
|
+
callBack instanceof Function && callBack(item);
|
|
430
|
+
};
|
|
431
|
+
// 菜单项-画线预警
|
|
432
|
+
const drawLineWarning = () => {
|
|
433
|
+
// 1.拿到当前主图配置项
|
|
434
|
+
const mainChartOption = mainChart.getOption();
|
|
435
|
+
// 2.将指示器改为虚线样式,并开启画笔模式
|
|
436
|
+
openPenMode.value = true;
|
|
437
|
+
const oldTooltip = mainChartOption.tooltip[0];
|
|
438
|
+
mainChart.setOption({
|
|
439
|
+
...mainChartOption,
|
|
440
|
+
// 指示器样式
|
|
441
|
+
tooltip: {
|
|
442
|
+
...oldTooltip,
|
|
443
|
+
// 坐标轴指示器
|
|
444
|
+
axisPointer: {
|
|
445
|
+
// 保留原有部分配置
|
|
446
|
+
...oldTooltip.axisPointer,
|
|
447
|
+
// X轴指示线的宽度
|
|
448
|
+
lineStyle: {
|
|
449
|
+
width: 0,
|
|
450
|
+
},
|
|
451
|
+
// Y轴指示线的宽度
|
|
452
|
+
crossStyle: {
|
|
453
|
+
width: 2,
|
|
454
|
+
},
|
|
455
|
+
// 文本标签
|
|
456
|
+
label: {
|
|
457
|
+
// 保留原有部分配置
|
|
458
|
+
...oldTooltip.axisPointer.label,
|
|
459
|
+
// 颜色改为透明
|
|
460
|
+
backgroundColor: "transparent",
|
|
461
|
+
// 仅显示Y轴值
|
|
462
|
+
formatter: (data) => {
|
|
463
|
+
const { axisDimension, value } = data;
|
|
464
|
+
// if (axisDimension === "y") {
|
|
465
|
+
// return String(formatValue(value));
|
|
466
|
+
// }
|
|
467
|
+
return "";
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
},
|
|
471
|
+
},
|
|
472
|
+
});
|
|
473
|
+
// 3.编写点击事件:获取到数据发送给后端
|
|
474
|
+
const handleClick = (el) => {
|
|
475
|
+
// (1).在触发点击事件后,第一时间将图表绑定的点击事件清除
|
|
476
|
+
mainChart.getZr().off("mousedown", handleClick);
|
|
477
|
+
// (2).根据点击位置获取到Y轴具体数据
|
|
478
|
+
const yAxisValue = mainChart.convertFromPixel({ yAxisIndex: 0 }, el.offsetY);
|
|
479
|
+
// (3).格式化画线预警价格
|
|
480
|
+
const newWarnPrice = Math.round(yAxisValue * 1000) / 1000;
|
|
481
|
+
// (4).将指示器恢复成原始样式
|
|
482
|
+
mainChart.setOption({
|
|
483
|
+
...mainChartOption,
|
|
484
|
+
// 指示器样式
|
|
485
|
+
tooltip: {
|
|
486
|
+
...oldTooltip,
|
|
487
|
+
axisPointer: {
|
|
488
|
+
...oldTooltip.axisPointer,
|
|
489
|
+
lineStyle: {
|
|
490
|
+
width: 1,
|
|
491
|
+
},
|
|
492
|
+
crossStyle: {
|
|
493
|
+
width: 1,
|
|
494
|
+
},
|
|
495
|
+
label: {
|
|
496
|
+
...oldTooltip.axisPointer.label,
|
|
497
|
+
backgroundColor: null,
|
|
498
|
+
},
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
});
|
|
502
|
+
// (5).关闭画笔模式
|
|
503
|
+
openPenMode.value = false;
|
|
504
|
+
// (6).发送保存预警线请求
|
|
505
|
+
console.log("模拟发送请求[新增预警线接口]-入参:", newWarnPrice);
|
|
506
|
+
// (7).模拟获取到的新的数据
|
|
507
|
+
lineData.value[0].data.push({
|
|
508
|
+
value: newWarnPrice,
|
|
509
|
+
text: newWarnPrice,
|
|
510
|
+
// 自定义信息
|
|
511
|
+
customInfo: {},
|
|
512
|
+
});
|
|
513
|
+
// (8).绘制预警线
|
|
514
|
+
draw("line");
|
|
515
|
+
ElMessage.success("画线预警成功!");
|
|
516
|
+
};
|
|
517
|
+
// 4.绑定echarts点击事件
|
|
518
|
+
mainChart.getZr().on("mousedown", handleClick);
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
// ------------------图表事件函数------------------
|
|
522
|
+
// 图表事件: 右键
|
|
523
|
+
const contextmenu = (params) => {
|
|
524
|
+
// 判断是否右击到主图中的graphic图形, 且自定义字段info中存在contextmenu回调函数
|
|
525
|
+
if (params.componentType === "graphic" && params.info?.contextmenu) {
|
|
526
|
+
// 由于事件冒泡导致线的右键会在菜单组件的关闭回调前执行,所以将其放入宏队列调整执行顺序
|
|
527
|
+
const timer = setTimeout(() => {
|
|
528
|
+
params.info.contextmenu instanceof Function && params.info.contextmenu(params);
|
|
529
|
+
clearTimeout(timer);
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
// 图表事件: 缩放拖拽
|
|
534
|
+
const dataZoom = debounce(() => {
|
|
535
|
+
draw("line");
|
|
536
|
+
props.chartMode === "价差分布图" && draw("distribution");
|
|
537
|
+
});
|
|
538
|
+
// 绑定图表事件
|
|
539
|
+
const bindMainChartEvent = () => {
|
|
540
|
+
mainChart.on("highlight", (data) => {});
|
|
541
|
+
mainChart.on("globalout", () => {});
|
|
542
|
+
mainChart.on("contextmenu", (params) => {
|
|
543
|
+
contextmenu(params);
|
|
544
|
+
});
|
|
545
|
+
mainChart.on("datazoom", (params) => {
|
|
546
|
+
dataZoom();
|
|
547
|
+
});
|
|
548
|
+
};
|
|
549
|
+
// 解绑图表事件
|
|
550
|
+
const unbindMainChartEvent = () => {
|
|
551
|
+
mainChart.off("highlight");
|
|
552
|
+
mainChart.off("globalout");
|
|
553
|
+
mainChart.off("contextmenu");
|
|
554
|
+
mainChart.off("datazoom");
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
// ------------------获取API函数------------------
|
|
558
|
+
// 获取K线数据
|
|
559
|
+
const getKlineData = async (params) => {
|
|
560
|
+
const apiParams = {
|
|
561
|
+
contractType: 0, // 合约类型 0-主连 1-加权
|
|
562
|
+
variety: props.code, // 品种
|
|
563
|
+
right: 1, // 0-不复权 1-前复权 2-后复权
|
|
564
|
+
...params,
|
|
565
|
+
};
|
|
566
|
+
const res = await getKlineDataApi(apiParams);
|
|
567
|
+
return res;
|
|
568
|
+
};
|
|
569
|
+
// 获取额外画线数据
|
|
570
|
+
const getLineData = async () => {
|
|
571
|
+
// 将通过接口获取到的数据格式化
|
|
572
|
+
lineData.value = [
|
|
573
|
+
// 预警线数据
|
|
574
|
+
{
|
|
575
|
+
name: "warningLine",
|
|
576
|
+
data: [
|
|
577
|
+
{
|
|
578
|
+
value: 15000,
|
|
579
|
+
text: "15000",
|
|
580
|
+
// 自定义参数
|
|
581
|
+
customInfo: {
|
|
582
|
+
value: 15000,
|
|
583
|
+
// 右击的回调
|
|
584
|
+
contextmenu: (params) => {
|
|
585
|
+
const { value } = params;
|
|
586
|
+
menuData.value = [
|
|
587
|
+
{
|
|
588
|
+
label: "删除画线",
|
|
589
|
+
callBack: () => {
|
|
590
|
+
console.log("当前删除的预警线,Y值为:", value);
|
|
591
|
+
},
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
label: "修改画线",
|
|
595
|
+
callBack: () => {
|
|
596
|
+
console.log("当前修改的预警线,Y值为:", value);
|
|
597
|
+
},
|
|
598
|
+
},
|
|
599
|
+
];
|
|
600
|
+
},
|
|
601
|
+
},
|
|
602
|
+
},
|
|
603
|
+
],
|
|
604
|
+
},
|
|
605
|
+
// 持仓线数据
|
|
606
|
+
{
|
|
607
|
+
name: "positionLine",
|
|
608
|
+
data: [
|
|
609
|
+
{
|
|
610
|
+
value: 14500,
|
|
611
|
+
text: "持仓:192.14万(1份) 数量:4手 方向:多 浮动盈亏:-1280.00",
|
|
612
|
+
// 自定义参数
|
|
613
|
+
customInfo: {},
|
|
614
|
+
},
|
|
615
|
+
],
|
|
616
|
+
},
|
|
617
|
+
// 条件单数据
|
|
618
|
+
{
|
|
619
|
+
name: "conditionLine",
|
|
620
|
+
data: [
|
|
621
|
+
{
|
|
622
|
+
value: 14000,
|
|
623
|
+
text: "[多损][多盈] 开多↓14000 1份(22手)",
|
|
624
|
+
profitValue: 14200,
|
|
625
|
+
profitText: "上破14200",
|
|
626
|
+
lossValue: 13900,
|
|
627
|
+
lossText: "下破13900",
|
|
628
|
+
// 自定义参数
|
|
629
|
+
customInfo: {},
|
|
630
|
+
},
|
|
631
|
+
],
|
|
632
|
+
},
|
|
633
|
+
];
|
|
634
|
+
};
|
|
635
|
+
// 获取二腿相关度数据
|
|
636
|
+
const getRelevanceData = async () => {
|
|
637
|
+
// 将通过接口获取到的数据格式化
|
|
638
|
+
relevanceData.value = [
|
|
639
|
+
["2024-03-08 23:00:00", -0.5],
|
|
640
|
+
["2024-04-22 15:00:00", 1.5],
|
|
641
|
+
];
|
|
642
|
+
};
|
|
643
|
+
// 获取价差周期性数据
|
|
644
|
+
const getYearChartData = async () => {
|
|
645
|
+
yearChartData.value = [
|
|
646
|
+
{
|
|
647
|
+
year: "2023",
|
|
648
|
+
infos: [
|
|
649
|
+
{
|
|
650
|
+
genTime: "01-01",
|
|
651
|
+
close: 1000,
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
genTime: "05-01",
|
|
655
|
+
close: 2000,
|
|
656
|
+
},
|
|
657
|
+
],
|
|
658
|
+
},
|
|
659
|
+
{
|
|
660
|
+
year: "2024",
|
|
661
|
+
infos: [
|
|
662
|
+
{
|
|
663
|
+
genTime: "01-01",
|
|
664
|
+
close: 600,
|
|
665
|
+
},
|
|
666
|
+
{
|
|
667
|
+
genTime: "07-01",
|
|
668
|
+
close: 1200,
|
|
669
|
+
},
|
|
670
|
+
],
|
|
671
|
+
},
|
|
672
|
+
];
|
|
673
|
+
};
|
|
674
|
+
</script>
|
|
675
|
+
|
|
676
|
+
<style lang="scss" scoped>
|
|
677
|
+
.kline {
|
|
678
|
+
width: 100%;
|
|
679
|
+
height: 100%;
|
|
680
|
+
display: flex;
|
|
681
|
+
flex-direction: column;
|
|
682
|
+
background: #000;
|
|
683
|
+
// K线主图
|
|
684
|
+
&-mainChart {
|
|
685
|
+
flex: 1;
|
|
686
|
+
overflow: hidden;
|
|
687
|
+
.chart {
|
|
688
|
+
width: 100%;
|
|
689
|
+
height: 100%;
|
|
690
|
+
}
|
|
691
|
+
// 菜单
|
|
692
|
+
.menu {
|
|
693
|
+
border-radius: 4px;
|
|
694
|
+
overflow: hidden;
|
|
695
|
+
.menu-item {
|
|
696
|
+
font-size: 16px;
|
|
697
|
+
height: 40px;
|
|
698
|
+
border-top: 1px solid silver;
|
|
699
|
+
&:nth-child(1) {
|
|
700
|
+
border-top: none;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
// 价差周期性
|
|
706
|
+
.year-chart {
|
|
707
|
+
flex: 0.4;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
</style>
|
|
711
|
+
<style lang="scss">
|
|
712
|
+
// 画笔模式: 需要写在外面,不然会被Vue唯一标识符顶掉导致样式不生效
|
|
713
|
+
.penMode canvas {
|
|
714
|
+
cursor: url(./images/pen.png) -30 30, auto !important;
|
|
715
|
+
}
|
|
716
|
+
</style>
|