vue拖拽

 1. 定义拖拽指令

 2. 使用

 3. 效果

4. 完整代码 

<template>
  <div class="optimization-result-company" v-loading="loading">
    <div class="optimization-result-company-table">
      <AgBasicTable
        style="height: 100%;width:100%"
        :horizontalScrollHidden="true"
        :tableData="tableData"
        :suppressCellSelection="true"
        :columns="columns"
        customOverlayNoRowsTemplate="暂无数据"
      />
    </div>
    <div class="optimization-result-company-scatter_chart">
      <el-empty
        class="optimization-result-company-scatter_chart-empty"
        v-if="tableData.length === 0"
        description=" "
        :image-size="200"
      />
      <div v-else class="optimization-result-company-scatter_chart-data drag-parent">
        <div class="xAxisName">{{ optimizeInfo.optimizeMethodName }}模型得分</div>
        <div class="yAxisName">{{ optimizeInfo.targetTypeName }}得分</div>
        <div class="legend drag_box" v-drag v-if="optimizeInfo.vcorr || optimizeInfo.rcorr">
          <p>相关系数:{{ optimizeInfo.vcorr }}</p>
          <p>排序相关系数:{{ optimizeInfo.rcorr }}</p>
        </div>
        <v-chart autoresize style="width: 100%; height: 100%" :options="option" />
      </div>
    </div>
  </div>
</template>

<script>
import AgBasicTable from "@/pc/components/AgBasicTable.vue";
import { lte } from "lodash";
let tableDataMap = {};
export default {
  name: "OptimizationResult",
  components: {
    AgBasicTable
  },
  props: {
    menuParams: {
      type: Object
    }
  },
  watch: {
    "menuParams.planId"(value) {
      this.getData(value);
    }
  },
  directives: {
    drag: function(el) {
      const dragBox = el; //获取当前元素
      // offsetLeft 是一个只读属性,返回当前元素相对于 offsetParent 节点左边界的偏移像素值。
      dragBox.onmousedown = e => {
        const parentHeight = dragBox.parentNode.offsetHeight;
        const parentWidth = dragBox.parentNode.offsetWidth;
        const currentWidth = dragBox.offsetWidth;
        const currentHeight = dragBox.offsetHeight;
        const rightWidth = parentWidth - currentWidth;
        const topHeight = parentHeight - currentHeight;
        //算出鼠标相对元素的位置
        const disX = e.clientX - dragBox.offsetLeft;
        const disY = e.clientY - dragBox.offsetTop;
        document.onmousemove = e => {
          //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
          let left = e.clientX - disX;
          let top = e.clientY - disY;
          console.log("letft=", left, "top=", top);
          //移动当前元素
          if (left < 0) {
            left = 0;
          }
          if (left > rightWidth) {
            left = rightWidth - 10;
          }
          if (top < 0) {
            top = 0;
          }
          if (top > topHeight) {
            top = topHeight;
          }
          dragBox.style.left = left + "px";
          dragBox.style.top = top + "px";
        };
        document.onmouseup = e => {
          //鼠标弹起来的时候不再移动
          document.onmousemove = null;
          //预防鼠标弹起来后还会循环(即预防鼠标放上去的时候还会移动)
          document.onmouseup = null;
        };
      };
    }
  },
  data() {
    return {
      option: {},
      loading: false,
      tableData: [],
      optimizeInfo: {},
      columns: [
        {
          prop: "companyFullName",
          label: "主体全称",
          minWidth: 220,
          align: "left"
        },
        {
          prop: "companyShortName",
          label: "主体简称",
          minWidth: 100,
          align: "left"
        },
        {
          prop: "targetValue",
          label: "目标值",
          minWidth: 80,
          type: "number"
        },
        {
          prop: "score",
          label: "模型得分",
          minWidth: 80,
          type: "number"
        }
      ]
    };
  },
  methods: {
    async getData(planId) {
      this.loading = true;
      try {
        const data = await this.$api.CreditScore.listOptimizationResult({
          batchId: planId
        });
        this.tableData = data?.optimizationResultList || [];
        if (this.tableData.length === 0) return;
        tableDataMap = this.tableData.reduce((targetMap, cur) => {
          const key = `${cur.score}|${cur.targetValue}`;
          if (!targetMap[key]) {
            targetMap[key] = cur;
          }
          return targetMap;
        }, {});
        this.optimizeInfo = data.optimizeInfo;
        this.initScatterEcharts();
      } finally {
        this.loading = false;
      }
    },
    initScatterEcharts() {
      const data = this.tableData.map(item => [item.score, item.targetValue]);
      this.option = {
        tooltip: {
          formatter: function(params) {
            const info = tableDataMap[`${params.data[0] || ""}|${params.data[1] || ""}`];
            const style = `<div>
                <p>主体名称: ${info.companyFullName || ""}</p>
                <p>目标值: ${info.targetValue?.toFixed(2) || ""}</p>
                <p>模型得分: ${info.score?.toFixed(2) || ""}</p>
              </div>`;
            return style;
          }
        },
        xAxis: {
          splitLine: { show: false },
          scale: true,
          axisLine: {
            lineStyle: { color: "#909399" }
          }
        },
        yAxis: {
          scale: true,
          splitLine: {
            show: false,
            lineStyle: {
              // 使用深浅的间隔色
              color: ["#dde2eb"]
            }
          },
          axisLine: {
            lineStyle: { color: "#909399" }
          }
        },
        grid: { left: "40", top: "10", right: "30", bottom: "40", show: false },
        series: [
          {
            type: "scatter",
            data: data,
            symbolSize: 8,
            itemStyle: { color: "#4e81bf" }
          }
        ]
      };
    }
  },
  created() {
    this.getData(this.menuParams.planId);
  }
};
</script>

<style lang="less" scoped>
.noselect {
  -webkit-touch-callout: none; /* iOS Safari */
  -webkit-user-select: none; /* Chrome/Safari/Opera */
  -khtml-user-select: none; /* Konqueror */
  -moz-user-select: none; /* Firefox */
  -ms-user-select: none; /* Internet Explorer/Edge */
  user-select: none; /* Non-prefixed version, currently*/
}
.optimization-result-company {
  height: 380px;
  border-radius: 2px;
  border: 1px solid rgba(53, 56, 63, 0.1);
  box-sizing: border-box;
  background-color: #fff;
  padding: 8px 10px;
  display: flex;
  flex-direction: row-reverse;
  &-table {
    flex: 1;
    height: calc(100%);
  }
  &-scatter_chart {
    flex: 1;
    &-empty {
      text-align: center;
      ::v-deep.el-empty__image {
        margin: 0 auto;
      }
    }
    &-data {
      width: 100%;
      height: 100%;
      position: relative;
      font-size: 12px;
      font-weight: bold;
      color: rgb(96, 98, 102);
      .xAxisName {
        position: absolute;
        bottom: 0;
        left: 50%;
        transform: translateX(-50%);
        letter-spacing: 1px;
      }
      .yAxisName {
        position: absolute;
        left: 0;
        top: 40%;
        transform: translateY(-50%);
        width: 14px;
        word-wrap: break-word;
        letter-spacing: 1px;
      }
      .legend {
        position: absolute;
        width: 150px;
        top: 8px;
        right: 10px;
        padding: 5px;
        font-weight: normal;
        background: rgba(0, 0, 0, 0.1);
        box-shadow: 3px 3px 6px 3px rgba(0, 0, 0, 0.3);
        cursor: move;
        .noselect();
        z-index: 3000;
        > p::before {
          content: "";
          display: inline-block;
          width: 8px;
          height: 8px;
          background-color: #bd8c46;
          margin-right: 4px;
          vertical-align: inherit;
        }
        &::before {
          content: "";
          position: absolute;
          top: 0;
          bottom: 0;
          left: 0;
          right: 0;
          filter: blur(20px);
          z-index: -1;
          margin: -10px;
        }
      }
    }
  }
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好喝的西北风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值