st-comp 0.0.21 → 0.0.23

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.
@@ -1,466 +1,528 @@
1
1
  <!-- 单品种单周期K线组件-Demo -->
2
2
  <script setup lang="ts">
3
- import { RefreshRight } from '@element-plus/icons-vue'
4
- import { ref, onMounted, onUnmounted, computed, watch } from 'vue'
5
- import dayjs from 'dayjs'
6
- import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'
7
- import { ElMessage } from 'element-plus'
8
- import 'element-plus/dist/index.css'
9
- import { formatValue } from '../../../../packages/Kline/utils'
10
- import { getSingleCycleSingleVariety, getDict } from '../api.ts'
11
- import { mainIndicatorList } from 'st-func'
3
+ import { RefreshRight } from "@element-plus/icons-vue";
4
+ import { ref, onMounted, onUnmounted, computed, watch } from "vue";
5
+ import dayjs from "dayjs";
6
+ import isSameOrAfter from "dayjs/plugin/isSameOrAfter";
7
+ import { ElMessage } from "element-plus";
8
+ import "element-plus/dist/index.css";
9
+ import { formatValue } from "../../../../packages/Kline/utils";
10
+ import { getSingleCycleSingleVariety, getDict } from "../api.ts";
11
+ import { mainIndicatorList } from "st-func";
12
12
 
13
- dayjs.extend(isSameOrAfter)
13
+ dayjs.extend(isSameOrAfter);
14
14
 
15
- const props = defineProps({
16
- deBugValue: {
17
- type: Number,
18
- },
19
- })
15
+ const props = defineProps({
16
+ deBugValue: {
17
+ type: Number,
18
+ },
19
+ });
20
20
 
21
- const loading = ref(true)
22
- const netWorkErrorMsg = ref('')
21
+ const loading = ref(true);
22
+ const netWorkErrorMsg = ref("");
23
23
 
24
- // 筛选条件相关参数
25
- const cycle = ref<any>('2')
26
- const cycleName = computed(() => {
27
- if (cycleOptions.value.length > 0) {
28
- return cycleOptions.value.find((item: any) => item.value === cycle.value).label
29
- }
30
- return null
31
- })
32
- const cycleOptions = ref<any>([]) // 周期下拉框数据
24
+ // 筛选条件相关参数
25
+ const cycle = ref<any>("2");
26
+ const cycleName = computed(() => {
27
+ if (cycleOptions.value.length > 0) {
28
+ return cycleOptions.value.find((item: any) => item.value === cycle.value).label;
29
+ }
30
+ return null;
31
+ });
32
+ const cycleOptions = ref<any>([]); // 周期下拉框数据
33
33
 
34
- const indicator = computed(() => {
35
- if (mainIndicatorList.length > 0) {
36
- return mainIndicatorList.find((item: any) => item.value === indicatorName.value)
37
- }
38
- return null
39
- })
40
- const indicatorName = ref<any>('DKX_EMA')
34
+ const indicator = computed(() => {
35
+ if (mainIndicatorList.length > 0) {
36
+ return mainIndicatorList.find((item: any) => item.value === indicatorName.value);
37
+ }
38
+ return null;
39
+ });
40
+ const indicatorName = ref<any>("DKX_EMA");
41
41
 
42
- const sellBuyType = ref(1)
43
- const sellBuyTypeName = computed(() => {
44
- if (sellBuyTypeOptions.value.length > 0) {
45
- return sellBuyTypeOptions.value.find((item: any) => item.value === sellBuyType.value).label
46
- }
47
- return null
48
- })
49
- const sellBuyTypeOptions = ref<any>([
50
- { label: '开平', value: 1 },
51
- { label: '买卖', value: 2 },
52
- ])
42
+ const sellBuyType = ref(1);
43
+ const sellBuyTypeName = computed(() => {
44
+ if (sellBuyTypeOptions.value.length > 0) {
45
+ return sellBuyTypeOptions.value.find((item: any) => item.value === sellBuyType.value).label;
46
+ }
47
+ return null;
48
+ });
49
+ const sellBuyTypeOptions = ref<any>([
50
+ { label: "开平", value: 1 },
51
+ { label: "买卖", value: 2 },
52
+ ]);
53
53
 
54
- // 接口原生-点位数据
55
- const originPointData = ref<any>([])
54
+ // 接口原生-点位数据
55
+ const originPointData = ref<any>([]);
56
56
 
57
- // K线组件入参
58
- const klineData = ref<any>([])
59
- const markData = ref<any>([])
60
- const lineData = ref<any>([])
61
- const brushRange = ref<any>(['2024-01-04 10:10:00', '2024-01-04 21:40:00'])
62
- const defaultMenuData = ref([
63
- {
64
- label: '画线预警',
65
- callBack: (echartsInstance: any, cursorPenVisible: any) => createWarning(echartsInstance, cursorPenVisible),
57
+ // K线组件入参
58
+ const isSelect = ref(false);
59
+ const klineData = ref<any>([]);
60
+ const markData = ref<any>([]);
61
+ const lineData = ref<any>([]);
62
+ const brushRange = ref<any>(["2024-01-04 10:10:00", "2024-01-04 21:40:00"]);
63
+ const defaultMenuData = ref([
64
+ {
65
+ label: "画线预警",
66
+ callBack: (echartsInstance: any, cursorPenVisible: any) => createWarning(echartsInstance, cursorPenVisible),
67
+ },
68
+ ]);
69
+ const config = ref({
70
+ totalBarCount: 2000,
71
+ preBarCount: 100,
72
+ tipsConfig: {
73
+ open: true,
74
+ heigh: true,
75
+ low: true,
76
+ close: true,
77
+ business: false,
78
+ riseAndFall: true,
79
+ },
80
+ dynamicLoadConfig: {
81
+ historyVisible: true,
82
+ historyLoadCallBack: async (historyIsAllLoad: any) => {
83
+ const { totalBarCount, preBarCount } = config.value;
84
+ // 1.如果当前K线数据量就小于API希望得到的数量,说明已经没有数据了,将API得到的数据作全部展示
85
+ // 并且打上标记,此K线数据已无更多
86
+ if (klineData.value.length < totalBarCount + preBarCount) {
87
+ config.value.totalBarCount = klineData.value.length;
88
+ console.log('K线数据已无更多-1')
89
+ historyIsAllLoad.value = true;
90
+ return;
91
+ }
92
+ // 2.已当前存储的K线数据第一条时间作为结束时间,往前再次请求
93
+ const params = {
94
+ right: 1, // 复权方式
95
+ variety: "au8888", // 品种
96
+ cycle: cycle.value, // 周期
97
+ endTime: klineData.value[0][0], // 结束时间
98
+ limit: 2000, // 总条数
99
+ queryType: 1, // 0-按时间,1-按结束时间,2-按开始时间
100
+ };
101
+ const res = await getSingleCycleSingleVariety(params);
102
+ const apiData = res.data.body.slice(0, res.data.body.length - 1)
103
+ klineData.value = [...apiData, ...klineData.value];
104
+ config.value.totalBarCount = config.value.totalBarCount + apiData.length;
105
+ // 3.如果请求到的数据量小于期望的条数,或者当前数据总根数大于限制的10000条数
106
+ // 也打上标记,此K线数据已无更多
107
+ if (apiData.length < 2000 - 1 || config.value.totalBarCount > 6000) {
108
+ console.log('K线数据已无更多-2')
109
+ historyIsAllLoad.value = true;
110
+ }
66
111
  },
67
- ])
68
- const config = ref({
69
- totalBarCount: 1900,
70
- preBarCount: 100,
71
- tipsConfig: {
72
- open: true,
73
- heigh: true,
74
- low: true,
75
- close: true,
76
- business: false,
77
- riseAndFall: true
78
- }
79
- })
112
+ futureVisible: true,
113
+ futureLoadCallBack: async (futureIsAllLoad: any) => {
114
+ const { totalBarCount, preBarCount } = config.value;
115
+ // 1.如果当前K线数据量就小于API希望得到的数量,说明已经没有数据了,将API得到的数据作全部展示
116
+ // 并且打上标记,此K线数据已无更多
117
+ if (klineData.value.length < totalBarCount + preBarCount) {
118
+ config.value.totalBarCount = klineData.value.length;
119
+ console.log('K线数据已无更多-1')
120
+ futureIsAllLoad.value = true;
121
+ return;
122
+ }
123
+ // 2.已当前存储的K线数据最后一条时间作为开始时间,往后再次请求
124
+ const params = {
125
+ right: 1, // 复权方式
126
+ variety: "au8888", // 品种
127
+ cycle: cycle.value, // 周期
128
+ startTime: klineData.value[klineData.value.length - 1][0], // 开始
129
+ limit: 20, // 总条数
130
+ queryType: 2, // 0-按时间,1-按结束时间,2-按开始时间
131
+ };
132
+ const res = await getSingleCycleSingleVariety(params);
133
+ const apiData = res.data.body.slice(1); // 取掉重复数据
134
+ klineData.value = [...klineData.value, ...apiData];
135
+ config.value.totalBarCount = config.value.totalBarCount + apiData.length;
136
+ // 3.如果请求到的数据量小于期望的条数,或者当前数据总根数大于限制的10000条数
137
+ // 也打上标记,此K线数据已无更多
138
+ if (apiData.length < 20 - 1 || config.value.totalBarCount > 6000) {
139
+ console.log('K线数据已无更多-2')
140
+ futureIsAllLoad.value = true;
141
+ }
142
+ },
143
+ },
144
+ });
80
145
 
81
- onMounted(() => {
82
- console.log('---------单品种单周期组件: onMounted挂载成功---------')
83
- })
146
+ onMounted(() => {
147
+ console.log("---------单品种单周期组件: onMounted挂载成功---------");
148
+ });
84
149
 
85
- // 初始化
86
- const componentInit = async () => {
87
- try {
88
- loading.value = true
89
- await getDictCycle()
90
- await getKlineData()
91
- await getKlinePointData()
92
- loading.value = false
93
- await getKlineExtendData()
94
- } catch (error) {
95
- console.log(error)
96
- } finally {
97
- loading.value = false
98
- }
150
+ // 初始化
151
+ const componentInit = async () => {
152
+ try {
153
+ loading.value = true;
154
+ await getDictCycle();
155
+ await getKlineData();
156
+ await getKlinePointData();
157
+ loading.value = false;
158
+ await getKlineExtendData();
159
+ } catch (error) {
160
+ console.log(error);
161
+ } finally {
162
+ loading.value = false;
99
163
  }
164
+ };
100
165
 
101
- /**
102
- * @description: 获取通用字典[周期]
103
- */
104
- const getDictCycle = async () => {
105
- const params = {
106
- dictIds: [1002],
107
- }
108
- const res = await getDict(params)
109
- cycleOptions.value = res.data.body[1002].map((item: any) => {
110
- return {
111
- label: item.dictName,
112
- value: item.dictCode,
113
- data: item,
114
- }
115
- })
116
- }
117
- /**
118
- * @description: 获取K线数据
119
- */
120
- const getKlineData = async () => {
121
- const params = {
122
- right: 1, // 复权方式
123
- variety: 'au8888', // 品种
124
- cycle: cycle.value, // 周期
125
- endTime: '2024-01-04 23:59:59', // 结束时间
126
- limit: config.value.totalBarCount + config.value.preBarCount, // 总条数
127
- queryType: 1, // 0-按时间,1-按结束时间,2-按开始时间
128
- }
129
- const res = await getSingleCycleSingleVariety(params)
130
- klineData.value = res.data.body
131
- }
132
- /**
133
- * @description: 获取点位数据
134
- * @todo: 1.获取点位接口数据 2.格式化处理[数据合并,匹配K线时间轴] 建议分开,此处demo所以简写
135
- */
136
- const getKlinePointData = async () => {
137
- const resultApi = [
138
- {
139
- key: 'sellBuy',
140
- data: [
141
- {
142
- tradeAction: '', // 交易动作
143
- direction: '', // 交易方向
144
- tradeType: '开多', // 交易类型
145
- amount: 2, // 手数
146
- part: 2, // 份数
147
- time: '2024-01-04 22:30:00', // 交易时间
148
- tooltip: '<div>买卖点1</div>',
149
- },
150
- {
151
- tradeAction: '', // 交易动作
152
- direction: '', // 交易方向
153
- tradeType: '平空', // 交易类型
154
- amount: 2, // 手数
155
- part: 2, // 份数
156
- time: '2024-01-04 22:40:00', // 交易时间
157
- tooltip: '<div>买卖点2</div>',
158
- },
159
- {
160
- tradeAction: '', // 交易动作
161
- direction: '', // 交易方向
162
- tradeType: '开空', // 交易类型
163
- amount: 2, // 手数
164
- part: 2, // 份数
165
- time: '2024-01-04 23:50:00', // 交易时间
166
- tooltip: '<div>买卖点3</div>',
167
- },
168
- ],
169
- },
170
- {
171
- key: 'openClose',
172
- data: [
173
- {
174
- tradeAction: '', // 交易动作
175
- direction: '', // 交易方向
176
- tradeType: '开多', // 交易类型
177
- amount: 2, // 手数
178
- part: 2, // 份数
179
- time: '2024-01-04 22:30:00', // 交易时间
180
- tooltip: '<div>开平点1</div>',
181
- },
182
- {
183
- tradeAction: '平', // 交易动作
184
- direction: '空', // 交易方向
185
- tradeType: '平空', // 交易类型
186
- amount: 2, // 手数
187
- part: 2, // 份数
188
- time: '2024-01-04 22:40:00', // 交易时间
189
- tooltip: '<div>开平点2</div>',
190
- },
191
- {
192
- tradeAction: '开', // 交易动作
193
- direction: '空', // 交易方向
194
- tradeType: '开空', // 交易类型
195
- amount: 2, // 手数
196
- part: 2, // 份数
197
- time: '2024-01-04 23:50:00', // 交易时间
198
- tooltip: '<div>买卖点3</div>',
199
- },
200
- ],
201
- },
202
- {
203
- key: 'signal',
204
- data: [],
205
- },
206
- ]
207
- // 进行时间轴匹配
208
- const klineTimeAry = klineData.value.map((item: any) => item[0])
209
- originPointData.value = resultApi.reduce((result: any, next) => {
210
- const { data } = next
211
- result.push({
212
- key: next.key,
213
- data: data.map((item: any) => {
214
- const time = klineTimeAry.find((klineTime: string) => dayjs(klineTime).isSameOrAfter(item.time))
215
- return {
216
- ...item,
217
- time,
218
- }
219
- }),
220
- })
221
- return result
222
- }, [])
223
- // 判断展示开平/买卖
224
- sellBuyTypeChange()
225
- }
226
- /**
227
- * @description: 获取K线额外画线数据
228
- */
229
- const getKlineExtendData = async () => {
230
- lineData.value = [
231
- {
232
- key: 'warning',
233
- data: [
234
- {
235
- value: 479,
236
- text: 479,
237
- // 自定义信息
238
- info: {},
239
- // 自定义配置
240
- config: {
241
- draggable: true,
242
- },
243
- },
244
- ],
245
- ondragstart: (params: any, info: any) => {
246
- console.log('拖拽开始', params, info)
166
+ /**
167
+ * @description: 获取通用字典[周期]
168
+ */
169
+ const getDictCycle = async () => {
170
+ const params = {
171
+ dictIds: [1002],
172
+ };
173
+ const res = await getDict(params);
174
+ cycleOptions.value = res.data.body[1002].map((item: any) => {
175
+ return {
176
+ label: item.dictName,
177
+ value: item.dictCode,
178
+ data: item,
179
+ };
180
+ });
181
+ };
182
+ /**
183
+ * @description: 获取K线数据
184
+ */
185
+ const getKlineData = async () => {
186
+ const params = {
187
+ right: 1, // 复权方式
188
+ variety: "au8888", // 品种
189
+ cycle: cycle.value, // 周期
190
+ endTime: "2024-01-04 23:59:59", // 结束时间
191
+ limit: config.value.totalBarCount + config.value.preBarCount, // 总条数
192
+ queryType: 1, // 0-按时间,1-按结束时间,2-按开始时间
193
+ };
194
+ const res = await getSingleCycleSingleVariety(params);
195
+ klineData.value = res.data.body;
196
+ };
197
+ /**
198
+ * @description: 获取点位数据
199
+ * @todo: 1.获取点位接口数据 2.格式化处理[数据合并,匹配K线时间轴] 建议分开,此处demo所以简写
200
+ */
201
+ const getKlinePointData = async () => {
202
+ const resultApi = [
203
+ {
204
+ key: "sellBuy",
205
+ data: [
206
+ {
207
+ tradeAction: "", // 交易动作
208
+ direction: "", // 交易方向
209
+ tradeType: "开多", // 交易类型
210
+ amount: 2, // 手数
211
+ part: 2, // 份数
212
+ time: "2024-01-04 22:30:00", // 交易时间
213
+ tooltip: "<div>买卖点1</div>",
214
+ },
215
+ {
216
+ tradeAction: "", // 交易动作
217
+ direction: "", // 交易方向
218
+ tradeType: "平空", // 交易类型
219
+ amount: 2, // 手数
220
+ part: 2, // 份数
221
+ time: "2024-01-04 22:40:00", // 交易时间
222
+ tooltip: "<div>买卖点2</div>",
223
+ },
224
+ {
225
+ tradeAction: "", // 交易动作
226
+ direction: "", // 交易方向
227
+ tradeType: "开空", // 交易类型
228
+ amount: 2, // 手数
229
+ part: 2, // 份数
230
+ time: "2024-01-04 23:50:00", // 交易时间
231
+ tooltip: "<div>买卖点3</div>",
232
+ },
233
+ ],
234
+ },
235
+ {
236
+ key: "openClose",
237
+ data: [
238
+ {
239
+ tradeAction: "", // 交易动作
240
+ direction: "", // 交易方向
241
+ tradeType: "开多", // 交易类型
242
+ amount: 2, // 手数
243
+ part: 2, // 份数
244
+ time: "2024-01-04 22:30:00", // 交易时间
245
+ tooltip: "<div>开平点1</div>",
247
246
  },
248
- ondragend: (params: any, info: any, yAxisValue: number) => {
249
- console.log('拖拽结束', params, info, yAxisValue)
250
- ElMessage.success('预警线修改更新成功!')
247
+ {
248
+ tradeAction: "平", // 交易动作
249
+ direction: "空", // 交易方向
250
+ tradeType: "平空", // 交易类型
251
+ amount: 2, // 手数
252
+ part: 2, // 份数
253
+ time: "2024-01-04 22:40:00", // 交易时间
254
+ tooltip: "<div>开平点2</div>",
251
255
  },
252
- oncontextmenu: (params: any, info: any, menuData: any) => {
253
- console.log('右击了', params, info)
254
- menuData.value = [
255
- {
256
- label: '删除画线',
257
- callBack: () => ElMessage.success('预警线删除成功!'),
258
- },
259
- {
260
- label: '修改画线',
261
- callBack: () => ElMessage.success('预警线修改成功!'),
262
- },
263
- ]
256
+ {
257
+ tradeAction: "开", // 交易动作
258
+ direction: "空", // 交易方向
259
+ tradeType: "开空", // 交易类型
260
+ amount: 2, // 手数
261
+ part: 2, // 份数
262
+ time: "2024-01-04 23:50:00", // 交易时间
263
+ tooltip: "<div>买卖点3</div>",
264
264
  },
265
+ ],
266
+ },
267
+ {
268
+ key: "signal",
269
+ data: [],
270
+ },
271
+ ];
272
+ // 进行时间轴匹配
273
+ const klineTimeAry = klineData.value.map((item: any) => item[0]);
274
+ originPointData.value = resultApi.reduce((result: any, next) => {
275
+ const { data } = next;
276
+ result.push({
277
+ key: next.key,
278
+ data: data.map((item: any) => {
279
+ const time = klineTimeAry.find((klineTime: string) => dayjs(klineTime).isSameOrAfter(item.time));
280
+ return {
281
+ ...item,
282
+ time,
283
+ };
284
+ }),
285
+ });
286
+ return result;
287
+ }, []);
288
+ // 判断展示开平/买卖
289
+ sellBuyTypeChange();
290
+ };
291
+ /**
292
+ * @description: 获取K线额外画线数据
293
+ */
294
+ const getKlineExtendData = async () => {
295
+ lineData.value = [
296
+ {
297
+ key: "warning",
298
+ data: [
299
+ {
300
+ value: 479,
301
+ text: 479,
302
+ // 自定义信息
303
+ info: {},
304
+ // 自定义配置
305
+ config: {
306
+ draggable: true,
307
+ },
308
+ },
309
+ ],
310
+ ondragstart: (params: any, info: any) => {
311
+ console.log("拖拽开始", params, info);
312
+ },
313
+ ondragend: (params: any, info: any, yAxisValue: number) => {
314
+ console.log("拖拽结束", params, info, yAxisValue);
315
+ ElMessage.success("预警线修改更新成功!");
265
316
  },
266
- {
267
- key: 'position',
268
- data: [
317
+ oncontextmenu: (params: any, info: any, menuData: any) => {
318
+ console.log("右击了", params, info);
319
+ menuData.value = [
269
320
  {
270
- value: 480,
271
- text: '持仓:192.14万(1份) 数量:4手 方向:多 浮动盈亏:-1280.00',
272
- // 自定义信息
273
- info: {},
274
- // 自定义配置
275
- config: {},
321
+ label: "删除画线",
322
+ callBack: () => ElMessage.success("预警线删除成功!"),
276
323
  },
277
- ],
278
- },
279
- {
280
- key: 'condition',
281
- data: [
282
324
  {
283
- value: 482,
284
- text: '[多损][多盈] 开多↓2269 1份(22手)',
285
- profitValue: 483,
286
- profitText: '上破484',
287
- lossValue: 481,
288
- lossText: '下破482',
289
- // 自定义信息
290
- info: {},
291
- // 自定义配置
292
- config: {},
325
+ label: "修改画线",
326
+ callBack: () => ElMessage.success("预警线修改成功!"),
293
327
  },
294
- ],
328
+ ];
295
329
  },
296
- ]
297
- }
330
+ },
331
+ {
332
+ key: "position",
333
+ data: [
334
+ {
335
+ value: 480,
336
+ text: "持仓:192.14万(1份) 数量:4手 方向:多 浮动盈亏:-1280.00",
337
+ // 自定义信息
338
+ info: {},
339
+ // 自定义配置
340
+ config: {},
341
+ },
342
+ ],
343
+ },
344
+ {
345
+ key: "condition",
346
+ data: [
347
+ {
348
+ value: 482,
349
+ text: "[多损][多盈] 开多↓2269 1份(22手)",
350
+ profitValue: 483,
351
+ profitText: "上破484",
352
+ lossValue: 481,
353
+ lossText: "下破482",
354
+ // 自定义信息
355
+ info: {},
356
+ // 自定义配置
357
+ config: {},
358
+ },
359
+ ],
360
+ },
361
+ ];
362
+ };
298
363
 
299
- /**
300
- * @description: 周期切换
301
- */
302
- const cycleChange = async () => {
303
- try {
304
- loading.value = true
305
- await getKlineData()
306
- await getKlinePointData()
307
- loading.value = false
308
- } catch (error) {
309
- console.log(error)
310
- } finally {
311
- loading.value = false
312
- }
364
+ /**
365
+ * @description: 周期切换
366
+ */
367
+ const cycleChange = async () => {
368
+ try {
369
+ loading.value = true;
370
+ config.value.totalBarCount = 2000;
371
+ await getKlineData();
372
+ await getKlinePointData();
373
+ loading.value = false;
374
+ } catch (error) {
375
+ console.log(error);
376
+ } finally {
377
+ loading.value = false;
313
378
  }
379
+ };
314
380
 
315
- /**
316
- * @description: 买卖点,开平点切换
317
- */
318
- const sellBuyTypeChange = () => {
319
- if (sellBuyType.value === 1) {
320
- markData.value = originPointData.value.filter((item: any) => {
321
- return item.key !== 'sellBuy'
322
- })
323
- } else {
324
- markData.value = originPointData.value.filter((item: any) => {
325
- return item.key !== 'openClose'
326
- })
327
- }
381
+ /**
382
+ * @description: 买卖点,开平点切换
383
+ */
384
+ const sellBuyTypeChange = () => {
385
+ if (sellBuyType.value === 1) {
386
+ markData.value = originPointData.value.filter((item: any) => {
387
+ return item.key !== "sellBuy";
388
+ });
389
+ } else {
390
+ markData.value = originPointData.value.filter((item: any) => {
391
+ return item.key !== "openClose";
392
+ });
328
393
  }
394
+ };
329
395
 
330
- // 画线预警
331
- const createWarning = (echartsInstance: any, cursorPenVisible: any) => {
332
- // 1.打开画笔模式,并修改指示器样式[画预览线]
333
- cursorPenVisible.value = true
334
- const echartsOptions = echartsInstance.getOption()
335
- const oldTooltip = (echartsOptions.tooltip as Array<any>)[0]
396
+ // 画线预警
397
+ const createWarning = (echartsInstance: any, cursorPenVisible: any) => {
398
+ // 1.打开画笔模式,并修改指示器样式[画预览线]
399
+ cursorPenVisible.value = true;
400
+ const echartsOptions = echartsInstance.getOption();
401
+ const oldTooltip = (echartsOptions.tooltip as Array<any>)[0];
402
+ echartsInstance.setOption({
403
+ ...echartsOptions,
404
+ // 指示器样式
405
+ tooltip: {
406
+ ...oldTooltip,
407
+ // 坐标轴指示器
408
+ axisPointer: {
409
+ // 保留原有部分配置
410
+ ...oldTooltip.axisPointer,
411
+ // X轴指示线的宽度
412
+ lineStyle: {
413
+ width: 0,
414
+ },
415
+ // Y轴指示线的宽度
416
+ crossStyle: {
417
+ width: 2,
418
+ },
419
+ // 文本标签
420
+ label: {
421
+ // 保留原有部分配置
422
+ ...oldTooltip.axisPointer.label,
423
+ // 颜色改为透明
424
+ backgroundColor: "transparent",
425
+ // 仅显示Y轴值
426
+ formatter: (data: any) => {
427
+ const { axisDimension, value } = data;
428
+ if (axisDimension === "y") {
429
+ return String(formatValue(value));
430
+ }
431
+ return "";
432
+ },
433
+ },
434
+ },
435
+ },
436
+ });
437
+ // 2.获取当前列数据并发送请求至后端记录
438
+ const handleClick = (el: any) => {
439
+ // 关闭画笔模式,并移除echarts点击事件
440
+ cursorPenVisible.value = false;
441
+ echartsInstance.getZr().off("mousedown", handleClick);
442
+ const yAxisValue = echartsInstance.convertFromPixel({ yAxisIndex: 0 }, el.offsetY);
443
+ const newWarnPrice = Math.round(yAxisValue * 1000) / 1000;
444
+ // 3.恢复指示器样式
336
445
  echartsInstance.setOption({
337
446
  ...echartsOptions,
338
447
  // 指示器样式
339
448
  tooltip: {
340
449
  ...oldTooltip,
341
- // 坐标轴指示器
342
450
  axisPointer: {
343
- // 保留原有部分配置
344
451
  ...oldTooltip.axisPointer,
345
- // X轴指示线的宽度
346
452
  lineStyle: {
347
- width: 0,
453
+ width: 1,
348
454
  },
349
- // Y轴指示线的宽度
350
455
  crossStyle: {
351
- width: 2,
456
+ width: 1,
352
457
  },
353
- // 文本标签
354
458
  label: {
355
- // 保留原有部分配置
356
459
  ...oldTooltip.axisPointer.label,
357
- // 颜色改为透明
358
- backgroundColor: 'transparent',
359
- // 仅显示Y轴值
360
- formatter: (data: any) => {
361
- const { axisDimension, value } = data
362
- if (axisDimension === 'y') {
363
- return String(formatValue(value))
364
- }
365
- return ''
366
- },
460
+ backgroundColor: null,
367
461
  },
368
462
  },
369
463
  },
370
- })
371
- // 2.获取当前列数据并发送请求至后端记录
372
- const handleClick = (el: any) => {
373
- // 关闭画笔模式,并移除echarts点击事件
374
- cursorPenVisible.value = false
375
- echartsInstance.getZr().off('mousedown', handleClick)
376
- const yAxisValue = echartsInstance.convertFromPixel({ yAxisIndex: 0 }, el.offsetY)
377
- const newWarnPrice = Math.round(yAxisValue * 1000) / 1000
378
- // 3.恢复指示器样式
379
- echartsInstance.setOption({
380
- ...echartsOptions,
381
- // 指示器样式
382
- tooltip: {
383
- ...oldTooltip,
384
- axisPointer: {
385
- ...oldTooltip.axisPointer,
386
- lineStyle: {
387
- width: 1,
388
- },
389
- crossStyle: {
390
- width: 1,
391
- },
392
- label: {
393
- ...oldTooltip.axisPointer.label,
394
- backgroundColor: null,
395
- },
396
- },
397
- },
398
- })
399
- // 4.发送保存预警线请求
400
- lineData.value[0].data.push({
401
- value: newWarnPrice,
402
- text: newWarnPrice,
403
- // 自定义信息
404
- info: {},
405
- // 自定义配置
406
- config: {
407
- draggable: true,
408
- },
409
- })
410
- console.log(lineData.value[0].data)
411
- ElMessage.success('画线预警成功!')
412
- }
413
- // 绑定echarts点击事件
414
- echartsInstance.getZr().on('mousedown', handleClick)
415
- }
464
+ });
465
+ // 4.发送保存预警线请求
466
+ lineData.value[0].data.push({
467
+ value: newWarnPrice,
468
+ text: newWarnPrice,
469
+ // 自定义信息
470
+ info: {},
471
+ // 自定义配置
472
+ config: {
473
+ draggable: true,
474
+ },
475
+ });
476
+ console.log(lineData.value[0].data);
477
+ ElMessage.success("画线预警成功!");
478
+ };
479
+ // 绑定echarts点击事件
480
+ echartsInstance.getZr().on("mousedown", handleClick);
481
+ };
416
482
 
417
- watch(
418
- () => props.deBugValue,
419
- (newValue: any) => {
420
- if (newValue === 1) {
421
- // 正常模式
422
- netWorkErrorMsg.value = ''
423
- componentInit()
424
- } else if (newValue === 2) {
425
- // 网络故障
426
- loading.value = true
427
- setTimeout(() => {
428
- netWorkErrorMsg.value = '网络加载失败,请刷新重试'
429
- loading.value = false
430
- }, 1000)
431
- } else if (newValue === 3) {
432
- // 空数据
433
- netWorkErrorMsg.value = ''
434
- loading.value = true
435
- setTimeout(() => {
436
- klineData.value = []
437
- loading.value = false
438
- }, 1000)
439
- }
440
- },
441
- {
442
- immediate: true,
483
+ watch(
484
+ () => props.deBugValue,
485
+ (newValue: any) => {
486
+ if (newValue === 1) {
487
+ // 正常模式
488
+ netWorkErrorMsg.value = "";
489
+ componentInit();
490
+ } else if (newValue === 2) {
491
+ // 网络故障
492
+ loading.value = true;
493
+ setTimeout(() => {
494
+ netWorkErrorMsg.value = "网络加载失败,请刷新重试";
495
+ loading.value = false;
496
+ }, 1000);
497
+ } else if (newValue === 3) {
498
+ // 空数据
499
+ netWorkErrorMsg.value = "";
500
+ loading.value = true;
501
+ setTimeout(() => {
502
+ klineData.value = [];
503
+ loading.value = false;
504
+ }, 1000);
443
505
  }
444
- )
506
+ },
507
+ {
508
+ immediate: true,
509
+ }
510
+ );
445
511
 
446
- onUnmounted(() => {
447
- console.log('---------单品种单周期组件: onUnmounted卸载成功---------')
448
- })
512
+ onUnmounted(() => {
513
+ console.log("---------单品种单周期组件: onUnmounted卸载成功---------");
514
+ });
449
515
 
450
- // 刷新按钮
451
- const reFresh = () => {
452
- netWorkErrorMsg.value = ''
453
- componentInit()
454
- }
516
+ // 刷新按钮
517
+ const reFresh = () => {
518
+ netWorkErrorMsg.value = "";
519
+ componentInit();
520
+ };
455
521
  </script>
456
522
 
457
523
  <template>
458
- <div id="single-cycle-single-variety">
459
- <div
460
- class="st-Kline"
461
- v-loading="loading"
462
- element-loading-text="正在加载数据中,请稍等..."
463
- >
524
+ <div id="single-cycle-single-variety" @mousemove="isSelect = true" @mouseout="isSelect = false">
525
+ <div class="st-Kline" v-loading="loading" element-loading-text="正在加载数据中,请稍等...">
464
526
  <!-- 功能区 -->
465
527
  <div class="kline-header">
466
528
  <!-- 品种名称 -->
@@ -468,26 +530,14 @@
468
530
  <!-- 周期展示 + 选择 -->
469
531
  <div class="kline-header-item cycleSelect">
470
532
  <span>{{ cycleName }}</span>
471
- <el-select
472
- v-model="cycle"
473
- popper-class="element-dark"
474
- @change="cycleChange"
475
- >
476
- <el-option
477
- v-for="(item, index) in cycleOptions"
478
- :key="index"
479
- :label="item.label"
480
- :value="item.value"
481
- />
533
+ <el-select v-model="cycle" popper-class="element-dark" @change="cycleChange">
534
+ <el-option v-for="(item, index) in cycleOptions" :key="index" :label="item.label" :value="item.value" />
482
535
  </el-select>
483
536
  </div>
484
537
  <!-- 指标展示 + 选择 -->
485
538
  <div class="kline-header-item cycleSelect">
486
539
  <span>{{ indicatorName }}</span>
487
- <el-select
488
- v-model="indicatorName"
489
- popper-class="element-dark"
490
- >
540
+ <el-select v-model="indicatorName" popper-class="element-dark">
491
541
  <el-option
492
542
  v-for="(item, index) in mainIndicatorList"
493
543
  :key="index"
@@ -499,11 +549,7 @@
499
549
  <!-- 开平/买卖展示 + 选择 -->
500
550
  <div class="kline-header-item sellBuySelect">
501
551
  <span>{{ sellBuyTypeName }}</span>
502
- <el-select
503
- v-model="sellBuyType"
504
- popper-class="element-dark"
505
- @change="sellBuyTypeChange"
506
- >
552
+ <el-select v-model="sellBuyType" popper-class="element-dark" @change="sellBuyTypeChange">
507
553
  <el-option
508
554
  v-for="(item, index) in sellBuyTypeOptions"
509
555
  :key="index"
@@ -523,25 +569,16 @@
523
569
  :lineData="lineData"
524
570
  :brushRange="brushRange"
525
571
  :defaultMenuData="defaultMenuData"
572
+ :isSelect="isSelect"
526
573
  :config="config"
527
574
  />
528
575
  <!-- 网络请求错误时 -->
529
- <div
530
- v-if="netWorkErrorMsg"
531
- class="netWorkError"
532
- >
576
+ <div v-if="netWorkErrorMsg" class="netWorkError">
533
577
  <span>{{ netWorkErrorMsg }}</span>
534
- <el-button
535
- @click="reFresh"
536
- :icon="RefreshRight"
537
- >刷新</el-button
538
- >
578
+ <el-button @click="reFresh" :icon="RefreshRight">刷新</el-button>
539
579
  </div>
540
580
  <!-- 空数据时 -->
541
- <div
542
- class="empty"
543
- v-else-if="!loading && klineData.length === 0"
544
- >
581
+ <div class="empty" v-else-if="!loading && klineData.length === 0">
545
582
  <el-empty description="暂无数据" />
546
583
  </div>
547
584
  </div>
@@ -549,106 +586,106 @@
549
586
  </template>
550
587
 
551
588
  <style lang="scss" scoped>
552
- #single-cycle-single-variety {
553
- margin: auto;
554
- width: 100%;
589
+ #single-cycle-single-variety {
590
+ margin: auto;
591
+ width: 100%;
592
+ height: 100%;
593
+ .st-Kline {
555
594
  height: 100%;
556
- .st-Kline {
557
- height: 100%;
595
+ display: flex;
596
+ flex-direction: column;
597
+ border-radius: 2px;
598
+ box-sizing: border-box;
599
+ background-color: black;
600
+ color-scheme: dark;
601
+ --el-mask-color: rgba(0, 0, 0, 0.8);
602
+ .kline-header {
558
603
  display: flex;
559
- flex-direction: column;
560
- border-radius: 2px;
561
- box-sizing: border-box;
562
- background-color: black;
563
- color-scheme: dark;
564
- --el-mask-color: rgba(0, 0, 0, 0.8);
565
- .kline-header {
604
+ align-items: center;
605
+ color: white;
606
+ border-bottom: 1px solid rgb(153, 153, 153);
607
+ .kline-header-item {
566
608
  display: flex;
567
609
  align-items: center;
568
- color: white;
569
- border-bottom: 1px solid rgb(153, 153, 153);
570
- .kline-header-item {
571
- display: flex;
572
- align-items: center;
573
- border-right: 1px solid rgb(153, 153, 153);
574
- padding: 6px;
575
- box-sizing: border-box;
576
- }
577
- // 功能区: 周期
578
- .cycleSelect {
579
- :deep(.el-select) {
580
- margin-left: 6px;
610
+ border-right: 1px solid rgb(153, 153, 153);
611
+ padding: 6px;
612
+ box-sizing: border-box;
613
+ }
614
+ // 功能区: 周期
615
+ .cycleSelect {
616
+ :deep(.el-select) {
617
+ margin-left: 6px;
618
+ width: 16px;
619
+ .el-input__wrapper {
620
+ height: 16px;
621
+ padding: 0;
622
+ border-radius: 50%;
623
+ background-color: #ccc;
624
+ }
625
+ .el-input__inner {
626
+ width: 0;
627
+ }
628
+ .el-select__icon {
629
+ color: black;
581
630
  width: 16px;
582
- .el-input__wrapper {
583
- height: 16px;
584
- padding: 0;
585
- border-radius: 50%;
586
- background-color: #ccc;
587
- }
588
- .el-input__inner {
589
- width: 0;
590
- }
591
- .el-select__icon {
592
- color: black;
593
- width: 16px;
594
- height: 16px;
595
- margin-left: 0;
596
- }
631
+ height: 16px;
632
+ margin-left: 0;
597
633
  }
598
634
  }
599
- // 功能区: 开平/买卖
600
- .sellBuySelect {
601
- :deep(.el-select) {
602
- margin-left: 6px;
635
+ }
636
+ // 功能区: 开平/买卖
637
+ .sellBuySelect {
638
+ :deep(.el-select) {
639
+ margin-left: 6px;
640
+ width: 16px;
641
+ .el-input__wrapper {
642
+ height: 16px;
643
+ padding: 0;
644
+ border-radius: 50%;
645
+ background-color: #ccc;
646
+ }
647
+ .el-input__inner {
648
+ width: 0;
649
+ }
650
+ .el-select__icon {
651
+ color: black;
603
652
  width: 16px;
604
- .el-input__wrapper {
605
- height: 16px;
606
- padding: 0;
607
- border-radius: 50%;
608
- background-color: #ccc;
609
- }
610
- .el-input__inner {
611
- width: 0;
612
- }
613
- .el-select__icon {
614
- color: black;
615
- width: 16px;
616
- height: 16px;
617
- margin-left: 0;
618
- }
653
+ height: 16px;
654
+ margin-left: 0;
619
655
  }
620
656
  }
621
657
  }
622
- .kline {
623
- flex: 1;
624
- }
625
658
  }
626
- .netWorkError {
627
- color: white;
628
- font-weight: 600;
629
- display: flex;
630
- flex-direction: column;
631
- align-items: center;
632
- justify-content: center;
633
- width: 100%;
634
- height: 100%;
635
- font-size: 24px;
636
- .el-button {
637
- margin-top: 10px;
638
- background-color: rgb(0, 0, 0);
639
- color: white;
640
- }
659
+ .kline {
660
+ flex: 1;
641
661
  }
642
- .empty {
662
+ }
663
+ .netWorkError {
664
+ color: white;
665
+ font-weight: 600;
666
+ display: flex;
667
+ flex-direction: column;
668
+ align-items: center;
669
+ justify-content: center;
670
+ width: 100%;
671
+ height: 100%;
672
+ font-size: 24px;
673
+ .el-button {
674
+ margin-top: 10px;
675
+ background-color: rgb(0, 0, 0);
643
676
  color: white;
644
- font-weight: 600;
645
- display: flex;
646
- flex-direction: column;
647
- align-items: center;
648
- justify-content: center;
649
- width: 100%;
650
- height: 100%;
651
- font-size: 24px;
652
677
  }
653
678
  }
679
+ .empty {
680
+ color: white;
681
+ font-weight: 600;
682
+ display: flex;
683
+ flex-direction: column;
684
+ align-items: center;
685
+ justify-content: center;
686
+ width: 100%;
687
+ height: 100%;
688
+ font-size: 24px;
689
+ }
690
+ }
654
691
  </style>