index.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. <template>
  2. <div class="mtp-echats-timeline">
  3. <ul class="legend">
  4. <li class="legend-item">收: {{timeDetail && timeDetail.close}}</li>
  5. <li class="legend-item">MA5: {{timeDetail && timeDetail.ma5}}</li>
  6. </ul>
  7. <mtp-echarts :option="timeOption" :empty="showEmpty" v-model:index="dataIndex" v-model:loading="loading" @ready="initData" />
  8. </div>
  9. </template>
  10. <script lang="ts">
  11. import { defineComponent, ref, watch, computed } from 'vue'
  12. import { QueryQuoteDayRsp } from '@/services/go/quote/interface';
  13. import { QueryTSData } from '@/services/go/quote';
  14. import { getQuoteDayInfoByCode } from '@/services/bus/goods';
  15. import { throttle } from '@/utils/time'
  16. import { useDataset } from './dataset'
  17. import { useOptions } from './options'
  18. import moment from 'moment';
  19. import MtpEcharts from '../../echarts/echarts-base/index.vue'
  20. export default defineComponent({
  21. emits: ['ready'],
  22. components: {
  23. MtpEcharts,
  24. },
  25. props: {
  26. goodscode: {
  27. type: String,
  28. default: '',
  29. },
  30. },
  31. setup(props, { emit }) {
  32. const loading = ref(false),
  33. showEmpty = ref(false),
  34. dataIndex = ref(0), // 当前数据索引值
  35. quote = ref<QueryQuoteDayRsp>(getQuoteDayInfoByCode(props.goodscode)!); // 商品实时行情
  36. const { state, handleData, calcIndicator } = useDataset();
  37. const { timeOption, initOptions, updateOptions } = useOptions(state);
  38. const timeDetail = computed(() => {
  39. const { close, ma5 } = state.dataset.source;
  40. return {
  41. close: close[dataIndex.value] ?? '--',
  42. ma5: ma5[dataIndex.value] ?? '--',
  43. }
  44. });
  45. // 初始化数据
  46. const initData = () => {
  47. showEmpty.value = false;
  48. loading.value = true;
  49. state.dataset.source = {
  50. date: [],
  51. close: [],
  52. ma5: []
  53. }
  54. // 查询历史数据
  55. QueryTSData(props.goodscode).then((res) => {
  56. if (res.historyDatas.length) {
  57. dataIndex.value = res.historyDatas.length - 1;
  58. handleData(res);
  59. initOptions();
  60. } else {
  61. showEmpty.value = true;
  62. }
  63. // 调用父级函数查询tik数据 (不合理的逻辑处理,待优化)
  64. emit('ready', res.startTime, res.endTime);
  65. }).catch((err) => {
  66. console.error(err);
  67. showEmpty.value = true;
  68. }).finally(() => {
  69. loading.value = false;
  70. });
  71. }
  72. // 更新图表数据
  73. const updateChartData = () => {
  74. const { close, ma5 } = state.dataset.source,
  75. lastIndex = close.length - 1, // 历史行情最后索引位置
  76. cycleMilliseconds = 60 * 1000, // 一分钟毫秒数
  77. newTime = moment(quote.value.lasttime), // 实时行情最新时间
  78. newPrice = quote.value.last; // 实时行情最新价
  79. const oldTime = lastIndex === -1 ? newTime : moment(state.rawDate[lastIndex]); // 历史行情最后时间
  80. const diffTime = newTime.valueOf() - oldTime.valueOf(); // 计算时间差
  81. if (diffTime > cycleMilliseconds * 2) {
  82. // 时间间隔超过两个周期,重新请求历史数据
  83. } else {
  84. // 判断时间差是否大于周期时间
  85. if (lastIndex === -1 || diffTime > cycleMilliseconds) {
  86. oldTime.add(cycleMilliseconds, 'ms');
  87. const newDate = oldTime.format('YYYY-MM-DD HH:mm:ss');
  88. // 新增分时数据
  89. state.rawDate.push(newDate);
  90. close.push(newPrice);
  91. ma5.push('-')
  92. } else {
  93. close[lastIndex] = newPrice; // 更新最后一条记录的收盘价
  94. }
  95. // 更新各种指标
  96. calcIndicator(lastIndex === -1 ? 0 : lastIndex);
  97. // 延迟图表更新,减少卡顿
  98. throttle(() => {
  99. updateOptions();
  100. }, 1000)
  101. }
  102. }
  103. // 监听行情推送
  104. watch(() => quote.value.last, () => {
  105. if (!loading.value) {
  106. updateChartData();
  107. }
  108. })
  109. return {
  110. loading,
  111. showEmpty,
  112. dataIndex,
  113. timeOption,
  114. timeDetail,
  115. initData,
  116. }
  117. }
  118. })
  119. </script>
  120. <style lang="less">
  121. @import './index.less';
  122. </style>