0510航天交易所ui仿制,代码使用的jiem
lxf
2025-06-21 c42857f46e7c6fa6f8bb0b75f399707789c4ab72
k线添加网格
1 files modified
319 ■■■■■ changed files
src/components/kline-charts/index.vue 319 ●●●●● patch | view | raw | blame | history
src/components/kline-charts/index.vue
@@ -1,196 +1,309 @@
<template>
  <div class="kline-charts">
    <ul class="flex px-32 pb-20 box-border justify-between text-grey fontStyle font-26"
      style="border-bottom:1px solid rgba(68,75,88,0.2);">
      <li v-for="item in timeList" :key="item.id" class="mr-10" :class="{ 'textColor': item.id === timeValue.id }"
        @click="choiceTime(item)">{{ item.text }}</li>
    <ul
      class="flex px-32 pb-20 box-border justify-between text-grey fontStyle font-26"
      style="border-bottom: 1px solid rgba(68, 75, 88, 0.2)"
    >
      <li
        v-for="item in timeList"
        :key="item.id"
        class="mr-10"
        :class="{ textColor: item.id === timeValue.id }"
        @click="choiceTime(item)"
      >
        {{ item.text }}
      </li>
    </ul>
    <div class="relative">
      <div id="kline" class="h-828"></div>
      <div
        class="flex justify-center items-center text-center text-grey absolute left-0 top-0  w-full h-full z-10 mainBackground"
        v-if="chartLoading">
        class="flex justify-center items-center text-center text-grey absolute left-0 top-0 w-full h-full z-10 mainBackground"
        v-if="chartLoading"
      >
        <van-loading type="spinner"></van-loading>
      </div>
    </div>
    <ul class="flex  px-32 py-20 box-border justify-between text-grey font-26" v-if="showBottom"
      style="border-top:1px solid rgba(68,75,88,0.2);">
      <li v-for="item in subTechnicalIndicatorTypes" :key="item" class="mr-20"
        :class="{ 'textColor': typeValue === item }" @click="choiceType(item)">{{ item }}</li>
    <ul
      class="flex px-32 py-20 box-border justify-between text-grey font-26"
      v-if="showBottom"
      style="border-top: 1px solid rgba(68, 75, 88, 0.2)"
    >
      <li
        v-for="item in subTechnicalIndicatorTypes"
        :key="item"
        class="mr-20"
        :class="{ textColor: typeValue === item }"
        @click="choiceType(item)"
      >
        {{ item }}
      </li>
    </ul>
  </div>
</template>
<script>
import { init, dispose } from 'klinecharts'
let chart = null
import { _getKline } from '@/API/trade.api'
import config from './config'
import { Loading } from 'vant';
import { init, dispose } from "klinecharts";
let chart = null;
import { _getKline } from "@/API/trade.api";
import config from "./config";
import { Loading } from "vant";
import { scientificNotationToString } from "@/utils/utis";
export default {
  name: 'KlineCharts',
  name: "KlineCharts",
  data() {
    return {
      // symbol: 'btc',
      dealInfo: {},//交易对信息
      dealInfo: {}, //交易对信息
      timeValue: {}, // 当前k线周期
      subTechnicalIndicatorTypes: ['MA', 'EMA', 'BOLL', 'VOL', 'MACD', 'KDJ', 'RSI'],
      typeValue: 'VOL',//图形类型
      klinecharts: null,//K线图实例
      subTechnicalIndicatorTypes: [
        "MA",
        "EMA",
        "BOLL",
        "VOL",
        "MACD",
        "KDJ",
        "RSI",
      ],
      typeValue: "VOL", //图形类型
      klinecharts: null, //K线图实例
      chart: null,
      // resolution: '1',//分辨率
      // lang: 'en', //语言
      chartLoading: true, //加载动画
      paneId: '',
      paneId: "",
      chartData: [], // 图表数据
      timer: null
    }
      timer: null,
      grid: {
        show: true,
        horizontal: {
          show: true,
          size: 0.1,
          color: "#f0f0f0",
          style: "dashed",
          dashedValue: [1, 2],
        },
        vertical: {
          show: true,
          size: 0.1,
          color: "#f0f0f0",
          style: "dashed",
          dashedValue: [1, 2],
        },
      },
    };
  },
  computed: {
    timeList() {
      return [
        { id: '1min', time: '1min', text: this.$t('分时'), ts: 1 * 60 * 1000 },
        { id: '1mins', time: '1min', text: '1' + this.$t('分'), ts: 1 * 60 * 1000 },
        { id: '5min', time: '5min', text: '5' + this.$t('分'), ts: 5 * 60 * 1000 },
        { id: '15min', time: '15min', text: '15' + this.$t('分'), ts: 15 * 60 * 1000 },
        { id: '30min', time: '30min', text: '30' + this.$t('分'), ts: 30 * 60 * 1000 },
        { id: '60min', time: '60min', text: '1' + this.$t('小时'), ts: 60 * 60 * 1000 },
        { id: '4hour', time: '4hour', text: '4' + this.$t('小时'), ts: 4 * 60 * 60 * 1000 },
        { id: '1day', time: '1day', text: '1' + this.$t('天'), ts: 24 * 60 * 60 * 1000 },
        { id: '1week', time: '1week', text: '1' + this.$t('周'), ts: 7 * 24 * 60 * 60 * 1000 },
        { id: '1mon', time: '1mon', text: '1' + this.$t('月'), ts: 30 * 24 * 60 * 60 * 1000 }
      ]//时间列表
    }
        { id: "1min", time: "1min", text: this.$t("分时"), ts: 1 * 60 * 1000 },
        {
          id: "1mins",
          time: "1min",
          text: "1" + this.$t("分"),
          ts: 1 * 60 * 1000,
        },
        {
          id: "5min",
          time: "5min",
          text: "5" + this.$t("分"),
          ts: 5 * 60 * 1000,
        },
        {
          id: "15min",
          time: "15min",
          text: "15" + this.$t("分"),
          ts: 15 * 60 * 1000,
        },
        {
          id: "30min",
          time: "30min",
          text: "30" + this.$t("分"),
          ts: 30 * 60 * 1000,
        },
        {
          id: "60min",
          time: "60min",
          text: "1" + this.$t("小时"),
          ts: 60 * 60 * 1000,
        },
        {
          id: "4hour",
          time: "4hour",
          text: "4" + this.$t("小时"),
          ts: 4 * 60 * 60 * 1000,
        },
        {
          id: "1day",
          time: "1day",
          text: "1" + this.$t("天"),
          ts: 24 * 60 * 60 * 1000,
        },
        {
          id: "1week",
          time: "1week",
          text: "1" + this.$t("周"),
          ts: 7 * 24 * 60 * 60 * 1000,
        },
        {
          id: "1mon",
          time: "1mon",
          text: "1" + this.$t("月"),
          ts: 30 * 24 * 60 * 60 * 1000,
        },
      ]; //时间列表
    },
  },
  components: {
    [Loading.name]: Loading
    [Loading.name]: Loading,
  },
  props: {
    symbol: {
      type: String,
      default: ''
      default: "",
    },
    updateKey: {
      type: Number,
      default: 0
      default: 0,
    },
    updateData: {
      type: Object,
      default() {
        return {}
      }
        return {};
      },
    },
    showBottom: {
      type: Boolean,
      default: true
      default: true,
    },
    isChangeLine: {
      type: Boolean,
      default: false
      default: false,
    },
  },
  mounted() {
    this.initData()
    this.initData();
  },
  beforeDestroy() {
    this.clearTimer()
    dispose('kline')
    this.clearTimer();
    dispose("kline");
  },
  watch: {
    isChangeLine(val) {
      this.clearTimer()
      this.fetchData()
      this.clearTimer();
      this.fetchData();
    },
    updateKey() { // 更新charts
      const dataList = chart.getDataList()
      const lastData = dataList[dataList.length - 1]
      const nowData = this.updateData
      const timeValue = this.timeValue
    updateKey() {
      // 更新charts
      const dataList = chart.getDataList();
      const lastData = dataList[dataList.length - 1];
      const nowData = this.updateData;
      const timeValue = this.timeValue;
      const newData = {
        close: nowData.close / 1,
        current_time: lastData.current_time,
        high: lastData.high > nowData.close / 1 ? lastData.high : (nowData.close / 1),
        high:
          lastData.high > nowData.close / 1 ? lastData.high : nowData.close / 1,
        // high: lastData.high,
        line: timeValue.id,
        low: lastData.low < nowData.close / 1 ? lastData.low : (nowData.close / 1),
        low:
          lastData.low < nowData.close / 1 ? lastData.low : nowData.close / 1,
        // low: lastData.low,
        open: lastData.open,
        symbol: lastData.symbol,
        ts: lastData.ts, //
        timestamp: (nowData.ts - lastData.ts) < timeValue.ts ? lastData.ts : (lastData.ts + timeValue.ts),
        volume: lastData.volume / 1
      }
        timestamp:
          nowData.ts - lastData.ts < timeValue.ts
            ? lastData.ts
            : lastData.ts + timeValue.ts,
        volume: lastData.volume / 1,
      };
      this.$nextTick(() => {
        this.setChartType()
        chart.updateData(newData)
      })
    }
        this.setChartType();
        chart.updateData(newData);
      });
    },
  },
  methods: {
    initData() {
      this.timeValue = this.timeList[0]
      chart = init('kline', config);
      chart.setOffsetRightSpace(25)
      chart.setDataSpace(10)
      chart.setPriceVolumePrecision(4, 2)
      chart.createTechnicalIndicator('MA', false, { id: 'candle_pane' });
      this.paneId = chart.createTechnicalIndicator('VOL');
      this.fetchData()
      this.timeValue = this.timeList[0];
      chart = init("kline", config);
      chart.setOffsetRightSpace(25);
      chart.setDataSpace(10);
      chart.setPriceVolumePrecision(4, 2);
      chart.createTechnicalIndicator("MA", false, { id: "candle_pane" });
      chart.getStyleOptions().grid = this.grid;
      chart.setStyleOptions({
        grid: this.grid,
        // candle: {
        //   upColor: "#FF0000",
        //   downColor: "#00FF00",
        //   borderUpColor: "#FF0000",
        //   borderDownColor: "#00FF00",
        //   wickUpColor: "#FF0000",
        //   wickDownColor: "#00FF00",
        // },
      });
      this.paneId = chart.createTechnicalIndicator("VOL");
      this.fetchData();
    },
    fetchData(time) { // 获取数据
      this.chartLoading = true
    fetchData(time) {
      // 获取数据
      this.chartLoading = true;
      this.timer = setInterval(() => {
        _getKline(this.symbol, this.timeValue.time || time).then(data => {
          this.chartLoading = false
          data.map(item => {
            item.timestamp = item.ts
          })
        _getKline(this.symbol, this.timeValue.time || time).then((data) => {
          this.chartLoading = false;
          data.map((item) => {
            item.timestamp = item.ts;
          });
          //科学计数法时转成字符串
          let str = data[0] ? scientificNotationToString(data[data.length - 1].close.toString()) : ''
          let length = 2
          if (str.indexOf('.') != -1) {
            length = str.split('.')[1].length
          let str = data[0]
            ? scientificNotationToString(data[data.length - 1].close.toString())
            : "";
          let length = 2;
          if (str.indexOf(".") != -1) {
            length = str.split(".")[1].length;
          }
          //let length = data[0] ? data[0].close.toString().split('.')[1].length : 4
          chart.setPriceVolumePrecision(length, 2)
          this.setChartType()
          chart.setPriceVolumePrecision(length, 2);
          this.setChartType();
          chart.applyNewData(data);
          this.$emit('updataLine', false)
        })
          this.$emit("updataLine", false);
        });
      }, 1000);
    },
    setChartType() {
      let type = 'area'
      if (this.timeValue.id === '1min') {
        type = 'area'
      let type = "area";
      if (this.timeValue.id === "1min") {
        type = "area";
      } else {
        type = 'candle_solid'
        type = "candle_solid";
      }
      chart.setStyleOptions({
        candle: {
          type
        }
      })
          type,
        },
      });
    },
    choiceTime(value) { // 选择周期
      this.timeValue = value
      this.clearTimer()
      this.fetchData()
    choiceTime(value) {
      // 选择周期
      this.timeValue = value;
      this.clearTimer();
      this.fetchData();
    },
    choiceType(type) { // 选择副线
      this.typeValue = type
      chart.createTechnicalIndicator(type, false, { id: this.paneId })
    choiceType(type) {
      // 选择副线
      this.typeValue = type;
      chart.createTechnicalIndicator(type, false, { id: this.paneId });
    },
    clearTimer() {
      clearInterval(this.timer)
      this.timer = null
      clearInterval(this.timer);
      this.timer = null;
    },
  },
  deactivated() {
    this.clearTimer()
  }
}
    this.clearTimer();
  },
};
</script>
<style lang="scss" scoped>
.textColor {