Vue项目中实现自定义连线图

news2025/7/16 19:18:03

需求描述

在vue项目中实现由自定义块元素组成的连线图。

效果图

连线图

实现思路

Leader-Line 是一个用于 Web 的轻量级 JavaScript 库,专为创建从一个元素指向另一个元素的引导线而设计。它提供了高度自定义的能力,使得开发者能够轻松地在网页上实现各种指引用例,如表单验证指示、界面导航辅助等。该库支持现代浏览器,且不依赖任何大型框架,保证了其灵活性和性能。
利用Leader-Line组件可以实现把不同dom元素进行连接,且连线及箭头可以灵活自定义。

具体步骤

1、环境版本:

Node版本:16.20.2
Leader-Line版本: 1.0.8

2、使用npm或yarn安装leader-line依赖包

npm install leader-line  或  yarn add leader-line

3、找到装好的依赖包,把leader-line.min.js文件复制到自己的拓展工具类函数文件夹下面
例如放置路径:src\plugins\leader-line.min.js

4、在使用的地方引入leader-line.min.js文件

import LeaderLine from "@/plugins/leader-line.min.js";

5、创建连线
在这里插入图片描述

完整代码

<!-- 经营全景看板-产业链经营全景 -->
<template>
  <div class="chain-chart" :class="theme">
    <TabHeader title="产业链经营全景">
      <template #leftBtn>
        <div class="right-select">
          <template>
            <el-select
              class="common-simple-select"
              v-model="searchForm.keyProduct"
              placeholder="选择重点产品"
              :popper-append-to-body="true"
              popper-class="common-search-popper"
              clearable
            >
              <el-option
                v-for="item in keyProductOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              >
              </el-option>
            </el-select>
          </template>
        </div>
      </template>
      <div class="content-container">
        <!-- 销售计划 -->
        <div ref="box1" class="box sales-plan-box common-tab-header-border">
          <div class="corner-decoration top-left"></div>
          <div class="corner-decoration top-right"></div>
          <div class="corner-decoration bottom-left"></div>
          <div class="corner-decoration bottom-right"></div>
          <div class="header">
            <div class="type">计划执行</div>
            <div class="title">销售计划</div>
            <div class="sub-title"></div>
          </div>
          <div class="stats">
            <div class="stat-row">
              <div>本年计划</div>
              <div class="text-box">
                <span class="blue-text">5400</span
                ><span class="unit">万只</span>
              </div>
            </div>
            <div class="stat-row">
              <div>较去年实际</div>
              <div class="arrow">
                <img src="@/assets/icons/up_arrow.png" alt="" />
                <img src="@/assets/icons/down_arrow.png" alt="" v-if="false" />
                3.24%
              </div>
            </div>
            <div class="stat-row">
              <div>上期计划准确率</div>
              <div class="arrow">
                <img src="@/assets/icons/up_arrow.png" alt="" />
                <img src="@/assets/icons/down_arrow.png" alt="" v-if="false" />
                84.22%
              </div>
            </div>
          </div>
          <div class="switch-btns">
            <span :class="{ active: switchBtnState.salesPlan === 'quantity' }" @click="toggleSwitchBtn('salesPlan', 'quantity')"></span>
            <span :class="{ active: switchBtnState.salesPlan === 'amount' }" @click="toggleSwitchBtn('salesPlan', 'amount')"></span>
          </div>
        </div>
        <!-- 销售目标 -->
        <div ref="box2" class="box sales-target-box common-tab-header-border">
          <div class="corner-decoration top-left"></div>
          <div class="corner-decoration top-right"></div>
          <div class="corner-decoration bottom-left"></div>
          <div class="corner-decoration bottom-right"></div>
          <div class="header">
            <div class="type">计划执行</div>
            <div class="title">销售目标</div>
            <div class="sub-title" @click="toPath('/strategeAnalysis/pages/842?catalogId=8')">专题分析</div>
          </div>
          <div class="stats">
            <div class="stat-row">
              <div>本年达成率</div>
              <div class="text-box">
                <span class="red-text">75%</span>
                <!-- <img
                  src="@/assets/icons/tips_icon.png"
                  alt=""
                  class="tips-icon"
                /> -->
                <i class="el-icon-warning tips-icon"></i>
              </div>
            </div>
            <div class="stat-row">
              <div>本年实际量</div>
              <div class="text-box">
                <span class="blue-text">5400</span
                ><span class="unit">万只</span>
              </div>
            </div>
            <div class="stat-row">
              <div>同比</div>
              <div class="arrow">
                <img src="@/assets/icons/up_arrow.png" alt="" v-if="false" />
                <img src="@/assets/icons/down_arrow.png" alt="" />
                4.22%
              </div>
            </div>
          </div>
          <div class="switch-btns">
            <span :class="{ active: switchBtnState.salesTarget === 'quantity' }" @click="toggleSwitchBtn('salesTarget', 'quantity')"></span>
            <span :class="{ active: switchBtnState.salesTarget === 'amount' }" @click="toggleSwitchBtn('salesTarget', 'amount')"></span>
          </div>
        </div>
        <!-- 供应商履约 -->
        <div ref="box3" class="box supplier-box common-tab-header-border">
          <div class="corner-decoration top-left"></div>
          <div class="corner-decoration top-right"></div>
          <div class="corner-decoration bottom-left"></div>
          <div class="corner-decoration bottom-right"></div>
          <div class="header">
            <div class="type">计划执行</div>
            <div class="title">供应商履约</div>
            <div class="sub-title"></div>
          </div>
          <div class="stats">
            <div class="stat-row">
              <div>准时交付率</div>
              <div class="text-box">
                <span class="blue-text">85%</span>
              </div>
            </div>
            <div class="stat-row">
              <div>质量合格率</div>
              <div class="text-box">
                <span class="blue-text">90%</span>
              </div>
            </div>
            <div class="stat-row">
              <div>原料总用量</div>
              <div class="text-box">
                <span>5400</span><span class="unit">万只</span>
              </div>
            </div>
          </div>
        </div>
        <!-- 协议签订 -->
        <div ref="box4" class="box order-sign-box common-tab-header-border">
          <div class="corner-decoration top-left"></div>
          <div class="corner-decoration top-right"></div>
          <div class="corner-decoration bottom-left"></div>
          <div class="corner-decoration bottom-right"></div>
          <div class="header">
            <div class="type">计划执行</div>
            <div class="title">协议签订</div>
            <div class="sub-title"></div>
          </div>
          <div class="stats">
            <div class="stat-row">
              <div>本年履约率</div>
              <div class="text-box">
                <span class="blue-text">75%</span>
              </div>
            </div>
            <div class="stat-row">
              <div>本年协议量</div>
              <div class="text-box">
                <span>4400</span><span class="unit">万只</span>
              </div>
            </div>
            <div class="stat-row">
              <div>本年实际量</div>
              <div class="text-box">
                <span>3400</span><span class="unit">万只</span>
              </div>
            </div>
          </div>
          <div class="switch-btns">
            <span :class="{ active: switchBtnState.orderSign === 'quantity' }" @click="toggleSwitchBtn('orderSign', 'quantity')"></span>
            <span :class="{ active: switchBtnState.orderSign === 'amount' }" @click="toggleSwitchBtn('orderSign', 'amount')"></span>
          </div>
        </div>
        <!-- 生产计划 -->
        <div ref="box5" class="box prod-plan-box common-tab-header-border">
          <div class="corner-decoration top-left"></div>
          <div class="corner-decoration top-right"></div>
          <div class="corner-decoration bottom-left"></div>
          <div class="corner-decoration bottom-right"></div>
          <div class="header">
            <div class="type">计划执行</div>
            <div class="title">生产计划</div>
            <div class="sub-title"></div>
          </div>
          <div class="stats">
            <div class="stat-row">
              <div>生产成本</div>
              <div class="text-box">
                <span class="blue-text">XX万元</span>
              </div>
            </div>
            <div class="stat-row">
              <div>生产计划量</div>
              <div class="text-box">
                <span>600</span><span class="unit">万只</span>
              </div>
            </div>
            <div class="stat-row">
              <div>排产准确率</div>
              <div class="text-box">
                <span>100%</span>
              </div>
            </div>
          </div>
        </div>
        <!-- 订单情况 -->
        <div ref="box6" class="box order-detail-box common-tab-header-border">
          <div class="corner-decoration top-left"></div>
          <div class="corner-decoration top-right"></div>
          <div class="corner-decoration bottom-left"></div>
          <div class="corner-decoration bottom-right"></div>
          <div class="header">
            <div class="type">销售执行</div>
            <div class="title">订单情况</div>
            <div class="sub-title"></div>
          </div>
          <div class="stats">
            <div class="stat-row">
              <div>订单满足率</div>
              <div class="text-box">
                <span class="blue-text">75%</span>
              </div>
            </div>
            <div class="stat-row">
              <div>紧急订单占比</div>
              <div class="text-box">
                <span class="red-text">40%</span>
              </div>
            </div>
            <div class="stat-row">
              <div>未满足订单量</div>
              <div class="text-box">
                <span>3400</span><span class="unit">万只</span>
              </div>
            </div>
          </div>
        </div>
        <!-- 采购合同 -->
        <div ref="box7" class="box purchase-contract-box common-tab-header-border">
          <div class="corner-decoration top-left"></div>
          <div class="corner-decoration top-right"></div>
          <div class="corner-decoration bottom-left"></div>
          <div class="corner-decoration bottom-right"></div>
          <div class="header">
            <div class="type">采购执行</div>
            <div class="title">采购合同</div>
            <div class="sub-title"></div>
          </div>
          <div class="stats">
            <div class="stat-row">
              <div>生产采购成本</div>
              <div class="text-box">
                <span class="blue-text">XX万元</span>
              </div>
            </div>
            <div class="stat-row">
              <div>采购成本同比</div>
              <div class="text-box">
                <span>4.22%</span>
              </div>
            </div>
            <div class="stat-row">
              <div>采购成本环比</div>
              <div class="text-box">
                <span>2.31%</span>
              </div>
            </div>
          </div>
        </div>
        <!-- 回款情况 -->
        <div ref="box8" class="box collect-situation-box common-tab-header-border">
          <div class="corner-decoration top-left"></div>
          <div class="corner-decoration top-right"></div>
          <div class="corner-decoration bottom-left"></div>
          <div class="corner-decoration bottom-right"></div>
          <div class="header">
            <div class="type">销售执行</div>
            <div class="title">回款情况</div>
            <div class="sub-title" @click="toPath('/strategeAnalysis/pages/856?catalogId=25')">专题分析</div>
          </div>
          <div class="stats">
            <div class="stat-row">
              <div>应收账款逾期率</div>
              <div class="text-box">
                <span class="red-text">20%</span>
              </div>
            </div>
            <div class="stat-row">
              <div>回款周期</div>
              <div class="text-box">
                <span>85</span>
              </div>
            </div>
            <div class="stat-row">
              <div>预期总金额</div>
              <div class="text-box">
                <span>5000</span>
              </div>
            </div>
          </div>
        </div>
        <!-- 发货情况 -->
        <div ref="box9" class="box send-situation-box common-tab-header-border">
          <div class="corner-decoration top-left"></div>
          <div class="corner-decoration top-right"></div>
          <div class="corner-decoration bottom-left"></div>
          <div class="corner-decoration bottom-right"></div>
          <div class="header">
            <div class="type">物流执行</div>
            <div class="title">发货情况</div>
            <div class="sub-title"></div>
          </div>
          <div class="stats">
            <div class="stat-row">
              <div>准时发货率</div>
              <div class="text-box">
                <span class="blue-text">90%</span>
              </div>
            </div>
            <div class="stat-row">
              <div>已发货总量</div>
              <div class="text-box">
                <span>11</span><span class="unit">万只</span>
              </div>
            </div>
            <div class="stat-row">
              <div>已发货总金额</div>
              <div class="text-box">
                <span>500</span>
              </div>
            </div>
          </div>
        </div>
        <!-- 库存管理 -->
        <div ref="box10" class="box inventory-manage-box common-tab-header-border">
          <div class="corner-decoration top-left"></div>
          <div class="corner-decoration top-right"></div>
          <div class="corner-decoration bottom-left"></div>
          <div class="corner-decoration bottom-right"></div>
          <div class="header">
            <div class="type">物流执行</div>
            <div class="title">库存管理</div>
            <div class="sub-title" @click="toPath('/strategeAnalysis/pages/863?catalogId=41')">专题分析</div>
          </div>
          <div class="stats">
            <div class="stat-row">
              <div>可用库存可销月</div>
              <div class="text-box">
                <span class="blue-text">3个月</span>
              </div>
            </div>
            <div class="stat-row">
              <div>库存周转天数</div>
              <div class="text-box">
                <span>80</span>
              </div>
            </div>
            <div class="stat-row">
              <div>半年内近效期库存占比</div>
              <div class="text-box">
                <span class="red-text">10%</span>
              </div>
            </div>
          </div>
        </div>
         <!-- 生产执行 -->
         <div ref="box11" class="box prod-execution-box common-tab-header-border">
          <div class="corner-decoration top-left"></div>
          <div class="corner-decoration top-right"></div>
          <div class="corner-decoration bottom-left"></div>
          <div class="corner-decoration bottom-right"></div>
          <div class="header">
            <div class="type">生产执行</div>
            <div class="title">生产执行</div>
            <div class="sub-title"></div>
          </div>
          <div class="stats">
            <div class="stat-row">
              <div>生产批次合格率</div>
              <div class="text-box">
                <span class="blue-text">100%</span>
              </div>
            </div>
            <div class="stat-row">
              <div>已生产总量</div>
              <div class="text-box">
                <span>10</span><span class="unit">万只</span>
              </div>
            </div>
            <div class="stat-row">
              <div>紧急生产占比</div>
              <div class="text-box">
                <span>10%</span>
              </div>
            </div>
          </div>
        </div>
          <!-- 商业库存 -->
          <div ref="box12" class="box business-inventory-box common-tab-header-border">
          <div class="corner-decoration top-left"></div>
          <div class="corner-decoration top-right"></div>
          <div class="corner-decoration bottom-left"></div>
          <div class="corner-decoration bottom-right"></div>
          <div class="header">
            <div class="type">商业流通</div>
            <div class="title">商业库存</div>
            <div class="sub-title"></div>
          </div>
          <div class="stats">
            <div class="stat-row">
              <div>商业库存总量</div>
              <div class="text-box">
                <span class="blue-text">50</span><span class="unit">万只</span>
              </div>
            </div>
            <div class="stat-row">
              <div>库存过低</div>
              <div class="text-box">
                <span class="red-text">16</span>
              </div>
            </div>
            <div class="stat-row">
              <div>库存过高</div>
              <div class="text-box">
                <span>13</span>
              </div>
            </div>
          </div>
        </div>
         <!-- 终端覆盖 -->
         <div ref="box13" class="box terminal-coverage-box common-tab-header-border">
          <div class="corner-decoration top-left"></div>
          <div class="corner-decoration top-right"></div>
          <div class="corner-decoration bottom-left"></div>
          <div class="corner-decoration bottom-right"></div>
          <div class="header">
            <div class="type">终端分析</div>
            <div class="title">终端覆盖</div>
            <div class="sub-title"  @click="toPath()">专题分析</div>
          </div>
          <div class="stats">
            <div class="stat-row">
              <div>目标终端覆盖率</div>
              <div class="text-box">
                <span class="blue-text">75%</span>
              </div>
            </div>
            <div class="stat-row">
              <div>纯销总量</div>
              <div class="text-box">
                <span>10</span><span class="unit">万只</span>
              </div>
            </div>
            <div class="stat-row">
              <div>未开发终端总量</div>
              <div class="text-box">
                <span>XX</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </TabHeader>
  </div>
</template>

<script>
import TabHeader from "@/components/common_components/tabHeader.vue";
import LeaderLine from "@/plugins/leader-line.min.js";
import { Notification } from 'element-ui'

export default {
  components: {
    TabHeader,
  },
  props: {
    width: {
      type: Number,
      default: null,
    },
    height: {
      type: Number,
      default: null,
    },
    theme: {
      type: String,
      default: "theme-dark",
    },
  },
  data() {
    return {
      lines: [],
      switchBtnState: {
        salesPlan: 'quantity', // 销售计划
        salesTarget: 'quantity', // 销售目标
        orderSign: 'quantity', // 协议签订
      },
      keyProductOptions: [
        {
          label: "重点产品1",
          value: "1",
        },
        {
          label: "重点产品2",
          value: "2",
        },
        {
          label: "重点产品3",
          value: "3",
        },
      ],
      searchForm: {
        keyProduct: ''
      }
    };
  },
  computed: {},
  mounted() {
    // id为当前页id的时候才做初始化查询
    if (this.$route.params.id == 865) {
      this.$nextTick(() => {
        this.initLines();
      });
    }
    // 添加窗口大小变化的监听
    window.addEventListener('resize', this.debounceResize);
  },
  beforeDestroy() {
    // 组件销毁前清除所有连线
    this.lines.forEach((line) => line.remove());
    // 移除窗口大小变化的监听
    window.removeEventListener('resize', this.debounceResize);
  },
  methods: {
    toggleSwitchBtn(boxName, value) {
      this.switchBtnState[boxName] = value;
    },
    // 防抖处理
    debounceResize: function() {
      if (this.resizeTimer) clearTimeout(this.resizeTimer);
      this.resizeTimer = setTimeout(() => {
        this.handleResize();
      }, 200);
    },
    // 处理窗口大小变化
    handleResize() {
      // 清除现有的连线
      if (this.lines && this.lines.length > 0) {
        this.lines.forEach((line) => {
          if (line && typeof line.remove === 'function') {
            line.remove();
          }
        });
        this.lines = [];
      }
      // 重新初始化连线
      this.$nextTick(() => {
        this.initLines();
      });
    },
    initLines() {
      // 确保所有ref都存在
      const refs = ['box1', 'box2', 'box3', 'box4', 'box5', 'box6', 'box7', 'box8', 'box9', 'box10', 'box11', 'box12', 'box13'];
      const missingRefs = refs.filter(ref => !this.$refs[ref]);
      if (missingRefs.length > 0) {
        return;
      }

      try {
        // 创建连线
        // 销售计划-销售目标
        const line1 = new LeaderLine(this.$refs.box1, this.$refs.box2, {
          color: "#0e75ed", // 连线颜色
          size: 1, // 连线粗细
          path: "straight", // 连线类型
          startSocket: "bottom", // 起点位置
          endSocket: "top", // 终点位置
          endPlug: 'behind' // 终点插件
        });
        // 销售计划-协议签订
        const line2 = new LeaderLine(this.$refs.box1, this.$refs.box4, {
          color: "#0e75ed",
          size: 1,
          path: "grid",
          startSocket: "right",
          endSocket: "top",
          endPlug: 'behind' 
        });
        // 销售计划-订单情况
        const line3 = new LeaderLine(this.$refs.box1, this.$refs.box6, {
          color: "#0e75ed",
          size: 1,
          path: "grid",
          startSocket: "right",
          endSocket: "top",
          endPlug: 'behind' 
        });
        // 订单情况-生产计划
        const line4 = new LeaderLine(this.$refs.box6, this.$refs.box5, {
          color: "#0e75ed",
          size: 1,
          path: "straight",
          startSocket: "bottom",
          endSocket: "top",
          endPlug: 'behind' 
        });
        // 生产计划-供应商履约
        const line5 = new LeaderLine(this.$refs.box5, this.$refs.box3, {
          color: "#0e75ed",
          size: 1,
          path: "straight",
          startSocket: "left",
          endSocket: "right",
          endPlug: 'behind' 
        });
        // 采购合同-生产计划
        const line6 = new LeaderLine(this.$refs.box7, this.$refs.box5, {
          color: "#0e75ed",
          size: 1,
          path: "straight",
          startSocket: "left",
          endSocket: "right",
          endPlug: 'behind'
        });
        // 回款情况-商业库存
        const line7 = new LeaderLine(this.$refs.box8, this.$refs.box12, {
          color: "#0e75ed",
          size: 1,
          path: "grid",
          startSocket: "top",
          endSocket: "top",
          endPlug: 'behind'
        });
        // 发货情况-商业库存
        const line8 = new LeaderLine(this.$refs.box9, this.$refs.box12, {
          color: "#0e75ed",
          size: 1,
          path: "straight",
          startSocket: "right",
          endSocket: "left",
          endPlug: 'behind'
        });
        // 发货情况-库存管理
        const line9 = new LeaderLine(this.$refs.box9, this.$refs.box10, {
          color: "#0e75ed",
          size: 1,
          path: "straight",
          startSocket: "bottom",
          endSocket: "top",
          endPlug: 'behind'
        });
        // 库存管理-生产执行
        const line10 = new LeaderLine(this.$refs.box10, this.$refs.box11, {
          color: "#0e75ed",
          size: 1,
          path: "straight",
          startSocket: "bottom",
          endSocket: "top",
          endPlug: 'behind'
        });
         // 生产执行-采购合同
         const line11 = new LeaderLine(this.$refs.box11, this.$refs.box7, {
          color: "#0e75ed",
          size: 1,
          path: "straight",
          startSocket: "left",
          endSocket: "right",
          endPlug: 'behind'
        });
         // 商业库存-终端覆盖
         const line12 = new LeaderLine(this.$refs.box12, this.$refs.box13, {
          color: "#0e75ed",
          size: 1,
          path: "straight",
          startSocket: "bottom",
          endSocket: "top",
          endPlug: 'behind'
        });
        this.lines = [line1, line2, line3, line4, line5, line6, line7, line8, line9, line10, line11, line12];
      } catch (error) {
        console.error('Error initializing lines:', error);
      }
    },
    // 路由跳转
    toPath(url) {
      if(!url) return  Notification.warning({
          title: '提示',
          message: '功能开发中',
        })
      this.$router.push(url)
    }
  },
};
</script>

<style lang="scss">
@import "~@/assets/css/variables.scss";
.chain-chart {
  height: 100%;
  .content-container {
    padding: vw(5) vw(10);
    height: calc(100% - vw(10));
    position: relative;
  }

  .box {
    background: rgba(12, 51, 101, 0.6);
    box-shadow: inset 0px 0px vw(25) 0px rgba(10, 77, 154, 0.6);
    // border: 1px solid #0e75ed;
    padding: vw(8);
    width: vw(240);
    color: #fff;
    font-family: "Microsoft YaHei", Arial, sans-serif;
    .header {
      display: flex;
      flex-direction: row;
      flex-wrap: nowrap;
      align-content: center;
      justify-content: space-between;
      border-bottom: 1px solid #0e75ed;
      padding-bottom: vw(5);
      align-items: center;
      .type {
        font-size: vw(11);
        border: 1px solid #0e75ed;
        padding: vw(2) vw(8);
        border-radius: vw(8);
      }
      .title {
        font-size: vw(15);
        font-weight: 600;
        margin-right: vw(12);
      }
      .sub-title {
        font-size: vw(11);
        color: #b0c4de;
        margin-right: vw(5);
        min-width: vw(35);
        cursor: pointer;
      }
    }
    .stats {
      margin-top: vw(5);
      .stat-row {
        display: flex;
        justify-content: space-between;
        align-items: center;
        font-size: vw(13);
        margin-bottom: vw(4);

        .blue-text {
          font-size: vw(16);
          color: #1bb7c7;
          font-weight: bold;
          margin-right: vw(3);
        }
        .unit {
          font-size: vw(12);
          color: #fff;
          margin-left: vw(2);
        }
        .red-text {
          font-size: vw(16);
          color: $defaultRedColor;
          font-weight: bold;
          margin-right: vw(3);
        }
        .text-box {
          display: flex;
          align-items: center;
        }
        .tips-icon {
          font-size: vw(18);
          color: $defaultYellowColor;
          margin-left: vw(5);
        }
        .arrow img {
          height: vw(12);
        }
      }
    }
    .switch-btns {
      margin-top: vw(6);
      display: flex;
      gap: vw(8);
      justify-content: flex-end;
      span {
        padding: vw(2) vw(10);
        border-radius: vw(8);
        border: 1px solid #0e75ed;
        color: #1bb7c7;
        cursor: pointer;
        font-size: vw(12);
        &.active {
          background: #0e75ed;
          color: #fff;
        }
      }
    }
  }
  // 销售计划
  .sales-plan-box {
    position: absolute;
    left: vw(10);
    top: vw(5);
  }
  // 销售目标
  .sales-target-box {
    position: absolute;
    left: vw(10);
    top: 37%;
  }
  // 供应商履约
  .supplier-box {
    position: absolute;
    left: vw(10);
    top: 74.5%;
  }
  // 协议签订
  .order-sign-box {
    position: absolute;
    left: 17.5%;
    top: 37%;
  }
  // 生产计划
  .prod-plan-box {
    position: absolute;
    left: 34%;
    top: 75%;
  }
  // 订单情况
  .order-detail-box {
    position: absolute;
    left: 34%;
    top: 37%;
  }
  // 采购合同
  .purchase-contract-box {
    position: absolute;
    left: 50.5%;
    top: 75%;
  }
  // 回款情况
  .collect-situation-box {
    position: absolute;
    left: 50.5%;
    top: 37%;
  }
  // 发货情况
  .send-situation-box {
    position: absolute;
    left: 67.5%;
    top: 10%;
  }
  // 库存管理
  .inventory-manage-box {
    position: absolute;
    left: 67.5%;
    top: 42%;
  }
  // 生产执行
  .prod-execution-box {
    position: absolute;
    left: 67.5%;
    top: 75%;
  }
  // 商业库存
  .business-inventory-box {
    position: absolute;
    right: vw(30);
    top: 9.5%;
  }
  // 终端覆盖
  .terminal-coverage-box {
    position: absolute;
    right: vw(30);
    top: 42%;
  }
}
</style>

注意

leader-line组件目前不支持直接引入依赖,需要下载对应leader-line.min.js文件,通过import文件才能正常使用。

报错排查方向

在这里插入图片描述
1、检查引入方式;
2、下载下来的leader-line.min.js该文件仅仅定义了一个LeaderLine 函数 ,并没有使用任何模块导出语句 (即没有module.export 或者 es6 export 导出语句)

针对第2个原因造成的报错,直接在leader-line.min.js后面增加导出语句即可
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2372449.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++编程语言:标准库:标准库概观(Bjarne Stroustrup)

第30章 标准库概观(Standard-Library Overview) 目录 30.1 引言 30.1.1 标准库设施 30.1.2 设计约束 30.1.3 描述风格 30.2 头文件 30.3 语言支持 30.3.1 对initializer_list的支持 30.3.2 对范围for的支持 30.4 异常处理 30.4.1 异常 30.4.1…

Shiro(八):JWT介绍

1、什么是JWT&#xff1f; JWT&#xff08;JSON Web Token&#xff0c;JSON Web令牌&#xff09;是一种开放标准&#xff08;RFC 7519&#xff09;&#xff0c;用于在网络应 用环境间安全地传递声明&#xff08;claims&#xff09;作为JSON对象&#xff1b;JWT会按指定的加密算…

【HDLBits刷题】Verilog Language——1.Basics

目录 一、题目与题解 1.Simple wire&#xff08;简单导线&#xff09; 2.Four wires&#xff08;4线&#xff09; 3.Inverter&#xff08;逆变器&#xff08;非门&#xff09;&#xff09; 4.AND gate &#xff08;与门&#xff09; 5. NOR gate &#xff08;或非门&am…

Python 常用内置函数详解(十):help()函数——查看对象的帮助信息

目录 一、语法参考二、示例 一、语法参考 help() 函数的语法格式如下&#xff1a; 参数说明&#xff1a; request&#xff1a;可选参数&#xff0c;要查看其帮助信息的对象&#xff0c;如类、函数、模块、数据类型等&#xff1b;返回值&#xff1a;返回对象的帮助信息。 二…

【Python系列】Python 中的 HTTP 请求处理

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

辉芒微离线烧录器“文件格式错误”问题解决

最近在使用辉芒微离线烧录器烧录程序时&#xff0c;提示“文件格式错误”&#xff0c;记录一下解决方法。 一、问题现象 经过多次尝试和排查&#xff0c;发现以下几种情况&#xff1a; 情况一&#xff1a;使用离线烧录器导入固件1&#xff08;boot程序&#xff09;&#xff0c…

【软件设计师:体系结构】15.计算机体系结构概论

计算机体系结构是指计算机系统的功能和属性,是程序员所看到的计算机的属性。它主要研究计算机体系的概念性结构和功能特性,包括指令集、数据类型、存储器寻址技术、I/O机制等。例如,计算机是否具备乘法指令的功能,这是一个体系结构的问题。 一、机内代码及运算 一、数的进…

vscode 配置doxygen注释和snippet

vscode 配置doxygen注释和snippet Doxygen的C/C注释原则 基于Doxygen的C/C注释原则 标注总述 1.文件头标注 2. 命名空间标注 3. 类、结构、枚举标注 4. 函数注释原则 5. 变量注释 6. 模块标注 7. 分组标注指令表格 命令字段名语法file文件名file [< name >]brief简介b…

HarmonyOS NEXT 免费无广告看电影app:从想法到实现的经验总结

学习一项新技能&#xff0c;最好也是最快的方法就是动手实战。学习鸿蒙也一样&#xff0c;给自己定一个小目标&#xff0c;直接找项目练,这样进步是最快的。最近&#xff0c;我在网上看到360周董的一句话&#xff1a;“想干什么就去干&#xff0c;干得烂总比不干强&#xff01;…

代码随想论图论part06冗余连接

图论part06 冗余连接 代码随想录 冗余边就是已经边已经在并查集里了&#xff0c;从图的角度来说构成了环&#xff08;冗余连接2要用到这个概念&#xff09; 代码其他部分为&#xff1a;并查集初始化&#xff0c;查根&#xff0c;判断是否在集合里&#xff0c;加入集合 冗余…

企业高性能WEB服务器—Nginx

Nginx介绍 Nginx是一款轻量级的网页服务器、反向代理服务器以及电子邮件代理服务器。 具有高并发&#xff08;特别是静态资源&#xff09;、占用系统资源少的特性。它不仅是Web服务软件&#xff0c;还具有反向代理负载均衡功能和缓存服务功能 具备如下基本特性 可针对静态资…

Python MNE-Python 脑功能磁共振数据分析

一、什​​么​​是​​Python MNE-Python 脑​​功​​能​​磁​​共​​振​​数​​据​​分​​析 为大脑功能磁共振成像数据分析工具&#xff0c;致力于为神经科学研究提供便捷、高效的数据分析处理工具。MNE-Python提供了处理和分析脑电图&#xff08;EEG&#xff09;、…

DevExpressWinForms-AlertControl-使用教程

文章目录 AlertControl-使用教程一、将 AlertControl 添加到 Form二、编辑 AlertControl 的 HtmlTemplateHTML Template Editor介绍编辑HTML Template 三、使用AlertControl弹出AlertAlert中的按钮事件获取 Alert 标题等信息向Alert传递参数 总结源码 AlertControl-使用教程 一…

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】电商数据分析案例-9.4 可视化报告输出

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 电商数据分析实战&#xff1a;基于PostgreSQL的可视化报告生成全流程9.4 可视化报告输出9.4.1 可视化报告设计框架9.4.1.1 报告目标与受众9.4.1.2 数据准备与指标体系 9.4.2…

屎上雕花系列-2nd

以下为“屎上雕花”的尝试2nd 使用Deepseek扩容而来&#xff0c;我竟然没有找到明显的错误&#xff0c;太强大了&#xff0c;工作改变生活了 LeCroy 以太网与 SAN 网络测试解决方案 硬件平台一&#xff1a;Xena 以太网流量生成器 Xena 以太网流量生成器是一款高性能的网络测…

MCP专题| 突破LLM三大瓶颈!模型上下文协议(MCP)如何重塑AI交互体验?

最近引爆了整个AI圈的Model Context Protocol&#xff08;MCP&#xff09;到底是什么&#xff1f;你是否也和小编一样一头雾水&#xff0c;不是说好的LLM风潮呢&#xff0c;怎么现在变成通信协议啦&#xff1f;最近小编也是找到一篇神仙综述&#xff0c;带你一遍搞清什么是MCP的…

我的AD快捷键方案【留存】

留存我的快捷键方案文件&#xff0c;以便换电脑的时候能够快速导入快捷键。 我的快捷键文件&#xff1a; 通过网盘分享的文件&#xff1a;JB20250509.DXPPrf 链接: https://pan.baidu.com/s/1t6V0GjdGFPNSFydP5Z_tfg?pwde4xs 提取码: e4xs 复制这段内容后打开百度网盘手机Ap…

Edwards爱德华STP泵软件用于操作和监控涡轮分子泵

Edwards爱德华STP泵软件用于操作和监控涡轮分子泵

QT6(35)4.8定时器QTimer 与QElapsedTimer:理论,例题的界面搭建,与功能的代码实现。

&#xff08;112&#xff09; &#xff08;113&#xff09;模仿随书老师给的源代码搭建的&#xff0c; LCD 显示的部分不一样 &#xff1a; &#xff08;114&#xff09;以下开始代码完善&#xff1a; 关联定时器的信号与槽函数 &#xff1a; &#xff08;115&#xff09;…

02 mysql 管理(Windows版)

一、启动及关闭 MySQL 服务器 1.1 通过 “服务” 管理工具 winr打开运行&#xff0c;输入services.msc 找到MySQL80&#xff0c;这个是我们在安装mysql的时候给的服务的名称&#xff0c;具体见文章mysql 安装 右键选择启动或者停止。 1.2 通过命令提示符 1.2.1 关闭命令…