tableQuote.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import { QueryQuoteDayRsp } from '@/services/go/quote/interface';
  2. import { addSubscribeQuotation, removeSubscribeQuotation } from '@/services/socket/quota';
  3. import TimerUtils from '@/utils/timer/timerUtil';
  4. import { v4 } from 'uuid';
  5. import { onBeforeUnmount, onMounted, Ref, ref, watchEffect } from "vue";
  6. /**
  7. * 处理行情按需订阅
  8. * @param tableList 全部表格数据
  9. * @param codeKey 需要订阅商品code对应的key
  10. * @param itemTableHeight 表格每一行的高度
  11. * @param selector 当前的滚动区域的选择器
  12. */
  13. export function handleSubcriteOnDemandQuote<T extends object>(tableList: Ref<T[]>, codeKey = 'goodscode', itemTableHeight = 31, selector = '.ant-table-body') {
  14. const beforeScrollTop = ref<number>(0)
  15. const uuid = v4();
  16. onMounted(() => {
  17. listenSrcoll(document.querySelector(selector)!)
  18. });
  19. onBeforeUnmount(() => {
  20. stopSubcribe()
  21. })
  22. // 第一次自动订阅当前可视区域的数据
  23. const stop = watchEffect(() => {
  24. const len = tableList.value.length
  25. if (len) {
  26. const end = len > 16 ? 16 : len;
  27. subscribeAction(0, end)
  28. }
  29. })
  30. // 停止订阅
  31. function stopSubcribe() {
  32. removeSubscribeQuotation(uuid);
  33. TimerUtils.clearTimeout('subscribeQuote')
  34. stop()
  35. }
  36. function listenSrcoll(ele: Element) {
  37. ele.addEventListener('scroll', (event: any) => {
  38. stop && stop()
  39. debounceSroll(event)
  40. }, true)
  41. }
  42. // 判断滚动方向
  43. function srollDrection(event: any) {
  44. const { scrollTop, offsetHeight } = event.target
  45. const diffSrollTop = scrollTop - beforeScrollTop.value
  46. if (diffSrollTop === 0) {
  47. // 横向滚动
  48. return
  49. } else if (diffSrollTop > 0) {
  50. // 向下滚动
  51. caclcuteSubcribeNum(scrollTop, offsetHeight)
  52. } else {
  53. // 向上滚动
  54. caclcuteSubcribeNum(scrollTop, offsetHeight)
  55. }
  56. beforeScrollTop.value = scrollTop
  57. }
  58. /**
  59. *
  60. * @param scrollTop 当前滚动条所处的位置
  61. * @param offsetHeight 当前滚动范围的可视区域的高度
  62. */
  63. function caclcuteSubcribeNum(scrollTop: number, offsetHeight: number) {
  64. // 可视区域的列表行数
  65. const rowNum = Math.ceil(offsetHeight / itemTableHeight) - 1;
  66. const tableIndex = scrollTop < itemTableHeight ? 0 : Math.ceil(scrollTop / itemTableHeight)
  67. // 开始订阅
  68. subscribeAction(tableIndex, tableIndex + rowNum)
  69. }
  70. // 防抖
  71. function debounceSroll(event: any) {
  72. TimerUtils.clearTimeout('subscribeQuote')
  73. TimerUtils.setTimeout(() => {
  74. srollDrection(event)
  75. }, 200, 'subscribeQuote')
  76. }
  77. // 开始订阅
  78. function subscribeAction(start: number, end: number) {
  79. removeSubscribeQuotation(uuid);
  80. const result: Array<{ exchangeCode: 250, goodsCode: string, subState: 0 }> = []
  81. for (let i = start; i < end; i++) {
  82. const obj = tableList.value[i] as unknown as any
  83. if (Reflect.has(obj, codeKey)) {
  84. result.push({ exchangeCode: 250, goodsCode: obj[codeKey], subState: 0 })
  85. } else {
  86. console.warn(`订阅商品的code对应的key${codeKey}不存在,请手动传入!`)
  87. }
  88. }
  89. console.log('开始订阅', result)
  90. addSubscribeQuotation(uuid, result);
  91. }
  92. return stopSubcribe
  93. }
  94. // 处理行情订阅,注意这里不是按需订阅
  95. export function handleSubcriteQuote() {
  96. const uuid = v4();
  97. function subscribeAction(goodscode: string[]) {
  98. removeSubscribeQuotation(uuid);
  99. const goodsList = goodscode.map(el => {
  100. return { exchangeCode: 250, goodsCode: el, subState: 0 };
  101. })
  102. // 行情订阅
  103. addSubscribeQuotation(uuid, goodsList);
  104. }
  105. onBeforeUnmount(() => {
  106. removeSubscribeQuotation(uuid);
  107. });
  108. return { subscribeAction }
  109. }
  110. function isPrice(price1: number | string, price2: number | string) {
  111. if (price2 && price2 !== '--' && price1 && price1 !== '--') {
  112. return true
  113. } else {
  114. return false
  115. }
  116. }
  117. /**
  118. * 处理行情价格颜色
  119. * @param value
  120. * @param presettle 昨结价
  121. * @returns
  122. */
  123. export function handleQuotePriceColor(value: number, presettle: number) {
  124. let result = ''
  125. if (isPrice(value, presettle)) {
  126. if (value === presettle) {
  127. result = ''
  128. } else if (value > presettle) {
  129. result = 'up-quote-color'
  130. } else {
  131. result = 'down-quote-color'
  132. }
  133. }
  134. return result
  135. }
  136. // 涨跌 最新价 - 昨结价
  137. export function quoteChange(record: QueryQuoteDayRsp, decimalplace = 2) {
  138. const { presettle, last } = record
  139. let result = '--'
  140. if (isPrice(last, presettle)) {
  141. result = (last - presettle).toFixed(decimalplace)
  142. }
  143. return result
  144. }
  145. // 幅度(最新价 - 昨结价) / 昨结价) * 100 %
  146. export function quoteAmplitude(record: QueryQuoteDayRsp, decimalplace = 2) {
  147. const result = quoteChange(record, decimalplace)
  148. return result === '--' ? '--' : (+result / record.presettle * 100).toFixed(decimalplace) + '%'
  149. }
  150. // 振幅 (最高价 - 最低价 ) / 最新价 * 100 %
  151. export function quoteAmplituOfVibration(record: QueryQuoteDayRsp, decimalplace = 2) {
  152. const { highest, lowest, last } = record
  153. let result = '--'
  154. if (isPrice(highest, lowest)) {
  155. if (last && (last as unknown as any) !== '--') {
  156. result = ((highest - lowest) / last * 100).toFixed(decimalplace) + '%'
  157. }
  158. }
  159. return result
  160. }
  161. // 处理 空值 或者 0的时候,显示 -- 的情况,
  162. export function handleNoneValue(value: number | string) {
  163. return value ? value : '--'
  164. }