index.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. <template>
  2. <div class="app-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. <app-echarts :option="timeOption" :empty="showEmpty" v-model:index="dataIndex" v-model:loading="loading" @ready="initData" />
  8. </div>
  9. </template>
  10. <script lang="ts" setup>
  11. import { ref, reactive, watch, computed } from 'vue'
  12. import { useDataset } from './dataset'
  13. import { useOptions } from './options'
  14. import { queryHistoryDatas } from '@/services/api/quote'
  15. import moment from 'moment';
  16. import AppEcharts from '@/components/base/echarts/index.vue'
  17. const props = defineProps({
  18. goodsCode: String,
  19. })
  20. const loading = ref(false),
  21. showEmpty = ref(false),
  22. dataIndex = ref(0); // 当前数据索引值
  23. const { state, handleData, calcIndicator } = useDataset();
  24. const { timeOption, initOptions } = useOptions(state);
  25. const timeDetail = computed(() => {
  26. const { close, ma5 } = state.dataset.source;
  27. return {
  28. close: close[dataIndex.value],
  29. ma5: ma5[dataIndex.value],
  30. }
  31. });
  32. // 模拟最新价推送
  33. const quote = reactive({
  34. last: 0,
  35. lasttime: new Date(),
  36. });
  37. // 初始化数据
  38. const initData = () => {
  39. showEmpty.value = false;
  40. loading.value = true;
  41. state.dataset.source = {
  42. date: [],
  43. close: [],
  44. ma5: []
  45. }
  46. // 获取历史行情
  47. queryHistoryDatas({
  48. data: {
  49. goodscode: props.goodsCode
  50. },
  51. success: (res) => {
  52. const data = res.data;
  53. if (data.length) {
  54. dataIndex.value = data.length - 1;
  55. handleData(data, () => initOptions(updateChartData));
  56. } else {
  57. showEmpty.value = true;
  58. }
  59. },
  60. complete: () => {
  61. loading.value = false;
  62. }
  63. })
  64. }
  65. // 更新图表数据
  66. const updateChartData = () => {
  67. const { date, close, ma5 } = state.dataset.source,
  68. lastIndex = close.length - 1, // 历史行情最后索引位置
  69. cycleMilliseconds = 60 * 1000, // 一分钟毫秒数
  70. newTime = moment(quote.lasttime), // 实时行情最新时间
  71. newPrice = quote.last; // 实时行情最新价
  72. const oldTime = lastIndex === -1 ? newTime : moment(date[lastIndex]); // 历史行情最后时间
  73. const diffTime = newTime.valueOf() - oldTime.valueOf(); // 计算时间差
  74. if (diffTime > cycleMilliseconds * 2) {
  75. // 时间间隔超过两个周期,重新请求历史数据
  76. } else {
  77. // 判断时间差是否大于周期时间
  78. if (lastIndex === -1 || diffTime > cycleMilliseconds) {
  79. oldTime.add(cycleMilliseconds, 'ms');
  80. const newDate = oldTime.format('YYYY-MM-DD HH:mm:ss');
  81. // 新增分时数据
  82. date.push(newDate);
  83. close.push(newPrice);
  84. ma5.push('-')
  85. } else {
  86. close[lastIndex] = newPrice; // 更新最后一条记录的收盘价
  87. }
  88. // 更新各种指标
  89. calcIndicator(lastIndex === -1 ? 0 : lastIndex);
  90. }
  91. }
  92. // 监听行情推送
  93. watch(() => quote.last, () => {
  94. if (!loading.value) {
  95. updateChartData();
  96. }
  97. })
  98. </script>
  99. <style lang="less">
  100. @import './index.less';
  101. </style>