st-comp 0.0.246 → 0.0.248
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/es/ChartLayout.js +4 -4
- package/es/CustomFunction.js +42 -42
- package/es/FactorWarning.js +33 -33
- package/es/Kline.js +17 -17
- package/es/KlineBasic.cjs +1 -1
- package/es/KlineBasic.js +520 -512
- package/es/KlineConfig.js +61 -61
- package/es/KlineNew.js +16 -16
- package/es/KlinePlus.cjs +4 -4
- package/es/KlinePlus.js +589 -575
- package/es/LinearLegend.cjs +1 -1
- package/es/LinearLegend.js +1 -63
- package/es/MonacoEditor.js +24 -24
- package/es/Pagination.js +73 -73
- package/es/PasswordPrompt.js +3 -3
- package/es/Table.js +38 -38
- package/es/User.js +44 -44
- package/es/VarSelectDialog.js +25 -25
- package/es/VarietyAutoComplete.js +10 -10
- package/es/VarietySearch.js +38 -38
- package/es/{VarietySelect-5a9dd50b.js → VarietySelect-b9fe3000.js} +4 -4
- package/es/VarietyTextCopy.cjs +3 -3
- package/es/VarietyTextCopy.js +15 -15
- package/es/VirtualTable.js +14 -14
- package/es/{_initCloneObject-c34c65bc.js → _initCloneObject-382335b2.js} +7 -7
- package/es/{base-a5af3db3.js → base-ff0e366f.js} +40 -40
- package/es/{castArray-7741a212.js → castArray-15070be9.js} +1 -1
- package/es/{config-provider-06a63185.js → config-provider-2e85eee8.js} +6 -6
- package/es/{debounce-8d53f4dd.js → debounce-e9e47f9a.js} +1 -1
- package/es/{dropdown-302f71e7.js → dropdown-2b35a683.js} +13 -13
- package/es/{el-autocomplete-ed75a659.js → el-autocomplete-18be2c5a.js} +16 -16
- package/es/{el-button-d09ff85f.js → el-button-f08c0639.js} +39 -39
- package/es/{el-checkbox-64648e02.js → el-checkbox-058dba2d.js} +31 -31
- package/es/{el-dialog-6a80e3d8.js → el-dialog-d328e0d8.js} +15 -15
- package/es/{el-divider-4e059794.js → el-divider-4fe55ebe.js} +1 -1
- package/es/{el-empty-33cb66f1.js → el-empty-ceecb81c.js} +5 -5
- package/es/{el-form-item-4eca95be.js → el-form-item-cb328886.js} +36 -36
- package/es/{el-input-cae60510.js → el-input-0f6ead19.js} +50 -50
- package/es/{el-input-number-c2499410.js → el-input-number-66e68609.js} +36 -36
- package/es/{el-loading-c738468d.js → el-loading-412370c7.js} +5 -5
- package/es/{el-menu-item-f904f685.js → el-menu-item-0ee8ad18.js} +22 -22
- package/es/{el-message-box-05d8cf39.js → el-message-box-6db52b29.js} +11 -11
- package/es/{el-message-0df23ae7.js → el-message-e6c755df.js} +23 -23
- package/es/{el-overlay-cc9bc792.js → el-overlay-981f8d49.js} +56 -56
- package/es/{el-popconfirm-a6f66a0e.js → el-popconfirm-005013fa.js} +20 -20
- package/es/{el-popper-a38874f4.js → el-popper-fdc7c793.js} +109 -109
- package/es/{el-segmented-51b1c797.js → el-segmented-050d0090.js} +8 -8
- package/es/{el-select-1b149fab.js → el-select-23a1f302.js} +64 -64
- package/es/{el-table-column-3e30ebae.js → el-table-column-d0c374cf.js} +15 -15
- package/es/{el-tag-0a25efdf.js → el-tag-f13f463b.js} +15 -15
- package/es/{el-text-73d899ff.js → el-text-27cef2be.js} +2 -2
- package/es/{index-42e59bf5.js → index-09bd2621.js} +43 -43
- package/es/{index-94e43e0d.js → index-15b9603e.js} +3 -3
- package/es/{index-960806da.js → index-269b8a8c.js} +36 -36
- package/es/{index-54d289d1.js → index-4a3f30c5.js} +12 -12
- package/es/{index-6e967429.js → index-80a7ad32.js} +17 -17
- package/es/{index-d77a7336.js → index-93a8960e.js} +1 -1
- package/es/{index-4194c942.js → index-b937ea22.js} +2 -2
- package/es/{index-ac98a4d8.js → index-c266c23a.js} +10 -10
- package/es/{index-6806997d.js → index-e0901394.js} +34 -34
- package/es/{index-87b4bf61.js → index-ec7ad93f.js} +31 -31
- package/es/{python-a914569a.js → python-823b276b.js} +24 -24
- package/es/raf-8e05a7f4.js +6 -0
- package/es/{scroll-679bd6bf.js → scroll-41b4f625.js} +5 -5
- package/es/style.css +1 -1
- package/es/{use-form-common-props-47e50c10.js → use-form-common-props-631cacae.js} +65 -65
- package/es/{use-global-config-f52caea0.js → use-global-config-5d001623.js} +14 -14
- package/es/{validator-94c04152.js → validator-4160d9e7.js} +1 -1
- package/es/{vnode-5ddb7ed1.js → vnode-06571d5b.js} +1 -1
- package/es/{zh-cn-4921961d.js → zh-cn-5df98ac2.js} +2 -2
- package/lib/bundle.js +1 -1
- package/lib/bundle.umd.cjs +162 -162
- package/lib/{index-2a325d42.js → index-f00d1e1f.js} +13173 -13151
- package/lib/{python-eb65d93b.js → python-0f34e2e6.js} +1 -1
- package/lib/style.css +1 -1
- package/package.json +1 -1
- package/packages/KlineBasic/components/KlineSub/index.vue +35 -15
- package/packages/KlineBasic/components/KlineTips/index.vue +2 -2
- package/packages/KlineBasic/index.vue +39 -41
- package/packages/KlinePlus/index.vue +88 -62
- package/src/App.vue +15 -4
- package/src/pages/KlineBasic/index.vue +7 -7
- package/src/pages/KlineNew/components/KlineAction/mockApi/index.js +1 -1
- package/src/pages/KlineNew/components/KlineBasic/utils.js +1 -1
- package/src/pages/KlineNew/components/KlineSlide/utils.js +1 -1
- package/src/pages/KlinePlus/KlineDialog/MultiCycle.vue +312 -0
- package/src/pages/KlinePlus/KlineDialog/api.js +108 -0
- package/src/pages/KlinePlus/KlineDialog/index.vue +582 -0
- package/src/pages/KlinePlus/KlineDialog/indicator.js +109 -0
- package/src/pages/KlinePlus/KlineDialog/tools.js +86 -0
- package/src/pages/KlinePlus/index.vue +23 -209
- package/es/raf-80ef0c0a.js +0 -6
package/package.json
CHANGED
|
@@ -37,22 +37,23 @@ import { formatIndicatorNumber } from "../../utils"
|
|
|
37
37
|
import { stMath } from "st-func";
|
|
38
38
|
const { round } = stMath;
|
|
39
39
|
|
|
40
|
-
let subChart;
|
|
41
|
-
let resizeRo
|
|
40
|
+
let subChart = null;
|
|
41
|
+
let resizeRo = null;
|
|
42
|
+
const isAlive = ref(true); // 组件活跃状态
|
|
42
43
|
|
|
43
44
|
const emit = defineEmits(["update:modelValue"]);
|
|
44
45
|
const props = defineProps({
|
|
45
46
|
cycle: {
|
|
46
47
|
type: [String, Number],
|
|
47
48
|
default: () => null,
|
|
48
|
-
},
|
|
49
|
+
},
|
|
49
50
|
data: { type: Object, require: true },
|
|
50
51
|
activeIndex: { type: [Number, String], require: true },
|
|
51
|
-
modelValue: { type: String, required: true },
|
|
52
|
-
subIndicatorList: { type: Array, required: true },
|
|
52
|
+
modelValue: { type: String, required: true },
|
|
53
|
+
subIndicatorList: { type: Array, required: true },
|
|
53
54
|
});
|
|
54
55
|
|
|
55
|
-
const subChartRef = ref();
|
|
56
|
+
const subChartRef = ref();
|
|
56
57
|
const subIndicator = computed({
|
|
57
58
|
get() {
|
|
58
59
|
return props.modelValue;
|
|
@@ -63,27 +64,41 @@ const subIndicator = computed({
|
|
|
63
64
|
});
|
|
64
65
|
|
|
65
66
|
const subIndicatorTips = computed(() => {
|
|
67
|
+
if (!isAlive.value) return [];
|
|
66
68
|
const { data, activeIndex } = props;
|
|
67
69
|
return data?.subIndicator?.map((item) => ({ label: item.key, color: item.color, value: formatIndicatorNumber(item.data[activeIndex]) })) || [];
|
|
68
70
|
});
|
|
71
|
+
|
|
69
72
|
onMounted(() => {
|
|
73
|
+
isAlive.value = true;
|
|
74
|
+
if (!subChartRef.value) return;
|
|
75
|
+
|
|
70
76
|
subChart = echarts.init(subChartRef.value);
|
|
71
|
-
|
|
77
|
+
|
|
72
78
|
let isFirst = true;
|
|
73
79
|
resizeRo = new ResizeObserver(() => {
|
|
74
80
|
if (isFirst) {
|
|
75
|
-
isFirst =
|
|
81
|
+
isFirst = false;
|
|
76
82
|
return;
|
|
77
83
|
}
|
|
78
|
-
subChart.
|
|
84
|
+
if (isAlive.value && subChart && !subChart.isDisposed()) {
|
|
85
|
+
subChart.resize();
|
|
86
|
+
}
|
|
79
87
|
});
|
|
80
88
|
resizeRo.observe(subChartRef.value);
|
|
81
89
|
});
|
|
82
90
|
|
|
83
91
|
onUnmounted(() => {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
92
|
+
isAlive.value = false;
|
|
93
|
+
|
|
94
|
+
if (subChart && !subChart.isDisposed()) {
|
|
95
|
+
subChart.dispose();
|
|
96
|
+
subChart = null;
|
|
97
|
+
}
|
|
98
|
+
if (resizeRo) {
|
|
99
|
+
resizeRo.disconnect();
|
|
100
|
+
resizeRo = null;
|
|
101
|
+
}
|
|
87
102
|
});
|
|
88
103
|
|
|
89
104
|
// 获取副图颜色
|
|
@@ -113,10 +128,15 @@ const getSubBarStyle = (data, index) => {
|
|
|
113
128
|
|
|
114
129
|
defineExpose({
|
|
115
130
|
connect: (chart) => {
|
|
131
|
+
if (!isAlive.value || !subChart || subChart.isDisposed()) return;
|
|
116
132
|
echarts.connect([chart, subChart]);
|
|
117
|
-
},
|
|
133
|
+
},
|
|
118
134
|
draw: (drawConfig, config) => {
|
|
135
|
+
if (!isAlive.value || !subChart || subChart.isDisposed()) return;
|
|
136
|
+
|
|
119
137
|
nextTick(() => {
|
|
138
|
+
if (!isAlive.value || !subChart || subChart.isDisposed()) return;
|
|
139
|
+
|
|
120
140
|
const { startValue, endValue, maxValueSpan } = drawConfig;
|
|
121
141
|
const { leftYAxisRange, rightYAxisRange } = props.data.subIndicator[0];
|
|
122
142
|
const series = props.data.subIndicator.map((item) => {
|
|
@@ -271,7 +291,7 @@ defineExpose({
|
|
|
271
291
|
true
|
|
272
292
|
);
|
|
273
293
|
});
|
|
274
|
-
},
|
|
294
|
+
},
|
|
275
295
|
});
|
|
276
296
|
</script>
|
|
277
297
|
|
|
@@ -309,4 +329,4 @@ defineExpose({
|
|
|
309
329
|
height: calc(100% - 26px);
|
|
310
330
|
}
|
|
311
331
|
}
|
|
312
|
-
</style>
|
|
332
|
+
</style>
|
|
@@ -32,13 +32,13 @@ const close = ref(null);
|
|
|
32
32
|
|
|
33
33
|
watch(() => props.activeIndex, () => {
|
|
34
34
|
if (close.value === null) {
|
|
35
|
-
close.value = props.data.data[props.activeIndex][1]
|
|
35
|
+
close.value = props.data.data[props.activeIndex]?.[1] ?? 0
|
|
36
36
|
}
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
watch(() => props.data, () => {
|
|
40
40
|
if (close.value === null) {
|
|
41
|
-
close.value = props.data.data[props.activeIndex][1]
|
|
41
|
+
close.value = props.data.data[props.activeIndex]?.[1] ?? 0
|
|
42
42
|
}
|
|
43
43
|
});
|
|
44
44
|
|
|
@@ -3,7 +3,7 @@ import dayjs from "dayjs";
|
|
|
3
3
|
import * as echarts from "echarts";
|
|
4
4
|
import { onMounted, onUnmounted, ref, watch, computed, nextTick } from "vue";
|
|
5
5
|
import { initRequestByEnv, getKlineBasic, getKline, getWarningLine, addWarningLine, updateWarningLine, deleteWarningLine } from "./api";
|
|
6
|
-
import { addResizeListener } from "st-func";
|
|
6
|
+
import { addResizeListener, debounce } from "st-func";
|
|
7
7
|
import { getMainOptions, getWarningLineOptions } from "./utils";
|
|
8
8
|
import KlineTips from "./components/KlineTips/index.vue";
|
|
9
9
|
import KlineSub from "./components/KlineSub/index.vue";
|
|
@@ -17,9 +17,6 @@ let renderFrameId = null; // 渲染帧ID
|
|
|
17
17
|
let drawLineFrameId = null; // 绘线帧ID
|
|
18
18
|
let brushFrameId = null; // 区域框选帧ID
|
|
19
19
|
|
|
20
|
-
let highlightTimer; // 高亮事件定时器
|
|
21
|
-
let mainDataZoomTimer; // datazoom事件定时器
|
|
22
|
-
|
|
23
20
|
let isLoadHistory = false; // 是否正在加载历史数据
|
|
24
21
|
let isloadAllHistory = false; // 是否加载完全部历史数据
|
|
25
22
|
|
|
@@ -103,10 +100,10 @@ const config = computed(() => {
|
|
|
103
100
|
addCounts: 2000,
|
|
104
101
|
maxShowCounts: 5000,
|
|
105
102
|
loadCheckCounts: 500,
|
|
106
|
-
showSubChart: true,
|
|
107
103
|
gridTop: 48,
|
|
108
104
|
gridLeft: 80,
|
|
109
105
|
gridRight: 50,
|
|
106
|
+
showSubChart: true,
|
|
110
107
|
showWarningLine: true,
|
|
111
108
|
getFactorData: true,
|
|
112
109
|
...props.config,
|
|
@@ -359,13 +356,13 @@ const getMainData = async () => {
|
|
|
359
356
|
params.endTime = endTime;
|
|
360
357
|
} else if (startTime) {
|
|
361
358
|
params.startTime = startTime;
|
|
362
|
-
params.limit =
|
|
359
|
+
params.limit = addCounts;
|
|
363
360
|
} else if (endTime) {
|
|
364
361
|
params.endTime = endTime;
|
|
365
|
-
params.limit =
|
|
362
|
+
params.limit = addCounts;
|
|
366
363
|
} else {
|
|
367
364
|
params.endTime = dayjs().add(1, "hour").format("YYYY-MM-DD HH:mm:ss");
|
|
368
|
-
params.limit =
|
|
365
|
+
params.limit = addCounts;
|
|
369
366
|
}
|
|
370
367
|
|
|
371
368
|
const res = await getKlineBasic(params);
|
|
@@ -496,9 +493,9 @@ const handleKeyDownEvent = ({ code, ctrlKey }) => {
|
|
|
496
493
|
};
|
|
497
494
|
// 图表事件
|
|
498
495
|
const addEventListener = () => {
|
|
499
|
-
mainChartIns?.on(
|
|
500
|
-
|
|
501
|
-
|
|
496
|
+
mainChartIns?.on(
|
|
497
|
+
"datazoom",
|
|
498
|
+
debounce((params) => {
|
|
502
499
|
const { loadCheckCounts } = config.value;
|
|
503
500
|
if (mainChartIns?.getOption()?.dataZoom?.[0]) {
|
|
504
501
|
const { startValue } = mainChartIns?.getOption()?.dataZoom?.[0];
|
|
@@ -508,33 +505,33 @@ const addEventListener = () => {
|
|
|
508
505
|
}
|
|
509
506
|
drawLine(); // 使用RAF优化的绘线
|
|
510
507
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
highlightTimer = setTimeout(() => {
|
|
522
|
-
activeIndex.value = index;
|
|
523
|
-
clearTimeout(highlightTimer);
|
|
524
|
-
}, 20);
|
|
525
|
-
});
|
|
526
|
-
|
|
527
|
-
mainChartIns?.on("globalout", () => {
|
|
528
|
-
const timer = setTimeout(() => {
|
|
529
|
-
clearTimeout(timer);
|
|
530
|
-
const index = mainChartIns?.getOption()?.dataZoom?.[0]?.endValue;
|
|
508
|
+
}, 100),
|
|
509
|
+
);
|
|
510
|
+
|
|
511
|
+
mainChartIns?.on(
|
|
512
|
+
"highlight",
|
|
513
|
+
debounce((data) => {
|
|
514
|
+
let index = data.dataIndex || -1;
|
|
515
|
+
if (data.batch) {
|
|
516
|
+
index = typeof data?.batch[0]?.dataIndex === "number" ? data?.batch[0]?.dataIndex : -1;
|
|
517
|
+
}
|
|
531
518
|
activeIndex.value = index;
|
|
532
|
-
},
|
|
533
|
-
|
|
519
|
+
}, 20),
|
|
520
|
+
);
|
|
521
|
+
|
|
522
|
+
mainChartIns?.on(
|
|
523
|
+
"globalout",
|
|
524
|
+
debounce(() => {
|
|
525
|
+
if (mainChartIns) {
|
|
526
|
+
const index = mainChartIns?.getOption()?.dataZoom?.[0]?.endValue;
|
|
527
|
+
activeIndex.value = index;
|
|
528
|
+
}
|
|
529
|
+
}, 30),
|
|
530
|
+
);
|
|
534
531
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
532
|
+
mainChartIns?.on(
|
|
533
|
+
"contextmenu",
|
|
534
|
+
debounce((params) => {
|
|
538
535
|
if (params.componentType === "graphic") {
|
|
539
536
|
warningItem.value = params.info;
|
|
540
537
|
menuData.value = [
|
|
@@ -542,10 +539,8 @@ const addEventListener = () => {
|
|
|
542
539
|
{ label: "修改画线", key: "changeWarningLine" },
|
|
543
540
|
];
|
|
544
541
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
});
|
|
548
|
-
});
|
|
542
|
+
}, 0),
|
|
543
|
+
);
|
|
549
544
|
};
|
|
550
545
|
|
|
551
546
|
// 预警线相关辅助函数
|
|
@@ -686,7 +681,10 @@ defineExpose({
|
|
|
686
681
|
@mousemove="isHover = true"
|
|
687
682
|
@mouseout="isHover = false"
|
|
688
683
|
>
|
|
689
|
-
<div
|
|
684
|
+
<div
|
|
685
|
+
v-if="chartData.time?.length"
|
|
686
|
+
class="klineBasic-tips"
|
|
687
|
+
>
|
|
690
688
|
<KlineTips
|
|
691
689
|
:variety="variety"
|
|
692
690
|
:data="chartData"
|
|
@@ -11,7 +11,6 @@ import SliderChart from "./components/SliderChart.vue";
|
|
|
11
11
|
const { round, formatValue } = stMath;
|
|
12
12
|
const { request } = inject("stConfig"); // 组件库全局配置
|
|
13
13
|
|
|
14
|
-
const sliderChartRef = ref();
|
|
15
14
|
const loading = ref(false);
|
|
16
15
|
const isHover = ref(false);
|
|
17
16
|
const props = defineProps({
|
|
@@ -53,8 +52,9 @@ let isloadAllHistory = false;
|
|
|
53
52
|
let resizeRo = null;
|
|
54
53
|
let subChartIns = null;
|
|
55
54
|
let mainChartIns = null;
|
|
56
|
-
const subChartRef = ref(null);
|
|
57
55
|
const mainChartRef = ref(null);
|
|
56
|
+
const subChartRef = ref(null);
|
|
57
|
+
const sliderChartRef = ref(null);
|
|
58
58
|
|
|
59
59
|
// K线数据
|
|
60
60
|
const klineData = ref({
|
|
@@ -112,57 +112,73 @@ const subIndicatorTips = computed(() => {
|
|
|
112
112
|
|
|
113
113
|
// 图表: 初始化
|
|
114
114
|
const initChart = () => {
|
|
115
|
-
|
|
115
|
+
// 检查DOM元素是否存在
|
|
116
|
+
if (!mainChartRef.value) {
|
|
117
|
+
console.warn("[K线] 主图DOM元素不存在,取消初始化");
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
if (mainChartIns) return true;
|
|
116
121
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
122
|
+
try {
|
|
123
|
+
// 主图
|
|
124
|
+
mainChartIns = echarts.init(mainChartRef.value);
|
|
125
|
+
mainChartIns.on(
|
|
126
|
+
"highlight",
|
|
127
|
+
debounce((params) => {
|
|
128
|
+
if (params.dataIndex) {
|
|
129
|
+
activeIndex.value = params.dataIndex;
|
|
130
|
+
} else {
|
|
131
|
+
activeIndex.value = params.batch?.[0].dataIndex ?? -1;
|
|
132
|
+
}
|
|
133
|
+
}, 10),
|
|
134
|
+
);
|
|
135
|
+
mainChartIns.on(
|
|
136
|
+
"datazoom",
|
|
137
|
+
debounce(async () => {
|
|
138
|
+
const { loadCheckCount } = loadKlineConfig;
|
|
139
|
+
const { startValue, endValue } = mainChartIns.getOption()?.dataZoom[0] ?? {};
|
|
140
|
+
// 当前开始索引 < 阈值边界, 触发加载更多数据
|
|
141
|
+
if (isLoadHistory === false && isloadAllHistory === false && startValue < loadCheckCount) await getMoreData("history");
|
|
142
|
+
// 当前结束索引 > 阈值边界, 触发加载更多数据
|
|
143
|
+
if (isLoadNew === false && isloadAllNew === false && endValue > klineData.value.time.length - loadCheckCount) await getMoreData("new");
|
|
144
|
+
getScreenTimeRange();
|
|
145
|
+
drawScreenMaxPrice();
|
|
146
|
+
}),
|
|
147
|
+
);
|
|
148
|
+
mainChartIns.on("globalout", () => {
|
|
149
|
+
if (mainChartIns) {
|
|
150
|
+
const option = mainChartIns.getOption();
|
|
151
|
+
activeIndex.value = option.dataZoom[0].endValue;
|
|
126
152
|
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const { loadCheckCount } = loadKlineConfig;
|
|
133
|
-
const { startValue, endValue } = mainChartIns.getOption()?.dataZoom[0] ?? {};
|
|
134
|
-
// 当前开始索引 < 阈值边界, 触发加载更多数据
|
|
135
|
-
if (isLoadHistory === false && isloadAllHistory === false && startValue < loadCheckCount) await getMoreData("history");
|
|
136
|
-
// 当前结束索引 > 阈值边界, 触发加载更多数据
|
|
137
|
-
if (isLoadNew === false && isloadAllNew === false && endValue > klineData.value.time.length - loadCheckCount) await getMoreData("new");
|
|
138
|
-
getScreenTimeRange();
|
|
139
|
-
drawScreenMaxPrice();
|
|
140
|
-
})
|
|
141
|
-
);
|
|
142
|
-
mainChartIns.on("globalout", () => {
|
|
143
|
-
const option = mainChartIns.getOption();
|
|
144
|
-
activeIndex.value = option.dataZoom[0].endValue;
|
|
145
|
-
});
|
|
146
|
-
mainChartIns.getZr().on("contextmenu", () => {
|
|
147
|
-
contextmenuKlineTime.value = klineData.value?.time[activeIndex.value];
|
|
148
|
-
});
|
|
149
|
-
window.addEventListener("keydown", handleKeyDownEvent);
|
|
153
|
+
});
|
|
154
|
+
mainChartIns.getZr().on("contextmenu", () => {
|
|
155
|
+
contextmenuKlineTime.value = klineData.value?.time[activeIndex.value];
|
|
156
|
+
});
|
|
157
|
+
window.addEventListener("keydown", handleKeyDownEvent);
|
|
150
158
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
159
|
+
// 副图
|
|
160
|
+
if (props.userKlineConfig.enable_subChart && subChartRef.value) {
|
|
161
|
+
subChartIns = echarts.init(subChartRef.value);
|
|
162
|
+
echarts.connect([mainChartIns, subChartIns]);
|
|
163
|
+
}
|
|
156
164
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
165
|
+
// DOM缩放
|
|
166
|
+
if (mainChartRef.value) {
|
|
167
|
+
resizeRo = addResizeListener(mainChartRef.value);
|
|
168
|
+
resizeRo.listen(() => {
|
|
169
|
+
requestAnimationFrame(() => {
|
|
170
|
+
mainChartIns?.resize();
|
|
171
|
+
subChartIns?.resize();
|
|
172
|
+
sliderChartRef.value?.resize();
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return true;
|
|
178
|
+
} catch (error) {
|
|
179
|
+
console.error("[st-klinePlus]: 初始化异常:", error);
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
166
182
|
};
|
|
167
183
|
// 图表: 获取数据 [首屏]
|
|
168
184
|
const getMainData = async ({ startTime, endTime }) => {
|
|
@@ -312,7 +328,16 @@ const getScreenTimeRange = () => {
|
|
|
312
328
|
|
|
313
329
|
// 图表: 绘制(主流程)
|
|
314
330
|
const draw = (params = { startValue: 0, endValue: 0 }) => {
|
|
315
|
-
initChart();
|
|
331
|
+
const isInitialized = initChart();
|
|
332
|
+
// 确保图表存在
|
|
333
|
+
if (!isInitialized || !mainChartIns) {
|
|
334
|
+
return console.warn("[st-klinePlus]: 图表未准备就绪, 跳过绘制");
|
|
335
|
+
}
|
|
336
|
+
// 检查数据是否存在
|
|
337
|
+
if (!klineData.value.time.length) {
|
|
338
|
+
return console.warn("[st-klinePlus]: 图表无数据, 跳过绘制");
|
|
339
|
+
}
|
|
340
|
+
|
|
316
341
|
const { maxValueSpan } = loadKlineConfig;
|
|
317
342
|
const { time, data, mainIndicator } = klineData.value;
|
|
318
343
|
|
|
@@ -570,7 +595,7 @@ const draw = (params = { startValue: 0, endValue: 0 }) => {
|
|
|
570
595
|
},
|
|
571
596
|
},
|
|
572
597
|
},
|
|
573
|
-
true
|
|
598
|
+
true,
|
|
574
599
|
);
|
|
575
600
|
if (props.userKlineConfig.enable_subChart) {
|
|
576
601
|
subChartIns.setOption(getSubOptions(klineData.value, startValue, endValue), true);
|
|
@@ -712,7 +737,7 @@ const drawScreenMaxPrice = () => {
|
|
|
712
737
|
{
|
|
713
738
|
notMerge: false, // 合并模式
|
|
714
739
|
replaceMerge: [], // 不替换任何配置
|
|
715
|
-
}
|
|
740
|
+
},
|
|
716
741
|
);
|
|
717
742
|
};
|
|
718
743
|
|
|
@@ -727,6 +752,7 @@ const handleSliderChange = (params) => {
|
|
|
727
752
|
};
|
|
728
753
|
// 键盘控制 [↑↓←→缩放平移]
|
|
729
754
|
const handleKeyDownEvent = ({ code, ctrlKey }) => {
|
|
755
|
+
if (!mainChartIns) return;
|
|
730
756
|
if (!(ctrlKey || isHover.value)) return;
|
|
731
757
|
const { xAxis, dataZoom } = mainChartIns.getOption();
|
|
732
758
|
const { data: xAxisData } = xAxis?.[0] ?? { data: [] };
|
|
@@ -801,7 +827,7 @@ watch(
|
|
|
801
827
|
const [startTime, endTime] = props.initTimeRange;
|
|
802
828
|
getMainData({ startTime, endTime });
|
|
803
829
|
},
|
|
804
|
-
{ deep: true }
|
|
830
|
+
{ deep: true },
|
|
805
831
|
);
|
|
806
832
|
// 监控: [周期选项] => 重加载K线 (缩放不变+校验时间间隔)
|
|
807
833
|
watch(
|
|
@@ -816,7 +842,7 @@ watch(
|
|
|
816
842
|
});
|
|
817
843
|
getMainData({ startTime, endTime });
|
|
818
844
|
},
|
|
819
|
-
{ deep: true }
|
|
845
|
+
{ deep: true },
|
|
820
846
|
);
|
|
821
847
|
// 监控: [主指标, 副指标, 指标配置, 复权选项, 常用选项] => 重加载K线 (缩放不变)
|
|
822
848
|
watch(
|
|
@@ -826,7 +852,7 @@ watch(
|
|
|
826
852
|
const [startTime, endTime] = [klineData.value.time[startValue], klineData.value.time[endValue]];
|
|
827
853
|
getMainData({ startTime, endTime });
|
|
828
854
|
},
|
|
829
|
-
{ deep: true }
|
|
855
|
+
{ deep: true },
|
|
830
856
|
);
|
|
831
857
|
// 监控: [成交点类型, 成交数据, 净值数据, 收益计算类型, 成交收益率数据] => 重绘K线 (缩放不变)
|
|
832
858
|
watch(
|
|
@@ -835,19 +861,19 @@ watch(
|
|
|
835
861
|
const { startValue, endValue } = mainChartIns.getOption()?.dataZoom[0] ?? {};
|
|
836
862
|
draw({ startValue, endValue });
|
|
837
863
|
},
|
|
838
|
-
{ deep: true }
|
|
864
|
+
{ deep: true },
|
|
839
865
|
);
|
|
840
866
|
onUnmounted(() => {
|
|
841
867
|
// 解绑
|
|
842
|
-
mainChartIns
|
|
843
|
-
mainChartIns
|
|
844
|
-
mainChartIns
|
|
845
|
-
mainChartIns
|
|
868
|
+
mainChartIns?.off("highlight");
|
|
869
|
+
mainChartIns?.off("globalout");
|
|
870
|
+
mainChartIns?.off("datazoom");
|
|
871
|
+
mainChartIns?.getZr()?.off("contextmenu");
|
|
846
872
|
window.removeEventListener("keydown", handleKeyDownEvent);
|
|
847
873
|
// 销毁
|
|
848
|
-
mainChartIns
|
|
874
|
+
mainChartIns?.dispose();
|
|
849
875
|
subChartIns?.dispose();
|
|
850
|
-
resizeRo
|
|
876
|
+
resizeRo?.dispose();
|
|
851
877
|
resizeRo = null;
|
|
852
878
|
});
|
|
853
879
|
defineExpose({
|
package/src/App.vue
CHANGED
|
@@ -39,14 +39,25 @@ import routes from "./router/routes.ts";
|
|
|
39
39
|
const route = useRoute();
|
|
40
40
|
|
|
41
41
|
// const VITE_RUN_ENV = import.meta.env; // 正常使用
|
|
42
|
+
// const VITE_RUN_ENV = {
|
|
43
|
+
// VITE_PROJECT_NAME: "动量回测",
|
|
44
|
+
// VITE_PROJECT_CLIENTID: "7",
|
|
45
|
+
// VITE_BASE_URL: "http://192.168.12.38:5173",
|
|
46
|
+
// BASE_URL: "/",
|
|
47
|
+
// MODE: "test49",
|
|
48
|
+
// DEV: true,
|
|
49
|
+
// PROD: false,
|
|
50
|
+
// SSR: false,
|
|
51
|
+
// };
|
|
52
|
+
|
|
42
53
|
const VITE_RUN_ENV = {
|
|
43
54
|
VITE_PROJECT_NAME: "动量回测",
|
|
44
55
|
VITE_PROJECT_CLIENTID: "7",
|
|
45
|
-
VITE_BASE_URL: "
|
|
56
|
+
VITE_BASE_URL: "//investapi.hzyotoy.com",
|
|
46
57
|
BASE_URL: "/",
|
|
47
|
-
MODE: "
|
|
48
|
-
DEV:
|
|
49
|
-
PROD:
|
|
58
|
+
MODE: "production",
|
|
59
|
+
DEV: false,
|
|
60
|
+
PROD: true,
|
|
50
61
|
SSR: false,
|
|
51
62
|
};
|
|
52
63
|
</script>
|
|
@@ -178,14 +178,14 @@ import { getCycleList, host } from './api';
|
|
|
178
178
|
const indicatorStore = useIndicatorStore();
|
|
179
179
|
|
|
180
180
|
// 显示模式
|
|
181
|
-
const displayMode = ref('
|
|
181
|
+
const displayMode = ref('multi'); // single: 单周期, multi: 多周期
|
|
182
182
|
const show = ref(false);
|
|
183
183
|
|
|
184
184
|
// 周期映射
|
|
185
185
|
const cycleMap = {
|
|
186
|
-
'15m': { value: '
|
|
187
|
-
'30m': { value: '
|
|
188
|
-
'60m': { value: '
|
|
186
|
+
'15m': { value: '3', label: '15分钟' },
|
|
187
|
+
'30m': { value: '4', label: '30分钟' },
|
|
188
|
+
'60m': { value: '5', label: '60分钟' },
|
|
189
189
|
'1d': { value: '6', label: '日线' },
|
|
190
190
|
'1w': { value: '7', label: '周线' },
|
|
191
191
|
'1mon': { value: '8', label: '月线' }
|
|
@@ -193,9 +193,9 @@ const cycleMap = {
|
|
|
193
193
|
|
|
194
194
|
// 多周期展示的周期列表
|
|
195
195
|
const multiCycleList = [
|
|
196
|
-
{ cycle: '
|
|
197
|
-
{ cycle: '
|
|
198
|
-
{ cycle: '
|
|
196
|
+
{ cycle: '3', cycleLabel: '15分钟' }, // 15m
|
|
197
|
+
{ cycle: '4', cycleLabel: '30分钟' }, // 30m
|
|
198
|
+
{ cycle: '5', cycleLabel: '60分钟' }, // 60m
|
|
199
199
|
{ cycle: '6', cycleLabel: '日线' }, // 1d
|
|
200
200
|
{ cycle: '7', cycleLabel: '周线' }, // 1w
|
|
201
201
|
{ cycle: '8', cycleLabel: '月线' } // 1mon
|
|
@@ -6,7 +6,7 @@ export const getKlineDataApi = async(params) => {
|
|
|
6
6
|
headers: {
|
|
7
7
|
token: '041fd377d5d5efc7e08e2ed5b61b0c8d',
|
|
8
8
|
},
|
|
9
|
-
url: 'http://invest.hzyotoy.com/common/qt/getSingleCycleSingleVariety',
|
|
9
|
+
url: 'http://invest.hzyotoy.com/common/webjars/qt/getSingleCycleSingleVariety',
|
|
10
10
|
data: params,
|
|
11
11
|
})
|
|
12
12
|
return res.data.body
|
|
@@ -38,7 +38,7 @@ export const getKlineDataApi = async(params) => {
|
|
|
38
38
|
headers: {
|
|
39
39
|
token: '36cbbea2e76aff9d99f88d50669c009c',
|
|
40
40
|
},
|
|
41
|
-
url: 'http://invest.hzyotoy.com/common/qt/getSingleCycleSingleVariety',
|
|
41
|
+
url: 'http://invest.hzyotoy.com/common/webjars/qt/getSingleCycleSingleVariety',
|
|
42
42
|
data: params,
|
|
43
43
|
})
|
|
44
44
|
getKlineNew(params)
|
|
@@ -71,7 +71,7 @@ export const getKlineDataApi = async(params) => {
|
|
|
71
71
|
headers: {
|
|
72
72
|
token: 'ee08db9f1b8085e3c84fa22b60835951',
|
|
73
73
|
},
|
|
74
|
-
url: 'http://invest.hzyotoy.com/common/qt/getSingleCycleSingleVariety',
|
|
74
|
+
url: 'http://invest.hzyotoy.com/common/webjars/qt/getSingleCycleSingleVariety',
|
|
75
75
|
data: params,
|
|
76
76
|
})
|
|
77
77
|
return res.data.body
|