st-comp 0.0.41 → 0.0.43

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "st-comp",
3
3
  "public": true,
4
- "version": "0.0.41",
4
+ "version": "0.0.43",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite",
@@ -539,10 +539,10 @@ const handleSellBuyConfig = (data: any[], originData: KlineDataType) => {
539
539
  * 简单判断该条K线上是否有多个数据即可判断出是否是买卖同时存在,如果同时存在图标变成T
540
540
  */
541
541
  const timeTradeList = data.filter((item: any) => item.time === next.time)
542
- let symbol = "image://" + new URL(`./images/${tradeType === "买" ? "buy" : "sell"}.svg`, import.meta.url).href;
542
+ let symbol = "image://" + new URL(`./images/${tradeType === "买" ? "buy" : "sell"}.svg`, import.meta.url).href;
543
543
  if (timeTradeList.length > 1) {
544
544
  // 存在多条数据, 处理出他们的交易类型, 进行去重
545
- const timeTradeTypes = [...new Set(...timeTradeList.map(i => handleTradeType(i, "sellBuy")))]
545
+ const timeTradeTypes = [...new Set(timeTradeList.map(i => handleTradeType(i, "sellBuy")))]
546
546
  if (timeTradeTypes.length > 1) {
547
547
  symbol = "image://" + new URL("./images/t.svg", import.meta.url).href;
548
548
  } else {
@@ -0,0 +1,8 @@
1
+ import { App } from "vue";
2
+ import StKlineNew from "./index.vue";
3
+
4
+ export default {
5
+ install(app: App) {
6
+ app.component("st-klineNew", StKlineNew);
7
+ },
8
+ }
@@ -0,0 +1,310 @@
1
+ <template>
2
+ <div
3
+ class="kline"
4
+ @mousemove="isSelect = true"
5
+ @mouseout="isSelect = false"
6
+ >
7
+ <div class="kline-mainChart" ref="mainChartRef"></div>
8
+ <div class="kline-subChart" ref="subChartRef"></div>
9
+ <div class="kline-slideChart" ref="slideChartRef"></div>
10
+ </div>
11
+ </template>
12
+
13
+ <script setup lang="ts">
14
+ import { ref, onMounted, onUnmounted } from "vue"
15
+ import * as echarts from 'echarts'
16
+ import type { EChartsType } from 'echarts'
17
+ import { getMainOption, getSubOption, getSlideOption } from './option.js'
18
+ import { getKlineDataApi } from './utils.js'
19
+ import dayjs from "dayjs"
20
+
21
+ const config = {
22
+ defaultShowDays: 50, // 默认展示天数
23
+ preLoadDays: 50, // 预加载天数
24
+ preLoadCount: 800, // 预加载数据条数(用于计算指标线)
25
+ loadCheckCount: 500, // 加载数据检查条数
26
+ }
27
+ let mainChart: EChartsType
28
+ let subChart: EChartsType
29
+ let slideChart: EChartsType
30
+ let mainDataZoomTimer: any = null
31
+ let slideDataZoomTimer: any = null
32
+ let isLoadHistory: boolean = false // 是否正在加载历史数据
33
+ let isloadAllHistory: boolean = false // 是否加载完全部历史数据
34
+ let isLoadNew: boolean = false // 是否正在加载新数据
35
+ let isloadAllNew: boolean = false // 是否加载完全部新数据
36
+ let resizeRo: any
37
+ let slideData: any[] = [] // 拖动轴数据
38
+ let klineData: any[] = [] // 时间轴数据
39
+
40
+ const mainChartRef = ref<HTMLElement>()
41
+ const subChartRef = ref<HTMLElement>()
42
+ const slideChartRef = ref<HTMLElement>()
43
+ const isSelect = ref(false)
44
+
45
+ onMounted(async () => {
46
+ // 请求滚动条数据
47
+ slideData = await getKlineData({
48
+ queryType: '0',
49
+ startTime: `${dayjs().subtract(5, 'year').format("YYYY-MM-DD")} 00:00:00`,
50
+ endTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
51
+ cycle: '6',
52
+ })
53
+ // 请求首屏k线数据
54
+ const { startTime, showStartTime, endTime, showEndTime } = getTime(slideData.length - 1 - config.defaultShowDays, slideData.length - 1)
55
+ klineData = await getKlineData({
56
+ queryType: '0',
57
+ startTime: `${startTime} 00:00:00`,
58
+ endTime: `${endTime} 24:00:00`,
59
+ cycle: '5',
60
+ })
61
+ init()
62
+ addEventListener()
63
+ draw('main', { showStartTime, showEndTime })
64
+ draw('sub', { showStartTime, showEndTime })
65
+ draw('slide')
66
+ // 绑定resize事件
67
+ let isFirst: boolean | null = true
68
+ resizeRo = new ResizeObserver(() => {
69
+ if (isFirst) {
70
+ isFirst = null
71
+ return
72
+ }
73
+ mainChart.resize()
74
+ subChart.resize()
75
+ slideChart.resize()
76
+ })
77
+ resizeRo.observe(mainChartRef.value)
78
+ window.addEventListener('keydown', keyDownEvent)
79
+ })
80
+
81
+ onUnmounted(() => {
82
+ window.removeEventListener('keydown', keyDownEvent)
83
+ mainChart.dispose()
84
+ subChart.dispose()
85
+ slideChart.dispose()
86
+ resizeRo.disconnect()
87
+ resizeRo = null
88
+ })
89
+
90
+ const init = () => {
91
+ mainChart = echarts.init(mainChartRef.value)
92
+ subChart = echarts.init(subChartRef.value)
93
+ slideChart = echarts.init(slideChartRef.value)
94
+ echarts.connect([mainChart, subChart])
95
+ }
96
+
97
+ const addEventListener = () => {
98
+ mainChart.on('datazoom', (params: any) => {
99
+ clearTimeout(mainDataZoomTimer)
100
+ mainDataZoomTimer = setTimeout(() => {
101
+ let startIndex = 0
102
+ let endIndex = 0
103
+ if (params.batch) {
104
+ const { start, end } = params.batch[0]
105
+ startIndex = Math.floor(start * klineData.length / 100)
106
+ endIndex = end === 100 ? klineData.length - 1 : Math.floor(end * klineData.length / 100)
107
+ } else {
108
+ startIndex = params.startValue
109
+ endIndex = params.endValue
110
+ }
111
+ // 加载数据
112
+ if (startIndex < config.loadCheckCount && isLoadHistory === false && isloadAllHistory === false) {
113
+ // 左侧数据小于1000条,加载左侧数据
114
+ isLoadHistory = true
115
+ getMoreData({
116
+ queryType: '1',
117
+ endTime: klineData[0][0],
118
+ cycle: '5',
119
+ limit: 2000,
120
+ })
121
+ }
122
+ if (endIndex > klineData.length - config.loadCheckCount && isLoadNew === false && isloadAllNew === false) {
123
+ // 右侧数据小于1000条,加载右侧数据
124
+ isLoadNew = true
125
+ getMoreData({
126
+ queryType: '2',
127
+ startTime: klineData[klineData.length - 1][0],
128
+ cycle: '5',
129
+ limit: 2000,
130
+ })
131
+ }
132
+ // 重置滚动条
133
+ const { startValue, endValue } = (mainChart.getOption().dataZoom as any[])[0]
134
+ const startTime = (klineData[startValue][0] as string).split(' ')[0]
135
+ const endTime = (klineData[endValue][0] as string).split(' ')[0]
136
+ const slideTime = slideData.map(item => (item[0] as string).split(' ')[0])
137
+ slideChart.dispatchAction({
138
+ type: 'dataZoom',
139
+ startValue: slideTime.indexOf(startTime),
140
+ endValue: slideTime.indexOf(endTime)
141
+ })
142
+ clearTimeout(mainDataZoomTimer)
143
+ }, 300)
144
+ })
145
+ slideChart.on('datazoom', (params: any) => {
146
+ if(!params.dataZoomId) return
147
+ clearTimeout(slideDataZoomTimer)
148
+ slideDataZoomTimer = setTimeout(async() => {
149
+ const { start, end } = params
150
+ const startIndex = Math.floor(start * slideData.length / 100)
151
+ const endIndex = end === 100 ? slideData.length - 1 : Math.floor(end * slideData.length / 100)
152
+ const { startTime, showStartTime, endTime, showEndTime } = getTime(startIndex, endIndex)
153
+ klineData = await getKlineData({
154
+ queryType: '0',
155
+ startTime: `${startTime} 00:00:00`,
156
+ endTime: `${endTime} 24:00:00`,
157
+ cycle: '5',
158
+ })
159
+ isLoadHistory = false
160
+ isloadAllHistory = false
161
+ isLoadNew = false
162
+ isloadAllNew = false
163
+ draw('main', { showStartTime, showEndTime })
164
+ draw('sub', { showStartTime, showEndTime })
165
+ clearTimeout(slideDataZoomTimer)
166
+ }, 100)
167
+ })
168
+ }
169
+
170
+ // 键盘事件
171
+ const keyDownEvent = e => {
172
+ // 只有选中或者按ctrl才激活按键
173
+ if (!(e.ctrlKey || isSelect.value)) return
174
+ const option = mainChart.getOption()
175
+ let { startValue, endValue } = (option.dataZoom as any)[0]
176
+ if (e.code === 'ArrowLeft') {
177
+ // 左按键
178
+ if (startValue === 0) {
179
+ return
180
+ }
181
+ startValue = startValue - 1
182
+ endValue = endValue - 1
183
+ mainChart.dispatchAction({
184
+ type: 'highlight',
185
+ dataIndex: endValue,
186
+ })
187
+ } else if (e.code === 'ArrowRight') {
188
+ // 右按键
189
+ if (endValue === (option.xAxis as any)[0].data.length - 1) {
190
+ return
191
+ }
192
+ startValue = startValue + 1
193
+ endValue = endValue + 1
194
+ mainChart.dispatchAction({
195
+ type: 'highlight',
196
+ dataIndex: endValue,
197
+ })
198
+ } else if (e.code === 'ArrowUp') {
199
+ // 上按键-放大 最少保持5条数据
200
+ if(endValue - startValue < 5) {
201
+ return
202
+ }
203
+ const diff = Math.floor((endValue - startValue) / 2) + 1
204
+ startValue = startValue + diff
205
+ if (endValue - startValue < 5) {
206
+ startValue = endValue - 4
207
+ }
208
+ } else if (e.code === 'ArrowDown') {
209
+ // 下按键-缩小
210
+ const diff = Math.min(500, (endValue - startValue))
211
+ startValue = startValue - diff - 1
212
+ }
213
+ mainChart.dispatchAction({
214
+ type: 'dataZoom',
215
+ startValue,
216
+ endValue
217
+ })
218
+ }
219
+
220
+ const getTime = (startIndex: number, endIndex: number) => {
221
+ const startTime = (slideData[startIndex - config.preLoadDays < 0 ? 0 : startIndex - config.preLoadDays][0] as string).split(' ')[0]
222
+ const showStartTime = (slideData[startIndex][0] as string).split(' ')[0]
223
+ const endTime = (slideData[endIndex + config.preLoadDays > slideData.length ? slideData.length - 1 : endIndex + config.preLoadDays][0] as string).split(' ')[0]
224
+ const showEndTime = (slideData[endIndex][0] as string).split(' ')[0]
225
+ return { startTime, showStartTime, endTime, showEndTime }
226
+ }
227
+
228
+ const getMoreData = async(params: any) => {
229
+ const { startValue, endValue } = (mainChart.getOption().dataZoom as any[])[0]
230
+ const showStartTime = klineData[startValue][0]
231
+ const showEndTime = klineData[endValue][0]
232
+ const res = await getKlineData(params)
233
+ if (params.queryType === '1') {
234
+ // 加载历史数据
235
+ if (new Date(slideData[0][0]) > new Date(res[0][0])) {
236
+ // 表示历史数据已加载完
237
+ isloadAllHistory = true
238
+ klineData = [
239
+ ...res.filter(item => new Date(item[0]) >= new Date(slideData[0][0])),
240
+ ...klineData.slice(1)
241
+ ]
242
+ } else {
243
+ klineData = [...res, ...klineData.slice(1)]
244
+ }
245
+ isLoadHistory = false
246
+ } else {
247
+ // 加载新数据
248
+ if (res.length === 0) {
249
+ // 表示已经加载完全部新数据
250
+ isloadAllNew = true
251
+ isLoadNew = false
252
+ return
253
+ }
254
+ klineData = [...klineData, ...res.slice(1)]
255
+ }
256
+ draw('main', { showStartTime, showEndTime })
257
+ draw('sub', { showStartTime, showEndTime })
258
+ }
259
+
260
+ const getKlineData = async(params: any) => {
261
+ const res = await getKlineDataApi({
262
+ contractType: 0, // 合约类型 0-主连 1-加权
263
+ variety: "RU", // 品种
264
+ preLimit: 0, // 向前多查询数量
265
+ postLimit: 0, // 向后多查询数量
266
+ right: 0, // 0-不复权 1-前复权 2-后复权
267
+ ...params,
268
+ })
269
+ return res
270
+ }
271
+
272
+ const draw = (type: string, params: any = {}) => {
273
+ const { showStartTime, showEndTime } = params
274
+ const { defaultShowDays } = config
275
+ const callBackMap = new Map([
276
+ [ "main", () => {
277
+ mainChart.setOption(getMainOption({ data: klineData, showStartTime, showEndTime }))
278
+ }],
279
+ [ "sub", () => {
280
+ subChart.setOption(getSubOption({ data: klineData, showStartTime, showEndTime }))
281
+ }],
282
+ [ "slide", () => {
283
+ slideChart.setOption(getSlideOption({ data: slideData, defaultShowDays }))
284
+ }],
285
+ ]);
286
+ const callBack = callBackMap.get(type);
287
+ if (callBack instanceof Function) {
288
+ callBack();
289
+ }
290
+ }
291
+ </script>
292
+
293
+ <style lang="scss" scoped>
294
+ .kline {
295
+ width: 100%;
296
+ height: 100%;
297
+ &-mainChart {
298
+ width: 100%;
299
+ height: 60%;
300
+ }
301
+ &-subChart {
302
+ width: 100%;
303
+ height: calc(40% - 50px);
304
+ }
305
+ &-slideChart {
306
+ width: 100%;
307
+ height: 50px;
308
+ }
309
+ }
310
+ </style>
@@ -0,0 +1,150 @@
1
+ export const getMainOption = (config: any) => {
2
+ const { data, showStartTime, showEndTime } = config
3
+ const xAxisData: any[] = []
4
+ const klineData: any[] = []
5
+ let startValue = -1
6
+ let endValue = -1
7
+ data.forEach((item: any, index: number) => {
8
+ xAxisData.push(item[0])
9
+ klineData.push([ item[1], item[4], item[3], item[2] ])
10
+ if (new Date(item[0]) >= new Date(showStartTime) && startValue === -1) {
11
+ startValue = index
12
+ }
13
+ if (new Date(item[0]) <= new Date(showEndTime)) {
14
+ endValue = index
15
+ }
16
+ })
17
+ return {
18
+ animation: false,
19
+ grid: {
20
+ left: '50px',
21
+ top: '20px',
22
+ right: '20px',
23
+ bottom: '20px',
24
+ },
25
+ dataZoom: [
26
+ {
27
+ type: 'inside',
28
+ realtime: true,
29
+ startValue,
30
+ endValue,
31
+ }
32
+ ],
33
+ tooltip: {
34
+ trigger: "axis",
35
+ axisPointer: {
36
+ type: "cross",
37
+ },
38
+ },
39
+ xAxis: {
40
+ type: 'category',
41
+ data: xAxisData
42
+ },
43
+ yAxis: {
44
+ type: 'value',
45
+ min: (value: any) => value.min,
46
+ max: (value: any) => value.max,
47
+ },
48
+ series: [
49
+ {
50
+ type: 'candlestick',
51
+ data: klineData,
52
+ }
53
+ ]
54
+ }
55
+ }
56
+
57
+ export const getSubOption = (config: any) => {
58
+ const { data, showStartTime, showEndTime } = config
59
+ const xAxisData: any[] = []
60
+ const barData: any[] = []
61
+ let startValue = -1
62
+ let endValue = -1
63
+ data.forEach((item: any, index: number) => {
64
+ xAxisData.push(item[0])
65
+ barData.push(item[5])
66
+ if (new Date(item[0]) >= new Date(showStartTime) && startValue === -1) {
67
+ startValue = index
68
+ }
69
+ if (new Date(item[0]) <= new Date(showEndTime)) {
70
+ endValue = index
71
+ }
72
+ })
73
+ return {
74
+ animation: false,
75
+ grid: {
76
+ left: '50px',
77
+ top: '20px',
78
+ right: '20px',
79
+ bottom: '20px',
80
+ },
81
+ dataZoom: [
82
+ {
83
+ type: 'inside',
84
+ realtime: true,
85
+ startValue,
86
+ endValue,
87
+ }
88
+ ],
89
+ tooltip: {
90
+ trigger: "axis",
91
+ axisPointer: {
92
+ type: "cross",
93
+ },
94
+ },
95
+ xAxis: {
96
+ type: 'category',
97
+ data: xAxisData
98
+ },
99
+ yAxis: {
100
+ type: 'value',
101
+ },
102
+ series: [
103
+ {
104
+ data: barData,
105
+ type: 'bar'
106
+ }
107
+ ]
108
+ }
109
+ }
110
+
111
+ export const getSlideOption = (config: any) => {
112
+ const { data, defaultShowDays } = config
113
+ const xAxisData = data.map((item: any) => item[0].split(' ')[0])
114
+ const lineData = data.map((item: any) => item[4])
115
+ return {
116
+ grid: {
117
+ height: 0,
118
+ left: '80px',
119
+ right: '80px',
120
+ },
121
+ dataZoom: [
122
+ {
123
+ show: true,
124
+ realtime: true,
125
+ startValue: data.length - 1 - defaultShowDays,
126
+ endValue: data.length - 1,
127
+ },
128
+ {
129
+ type: 'inside',
130
+ realtime: true,
131
+ startValue: data.length - 1 - defaultShowDays,
132
+ endValue: data.length - 1,
133
+ }
134
+ ],
135
+ xAxis: {
136
+ type: 'category',
137
+ data: xAxisData,
138
+ show: false,
139
+ },
140
+ yAxis: {
141
+ type: 'value'
142
+ },
143
+ series: [
144
+ {
145
+ data: lineData,
146
+ type: 'line'
147
+ }
148
+ ]
149
+ }
150
+ }
@@ -0,0 +1,13 @@
1
+ import axios from 'axios'
2
+
3
+ export const getKlineDataApi = async(params: any) => {
4
+ const res = await axios({
5
+ method: 'post',
6
+ headers: {
7
+ token: '78e4d78065e760bb3d0dcc3d442e6a0e',
8
+ },
9
+ url: 'http://192.168.12.49/common/qt/getSingleCycleSingleVariety',
10
+ data: params,
11
+ })
12
+ return res.data.body
13
+ }
package/packages/index.ts CHANGED
@@ -3,6 +3,7 @@ import StChartLayout from "./ChartLayout/index.ts"
3
3
  import StDialog from "./Dialog/index.ts"
4
4
  import StHeatMap from "./HeatMap/index.ts"
5
5
  import StKline from "./Kline/index.ts"
6
+ import StKlineNew from "./KlineNew/index.ts"
6
7
  import StLinearLegend from "./LinearLegend/index.ts"
7
8
  import StMap from "./Map/index.ts"
8
9
  import StPagination from "./Pagination/index.ts"
@@ -17,6 +18,7 @@ export default {
17
18
  StDialog.install(app)
18
19
  StHeatMap.install(app)
19
20
  StKline.install(app)
21
+ StKlineNew.install(app)
20
22
  StLinearLegend.install(app)
21
23
  StMap.install(app)
22
24
  StPagination.install(app)
@@ -7,9 +7,9 @@ export const getSingleCycleSingleVariety = async (data: any) => {
7
7
  return axios({
8
8
  method: 'post',
9
9
  headers: {
10
- token: '9593c16255001925afeed6dd2770eea7',
10
+ token: '4b26c72f990a5b02be1a79eb33c1bedf',
11
11
  },
12
- url: 'http://192.168.12.49:88/common/qt/getSingleCycleSingleVariety',
12
+ url: 'http://120.27.237.138/common/qt/getSingleCycleSingleVariety',
13
13
  data,
14
14
  })
15
15
  }
@@ -63,9 +63,9 @@ export const getNetPositionData = async (data: any) => {
63
63
  return axios({
64
64
  method: 'post',
65
65
  headers: {
66
- token: 'b1ef55eb206f7ae49b85b528231c5d87',
66
+ token: '4b26c72f990a5b02be1a79eb33c1bedf',
67
67
  },
68
- url: 'http://192.168.12.49:88/invest/analysis/queryVarietyNetPositionValue',
68
+ url: 'http://120.27.237.138/invest/analysis/queryVarietyNetPositionValue',
69
69
  data
70
70
  })
71
71
  }
@@ -77,9 +77,9 @@ export const queryPairedRecordByVariety = async (data: any) => {
77
77
  return axios({
78
78
  method: 'post',
79
79
  headers: {
80
- token: 'b1ef55eb206f7ae49b85b528231c5d87',
80
+ token: '4b26c72f990a5b02be1a79eb33c1bedf',
81
81
  },
82
- url: 'http://192.168.12.49:88/invest/analysis/queryPairedRecordByVariety',
82
+ url: 'http://120.27.237.138/invest/analysis/queryPairedRecordByVariety',
83
83
  data
84
84
  })
85
85
  }
@@ -22,7 +22,7 @@ const loading = ref(true);
22
22
  const netWorkErrorMsg = ref("");
23
23
 
24
24
  // 筛选条件相关参数
25
- const cycle = ref<any>("6");
25
+ const cycle = ref<any>("5");
26
26
  const cycleName = computed(() => {
27
27
  if (cycleOptions.value.length > 0) {
28
28
  return cycleOptions.value.find((item: any) => item.value === cycle.value).label;
@@ -191,12 +191,12 @@ const getKlineData = async () => {
191
191
  const params = {
192
192
  contractType: 0,
193
193
  cycle: cycle.value,
194
- endTime: "2015-04-09 15:00:00",
194
+ endTime: "2024-03-28 15:00:00",
195
195
  preLimit: 800,
196
196
  queryType: 0,
197
197
  right: 0,
198
- startTime: "2015-02-08 15:00:00",
199
- variety: "IF",
198
+ startTime: "2024-01-28 15:00:00",
199
+ variety: "RU",
200
200
  };
201
201
  const res = await getSingleCycleSingleVariety(params);
202
202
  klineData.value = res.data.body;
@@ -207,10 +207,10 @@ const getKlineData = async () => {
207
207
  const getKlinePointData = async () => {
208
208
  // ------
209
209
  const params = {
210
- analyseId: 2248,
210
+ analyseId: 3172,
211
211
  cycle: cycle.value,
212
212
  ifStock: 0,
213
- varietyName: "沪深300",
213
+ varietyName: "橡胶",
214
214
  };
215
215
  const res = await queryPairedRecordByVariety(params);
216
216
  const body = res.data.body;
@@ -0,0 +1,12 @@
1
+ <template>
2
+ <div style="width: 100%; height: 100%;">
3
+ <st-klineNew />
4
+ </div>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ </script>
9
+
10
+ <style lang="scss" scoped>
11
+
12
+ </style>
@@ -19,6 +19,11 @@ export default [
19
19
  name: 'Kline',
20
20
  component: () => import('../pages/Kline/index.vue'),
21
21
  },
22
+ {
23
+ path: '/klineNew',
24
+ name: 'KlineNew',
25
+ component: () => import('../pages/KlineNew/index.vue'),
26
+ },
22
27
  {
23
28
  path: '/linearLegend',
24
29
  name: 'LinearLegend',