npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

lvc-ui

v0.1.5

Published

LVC 工具库 - Vue 2.x 组件 + 工具集合 (UMD 单文件打包)

Readme

LvcUI

LVC 工具库 — Vue 2.x 组件 + 工具集合(UMD 单文件打包)

一个面向大屏 / 可视化 / 后台管理场景的 Vue 2.x 组件与工具库,全部组件和工具打包为单个 UMD 文件,一次引入即可使用。

在线演示台:https://lvminjie5201314.github.io/music/lvc-ui/

目录


安装

npm install lvc-ui

peerDependencies: 需要项目已安装 Vue 2.6+ / 2.7。


快速开始

ES Module(推荐)

import Vue from 'vue';
import LvcUI from 'lvc-ui';

Vue.use(LvcUI);

CommonJS

const Vue = require('vue');
const LvcUI = require('lvc-ui');

Vue.use(LvcUI);

浏览器 <script> 引入

<!-- 必须先引入 Vue -->
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<!-- 引入 LvcUI(压缩版) -->
<script src="https://unpkg.com/lvc-ui/dist/lvc-ui.min.js"></script>
<!-- window.Vue 存在时会自动注册所有组件,window.LvcUI 可用 -->

注册后即可在模板中使用所有 lvc-* 组件:

<template>
  <lvc-button type="primary" @click="onClick">点击</lvc-button>
  <lvc-select v-model="val" :options="opts" />
</template>

重要:CDN 方式下,所有工具函数都挂在 window.LvcUI 对象上,不会作为顶层全局变量暴露。直接写 createRouter(...)、Bus.emit(...) 会报 ReferenceError: xxx is not defined。必须通过 window.LvcUI.xxx 访问,或先解构:

// ✅ 正确:从 window.LvcUI 解构
const { createRouter, createFetch, Bus, LvcMessage, exportToExcel } = window.LvcUI;

const http = createFetch({ baseURL: '/api' });
const router = createRouter({ base: '/app' });

// ❌ 错误:createRouter 未定义(ReferenceError)
// createRouter({ base: '/app' });

同理,命令式 API 也需通过 window.LvcUI 访问:window.LvcUI.lvcDialog.show({...})、window.LvcUI.LvcLoading.start()、window.LvcUI.exportToExcel({...})。


组件

lvc-button 按钮组件

基础按钮,支持多种类型、朴素/圆角/圆形、加载状态、禁用、图标。

Props

| 名称 | 类型 | 默认值 | 说明 | |------|------|--------|------| | type | String | "default" | 类型:primary / success / warning / danger / info / default | | plain | Boolean | false | 朴素按钮(透明背景) | | round | Boolean | false | 圆角按钮 | | circle | Boolean | false | 圆形按钮 | | disabled | Boolean | false | 禁用 | | loading | Boolean | false | 加载中(显示旋转图标,禁用点击) | | icon | String | "" | 图标类名 |

Events

| 事件名 | 参数 | 说明 | |--------|------|------| | click | event: Event | 点击时触发(disabled/loading 时不触发) |

Slots

| 插槽 | 说明 | |------|------| | default | 按钮文本 |

示例

<lvc-button type="primary">主要按钮</lvc-button>
<lvc-button type="success" plain>朴素成功</lvc-button>
<lvc-button type="danger" round>圆角危险</lvc-button>
<lvc-button type="primary" loading>加载中</lvc-button>
<lvc-button type="info" disabled>禁用</lvc-button>
<lvc-button type="primary" icon="lvc-icon-edit">编辑</lvc-button>

lvc-switch 开关组件

开关选择器,支持自定义颜色、尺寸、禁用。

Props

| 名称 | 类型 | 默认值 | 说明 | |------|------|--------|------| | value | Boolean | false | 状态(v-model) | | disabled | Boolean | false | 禁用 | | width | Number | 34 | 宽度(px) | | height | Number | 18 | 高度(px) | | activeColor | String | "#42A3D6" | 激活背景色 | | inactiveColor | String | "#395E7C" | 未激活背景色 | | dotColor | String | "#ffffff" | 圆点颜色 |

Events

| 事件名 | 参数 | 说明 | |--------|------|------| | input | value: Boolean | v-model 同步 | | change | value: Boolean | 状态变化 |

示例

<lvc-switch v-model="isOpen" />

<lvc-switch
  v-model="enabled"
  :active-color="'#00e5ff'"
  :inactive-color="'#333'"
  :width="40"
  :height="22"
/>

<lvc-switch v-model="locked" disabled />

lvc-odometer 数字滚动组件

数字滚动动画组件,依赖外部 Odometer 库。

Props

| 名称 | 类型 | 默认值 | 说明 | |------|------|--------|------| | value | Number | 0 | 当前数值(变化时触发滚动动画) | | duration | Number | 1000 | 动画时长(ms) | | maxAnimations | Number | Infinity | 最大动画次数 | | unit | String | "" | 单位文本 | | unitSize | String | "inherit" | 单位字号 | | unitPosition | String | "right" | 单位位置:left / right |

Slots

| 插槽 | 说明 | |------|------| | unit-left | 左侧单位(覆盖 prop) | | unit-right | 右侧单位(覆盖 prop) |

示例

<!-- 需先引入 odometer 库(dist 目录已提供) -->
<link rel="stylesheet" href="./dist/odometer-theme-minimal.css" />
<script src="./dist/odometer.min.js"></script>

<lvc-odometer :value="count" :duration="1500" unit="kWh" unit-position="right" />

<lvc-odometer :value="price">
  <template #unit-left><span style="color:#ffd700">$</span></template>
</lvc-odometer>

lvc-load-more 滚动加载更多

基于 IntersectionObserver 的触底加载组件。

Props

| 名称 | 类型 | 默认值 | 说明 | |------|------|--------|------| | loading | Boolean | false | 是否正在加载 | | finished | Boolean | false | 是否已加载完毕 | | distance | String | "0px" | 触发距离(rootMargin 底部) | | container | String | "" | 滚动容器选择器(空=视口) | | loadingText | String | "正在加载更多..." | 加载中文本 | | finishedText | String | "没有更多数据了" | 完成文本 |

Events

| 事件名 | 参数 | 说明 | |--------|------|------| | load | 无 | 触底且非 loading/finished 时触发 |

示例

<div class="list-container" style="height:400px;overflow-y:auto;">
  <div v-for="item in list" :key="item.id">{{ item.name }}</div>
  <lvc-load-more
    :loading="loading"
    :finished="finished"
    container=".list-container"
    @load="loadMore"
  />
</div>
export default {
  data() {
    return { list: [], loading: false, finished: false, page: 1 };
  },
  methods: {
    async loadMore() {
      this.loading = true;
      const data = await fetch(`/api/list?page=${this.page++}`).then(r => r.json());
      this.list.push(...data);
      this.loading = false;
      if (data.length < 10) this.finished = true;
    }
  }
};

lvc-select 下拉选择

下拉选择器,支持清除、禁用项、iframe 跨窗口点击关闭。

Props

| 名称 | 类型 | 默认值 | 说明 | |------|------|--------|------| | value | String | Number | "" | 当前值(v-model) | | options | Array | [] | 选项数组 { label, value, disabled? } | | placeholder | String | "请选择" | 占位文本 | | clearable | Boolean | true | 可清除 |

Events

| 事件名 | 参数 | 说明 | |--------|------|------| | input | option: Object | "" | v-model 同步(清除时为 "") | | change | option: Object | "" | 值变化 | | clear | 无 | 清除时触发 |

示例

<lvc-select v-model="selected" :options="opts" placeholder="请选择" clearable />

<script>
export default {
  data() {
    return {
      selected: '',
      opts: [
        { label: '选项一', value: '1' },
        { label: '选项二', value: '2' },
        { label: '禁用项', value: '3', disabled: true }
      ]
    };
  }
};
</script>

lvc-table 表格

数据表格,支持斑马纹、选择列、列排序、自定义单元格(作用域插槽)。

Props

| 名称 | 类型 | 默认值 | 说明 | |------|------|--------|------| | data | Array | [] | 行数据 | | columns | Array | [] | 列配置 | | stripe | Boolean | true | 斑马纹 | | selection | Boolean | false | 显示选择列 |

columns 配置

| 字段 | 类型 | 说明 | |------|------|------| | label | String | 列标题 | | prop | String | 数据字段名 | | width | String|Number | 列宽 | | align | String | 对齐:left / center / right | | sortable | Boolean | 可排序 |

Events

| 事件名 | 参数 | 说明 | |--------|------|------| | selection-change | rows: Array | 选择变化 | | sort-change | { prop, order } | 排序变化(order: asc/desc/"") |

Scoped Slots

| 插槽名 | 作用域 | 用途 | |--------|--------|------| | header-{prop} | { column } | 自定义表头 | | {prop} | { row, index } | 自定义单元格 |

示例

<lvc-table
  :data="tableData"
  :columns="columns"
  selection
  @selection-change="onSel"
  @sort-change="onSort"
>
  <template #status="{ row }">
    <span :style="{ color: row.status === '在线' ? '#0f0' : '#f00' }">{{ row.status }}</span>
  </template>
</lvc-table>
export default {
  data() {
    return {
      tableData: [
        { id: 1, name: '设备A', status: '在线' },
        { id: 2, name: '设备B', status: '离线' }
      ],
      columns: [
        { label: 'ID', prop: 'id', sortable: true, width: '80' },
        { label: '名称', prop: 'name' },
        { label: '状态', prop: 'status', align: 'center' }
      ]
    };
  },
  methods: {
    onSel(rows) { console.log('选中:', rows); },
    onSort({ prop, order }) { console.log('排序:', prop, order); }
  }
};

lvc-date-picker 日期选择器

日期/日期时间/范围选择器,支持单面板/双面板、时间选择、范围 hover 预览。

Props

| 名称 | 类型 | 默认值 | 说明 | |------|------|--------|------| | value | String | Array | "" | 当前值(范围模式为数组) | | type | String | "date" | 类型,见下 | | rangeSeparator | String | "至" | 范围分隔符 | | singlePanel | Boolean | false | 范围模式单面板 |

type 取值

| type | 说明 | |------|------| | date | 单日期 | | datetime | 单日期+时间 | | daterange | 日期范围 | | datetimerange | 日期时间范围 | | datetimestartorend | 同一天起止时间 |

Events

| 事件名 | 参数 | 说明 | |--------|------|------| | input | value | v-model 同步 | | confirm | value | 点「确定」时触发 |

示例

<!-- 单日期 -->
<lvc-date-picker v-model="date" type="date" />

<!-- 日期时间 -->
<lvc-date-picker v-model="datetime" type="datetime" />

<!-- 日期时间范围(双面板) -->
<lvc-date-picker v-model="range" type="datetimerange" />

<!-- 日期范围(单面板) -->
<lvc-date-picker v-model="range" type="daterange" :single-panel="true" />

lvc-time-picker 时间选择器

时间选择器(时:分),支持 24:00 特殊值。

Props

| 名称 | 类型 | 默认值 | 说明 | |------|------|--------|------| | value | String | "00:00" | 时间 HH:mm(v-model) | | disabled | Boolean | false | 禁用 |

Events

| 事件名 | 参数 | 说明 | |--------|------|------| | input | time: String | v-model 同步 | | change | time: String | 确认选择时触发 |

示例

<lvc-time-picker v-model="time" />

<lvc-time-picker v-model="endTime" disabled />

lvc-year-picker 年份选择器

年份/年份范围选择器。

Props

| 名称 | 类型 | 默认值 | 说明 | |------|------|--------|------| | value | String | Array | "" | 当前值(范围模式为数组) | | yearRange | Number | 5 | 面板前后年份范围(共 yearRange*2+1 个) | | type | String | "year" | year / yearrange | | rangeSeparator | String | "至" | 范围分隔符 |

Events

| 事件名 | 参数 | 说明 | |--------|------|------| | input | value | v-model 同步 | | confirm | value | 点「确定」时触发 | | change | value | 点「确定」时触发 |

示例

<lvc-year-picker v-model="year" type="year" />

<lvc-year-picker v-model="yearRange" type="yearrange" :year-range="5" />

lvc-month-picker 月份选择器

月份/月份范围选择器。

Props

| 名称 | 类型 | 默认值 | 说明 | |------|------|--------|------| | value | String | Array | "" | 格式 YYYY-MM(范围模式为数组) | | type | String | "month" | month / monthrange | | rangeSeparator | String | "至" | 范围分隔符 | | singlePlaceholder | String | "请选择月份" | 单选占位符 | | startPlaceholder | String | "开始月份" | 范围起始占位符 | | endPlaceholder | String | "结束月份" | 范围结束占位符 |

Events

| 事件名 | 参数 | 说明 | |--------|------|------| | input | value | v-model 同步 | | confirm | value | 点「确定」时触发 |

示例

<lvc-month-picker v-model="month" type="month" />

<lvc-month-picker v-model="monthRange" type="monthrange" />

lvc-tree 树形控件

递归树,支持节点选择、展开/折叠、三态复选框、过滤、勾选数量限制。

Props

| 名称 | 类型 | 默认值 | 说明 | |------|------|--------|------| | data | Array | [] | 树形数据 | | selectedId | String | Number | null | 当前选中节点 ID | | defaultExpandAll | Boolean | false | 默认展开所有节点 | | showCheckbox | Boolean | false | 显示复选框 | | defaultCheckedKeys | Array | [] | 默认勾选的 key | | maxCheck | Number | 0 | 最多勾选叶子数(0=不限) | | filterNodeMethod | Function | null | 过滤方法 (text, node) => Boolean | | autoExpandOnFilter | Boolean | true | 过滤时自动展开匹配节点 |

节点数据结构

{
  id: String|Number,      // 必填
  label: String,          // 必填
  icon: String,           // 可选: 'folder'|'meter'|'data'|'device'|'default'
  expanded: Boolean,      // 可选: 初始展开
  children: Array         // 可选: 子节点
}

Events

| 事件名 | 参数 | 说明 | |--------|------|------| | select | node: Object | 节点选中(showCheckbox 模式下不触发) | | toggle | { node, expanded } | 展开/折叠 | | check-change | { node, checked, indeterminate, checkedKeys, checkedNodes } | 复选框变化 | | max-check-exceeded | { max, actual } | 超过 maxCheck 限制 | | filter-change | text: String | 过滤文本变化 |

Methods(通过 ref 调用)

| 方法名 | 参数 | 返回值 | 说明 | |--------|------|--------|------| | filter | text: String | - | 过滤(会清空勾选) | | getCheckedKeys | - | Array | 获取勾选的 key | | setCheckedKeys | keys: Array | - | 设置勾选 | | getHalfCheckedKeys | - | Array | 获取半选 key |

示例

<lvc-tree
  ref="tree"
  :data="treeData"
  :selected-id="selectedId"
  show-checkbox
  :max-check="20"
  :filter-node-method="filterFn"
  @select="onSelect"
  @check-change="onCheck"
/>

<script>
export default {
  data() {
    return {
      treeData: [
        {
          id: 1, label: '根节点', icon: 'folder', children: [
            { id: 2, label: '子节点1', icon: 'meter' },
            { id: 3, label: '子节点2', icon: 'data' }
          ]
        }
      ],
      selectedId: null
    };
  },
  methods: {
    filterFn(text, node) {
      return node.label.includes(text);
    },
    onSelect(node) { console.log('选中:', node); },
    onCheck({ checkedKeys }) { console.log('勾选:', checkedKeys); },
    getChecked() {
      return this.$refs.tree.getCheckedKeys();
    }
  }
};
</script>

lvc-dialog 对话框

模态对话框,支持模板用法和命令式 API。

Props

| 名称 | 类型 | 默认值 | 说明 | |------|------|--------|------| | visible | Boolean | false | 是否显示(.sync) | | title | String | "提示" | 标题 | | content | String | "" | 内容文本(被默认插槽覆盖时无效) | | width | String | "44.32vmin" | 宽度 | | confirmText | String | "确定" | 确认按钮文本 | | cancelText | String | "取消" | 取消按钮文本 | | showCancel | Boolean | true | 显示取消按钮 | | showClose | Boolean | true | 显示关闭按钮 | | showFooter | Boolean | true | 显示底部按钮区 | | closeOnClickModal | Boolean | true | 点击遮罩关闭 |

Events

| 事件名 | 参数 | 说明 | |--------|------|------| | update:visible | false | .sync 同步 | | close | - | 关闭 | | cancel | - | 取消 | | confirm | - | 确认(不自动关闭,由父级控制) |

Slots

| 插槽 | 说明 | |------|------| | default | 自定义主体内容 |

示例(模板用法)

<lvc-dialog :visible.sync="visible" title="编辑" @confirm="onConfirm">
  <p>自定义内容</p>
</lvc-dialog>

<script>
export default {
  data() { return { visible: false }; },
  methods: {
    onConfirm() {
      // 处理确认逻辑
      this.visible = false;
    }
  }
};
</script>

命令式用法见 lvcDialog 命令式对话框。


工具

Bus 跨窗口通讯总线

跨 iframe / 跨标签页的事件总线,支持 request-response 模式。

特性

  • 跨 iframe:postMessage 广播
  • 跨标签页:BroadcastChannel + localStorage 双通道
  • 支持 request-response

API

| 方法名 | 参数 | 返回值 | 说明 | |--------|------|--------|------| | on | event, fn | - | 监听事件 | | off | event, fn? | - | 移除监听(不传 fn 清空该事件全部) | | once | event, fn | - | 监听一次 | | emit | event, data | - | 触发事件 | | request | event, data, timeout=5000 | Promise | 请求-响应(超时 reject "timeout") |

示例

import { Bus } from 'lvc-ui';

// 监听
Bus.on('refresh', () => loadData());

// 监听并返回数据(供 request 调用)
Bus.on('getUser', () => ({ name: 'admin', role: 'root' }));

// 触发
Bus.emit('refresh', { id: 1 });

// 请求-响应
const user = await Bus.request('getUser');
console.log(user); // { name: 'admin', role: 'root' }

createFetch HTTP 请求封装

基于 fetch 的 HTTP 客户端工厂,支持拦截器、重试、缓存、去重、轮询、loading 监听。

工厂函数

import { createFetch } from 'lvc-ui';

const http = createFetch({
  baseURL: '/api',
  timeout: 10000,
  retries: 1,
  getToken: () => localStorage.getItem('myToken')
});

全局配置

| 字段 | 类型 | 默认值 | 说明 | |------|------|--------|------| | baseURL | String | "" | 基础 URL | | headers | Object | { "Content-Type": "application/json" } | 默认请求头 | | timeout | Number | 10000 | 超时(ms) | | retries | Number | 1 | 重试次数 | | retryDelay | Number | 500 | 重试延迟 | | cache | Number | 0 | GET 缓存时间(ms),0=不缓存 | | credentials | String | "same-origin" | fetch credentials | | responseType | String | "json" | json/text/blob | | concurrency | Number | Infinity | 最大并发 | | dedupe | Boolean | true | 相同请求去重 | | debounce | Number | 200 | 去抖(ms),0=不去抖 | | getToken | Function | () => localStorage.getItem("emstoken") | 取 token | | refreshToken | AsyncFunction | - | 刷新 token | | onRefreshFail | Function | - | 刷新失败回调 | | onError | Function | - | 错误回调 | | showLog | Boolean | false | 打印日志 |

实例方法

| 方法名 | 参数 | 返回值 | 说明 | |--------|------|--------|------| | get | url, opts={} | Promise | GET | | post | url, body, opts={} | Promise | POST | | put | url, body, opts={} | Promise | PUT | | delete | url, opts={} | Promise | DELETE | | request | options | Promise | 通用请求 | | poll | url, payload={}, options={} | poller | 启动轮询 | | stopAllPoll | - | - | 停止所有轮询 | | createCancelToken | - | { signal, cancel } | 创建可取消 token | | onLoading | cb | unsubscribe | 监听 loading 计数 | | setToken | token \| null | - | 设置/清除 token | | interceptors | - | - | 拦截器 { request, response } |

轮询示例

const poller = http.poll('/metrics', {}, {
  interval: 3000,
  callback: (data) => console.log('metrics:', data)
});

poller.on('error', err => console.error(err));

// 停止
poller.stop();

拦截器示例

http.interceptors.request.handlers.push({
  fulfilled: (config) => {
    config.headers['X-Custom'] = 'value';
    return config;
  },
  rejected: (err) => {}
});

createRouter Hash 路由

轻量级 Hash 路由,支持前置守卫、嵌套层级、登录鉴权。

工厂函数

import { createRouter } from 'lvc-ui';

const router = createRouter({
  routes: {
    home: { path: '#/home', meta: { requiresAuth: true } },
    settings: '#/settings',
    about: { path: '#/about' }
  },
  default: 'home',
  level: 1
});

配置

| 字段 | 类型 | 说明 | |------|------|------| | routes | Object | 路由表 { name: "path" \| { path, meta } } | | default | String | 默认路由名 | | level | Number | 路由层级(hash 第几段) | | loginPage | String | 登录页跳转地址 |

router 方法

| 方法名 | 参数 | 说明 | |--------|------|------| | init | vm | 初始化(绑定 Vue 实例,监听 hashchange) | | push | name | 跳转 | | beforeEach | fn | 注册前置守卫 fn(to, from, next) | | resolve | - | 解析当前 hash |

守卫 next 行为

  • next() / next(undefined):放行
  • next(false):中止
  • next("routeName"):重定向

示例

router.init(this);

router.beforeEach((to, from, next) => {
  console.log('跳转:', from, '->', to);
  next();
});

router.push('settings');

SocketClient WebSocket 客户端

带心跳、自动重连、消息分发的 WebSocket 客户端。

构造函数

import { SocketClient } from 'lvc-ui';

const ws = new SocketClient('ws://example.com/ws', {
  heartbeatInterval: 30000,
  reconnectInterval: 5000,
  maxReconnectAttempts: 5,
  pingMessage: 'ping'
});

配置

| 字段 | 类型 | 默认值 | 说明 | |------|------|--------|------| | heartbeatInterval | Number | 30000 | 心跳间隔(ms) | | reconnectInterval | Number | 5000 | 重连基础间隔 | | maxReconnectAttempts | Number | 5 | 最大重连次数(-1=无限) | | pingMessage | String | "ping" | 心跳内容 |

实例方法

| 方法名 | 参数 | 说明 | |--------|------|------| | send | data: Object\|String | 发送消息(未连接时入队列) | | on | eventName, callback | 监听事件 | | off | eventName, callback? | 移除监听 | | close | - | 手动关闭(不再重连) |

消息分发规则

收到消息后 JSON.parse,取 resData.topic 或 resData.type 作为事件名触发监听器,同时触发通用 message 事件。

示例

const ws = new SocketClient('ws://localhost:8080');

// 监听业务事件(由后端消息的 topic/type 字段决定)
ws.on('chat', (data) => {
  console.log('收到消息:', data);
});

// 监听原始消息
ws.on('message', (msg) => {
  console.log('raw:', msg);
});

// 发送
ws.send({ type: 'chat', text: 'hello' });

// 关闭
ws.close();

CanvasTopologyUtils Canvas 拓扑工具

Canvas 拓扑图绘制工具,支持节点、连线、流光动画、图片缓存、DPR 适配。

构造函数

import { CanvasTopologyUtils } from 'lvc-ui';

const topo = new CanvasTopologyUtils('myCanvas', '#container', 1280);

| 参数 | 类型 | 说明 | |------|------|------| | canvasId | String | Canvas 元素 ID | | containerSelector | String | 父容器选择器(用于尺寸适配) | | baseWidth | Number | 设计稿基准宽度,默认 1280 |

实例方法

| 方法名 | 参数 | 说明 | |--------|------|------| | init | - | 初始化画布 | | s | val: Number | 缩放转换(设计稿 px → 实际 px) | | clear | - | 清空画布 | | drawNode | x, y, r, color, label, isSub=false, labelY=15, fontS=12 | 绘制拓扑节点 | | drawNodeImgText | { url, x, y, w, h, text, ... } | 绘制图片+文字节点 | | drawFlowLine | points, options | 绘制流光动画虚线 | | drawDashLine | points, options | 绘制虚线 | | drawImage | url, x, y, w, h, isCenter=true | 绘制图片 | | drawText | text, x, y, options | 绘制文字 | | drawCircle | x, y, r, options | 绘制圆 | | drawPolygon | points, options | 绘制多边形 | | drawFlowCurve | p1, p2, offset | 绘制流动贝塞尔连线 |

points 路径格式

  • [x, y] → 直线
  • [cpX, cpY, x, y] → 二阶贝塞尔
  • [cp1X, cp1Y, cp2X, cp2Y, x, y] → 三阶贝塞尔

示例

const topo = new CanvasTopologyUtils('topoCanvas', '.topo-container', 1280);
topo.init();

// 绘制节点
topo.drawNode(100, 100, 20, '#00e5ff', '节点A');
topo.drawNode(300, 100, 20, '#ff9800', '节点B');

// 绘制流光连线(requestAnimationFrame 中持续更新 offset)
function animate() {
  topo.clear();
  topo.drawNode(100, 100, 20, '#00e5ff', '节点A');
  topo.drawNode(300, 100, 20, '#ff9800', '节点B');
  topo.drawFlowLine([[120, 100], [280, 100]], { offset: Date.now() / 30 });
  requestAnimationFrame(animate);
}
animate();

px2EchartsUrils ECharts 像素适配

将设计稿 px 转换为当前屏幕实际 px(模拟 vmin 逻辑,用于 ECharts 字号适配)。

API

import { px2EchartsUrils } from 'lvc-ui';

px2EchartsUrils.px2Echarts(pxValue, desWidth = 1280, desHeight = 800, keep1px = true);

| 参数 | 类型 | 说明 | |------|------|------| | pxValue | Number | 设计稿像素值 | | desWidth | Number | 设计稿宽度,默认 1280 | | desHeight | Number | 设计稿高度,默认 800 | | keep1px | Boolean | 是否对 1px 做保护,默认 true |

返回:保留 2 位小数的 Number。

示例

const fontSize = px2EchartsUrils.px2Echarts(14); // 在 1920×1080 屏幕上可能返回 16.80

// 在 ECharts 配置中使用
const option = {
  xAxis: {
    axisLabel: { fontSize: px2EchartsUrils.px2Echarts(12) }
  }
};

LvcLoading 全局 Loading

全局加载遮罩,支持单例、文本更新、过渡动画。

API

import { LvcLoading } from 'lvc-ui';

LvcLoading.show(options);  // 显示(字符串简写: show("加载中"))
LvcLoading.close();        // 关闭

show() 返回 instance 对象:

| 方法名 | 参数 | 说明 | |--------|------|------| | setText | text: String | 更新文本 | | close | - | 关闭 |

示例

// 浏览器全局
LvcLoading.show('加载中...');
await fetchData();
LvcLoading.close();

// Vue 组件内
this.$lvcLoading.show({ text: '提交中' });

// 更新文本
const inst = LvcLoading.show('处理中');
inst.setText('快好了');
inst.close();

LvcMessage 全局消息提示

全局消息提示,支持 info/success/warning/error 四种类型。

API

import { LvcMessage } from 'lvc-ui';

LvcMessage(options);              // 直接调用
LvcMessage("提示文本");            // 字符串简写
LvcMessage.success(options);      // 成功
LvcMessage.warning(options);      // 警告
LvcMessage.info(options);         // 信息
LvcMessage.error(options);        // 错误

options

| 字段 | 类型 | 默认值 | 说明 | |------|------|--------|------| | type | String | "info" | info/success/warning/error | | message | String | "" | 文本 | | duration | Number | 2000 | 显示时长(ms),0=不自动关闭 |

示例

LvcMessage.success('保存成功');
LvcMessage.error({ message: '网络错误', duration: 5000 });
LvcMessage.warning('请注意');
LvcMessage.info('提示');

// Vue 组件内
this.$lvcMessage.error('出错了');

lvcDialog 命令式对话框

命令式对话框 API,无需在模板中声明,直接调用即可弹出。

API

import { lvcDialog } from 'lvc-ui';

lvcDialog.show(options);

options

| 字段 | 类型 | 说明 | |------|------|------| | title | String | 标题 | | content | String | 内容文本 | | width | String | 宽度 | | confirmText | String | 确认按钮文本 | | cancelText | String | 取消按钮文本 | | showCancel | Boolean | 显示取消按钮 | | showFooter | Boolean | 显示底部按钮区 | | closeOnClickModal | Boolean | 点击遮罩关闭 | | onConfirm | () => Promise<Boolean\|undefined> | 确认回调(返回 false 阻止关闭) | | onCancel | Function | 取消回调 |

示例

import { lvcDialog } from 'lvc-ui';

// 简单提示
lvcDialog.show({
  title: '提示',
  content: '操作成功'
});

// 确认删除
lvcDialog.show({
  title: '确认删除',
  content: '确定要删除这条记录吗?',
  confirmText: '删除',
  cancelText: '取消',
  onConfirm: async () => {
    await deleteRecord();
    // 返回 false 可阻止关闭
  },
  onCancel: () => console.log('cancelled')
});

exportToExcel Excel 导出

Excel/CSV 文件导出工具,支持两种格式:

  • CSV(默认):无额外依赖,Excel 可直接打开,自动加 BOM 头解决中文乱码
  • XLSX:支持列宽、表头合并、单元格样式配置,需引入 xlsx-js-style 库(暴露全局 XLSX)

API

import { exportToExcel } from 'lvc-ui';

exportToExcel(data); // 返回 Promise<void>

data 数据格式

| 字段 | 类型 | 默认值 | 说明 | |------|------|--------|------| | fileName | String | "导出数据" | 文件名(不含扩展名) | | headers | Array | — | 表头数组(最后一行表头) | | data | Array | — | 二维数据数组 | | format | String | "csv" | 导出格式:csv / xlsx | | colWidth | Object | — | 列宽配置(仅 xlsx 有效,key 从 1 开始,如 {1: 50, 3: 100}) | | headerMerges | Array | — | 表头合并配置(仅 xlsx 有效) | | cellStyle | Object | — | 单元格样式配置(仅 xlsx 有效) |

headerMerges 配置

| 字段 | 类型 | 说明 | |------|------|------| | row | Number | 合并起始行(从 0 开始) | | col | Number | 合并起始列(从 0 开始) | | rowspan | Number | 合并行数(默认 1) | | colspan | Number | 合并列数(默认 1) | | value | String | 合并单元格显示的文本 |

示例

import { exportToExcel } from 'lvc-ui';

// CSV 导出(默认格式,无依赖)
exportToExcel({
  fileName: '用户列表',
  headers: ['姓名', '年龄', '城市'],
  data: [
    ['张三', 25, '北京'],
    ['李四', 30, '上海'],
    ['王五', 28, '深圳']
  ]
});

// XLSX 导出(需先引入 xlsx-js-style 库,暴露全局 XLSX)
// <script src="https://unpkg.com/xlsx-js-style/dist/xlsx.bundle.js"></script>
exportToExcel({
  fileName: '销售报表',
  format: 'xlsx',
  headers: ['产品', '销量', '金额'],
  data: [
    ['商品A', 120, 3600],
    ['商品B', 85, 2550]
  ],
  colWidth: { 1: 20, 2: 15, 3: 15 },
  headerMerges: [
    { row: 0, col: 0, colspan: 3, value: '2026 年销售统计' }
  ],
  cellStyle: {
    alignment: { vertical: 'center', horizontal: 'center' },
    font: { name: 'Calibri', sz: 11, bold: false },
    fill: { patternType: 'solid', fgColor: { rgb: 'FFFFFF' } }
  }
});

getRootWindow 获取根窗口

获取当前页面的根窗口(顶层 window)。用于跨 iframe 场景下定位同源的顶层窗口:若 window.top 同源则返回 window.top,否则(跨域或异常)回退到当前 window。

API

import { getRootWindow } from 'lvc-ui';

const root = getRootWindow(); // 返回 window 对象

CDN 方式下,通过 window.LvcUI.getRootWindow() 或解构 const { getRootWindow } = window.LvcUI; 使用,与其他工具一致。

示例

import { getRootWindow } from 'lvc-ui';

// 跨 iframe 获取根窗口共享状态
const root = getRootWindow();
root.__APP_SHARED__ = root.__APP_SHARED__ || { count: 0 };
root.__APP_SHARED__.count++;

// Bus 通讯也基于根窗口(内部已使用 getRootWindow)

按需引入

除了 Vue.use(LvcUI) 全量注册外,可以单独引入工具函数和组件定义:

// 工具
import { Bus, createFetch, createRouter, SocketClient, CanvasTopologyUtils, px2EchartsUrils, LvcLoading, LvcMessage, lvcDialog, exportToExcel } from 'lvc-ui';

// 组件定义对象(需手动注册)
import { lvcButton, LvcTree, lvcDialogComponent } from 'lvc-ui';

Vue.component('lvc-button', lvcButton);
Vue.component('lvc-tree', LvcTree);

外部依赖

| 依赖 | 说明 | |------|------| | vue@^2.6.0 \|\| ^2.7.0 | peerDependency,必须由项目提供 | | Odometer | lvc-odometer 组件依赖,需在使用前引入 odometer 库全局脚本(dist 目录已提供 odometer.min.js 和 odometer-theme-minimal.css) | | XLSX(xlsx-js-style) | exportToExcel 的 XLSX 格式依赖,需引入 xlsx-js-style 暴露全局 XLSX(CSV 格式无依赖) |

浏览器原生 API(无需引入):fetch、AbortController、WebSocket、IntersectionObserver、BroadcastChannel(可选)、localStorage。


构建

# 安装依赖
npm install

# 构建(生成 dist/lvc-ui.js + dist/lvc-ui.min.js)
npm run build

# 验证打包产物
npm run verify

目录结构

lvc-ui/
├── src/                    # 源文件
│   ├── utils.js            # Canvas 拓扑工具 + ECharts 像素适配
│   ├── bus.js              # 跨窗口通讯总线
│   ├── request.js          # HTTP 请求封装
│   ├── router.js           # Hash 路由
│   ├── socket.js           # WebSocket 客户端
│   ├── lvcLoading.js       # 全局 Loading
│   ├── lvcMessage.js       # 全局消息提示
│   ├── lvcButton.js        # 按钮组件
│   ├── lvcSwitch.js        # 开关组件
│   ├── lvcOdometer.js      # 数字滚动组件
│   ├── lvcLoadMore.js      # 滚动加载更多
│   ├── lvcSelect.js        # 下拉选择
│   ├── lvcTable.js         # 表格
│   ├── lvcDate.js          # 日期选择器
│   ├── lvcTimePicker.js    # 时间选择器
│   ├── lvcYearPicker.min.js    # 年份选择器
│   ├── lvcMonthPicker.min.js   # 月份选择器
│   ├── lvcTree.min.js      # 树形控件
│   └── lvcDialog.js        # 对话框
├── scripts/
│   ├── build.js            # 构建脚本
│   └── verify.js           # 验证脚本
├── dist/
│   ├── lvc-ui.js           # UMD 未压缩(215 KB)
│   └── lvc-ui.min.js       # UMD 压缩(128 KB)
└── package.json

License

MIT