TorUniverSheet 项目笔记整理(完整版)
📦 项目概述
项目名称: tor-univer-sheet
版本: 1.0.5
描述: 基于 Univer 的 Vue3 电子表格组件
作者: tortormore
许可证: MIT
🏗️ 技术栈
| 类别 |
技术 |
版本 |
| 框架 |
Vue |
^3.5.0 |
| UI 库 |
Element Plus |
^2.13.5 |
| 表格核心 |
Univer |
^0.15.5 |
| 构建工具 |
Vite |
^7.3.1 |
| 语言 |
TypeScript |
~5.9.3 |
| 日期处理 |
Dayjs |
^1.11.20 |
| 数值计算 |
Decimal.js |
^10.6.0 |
| Excel 处理 |
Xlsx |
^0.18.5 |
📁 项目结构
src/
├── components/
│ ├── ContentWrap/ # 内容包装组件
│ ├── Form/ # 表单组件
│ ├── GlobalLoading/ # 全局加载组件
│ ├── IndicatorPointSelect/ # 指标选择组件
│ └── UniverSheet/ # 核心表格组件
│ ├── plugins/ # 自定义插件
│ │ ├── importFile/ # 文件导入插件
│ │ ├── indicatorsContextMenu/ # 指标右键菜单插件
│ │ ├── saveButton/ # 保存按钮插件
│ │ ├── syncContextMenu/ # 同步右键菜单插件
│ │ └── timeConfigContextMenu/ # 时间配置右键菜单插件
│ ├── UniverSheet.vue # 主组件
│ ├── UniverSheet.data.ts # 数据类型定义
│ └── data.ts # 数据工具
├── hooks/ # 组合式函数
├── types/ # 类型定义
├── utils/ # 工具函数
├── index.ts # 入口文件
└── main.ts # 应用入口
🔌 核心组件 API
UniverSheet 组件
<template>
<UniverSheet
:mode="ModeEnum.edit"
:license="''"
show-import-file-plugin
show-indicators-context-menu-plugin
show-time-config-context-menu-plugin
/>
</template>
Props
| 属性 |
类型 |
默认值 |
说明 |
| [mode] |
'view' | 'edit' |
'view' |
组件模式 |
| [license] |
'' |
Univer Advanced 许可证 |
|
| [showImportFilePlugin] |
boolean |
false |
显示导入插件 |
| [showIndicatorsContextMenuPlugin] |
boolean |
false |
显示指标配置插件 |
| [showSyncContextMenuPlugin] |
boolean |
false |
显示同步插件 |
| [showTimeConfigContextMenuPlugin] |
boolean |
false |
显示时间配置插件 |
Exposed Methods
| 方法 |
返回值 |
说明 |
| [createUniverSheets(data)] |
Promise<boolean> |
创建表格实例 |
| [destroyUniver()] |
void |
销毁表格实例 |
| [getWorkbookData()] |
[IWorkbookData] |
获取工作簿数据 |
| [getActiveSheetData()] |
Promise<any> |
获取当前工作表数据 |
| [batchUpdateCells(cells, sheetId)] |
Promise<void> |
批量更新单元格 |
| [executeCalculation()] |
void |
执行公式计算 |
Events
| 事件 |
参数 |
说明 |
active-sheet-changed |
{ workbook, activeSheet } |
活动工作表切换时触发 |
🔧 自定义插件系统
插件列表
| 插件 |
功能 |
菜单位置 |
| [ImportFilePlugin] |
导入 XLSX 文件 |
工具栏 - 布局组 |
| [SaveButtonPlugin] |
保存工作簿 |
工具栏 - 布局组 |
| [IndicatorsContextMenuPlugin] |
指标配置右键菜单 |
右键菜单 - 其他组 |
| [TimeConfigContextMenuPlugin] |
时间配置右键菜单 |
右键菜单 - 其他组 |
| [SyncContextMenuPlugin] |
同步右键菜单 |
右键菜单 - 其他组 |
注册外部组件
// main.ts
import { registerExternalComponents } from 'tor-univer-sheet'
import IndicatorPointSelect from './components/IndicatorPointSelect.vue'
registerExternalComponents({
IndicatorPointSelect,
})
📝 表单配置 Schema
指标配置表单 (indicatorsFormSchemas)
{
title: '基本信息',
schemas: [
{ field: 'indicatorName', label: '指标名称', component: 'Input' },
{ field: 'indicatorCode', label: '指标编码', component: 'Input', disabled: true },
{ field: 'indicatorId', label: '指标 ID', component: 'Input', disabled: true },
{ field: 'indicatorDimensionName', label: '维度名称', component: 'Input', disabled: true },
{ field: 'indicatorDimensionConfig', label: '维度编码', component: 'Input', disabled: true },
{ field: 'required', label: '是否必填', component: 'ElCheckbox' }
]
}
时间配置表单 ([timeConfigFormSchemas])
{
title: '时间条件',
schemas: [
{ field: 'cycleType', label: '周期类型', component: 'Select' },
{ field: 'timeIncrement', label: '时间递增量', component: 'InputNumber' },
{ field: 'defaultShift', label: '默认排班班次', component: 'ElCheckbox' },
{ field: 'forwardPush', label: '向前推 7 天', component: 'ElCheckbox' }
]
},
{
title: '拓展形式',
schemas: [
{ field: 'copyType', label: '复制方式', component: 'Select' },
{ field: 'copyInterval', label: '跨多少 (行/列) 复制', component: 'InputNumber' }
]
}
周期类型枚举 ([CycleTypeEnum])
enum CycleTypeEnum {
无 = 'no',
年 = 'year',
月 = 'month',
周 = 'week',
天 = 'day',
班组 = 'shift',
小时 = 'hour',
半小时 = 'half_hour',
}
🛠️ 工具函数
decimal.ts - 数值计算
import { decimal } from 'tor-univer-sheet'
// 链式调用
const result = decimal(100).add(50).multiply(2).toNumber() // 300
| 方法 |
说明 |
| [add(num)] |
加法 |
| [subtract(num)] |
减法 |
| [multiply(num)] |
乘法 |
| [divide(num)] |
除法 |
| [toFixed(dp)] |
保留小数位 |
| [toNumber()] |
转换为数字 |
fileHelp.ts - 文件处理
| 方法 |
说明 |
| [openMultipleFileSelector(accept, multiple)] |
打开文件选择器 |
| [getXlsxData(file)] |
读取 Excel 数据 |
downloadBlobRes(res, filename) |
下载 Blob 文件 |
is.ts - 类型判断
| 方法 |
说明 |
isEmpty(val) |
判断是否为空 |
isString(val) |
判断是否为字符串 |
isNumber(val) |
判断是否为数字 |
isFunction(val) |
判断是否为函数 |
isArray(val) |
判断是否为数组 |
🚀 使用示例
基础用法
<template>
<div style="width: 100%; height: 100vh">
<UniverSheet ref="sheetRef" :mode="ModeEnum.edit" :license="''" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { UniverSheet, ModeEnum } from 'tor-univer-sheet'
const sheetRef = ref()
// 获取工作簿数据
const saveData = () => {
const data = sheetRef.value.getWorkbookData()
console.log(data)
}
</script>
启用插件
<template>
<UniverSheet
show-import-file-plugin
show-indicators-context-menu-plugin
show-time-config-context-menu-plugin
show-sync-context-menu-plugin
/>
</template>
批量更新单元格
const cells = {
0: {
0: {
v: 'Hello',
custom: {
cellType: 'indicator',
indicatorName: '测试指标',
businessDate: '2024-01-01',
},
},
},
}
await sheetRef.value.batchUpdateCells(cells, sheetId)
📋 开发命令
# 开发
npm run dev
# 构建
npm run build
# 类型检查
npm run type-check
# 测试
npm run test:unit
# 代码检查
npm run lint
# 代码格式化
npm run format
# 发布
npm publish
⚠️ 注意事项
- Peer Dependencies: 使用方需自行安装 [vue], [element-plus], [xlsx], [decimal.js], [dayjs]
- 样式引入: 需要单独引入
import 'tor-univer-sheet/dist/style.css'
- 许可证: Univer Advanced 功能需要有效的 license
- Node 版本: 要求 Node.js
^20.19.0 || >=22.12.0
- 外部组件注册: 使用 [IndicatorPointSelect] 等组件前需通过 [registerExternalComponents] 注册
- 2FA 认证: 发布时需准备 2FA 验证码,建议保存备用代码
- 版本管理: 遵循语义化版本规范,发布前更新 [package.json] 版本号
📝 版本记录
🔗 相关资源