dataset.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. import { reactive, toRefs, shallowRef } from 'vue'
  2. import { ChartCycleType } from '@/constants/chart'
  3. import { queryHistoryDatas } from '@/services/api/quote'
  4. import { NetworkFilterData, NetworkFilterCallback } from './types'
  5. import moment from 'moment'
  6. export function useDataset(goodsCode: string, cycleType = ChartCycleType.Minutes) {
  7. // 缓存全量数据
  8. const cache = shallowRef<Model.HistoryDatasRsp[]>([])
  9. const state = reactive({
  10. loading: false,
  11. symbol: '000000.et',
  12. cycleType
  13. })
  14. // K线图网路协议
  15. const networkProtocol = {
  16. historyData: 'KLineChartContainer::RequestHistoryData', // 分钟全量数据下载
  17. historyMinuteData: 'KLineChartContainer::ReqeustHistoryMinuteData' // 日线全量数据下载
  18. }
  19. const networkFilter = (data: NetworkFilterData, callback: NetworkFilterCallback) => {
  20. data.PreventDefault = true
  21. switch (data.Name) {
  22. case networkProtocol.historyData:
  23. case networkProtocol.historyMinuteData:
  24. state.symbol = data.Request.Data.symbol
  25. getHistoryData(data.Name, data, callback)
  26. break
  27. default:
  28. callback({ symbol: state.symbol, data: [] })
  29. }
  30. }
  31. // 获取历史行情
  32. const getHistoryData = (protocol: string, data: NetworkFilterData, callback: NetworkFilterCallback) => {
  33. queryHistoryDatas({
  34. data: {
  35. cycleType: state.cycleType,
  36. goodsCode,
  37. count: 1440,
  38. }
  39. }).then((res) => {
  40. cache.value = res.data.sort((a, b) => moment(a.ts).valueOf() - moment(b.ts).valueOf())
  41. }).finally(() => {
  42. if (cache.value.length) {
  43. callback({
  44. symbol: state.symbol,
  45. data: handleChartData(protocol, cache.value)
  46. })
  47. } else {
  48. data.Self.EnableSplashScreen({
  49. Title: '暂无数据',
  50. Draw: true,
  51. })
  52. }
  53. })
  54. }
  55. // 处理图表数据
  56. const handleChartData = (protocol: string, data: Model.HistoryDatasRsp[]) => {
  57. return data.map((e, i) => {
  58. const date = Number(moment(e.ts).format('YYYYMMDD'))
  59. const time = Number(moment(e.ts).format('HHmm'))
  60. const preclose = data[i - 1] // 上一个收盘价
  61. const close = preclose ? preclose.c : e.c
  62. switch (protocol) {
  63. // https://blog.csdn.net/jones2000/article/details/100557649
  64. case networkProtocol.historyData:
  65. return [
  66. date, // 日期
  67. close, // 前收盘
  68. e.o || null, // 开盘价
  69. e.h || null, // 最高
  70. e.l || null, // 最低
  71. e.c, // 收盘
  72. e.tv, // 成交量
  73. e.tt || null, // 成交金额
  74. e.hv || null // 持仓量
  75. ]
  76. // https://blog.csdn.net/jones2000/article/details/100557649
  77. case networkProtocol.historyMinuteData:
  78. return [
  79. date, // 日期
  80. close, // 前收盘
  81. e.o || null, // 开盘价
  82. e.h || null, // 最高
  83. e.l || null, // 最低
  84. e.c, // 收盘
  85. e.tv, // 成交量
  86. e.tt || null, // 成交金额
  87. time, // 时间
  88. e.hv || null // 持仓量
  89. ]
  90. default:
  91. return []
  92. }
  93. })
  94. }
  95. // 获取周期毫秒数
  96. const getCycleMilliseconds = () => {
  97. const milliseconds = 60 * 1000; // 一分钟毫秒数
  98. switch (state.cycleType) {
  99. case ChartCycleType.Minutes5: {
  100. return milliseconds * 5;
  101. }
  102. case ChartCycleType.Minutes30: {
  103. return milliseconds * 30;
  104. }
  105. case ChartCycleType.Minutes60: {
  106. return milliseconds * 60;
  107. }
  108. case ChartCycleType.Hours2: {
  109. return milliseconds * 2 * 60;
  110. }
  111. case ChartCycleType.Hours4: {
  112. return milliseconds * 4 * 60;
  113. }
  114. case ChartCycleType.Day: {
  115. return milliseconds * 24 * 60;
  116. }
  117. case ChartCycleType.Week: {
  118. return milliseconds * 24 * 60 * 7;
  119. }
  120. case ChartCycleType.Month: {
  121. return milliseconds * 24 * 60 * 30;
  122. }
  123. default: {
  124. return milliseconds;
  125. }
  126. }
  127. }
  128. // 更新最新数据
  129. const updateLastData = (q: Partial<Model.QuoteDayRsp>) => {
  130. const { last, lasttime } = q
  131. if (last && lasttime) {
  132. const lastIndex = cache.value.length - 1 // 历史数据最后索引位置
  133. const cycleMilliseconds = getCycleMilliseconds()
  134. const oldTime = lastIndex === -1 ? moment(lasttime) : moment(cache.value[lastIndex].ts) // 历史行情最后时间
  135. const diffTime = moment(lasttime).valueOf() - oldTime.valueOf() // 计算时间差
  136. // 判断时间差是否大于周期时间
  137. if (lastIndex === -1 || diffTime > cycleMilliseconds) {
  138. cache.value.push({
  139. o: last,
  140. h: last,
  141. l: last,
  142. c: last,
  143. tv: q.lastvolume ?? 0,
  144. tt: q.Lastturnover ?? 0,
  145. hv: q.holdvolume ?? 0,
  146. s: q.settle ?? 0,
  147. ts: lasttime,
  148. f: false
  149. })
  150. } else {
  151. // 更新列表中最后一条记录的数据
  152. const record = cache.value[lastIndex]
  153. if (record.l > last) {
  154. record.l = last // 更新最低价
  155. }
  156. if (record.h < last) {
  157. record.h = last // 更新最高价
  158. }
  159. record.c = last // 更新收盘价
  160. record.tv = q.lastvolume ?? record.tv
  161. record.tt = q.Lastturnover ?? record.tt
  162. record.hv = q.holdvolume ?? record.hv
  163. record.s = q.settle ?? record.s
  164. }
  165. const lastValue = cache.value.slice(-1)
  166. if (state.cycleType === ChartCycleType.Day) {
  167. return handleChartData(networkProtocol.historyData, lastValue)
  168. }
  169. return handleChartData(networkProtocol.historyMinuteData, lastValue)
  170. }
  171. return []
  172. }
  173. return {
  174. ...toRefs(state),
  175. networkFilter,
  176. updateLastData
  177. }
  178. }