st-comp 0.0.122 → 0.0.124

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.
Files changed (92) hide show
  1. package/es/ChartLayout.js +2 -2
  2. package/es/Dialog.cjs +1 -1
  3. package/es/Dialog.js +14 -13
  4. package/es/FactorWarning.cjs +1 -1
  5. package/es/FactorWarning.js +26 -25
  6. package/es/Kline.cjs +1 -1
  7. package/es/Kline.js +849 -1605
  8. package/es/KlineBasic.cjs +6 -0
  9. package/es/KlineBasic.js +2888 -0
  10. package/es/KlineNew.cjs +1 -1
  11. package/es/KlineNew.js +12 -12
  12. package/es/Pagination.cjs +1 -1
  13. package/es/Pagination.js +18 -17
  14. package/es/Pie.cjs +1 -1
  15. package/es/Pie.js +1 -1
  16. package/es/Table.cjs +1 -1
  17. package/es/Table.js +18 -17
  18. package/es/User.cjs +1 -1
  19. package/es/User.js +75 -74
  20. package/es/VarietySearch.cjs +1 -1
  21. package/es/VarietySearch.js +903 -1253
  22. package/es/VirtualTable.cjs +1 -1
  23. package/es/VirtualTable.js +13 -12
  24. package/es/{base-f7877059.js → base-a8f938bd.js} +6 -6
  25. package/es/{castArray-18f43497.js → castArray-5c01dae1.js} +1 -1
  26. package/es/config-provider-4954003d.cjs +1 -0
  27. package/es/{config-provider-6479d795.js → config-provider-d3edea8a.js} +3 -3
  28. package/es/{debounce-2336e546.js → debounce-edbff018.js} +10 -10
  29. package/es/{dropdown-46daf582.js → dropdown-7e381525.js} +4 -4
  30. package/es/el-button-c7b375c4.cjs +1 -0
  31. package/es/{el-button-802f579a.js → el-button-ce99c64e.js} +6 -5
  32. package/es/{el-empty-3c5ec277.js → el-empty-ed6c115b.js} +1 -1
  33. package/es/{el-form-item-84099d46.js → el-form-item-b686a8bb.js} +9 -9
  34. package/es/{el-form-item-c39f717e.cjs → el-form-item-ff0d8d07.cjs} +1 -1
  35. package/es/{el-input-fac5b401.js → el-input-21e079e4.js} +5 -5
  36. package/es/el-menu-item-9369a2ad.js +771 -0
  37. package/es/el-menu-item-dc904a35.cjs +1 -0
  38. package/es/el-message-e97bdea1.cjs +1 -0
  39. package/es/el-message-fd827012.js +374 -0
  40. package/es/el-overlay-7b90d61c.cjs +1 -0
  41. package/es/{el-overlay-69e9ae49.js → el-overlay-9245ec1e.js} +77 -76
  42. package/es/{el-popover-694ded47.js → el-popover-6f075cee.js} +4 -4
  43. package/es/{el-popover-8735b1fa.cjs → el-popover-6f48d00b.cjs} +1 -1
  44. package/es/{el-popper-6126b1f6.js → el-popper-8dca8dd4.js} +4 -4
  45. package/es/{el-scrollbar-e0493906.js → el-scrollbar-906103f8.js} +1 -1
  46. package/es/{el-select-513126a5.js → el-select-6d6093eb.js} +10 -10
  47. package/es/el-table-column-26e7f13f.cjs +14 -0
  48. package/es/{el-table-column-3c920bdd.js → el-table-column-3f388c44.js} +15 -14
  49. package/es/{el-tag-5becabc9.js → el-tag-cdf0019e.js} +19 -19
  50. package/es/{index-7e40be25.js → index-53bce290.js} +3 -3
  51. package/es/index-669a0983.js +14 -0
  52. package/es/{index-048dca7e.js → index-6ced00c4.js} +1 -1
  53. package/es/index-c4649a37.cjs +3 -0
  54. package/es/{index-dc273ea2.cjs → index-d1b7c61e.cjs} +39 -39
  55. package/es/{index-57f8f7b9.js → index-f8e448bc.js} +5893 -5856
  56. package/es/{raf-07da7cdf.js → raf-b584bce8.js} +1 -1
  57. package/es/{refs-1b1fe6ca.js → refs-e1675167.js} +1 -1
  58. package/es/{scroll-3b521d81.js → scroll-25ec9230.js} +1 -1
  59. package/es/style.css +1 -1
  60. package/es/{use-form-common-props-f3a520d0.js → use-form-common-props-f7d2e83c.js} +18 -18
  61. package/es/use-global-config-8429db7d.js +72 -0
  62. package/es/{index-8a0b1c53.cjs → use-global-config-ac2dad80.cjs} +1 -3
  63. package/es/{vnode-25d7c2f5.js → vnode-699e61cb.js} +1 -1
  64. package/es/{zh-cn-74781bbd.js → zh-cn-61ca7f91.js} +2 -2
  65. package/es/{zh-cn-ab9a583d.cjs → zh-cn-a20960b5.cjs} +1 -1
  66. package/lib/bundle.js +1 -1
  67. package/lib/bundle.umd.cjs +213 -208
  68. package/lib/{index-62c62885.js → index-741ecbcc.js} +38391 -35484
  69. package/lib/{python-6cdad7a6.js → python-5a672b35.js} +1 -1
  70. package/lib/style.css +1 -1
  71. package/package.json +2 -2
  72. package/packages/KlineBasic/api.js +60 -0
  73. package/packages/KlineBasic/components/Contextmenu/index.vue +105 -0
  74. package/packages/KlineBasic/components/KlineSub/index.vue +297 -0
  75. package/packages/KlineBasic/components/KlineTips/index.vue +66 -0
  76. package/packages/KlineBasic/components/Tips/index.vue +33 -0
  77. package/packages/KlineBasic/index.ts +8 -0
  78. package/packages/KlineBasic/index.vue +565 -0
  79. package/packages/KlineBasic/utils.js +86 -0
  80. package/packages/VarietySearch/components/FactorScreen/index.vue +7 -7
  81. package/packages/index.ts +2 -0
  82. package/src/main.ts +2 -0
  83. package/src/pages/KlineBasic/api.js +45 -0
  84. package/src/pages/KlineBasic/index.vue +74 -0
  85. package/src/pages/KlineBasic/indicator.js +114 -0
  86. package/src/pages/VarietySearch/index.vue +3 -2
  87. package/src/router/routes.ts +5 -0
  88. package/es/config-provider-7cdfca4d.cjs +0 -1
  89. package/es/el-button-196807af.cjs +0 -1
  90. package/es/el-overlay-891dcc40.cjs +0 -1
  91. package/es/el-table-column-dd8b62aa.cjs +0 -14
  92. package/es/index-35117549.js +0 -81
@@ -0,0 +1,565 @@
1
+ <template>
2
+ <div class="klineBasic">
3
+ <div class="klineBasic-tips">
4
+ <KlineTips :data="chartData" :activeIndex="activeIndex" />
5
+ </div>
6
+ <div
7
+ class="klineBasic-main"
8
+ :style="{ height: config.showSubChart ? '70%' : '100%' }"
9
+ >
10
+ <Contextmenu>
11
+ <div ref="klineBasicMainRef" style="height: 100%;"></div>
12
+ <template #popover>
13
+ <el-menu
14
+ :style="{
15
+ borderRadius: '4px',
16
+ overflow: 'hidden',
17
+ background: '#fff',
18
+ borderRight: 0,
19
+ }"
20
+ >
21
+ <el-menu-item
22
+ v-for="item in menuData"
23
+ style="height: 36px"
24
+ :key="item.key"
25
+ :index="item.key"
26
+ @click="menuClick(item)"
27
+ >
28
+ {{ item.label }}
29
+ </el-menu-item>
30
+ </el-menu>
31
+ </template>
32
+ </Contextmenu>
33
+ </div>
34
+ <div class="klineBasic-sub" v-if="config.showSubChart">
35
+ <KlineSub
36
+ ref="klineSubRef"
37
+ v-model="subIndicator"
38
+ :data="chartData"
39
+ :activeIndex="activeIndex"
40
+ :subIndicatorList="indicatorStore?.subIndicatorList"
41
+ />
42
+ </div>
43
+ </div>
44
+ </template>
45
+
46
+ <script setup>
47
+ import { onMounted, onUnmounted, ref, watch, computed } from "vue"
48
+ import * as echarts from "echarts"
49
+ import dayjs from "dayjs"
50
+ import { getKlineBasic, getKline, addWarningLine } from './api'
51
+ import { addResizeListener, stMath } from 'st-func'
52
+ import { getWarningLineOptions } from './utils'
53
+ import KlineTips from './components/KlineTips/index.vue'
54
+ import KlineSub from './components/KlineSub/index.vue'
55
+ import Contextmenu from './components/Contextmenu/index.vue'
56
+
57
+ const { round } = stMath;
58
+
59
+ let resizeRo = null; // dom元素监听事件
60
+ let mainChartIns = null // 主图实例
61
+
62
+ let highlightTimer // 高亮事件定时器
63
+ let mainDataZoomTimer // datazoom事件定时器
64
+
65
+ let isLoadHistory = false; // 是否正在加载历史数据
66
+ let isloadAllHistory = false; // 是否加载完全部历史数据
67
+
68
+ const emit = defineEmits(['change', 'getFactorData']);
69
+
70
+ const props = defineProps({
71
+ variety: {
72
+ type: [String, Number],
73
+ required: true,
74
+ }, // 品种代码
75
+ varietyName: {
76
+ type: [String, Number],
77
+ default: () => ''
78
+ }, // 品种名称
79
+ featureId: {
80
+ type: [String, Number],
81
+ default: () => ''
82
+ }, // 合约id
83
+ featureType: {
84
+ type: [String, Number],
85
+ default: () => ''
86
+ }, // 合约类型
87
+ cycle: {
88
+ type: String,
89
+ required: true,
90
+ }, // 周期id
91
+ mainIndicator: {
92
+ type: Object,
93
+ default: () => ''
94
+ }, // 主图指标名称
95
+ indicatorStore: {
96
+ type: Object,
97
+ default: () => null
98
+ }, // 指标配置Store
99
+ startTime: {
100
+ type: String,
101
+ default: () => null,
102
+ },
103
+ endTime: {
104
+ type: String,
105
+ default: () => null,
106
+ },
107
+ right: {
108
+ type: Number,
109
+ default: 1,
110
+ }, // 复权方式,前复权-1,不复权-0
111
+ config: {
112
+ type: Object,
113
+ default: () => ({})
114
+ }, // 配置
115
+ })
116
+
117
+ const klineBasicMainRef = ref(null) // 主图Dom元素
118
+ const klineSubRef = ref(null) // 副图组件元素
119
+ const subIndicator = ref('VOL') // 副图指标
120
+ const activeIndex = ref(0) // 当前选中的k线
121
+
122
+ const chartData = ref({}) // 图表数据
123
+ const warningLineData = ref([]) // 预警线数据
124
+
125
+ const menuData = ref([{ label: "画线预警", key: "drawWarningLine" }]);
126
+
127
+ const config = computed(() => {
128
+ return {
129
+ defaultShowCounts: 500, // 默认展示条数
130
+ addCounts: 2000, // 滚动加载条数
131
+ maxShowCounts: 5000, // 单页最大展示条数
132
+ loadCheckCounts: 500, // 滚动加载检测的条数
133
+ showSubChart: true, // 是否展示副图
134
+ gridLeft: 80, // 主图左侧距离
135
+ gridRight: 50, // 主图右侧距离
136
+ showWarningLine: true, // 是否展示预警线
137
+ getFactorData: true, // 是否获取因子数据
138
+ ...props.config,
139
+ }
140
+ })
141
+
142
+ watch(
143
+ () => [
144
+ props.variety, props.cycle, props.mainIndicator, subIndicator.value,
145
+ indicatorStore.filterIndicator, indicatorStore.customIndicator
146
+ ],
147
+ () => {
148
+ getMainData()
149
+ },
150
+ { deep: true }
151
+ )
152
+
153
+ onMounted(() => {
154
+ getMainData()
155
+ })
156
+
157
+ onUnmounted(() => {
158
+ mainChartIns?.off("datazoom")
159
+ mainChartIns?.off("highlight")
160
+ mainChartIns?.off("globalout")
161
+ mainChartIns?.dispose()
162
+ resizeRo?.dispose()
163
+ })
164
+
165
+ // 初始化图表
166
+ const initChart = () => {
167
+ if (mainChartIns) return
168
+ mainChartIns = echarts.init(klineBasicMainRef.value)
169
+ addEventListener()
170
+ if (config.value.showSubChart) {
171
+ klineSubRef.value.connect(mainChartIns)
172
+ }
173
+ resizeRo = addResizeListener(klineBasicMainRef.value)
174
+ resizeRo.listen(() => {
175
+ requestAnimationFrame(() => {
176
+ mainChartIns.resize()
177
+ })
178
+ })
179
+ }
180
+ // 图表事件
181
+ const addEventListener = () => {
182
+ // datazoom事件
183
+ mainChartIns?.on("datazoom", (params) => {
184
+ clearTimeout(mainDataZoomTimer);
185
+ mainDataZoomTimer = setTimeout(() => {
186
+ const { loadCheckCounts } = config.value;
187
+ if (mainChartIns?.getOption()?.dataZoom?.[0]) {
188
+ const { startValue } = mainChartIns?.getOption()?.dataZoom?.[0];
189
+ // 加载历史数据
190
+ if (startValue < loadCheckCounts && isLoadHistory === false && isloadAllHistory === false) {
191
+ // 左侧数据小于检测条数,加载左侧数据
192
+ isLoadHistory = true;
193
+ getMoreData('history');
194
+ }
195
+ drawLine()
196
+ }
197
+ clearTimeout(mainDataZoomTimer);
198
+ }, 100);
199
+ });
200
+ // 高亮事件
201
+ mainChartIns?.on("highlight", (data) => {
202
+ let index = data.dataIndex || -1;
203
+ if (data.batch) {
204
+ index = typeof data?.batch[0]?.dataIndex === "number" ? data?.batch[0]?.dataIndex : -1;
205
+ }
206
+ clearTimeout(highlightTimer);
207
+ highlightTimer = setTimeout(() => {
208
+ activeIndex.value = index;
209
+ clearTimeout(highlightTimer);
210
+ }, 20);
211
+ });
212
+ // 移出图表事件
213
+ mainChartIns?.on("globalout", () => {
214
+ const index = mainChartIns?.getOption()?.dataZoom?.[0]?.endValue;
215
+ activeIndex.value = index;
216
+ });
217
+ // 右键点击事件
218
+ // let echartsContextMenuTimer = null;
219
+ // mainChart?.on("contextmenu", (params) => {
220
+ // echartsContextMenuTimer = setTimeout(() => {
221
+ // if (params.componentType === "graphic") {
222
+ // warningItem.value = params.info;
223
+ // menuData.value = [
224
+ // { label: "删除画线", key: "delete" },
225
+ // { label: "修改画线", key: "change" },
226
+ // ];
227
+ // }
228
+ // clearTimeout(echartsContextMenuTimer);
229
+ // echartsContextMenuTimer = null;
230
+ // });
231
+ // });
232
+ };
233
+
234
+ const getMainData = async () => {
235
+ if (!props.variety || !props.cycle) return
236
+ const {
237
+ variety, featureId, cycle, indicatorStore, mainIndicator, right, startTime, endTime,
238
+ } = props
239
+ const { defaultShowCounts, addCounts, showWarningLine, getFactorData } = config.value
240
+ const params = {
241
+ variety,
242
+ featureId,
243
+ cycle,
244
+ mainIndicatorList: indicatorStore.getIndicatorParams(mainIndicator),
245
+ subIndicator: subIndicator.value,
246
+ right,
247
+ showWarningLine,
248
+ getFactorData,
249
+ }
250
+ if (startTime && endTime) {
251
+ // 开始时间+结束时间
252
+ params.startTime = startTime
253
+ params.endTime = endTime
254
+ } else if (startTime) {
255
+ // 开始时间
256
+ params.startTime = startTime
257
+ params.limit = defaultShowCounts + addCounts
258
+ } else if (endTime) {
259
+ // 结束时间
260
+ params.endTime = endTime
261
+ params.limit = defaultShowCounts + addCounts
262
+ } else {
263
+ // 未传入时间,使用最新时间作为结束时间请求数据
264
+ params.endTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
265
+ params.limit = defaultShowCounts + addCounts
266
+ }
267
+ const res = await getKlineBasic(params)
268
+ chartData.value = res?.body?.kline
269
+ warningLineData.value = res?.body?.warningLine || []
270
+ draw()
271
+ drawLine()
272
+ if (getFactorData) {
273
+ emit('getFactorData', res?.body?.factorData?.filter(i => i.freqId === cycle))
274
+ }
275
+ }
276
+
277
+ // 加载历史/未来数据
278
+ const getMoreData = async (type) => {
279
+ const { variety, cycle, indicatorStore, mainIndicator, right } = props
280
+ const { addCounts } = config.value
281
+ const { time } = chartData.value
282
+ if (type === 'history') {
283
+ // 加载历史数据
284
+ const res = await getKline({
285
+ variety,
286
+ cycle,
287
+ endTime: time[0],
288
+ limit: addCounts,
289
+ mainIndicatorList: indicatorStore.getIndicatorParams(mainIndicator),
290
+ subIndicator: subIndicator.value,
291
+ right,
292
+ })
293
+ // 合并数据
294
+ chartData.value = {
295
+ time: [ ...res.body.time, ...chartData.value.time.slice(1) ],
296
+ data: [ ...res.body.data, ...chartData.value.data.slice(1) ],
297
+ mainIndicator: chartData.value.mainIndicator.map((item, index) => {
298
+ return {
299
+ ...item,
300
+ data: [ ...res.body.mainIndicator[index].data, ...item.data.slice(1) ],
301
+ }
302
+ }),
303
+ subIndicator: chartData.value.subIndicator.map((item, index) => {
304
+ return {
305
+ ...item,
306
+ data: [ ...res.body.subIndicator[index].data, ...item.data.slice(1) ],
307
+ }
308
+ }),
309
+ }
310
+ // 绘制
311
+ draw(true)
312
+ // 判断是否加载完全部数据
313
+ if (res.body.data.length < addCounts) {
314
+ isloadAllHistory = true;
315
+ }
316
+ isLoadHistory = false;
317
+ } else {
318
+ // 加载未来数据
319
+ }
320
+ }
321
+
322
+ const draw = (keepDataZoom = false) => {
323
+ initChart()
324
+ const { data, time } = chartData.value
325
+ const { gridRight, gridLeft, defaultShowCounts, maxShowCounts, showSubChart } = config.value
326
+ let startValue = data.length - 1 - defaultShowCounts
327
+ let endValue = data.length - 1
328
+ // 保持缩放位置
329
+ if (keepDataZoom) {
330
+ const originOption = mainChartIns.getOption()
331
+ const originTime = originOption?.xAxis?.[0]?.data
332
+ const originDataZoom = originOption?.dataZoom?.[0]
333
+ const originStartTime = originTime[originDataZoom?.startValue]
334
+ const originEndTime = originTime[originDataZoom?.endValue]
335
+ startValue = time.findIndex((item) => item === originStartTime)
336
+ endValue = time.findIndex((item) => item === originEndTime)
337
+ }
338
+ mainChartIns.setOption({
339
+ animation: false,
340
+ grid: {
341
+ top: '48px',
342
+ right: `${gridRight}px`,
343
+ bottom: showSubChart ? '6px' : '24px',
344
+ left: `${gridLeft}px`,
345
+ },
346
+ dataZoom: [
347
+ {
348
+ type: "inside",
349
+ startValue,
350
+ endValue,
351
+ maxValueSpan: maxShowCounts,
352
+ },
353
+ ],
354
+ tooltip: {
355
+ trigger: "axis",
356
+ appendToBody: true,
357
+ confine: true,
358
+ axisPointer: {
359
+ type: "cross",
360
+ label: {
361
+ rich: {},
362
+ formatter: (data) => {
363
+ const { axisDimension, value } = data;
364
+ if (axisDimension === "x") {
365
+ return showSubChart ? "" : value;
366
+ } else {
367
+ return String(round(value));
368
+ }
369
+ },
370
+ },
371
+ },
372
+ formatter: () => "",
373
+ },
374
+ xAxis: {
375
+ show: showSubChart ? false : true,
376
+ type: "category",
377
+ data: time,
378
+ splitLine: {
379
+ show: false,
380
+ },
381
+ },
382
+ yAxis: {
383
+ type: "value",
384
+ axisLine: {
385
+ show: true,
386
+ },
387
+ splitLine: {
388
+ show: true,
389
+ lineStyle: {
390
+ type: "dotted",
391
+ color: "#333",
392
+ },
393
+ },
394
+ min: (value) => round(value.min),
395
+ max: (value) => round(value.max),
396
+ },
397
+ series: [
398
+ {
399
+ type: "candlestick",
400
+ data,
401
+ itemStyle: {
402
+ color: "transparent",
403
+ color0: "#00FFFF",
404
+ borderColor: "#FF0000",
405
+ borderColor0: "#00FFFF",
406
+ borderWidth: 1,
407
+ },
408
+ },
409
+ ...chartData.value.mainIndicator.map((item) => {
410
+ return {
411
+ name: item.key,
412
+ type: 'line',
413
+ silent: true,
414
+ symbol: 'none',
415
+ data: item.data,
416
+ lineStyle: {
417
+ width: item.width || 1,
418
+ },
419
+ itemStyle: {
420
+ color: item.color,
421
+ }
422
+ }
423
+ })
424
+ ],
425
+ }, true)
426
+ activeIndex.value = endValue
427
+ if (showSubChart) {
428
+ klineSubRef.value.draw(
429
+ { startValue, endValue, maxValueSpan: maxShowCounts },
430
+ { gridLeft, gridRight }
431
+ )
432
+ }
433
+ }
434
+
435
+ // 绘制线
436
+ const drawLine = () => {
437
+ if (!mainChartIns) return;
438
+ const mainChartOption = mainChartIns?.getOption();
439
+ if (!mainChartOption) return;
440
+ mainChartIns?.setOption(
441
+ {
442
+ ...mainChartOption,
443
+ graphic: [
444
+ ...getWarningLineOptions(mainChartIns, warningLineData.value, props, config.value, (newWarningLineData) => {
445
+ warningLineData.value = newWarningLineData;
446
+ drawLine()
447
+ emit('change', 'warningLine', newWarningLineData);
448
+ })
449
+ ],
450
+ },
451
+ true
452
+ );
453
+ }
454
+
455
+ const menuClick = (item) => {
456
+ const { variety, varietyName, featureId, featureType } = props
457
+ if (item.key === 'drawWarningLine') {
458
+ // 画线预警
459
+ // 拿到当前主图配置项
460
+ const mainChartOption = mainChartIns?.getOption();
461
+ const oldTooltip = mainChartOption.tooltip[0];
462
+ mainChartIns?.setOption({
463
+ ...mainChartOption,
464
+ // 指示器样式
465
+ tooltip: {
466
+ ...oldTooltip,
467
+ // 坐标轴指示器
468
+ axisPointer: {
469
+ // 保留原有部分配置
470
+ ...oldTooltip.axisPointer,
471
+ // X轴指示线的宽度
472
+ lineStyle: {
473
+ width: 0,
474
+ },
475
+ // Y轴指示线的宽度
476
+ crossStyle: {
477
+ width: 2,
478
+ },
479
+ // 文本标签
480
+ label: {
481
+ // 保留原有部分配置
482
+ ...oldTooltip.axisPointer.label,
483
+ // 颜色改为透明
484
+ backgroundColor: "transparent",
485
+ // 仅显示Y轴值
486
+ formatter: (data) => "",
487
+ },
488
+ },
489
+ },
490
+ });
491
+ // 编写点击事件:获取到数据发送给后端
492
+ const handleClick = async (el) => {
493
+ // (1).在触发点击事件后,第一时间将图表绑定的点击事件清除
494
+ mainChartIns?.getZr().off("mousedown", handleClick);
495
+ // (2).根据点击位置获取到Y轴具体数据
496
+ const yAxisValue = mainChartIns?.convertFromPixel({ yAxisIndex: 0 }, el.offsetY);
497
+ // (3).格式化画线预警价格
498
+ const newWarnPrice = Math.round(yAxisValue * 1000) / 1000;
499
+ // (4).将指示器恢复成原始样式
500
+ mainChartIns?.setOption({
501
+ ...mainChartOption,
502
+ // 指示器样式
503
+ tooltip: {
504
+ ...oldTooltip,
505
+ axisPointer: {
506
+ ...oldTooltip.axisPointer,
507
+ lineStyle: {
508
+ width: 1,
509
+ },
510
+ crossStyle: {
511
+ width: 1,
512
+ },
513
+ label: {
514
+ ...oldTooltip.axisPointer.label,
515
+ backgroundColor: null,
516
+ },
517
+ },
518
+ },
519
+ });
520
+ // (6).发送新增预警线请求
521
+ await addWarningLine({
522
+ featureCode: variety, //品种代码
523
+ featureName: varietyName, //品种名称
524
+ featureId, //品种id
525
+ featureType, //品种类型
526
+ warnPrice: newWarnPrice,
527
+ });
528
+ ElMessage.success("画线预警成功!");
529
+ };
530
+ // 4.绑定echarts点击事件
531
+ mainChartIns?.getZr().on("mousedown", handleClick);
532
+ }
533
+ }
534
+
535
+ defineExpose({
536
+ draw(type, data) {
537
+ if (type === 'warningLine') {
538
+ warningLineData.value = data;
539
+ drawLine()
540
+ }
541
+ }
542
+ })
543
+ </script>
544
+
545
+ <style lang="scss" scoped>
546
+ .klineBasic {
547
+ width: 100%;
548
+ height: 100%;
549
+ position: relative;
550
+ background: #000;
551
+ &-tips {
552
+ position: absolute;
553
+ width: 100%;
554
+ top: 0;
555
+ }
556
+ &-main {
557
+ width: 100%;
558
+ height: 70%;
559
+ }
560
+ &-sub {
561
+ width: 100%;
562
+ height: 30%;
563
+ }
564
+ }
565
+ </style>
@@ -0,0 +1,86 @@
1
+ import { stMath } from "st-func";
2
+ import { updateWarningLine, getWarningLine } from './api'
3
+
4
+ const { round } = stMath;
5
+
6
+ export const getWarningLineOptions = (mainChartIns, warningLineData, props, config, callback) => {
7
+ const { variety, featureId, featureType } = props
8
+ const { gridLeft, gridRight } = config;
9
+ return warningLineData.map((item) => {
10
+ const { warnPrice } = item;
11
+ const y = mainChartIns?.convertToPixel({ yAxisIndex: 0 }, warnPrice)
12
+ let dragStart = 0; // 记录拖拽开始的位置
13
+ return {
14
+ type: "group",
15
+ name: "warningLine",
16
+ info: item,
17
+ draggable: "vertical",
18
+ children: [
19
+ {
20
+ type: "line",
21
+ info: item,
22
+ shape: {
23
+ x1: gridLeft, // 开始X坐标
24
+ y1: y, // 开始Y坐标
25
+ x2: mainChartIns?.getWidth() - gridRight, // 结束X坐标
26
+ y2: y, // 结束Y坐标
27
+ },
28
+ style: {
29
+ stroke: "#FFF",
30
+ lineWidth: 1,
31
+ lineDash: [8, 4],
32
+ },
33
+ z: 10,
34
+ },
35
+ {
36
+ type: "text",
37
+ info: item,
38
+ x: mainChartIns?.getWidth() - gridRight,
39
+ y: y - 5,
40
+ style: {
41
+ fill: "#FFF",
42
+ text: warnPrice,
43
+ stroke: "#000",
44
+ lineWidth: 1,
45
+ opacity: 1,
46
+ },
47
+ z: 10,
48
+ },
49
+ ],
50
+ // 事件:开始拖拽
51
+ ondragstart: (params) => {
52
+ dragStart = params.offsetY; // 记录拖拽开始坐标
53
+ },
54
+ ondrag: params => {
55
+ if (params.target && params.target.childAt(1)) {
56
+ const newValue = mainChartIns.convertFromPixel({ yAxisIndex: 0 }, y + (params.offsetY - dragStart))
57
+ params.target.childAt(1)?.animate('style', false).when(1, { text: round(newValue, 3) }).start()
58
+ }
59
+ },
60
+ // 事件:结束拖拽
61
+ ondragend: async (params) => {
62
+ /**
63
+ * 之所以不直接使用dragEnd,是因为echarts拖拽会有偏差问题
64
+ * 需要使用偏移量才会更加准备,不然会出现画完线渲染位置和拖拽位置不一致
65
+ */
66
+ const dragEnd = params.offsetY; // 记录结束拖拽坐标
67
+ const dragInterval = dragEnd - dragStart; // 拖拽偏移量
68
+ if (dragInterval !== 0) {
69
+ // 计算偏移后对应的Y轴数据
70
+ const yAxisValue = mainChartIns?.convertFromPixel({ yAxisIndex: 0 }, dragInterval + y);
71
+ const params = {
72
+ id: item.id,
73
+ warnPrice: round(yAxisValue, 3),
74
+ featureId, //品种id
75
+ featureCode: variety, //品种代码
76
+ featureType, //品种类型
77
+ };
78
+ await updateWarningLine(params);
79
+ ElMessage.success("画线预警修改成功");
80
+ const res = await getWarningLine({ featureId })
81
+ callback && callback(res?.body || []);
82
+ }
83
+ },
84
+ };
85
+ })
86
+ };
@@ -268,7 +268,7 @@ const handleDeleteTag = (aciton, index) => {
268
268
  >
269
269
  <!-- 序列号 -->
270
270
  <span class="index">{{ `条件${index + 1}` }}</span>
271
- <!-- 对比因子 -->
271
+ <!-- 对比因子: 分值因子 -->
272
272
  <template v-if="item.key === 'compare'">
273
273
  <!-- 周期 -->
274
274
  <el-form-item
@@ -304,7 +304,7 @@ const handleDeleteTag = (aciton, index) => {
304
304
  no-match-text="无匹配数据"
305
305
  >
306
306
  <el-option
307
- v-for="{ label, value } in config.factorOptions"
307
+ v-for="{ label, value } in config.factorOptions?.filter((item) => [4].includes(item.type))"
308
308
  :label="label"
309
309
  :value="value"
310
310
  :key="value"
@@ -359,7 +359,7 @@ const handleDeleteTag = (aciton, index) => {
359
359
  no-match-text="无匹配数据"
360
360
  >
361
361
  <el-option
362
- v-for="{ label, value } in config.factorOptions"
362
+ v-for="{ label, value } in config.factorOptions?.filter((item) => [4].includes(item.type))"
363
363
  :label="label"
364
364
  :value="value"
365
365
  :key="value"
@@ -367,7 +367,7 @@ const handleDeleteTag = (aciton, index) => {
367
367
  </el-select>
368
368
  </el-form-item>
369
369
  </template>
370
- <!-- 常规因子 -->
370
+ <!-- 常规因子: 机器打分, 人工打分因子 -->
371
371
  <template v-else>
372
372
  <!-- 周期 -->
373
373
  <el-form-item
@@ -403,7 +403,7 @@ const handleDeleteTag = (aciton, index) => {
403
403
  no-match-text="无匹配数据"
404
404
  >
405
405
  <el-option
406
- v-for="{ label, value } in config.factorOptions"
406
+ v-for="{ label, value } in config.factorOptions?.filter((item) => [1, 3].includes(item.type))"
407
407
  :label="label"
408
408
  :value="value"
409
409
  :key="value"
@@ -496,10 +496,10 @@ const handleDeleteTag = (aciton, index) => {
496
496
  </template>
497
497
  </el-dialog>
498
498
  </div>
499
- <!-- 因子说明 -->
499
+ <!-- 因子说明: 机器打分, 人工打分因子 -->
500
500
  <FactorDescription
501
501
  v-model:visible="visibleDescriptions"
502
- :data="config.factorDescriptions"
502
+ :data="config.factorDescriptions?.filter((item) => [1, 3].includes(item.type))"
503
503
  />
504
504
  </template>
505
505