gantt

$("#gantttable").on('mouseover mousemove','.progress',function(e,b,c){
    console.log(e);
    let parentleft=e.target.style.transform.replace(/\D/g,'');
    let left=Number(parentleft)+e.offsetX+40;  
    let top=e.target.offsetTop+e.offsetY+40;  
    $(e.target).prev().css({
        "display":"block",
        "position":"absolute",
        "background":"red",
        "left":left+'px',
        "top":top+'px',
        "z-index":'999',
    })
    })

    $("#gantttable").on('mouseout','.progress',function(e,b,c){
       
        $(e.target).prev().css({
            "display":"none",
           
        })
 })

<template>
  <div class="box" ref="box">
    <div class="placeholder" v-show="!ganttTitleDate.length">暂无数据</div>
    <div class="top" v-show="ganttTitleDate.length">
      <div v-for="item in ganttTitleDate" :key="item.id">{{ item.name }}</div>
    </div>
    <div class="main" v-show="ganttTitleDate.length">
      <div class="row" v-for="(item, index) in calcList" :key="item.id">
        <div class="posx" :style="{ width: width + 'px' }">
          <!-- 蓝色 -->

          <div v-show="false">{{ `${item.planTimeScope}` }}</div>
          <div
            class="progress"
            slot="reference"
            :style="handlecalc(item, ['planStartTime', 'planEndTime'])"
            @mouseenter="handlerMouseenter($event, '1popover' + index)"
          ></div>

          <div v-show="false">
            <div class="vc-toolbox" v-if="item.status === '2'">
              <p style="text-align: center">{{ item.actTimeScope || "" }}</p>

              <div v-if="item.weekbackTime">
                <p style="text-align: center">最新周反馈:</p>
                <p>周时间段: {{ item.weekbackTime }}</p>
                <p>周反馈内容:</p>
                <p>{{ item.weekbackContent }}</p>
              </div>

              <p style="text-align: center" v-else>最新周反馈:无</p>
            </div>
            <div v-else>{{ `${item.actTimeScope}` }}</div>
          </div>

          <div
            class="progress"
            slot="reference"
            :class="getStyleclass(item.status, index, 'class')"
            :style="handlecalc(item, ['actStartTime', 'actEndTime'])"
            @mouseenter="handlerMouseenter($event, '2popover' + index)"
          ></div>
        </div>

        <!-- <div class='fixed1'>111</div>
        <div class='fixed2'>22</div>-->
        <div v-for="item in ganttTitleDate" :key="item.id" class="cell"></div>
      </div>
    </div>
    <div class="point_line" v-if="showpointline" :style="{ left: showpointlineleft + 'px' }"></div>
  </div>
</template>

<script>
import dayjs from "dayjs"; // 导入日期js

const uuidv4 = () =>
  "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
    const r = (Math.random() * 16) | 0;
    const v = c == "x" ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
export default {
  props: {
    type: {
      default: "月",
      type: String,
    },
    isfullscreen: {
      default: false,
      type: Boolean,
    },
    listshow: {
      default: () => [],
      type: Array,
    },
  },
  data() {
    return {
      startTime: "2023-01-01",
      endTime: "2026-01-01",
      width: "",
      ganttTitleDate: [],
      list: [],
      showpointline: false,
      showpointlineleft: 0,
    };
  },
  computed: {
    //显示的数据 listshow
    calcList() {
      if (Array.isArray(this.listshow) && Array.isArray(this.list)) {
        return this.list.filter((item, index) => this.listshow.includes(index));
      }
      return [];
    },
    // 单元格宽度
    cellWidth() {
      if (this.width && this.ganttTitleDate.length) {
        return parseInt(this.width / this.ganttTitleDate.length);
      }
      return 0;
    },
  },
  directives: {
    tooltip(el, binding) {
      const config = binding.value || {};
      const classname = `${config.type || ""}_tootip`;
      // 鼠标移入时,将浮沉元素插入到body中
      el.onmouseenter = function (e) {
        // 创建浮层元素并设置样式
        const vcTooltipDom = document.createElement("div");
        vcTooltipDom.style.cssText = `
                  position:absolute;
                  font-size:14px;
                  z-index:1000
            `;
        // 设置id方便寻找
        vcTooltipDom.setAttribute("id", "vc-tooltip");
        vcTooltipDom.setAttribute("class", classname);
        // 将浮层插入到body中
        document.body.appendChild(vcTooltipDom);

        // 浮层中的文字 通过属性值传递动态的显示文案
        document.getElementById("vc-tooltip").innerHTML = config.text;
      };
      // 鼠标移动时,动态修改浮沉的位置属性
      el.onmousemove = function (e) {
        const vcTooltipDom = document.getElementById("vc-tooltip");
        vcTooltipDom.style.top = `${e.clientY + 15}px`;
        vcTooltipDom.style.left = `${e.clientX + 15}px`;
      };
      // 鼠标移出时将浮层元素销毁
      el.onmouseleave = function () {
        // 找到浮层元素并移出
        const vcTooltipDom = document.getElementById("vc-tooltip");
        vcTooltipDom && document.body.removeChild(vcTooltipDom);
      };
    },
  },
  watch: {
    type(val) {
      this.typechange();
    },
  },
  mounted() {
    this.init(0);
    // 监听 window.onresize
    // window.addEventListener("resize", this.resize, false);
  },
  beforeDestroy() {
    window.removeEventListener("resize", this.resize);
  },
  methods: {
    typechange() {
      this.ganttTitleDate = this.generateHeader();
      this.handlelist();
      this.resize();
      this.showpointline = false;
      document.getElementById("gantttable").scrollLeft = 0;
    },
    resize() {
      this.width = 0;
      this.$nextTick(() => {
        this.width = this.$refs.box.scrollWidth;
      });
    },
    ganttfix(e) {
      const index = e.number;
      const fixed = this.list[index].planStartTimepos;

      const width = fixed * this.cellWidth;
      this.$refs.box.scrollLeft = width;
    },
    getStyleclass(status, index, type) {
      let result = "info";
      switch (status) {
        case "0":
          result = "info";
          break;
        case "1":
          result = "primary";
          break;
        case "2":
          result = "danger";
          break;
        case "3":
          result = "info";
          break;
        case "4":
          result = "success";
          break;
        case "5":
          result = "warning";
          break;

        default:
          result = "emptyState";
          break;
      }
      if (index === 0 || index === this.list.length - 1) {
        return "primary";
      }
      if (type === "class") {
        return {
          [result]: true,
        };
      }
      return result;
    },
    handlerMouseenter(event, ref) {
      // 鼠标进入触发元素
      const popover = this.$refs[ref][0];

      const timer = setTimeout(() => {
        const { clientX } = event;
        const bodyWidth = document.body.clientWidth;
        // 找到气泡元素
        const { popperElm } = popover;
        /**
         * 鼠标位置+气泡弹框宽度是否小于body的宽度
         * 1. 是,设置鼠标位置为气泡弹框横向位移
         * 2. 否,设置body宽度-气泡弹框宽度为气泡弹框横向位移
         */
        const disX =
          clientX + popperElm.offsetWidth < bodyWidth
            ? clientX
            : bodyWidth - popperElm.offsetWidth;

        popover.popperElm.style.left = `${disX}px`;

        clearTimeout(timer);
      }, 5);
    },
    init(top) {
      this.width = 0;

      this.ganttTitleDate = this.generateHeader();
      this.$nextTick(() => {
        this.width = this.$refs.box.scrollWidth;
      });
      //处理列表 得到所有单元格列+百分比
      this.handlelist();
      // this.$nextTick(() => {
      //   this.$refs.box.scrollTop = top;
      //   this.$refs.box.scrollLeft = 0;
      // });
    },
    // 生成表头
    generateHeader() {
      if (this.startTime === "" && this.endTime === "") {
        return [];
      }
      // 分解开始和结束日期
      const start_date_spilt = dayjs(this.startTime)
        .format("YYYY-M-D")
        .split("-");
      const end_date_spilt = dayjs(this.endTime).format("YYYY-M-D").split("-");
      const start_year = Number(start_date_spilt[0]);
      const start_mouth = Number(start_date_spilt[1]);
      const end_year = Number(end_date_spilt[0]);
      const end_mouth = Number(end_date_spilt[1]);
      let database = [];
      if (this.type === "月") {
        database = this.yearAndMouthTitleDate(
          start_year,
          start_mouth,
          end_year,
          end_mouth
        );
        database = this.databasechange(database);
      } else if (this.type === "年") {
        database = this.yearTitleDate(start_year, end_year);
      } else if (this.type === "季度") {
        database = this.jdTitleDate(
          start_year,
          start_mouth,
          end_year,
          end_mouth
        );
      }

      console.log(database);
      this.$nextTick(() => {
        this.width = this.$refs.box.scrollWidth; //总宽度
      });
      return database;
    },
    //跳转到今天 等
    toTimePos(toTime) {
      //位置+ 容器一半宽度
      if (this.ganttTitleDate.length) {
        if (
          new Date(toTime).valueOf() < new Date(this.startTime).valueOf() ||
          new Date(toTime).valueOf() > new Date(this.endTime).valueOf()
        ) {
          return this.$message.warning("今天不在当前范围");
        }
        let left = document.getElementById("gantttable").offsetWidth / 2;
        const downindex = this.ganttTitleDate.findIndex((item) => {
          return (
            new Date(item.endTime).valueOf() >= new Date(toTime).valueOf() &&
            new Date(item.startTime).valueOf() <= new Date(toTime).valueOf()
          );
        });
        let all =
          new Date(this.ganttTitleDate[downindex].endTime).valueOf() -
          new Date(this.ganttTitleDate[downindex].startTime).valueOf();
        let thisitem =
          new Date(toTime).valueOf() -
          new Date(this.ganttTitleDate[downindex].startTime).valueOf();
        const downratio = (thisitem / all).toFixed(4);
        let width = this.cellWidth * (downindex + Number(downratio));
        this.showpointline = true;
        this.showpointlineleft = width;
        document.getElementById("gantttable").scrollLeft = width - left;
      }
    },
    // 处理list  获取区间width 和偏移量
    handlelist() {
      this.list = this.list.map((item) => this.handlelistitemcalc(item));
    },
    handlelistitemcalcnext(item = {}, fieldmap = ["", ""]) {
      let uppos = []; // 值1为 单元格索引   值2为在单元格的百分比
      let downpos = [];
      const startTime = item[fieldmap[0]];
      const endTime = item[fieldmap[1]];
      const celllenindex = this.ganttTitleDate.length - 1;

      // 开始时间不在区间
      if (new Date(startTime).valueOf() < new Date(this.startTime).valueOf()) {
        uppos = [0, 0];
      } else if (
        new Date(startTime).valueOf() > new Date(this.endTime).valueOf()
      ) {
        uppos = [celllenindex, 100];
      } else {
        if (this.type === "月") {
          const upindex = this.ganttTitleDate.findIndex(
            (item) => item.full_date === dayjs(startTime).format("YYYY-M")
          );
          const upgetMonthDay = this.getMonthDay(
            dayjs(startTime).format("YYYY-M")
          );
          const upday = dayjs(startTime).format("D");
          let upratio = "";
          if (upday == 1) {
            upratio = 0;
          } else if (upday == upgetMonthDay) {
            upratio = 1;
          } else {
            upratio = parseFloat(upday / upgetMonthDay).toFixed(3);
          }

          uppos = [upindex, upratio];
        } else if (this.type === "年") {
          const upindex = this.ganttTitleDate.findIndex(
            (item) => item.full_date === dayjs(startTime).format("YYYY")
          );
          let all =
            new Date(this.ganttTitleDate[upindex].endTime).valueOf() -
            new Date(this.ganttTitleDate[upindex].startTime).valueOf();
          let thisitem =
            new Date(startTime).valueOf() -
            new Date(this.ganttTitleDate[upindex].startTime).valueOf();
          const upratio = (thisitem / all).toFixed(5);
          uppos = [upindex, upratio];
        } else if (this.type === "季度") {
          const upindex = this.ganttTitleDate.findIndex((item) => {
            return (
              new Date(item.endTime).valueOf() >=
                new Date(startTime).valueOf() &&
              new Date(item.startTime).valueOf() <=
                new Date(startTime).valueOf()
            );
          });

          let all =
            new Date(this.ganttTitleDate[upindex].endTime).valueOf() -
            new Date(this.ganttTitleDate[upindex].startTime).valueOf();
          let thisitem =
            new Date(startTime).valueOf() -
            new Date(this.ganttTitleDate[upindex].startTime).valueOf();
          const upratio = (thisitem / all).toFixed(4);
          uppos = [upindex, upratio];
        }
      }
      // 结束时间不在区间
      if (new Date(endTime).valueOf() < new Date(this.startTime).valueOf()) {
        downpos = [0, 0];
      } else if (
        new Date(endTime).valueOf() > new Date(this.endTime).valueOf()
      ) {
        downpos = [celllenindex, 100];
      } else {
        if (this.type === "月") {
          const downindex = this.ganttTitleDate.findIndex(
            (item) => item.full_date === dayjs(endTime).format("YYYY-M")
          );
          const downgetMonthDay = this.getMonthDay(
            dayjs(endTime).format("YYYY-M")
          );
          const downday = dayjs(endTime).format("D");
          let downratio = "";
          if (downday == 1) {
            downratio = 0;
          } else if (downday == downgetMonthDay) {
            downratio = 1;
          } else {
            downratio = parseFloat(downday / downgetMonthDay).toFixed(3);
          }

          downpos = [downindex, downratio];
        } else if (this.type === "年") {
          const downindex = this.ganttTitleDate.findIndex(
            (item) => item.full_date === dayjs(endTime).format("YYYY")
          );
          let all =
            new Date(this.ganttTitleDate[downindex].endTime).valueOf() -
            new Date(this.ganttTitleDate[downindex].startTime).valueOf();
          let thisitem =
            new Date(endTime).valueOf() -
            new Date(this.ganttTitleDate[downindex].startTime).valueOf();
          const downratio = (thisitem / all).toFixed(5);

          downpos = [downindex, downratio];
        } else if (this.type === "季度") {
          const downindex = this.ganttTitleDate.findIndex((item) => {
            return (
              new Date(item.endTime).valueOf() >= new Date(endTime).valueOf() &&
              new Date(item.startTime).valueOf() <= new Date(endTime).valueOf()
            );
          });
          let all =
            new Date(this.ganttTitleDate[downindex].endTime).valueOf() -
            new Date(this.ganttTitleDate[downindex].startTime).valueOf();
          let thisitem =
            new Date(endTime).valueOf() -
            new Date(this.ganttTitleDate[downindex].startTime).valueOf();
          const downratio = (thisitem / all).toFixed(4);
          //--
          downpos = [downindex, downratio];
        }
      }

      return {
        [`${fieldmap[0]}pos`]: uppos[0] + Number(uppos[1]),
        [`${fieldmap[1]}pos`]: downpos[0] + Number(downpos[1]),
      };
    },
    handlelistitemcalc(item) {
      const { actStartTimepos, actEndTimepos } = this.handlelistitemcalcnext(
        item,
        ["actStartTime", "actEndTime"]
      );

      const { planStartTimepos, planEndTimepos } = this.handlelistitemcalcnext(
        item,
        ["planStartTime", "planEndTime"]
      );
      return {
        ...item,
        // 计划
        planStartTimepos,
        planEndTimepos,
        // 实际
        actStartTimepos,
        actEndTimepos,
      };
    },
    // 计算 开头 结尾所在的单元格 //计算 单元格内的具体百分比 //已经是否超出当前区间
    handlecalc(item, fieldmap = ["", ""]) {
      if (
        item[fieldmap[0]] &&
        item[fieldmap[1]] &&
        new Date(item[fieldmap[0]]).valueOf() <=
          new Date(item[fieldmap[1]]).valueOf()
      ) {
        const start = item[`${fieldmap[0]}pos`];
        const end = item[`${fieldmap[1]}pos`];
        const startpx = start * this.cellWidth;
        let progresswidth = end * this.cellWidth - startpx;

        if (
          new Date(item[fieldmap[0]]).valueOf() ===
            new Date(item[fieldmap[1]]).valueOf() &&
          new Date(item[fieldmap[0]]).valueOf() >=
            new Date(this.startTime).valueOf() &&
          new Date(item[fieldmap[0]]).valueOf() <=
            new Date(this.endTime).valueOf()
        ) {
          progresswidth = "3";
        }
        return {
          width: `${progresswidth}px`,
          transform: `translateX(${startpx}px)`,
        };
      }
      return {
        width: 0,
        display: "none",
      };
    },
    // 获取一个月有多少天
    getMonthDay(time) {
      const date = new Date(time);
      date.setMonth(date.getMonth() + 1); // 先设置为下个月
      date.setDate(0); // 再置0,变成当前月最后一天
      return date.getDate();
    },
    databasechange(data) {
      const array = [];
      if (Array.isArray(data) && data.length) {
        data.forEach((item) => {
          if (Array.isArray(item.children) && data.length) {
            item.children.forEach((item2) => {
              let monthdays = new Date(
                item2.full_date.split("-")[0],
                item2.full_date.split("-")[1],
                0
              ).getDate();
              array.push({
                ...item2,
                startTime: item2.full_date + "-1",
                endTime: item2.full_date + "-" + monthdays,
                name: item.name + item2.name,
              });
            });
          }
        });
      }
      return array;
    },
    /**
     * 是否闰年函数
     * year: Number 当前年份
     */
    isLeap(year) {
      return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
    },
    /**
     * 生成月份函数
     * year: Number 当前年份
     * start_num: Number 开始月分
     * end_num:Number 结束月份
     * isLeap: Boolean 是否闰年
     * insert_days: Boolean 是否需要插入 日
     * week: 是否以周的间隔
     */
    generationMonths(
      year,
      start_num = 1,
      end_num = 13,
      isLeap = false,
      insert_days = true,
      week = false
    ) {
      const months = [];
      if (insert_days) {
        // 无需 日 的模式
        for (let i = start_num; i < end_num; i++) {
          // 需要 日 的模式
          const days = this.generationDays(year, i, isLeap, week);
          months.push({
            name: `${i}月`,
            date: i,
            full_date: `${year}-${i}`,
            children: days,
            id: uuidv4(),
          });
        }
        return months;
      }
      for (let i = start_num; i < end_num; i++) {
        // 需要 日 的模式
        months.push({
          name: `${i}月`,
          date: i,
          full_date: `${year}-${i}`,
          id: uuidv4(),
        });
      }
      return months;
    },
    yearTitleDate(start_year, end_year) {
      if (end_year && start_year && end_year >= start_year) {
        let res = [];
        while (start_year <= end_year) {
          res.push({
            name: start_year + "年",
            startTime: start_year + "-1-1", //区间开始时间
            endTime: start_year + "-12-31", //结束开始时间
            full_date: `${start_year}`,
            id: uuidv4(),
          });
          start_year++;
        }

        return res;
      }
      return [];
    },
    jdTitleDate(start_year, start_mouth, end_year, end_mouth) {
      if (end_year && start_year && end_year >= start_year) {
        let timespace = [
          { name: "一", start: "01-01", end: "03-31" },
          { name: "二", start: "04-01", end: "06-30" },
          { name: "三", start: "07-01", end: "09-30" },
          { name: "四", start: "10-01", end: "12-31" },
        ];
        function getQuarterByMonth(month) {
          if (month >= 1 && month <= 3) {
            return 0;
          } else if (month >= 4 && month <= 6) {
            return 1;
          } else if (month >= 7 && month <= 9) {
            return 2;
          } else {
            return 3;
          }
        }
        let jd1 = getQuarterByMonth(start_mouth);
        let jd2 = getQuarterByMonth(end_mouth);
        console.log(jd1, jd2);
        let res = [];
        while (Number(start_year + "." + jd1) <= Number(end_year + "." + jd2)) {
          res.push({
            name: start_year + "年第" + timespace[jd1].name + "季度",
            startTime: start_year + "-" + timespace[jd1].start, //区间开始时间
            endTime: start_year + "-" + timespace[jd1].end, //结束开始时间
            id: uuidv4(),
          });
          jd1++;
          if (jd1 > 3) {
            jd1 = 0;
            start_year++;
          }
          console.log(111);
        }
        return res;
      } else {
        return [];
      }
    },
    yearAndMouthTitleDate(start_year, start_mouth, end_year, end_mouth) {
      // 日期数据盒子
      const dates = [
        {
          name: `${start_year}年`,
          date: start_year,
          id: uuidv4(),
          children: [],
        },
      ];
      // 处理年份
      const year_diff = end_year - start_year;
      // 年间隔小于一年
      if (year_diff === 0) {
        const isLeap = this.isLeap(start_year); // 是否闰年
        const mouths = this.generationMonths(
          start_year,
          start_mouth,
          end_mouth + 1,
          isLeap,
          false
        ); // 处理月份
        dates[0].children = mouths;
        return dates;
      }
      // 处理开始月份
      const startIsLeap = this.isLeap(start_year);
      const start_mouths = this.generationMonths(
        start_year,
        start_mouth,
        13,
        startIsLeap,
        false
      );
      // 处理结束月份
      const endIsLeap = this.isLeap(end_year);
      const end_mouths = this.generationMonths(
        end_year,
        1,
        end_mouth + 1,
        endIsLeap,
        false
      );
      // 年间隔等于一年
      if (year_diff === 1) {
        dates[0].children = start_mouths;
        dates.push({
          name: `${end_year}年`,
          date: end_year,
          children: end_mouths,
          id: uuidv4(),
        });
        return dates;
      }
      // 年间隔大于1年
      if (year_diff > 1) {
        dates[0].children = start_mouths;
        for (let i = 1; i < year_diff; i++) {
          const item_year = start_year + i;
          const isLeap = this.isLeap(item_year);
          const month_and_day = this.generationMonths(
            item_year,
            1,
            13,
            isLeap,
            false
          );
          dates.push({
            name: `${item_year}年`,
            date: item_year,
            id: uuidv4(),
            children: month_and_day,
          });
        }
        dates.push({
          name: `${end_year}年`,
          date: end_year,
          children: end_mouths,
          id: uuidv4(),
        });
        return dates;
      }
    },
  },
};
</script>

<style scoped lang="scss">
.box {
  width: max-content;
  position: relative;
  min-width: 100%;
}
.placeholder {
  display: flex;
  height: 100%;
  width: 100%;
  align-items: center;
  justify-content: center;
  border-right: 1px solid #ccc;
}
.top {
  display: flex;
  position: sticky;
  top: 0;
  z-index: 99;

  > div + div {
    border-left-width: 0;
  }
}
.top > div {
  min-width: 150px;
  border: 1px solid #ccc;
  border-top-width: 0;

  flex: 1;
  text-align: center;
  font-size: 14px;
  font-weight: 700;
  // padding: 10px 0;
  background: #fff;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.row {
  display: flex;
  position: relative;

  > div.cell + div.cell {
    border-left-width: 0;
  }
}
.row > div.cell {
  min-width: 150px;
  border: 1px solid #ccc;
  flex: 1;
  height: 60px;
  border-top-width: 0;
}
.posx {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 10;
  height: 100%;
  width: 100%;
  // overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.progress {
  height: 16px;
  background: #409eff;
}
.progress.success {
  background: #cff1c0;
  margin-top: 5px;
}
.progress.danger {
  background: #fcd9d9;
  margin-top: 5px;
}
.progress.warning {
  background: #f9ecd9;
  margin-top: 5px;
}
.progress.primary {
  background: #c1e0ff;
  margin-top: 5px;
}
</style>
<style lang="scss">
.vc-toolbox {
  max-width: 600px;
  p {
    word-break: break-all;
  }
}
.el-popover.el-popper.success {
  color: #67c23a;
  background: #f0f9eb;
  border-color: #c2e7b0;
}
.el-popover.el-popper.primary {
  color: #409eff;
  background: #ecf5ff;
  border-color: #b3d8ff;
}
.el-popover.el-popper.danger {
  color: #f56c6c;
  background: #fef0f0;
  border-color: #fbc4c4;
}
.el-popover.el-popper.emptyState {
  color: #fff;
  background: #7d7d7d;
  border-color: #7d7d7d;
}
.point_line {
  background: #4881fd;
  width: 2px;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0px;
  z-index: 20;
}
.fixed1 {
  width: 50px;
  height: 20px;
  background: #409eff;
  position: absolute;
  left: 10px;
}
.fixed2 {
  width: 50px;
  height: 20px;
  background: #409eff;
  position: absolute;
  left: 10px;
  top: 20px;
}
</style>

posted @ 2023-08-26 22:28  7c89  阅读(7)  评论(0编辑  收藏  举报