lvc-ui
v0.1.5
Published
LVC 工具库 - Vue 2.x 组件 + 工具集合 (UMD 单文件打包)
Maintainers
Readme
LvcUI
LVC 工具库 — Vue 2.x 组件 + 工具集合(UMD 单文件打包)
一个面向大屏 / 可视化 / 后台管理场景的 Vue 2.x 组件与工具库,全部组件和工具打包为单个 UMD 文件,一次引入即可使用。
在线演示台:https://lvminjie5201314.github.io/music/lvc-ui/
目录
安装
npm install lvc-uipeerDependencies: 需要项目已安装 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.jsonLicense
MIT
