@xieqx/formula-editor
v0.1.0
Published
A Vue 3 formula editor component with Monaco Editor, sandbox execution, and field auto-detection.
Maintainers
Readme
@xieqx/formula-editor
Vue 3 通用公式编辑器组件库,基于 Monaco Editor + Element Plus,支持沙箱执行与字段自动提取。
安装
pnpm add @xieqx/formula-editorPeer Dependencies
确保项目中已安装以下依赖:
pnpm add vue element-plus monaco-editorMonaco Editor Worker 配置
使用 vite-plugin-monaco-editor 配置 Monaco Web Worker:
// vite.config.ts
import monacoEditorPlugin from 'vite-plugin-monaco-editor'
export default {
plugins: [
monacoEditorPlugin({
languageWorkers: ['editorWorkerService', 'typescript', 'json'],
}),
],
}使用
<script setup lang="ts">
import { ref } from 'vue'
import {
FormulaEditor,
FormulaInput,
FormulaPopover,
type CalculateFormula,
createEmptyFormula,
} from '@xieqx/formula-editor'
import '@xieqx/formula-editor/dist/style.css'
const formula = ref<CalculateFormula | null>(createEmptyFormula())
const availableRowKeys = ['field_a', 'field_b']
const availableColKeys = ['col_x', 'col_y', '年作业天数', '多宝山_日处理能力']
</script>
<template>
<!-- 完整编辑器 -->
<FormulaEditor
v-model="formula"
:available-row-keys="availableRowKeys"
:available-col-keys="availableColKeys"
height="400px"
/>
<!-- 行内展示 + 悬浮预览 -->
<FormulaInput
:formula="formula"
:show-validation="true"
:available-row-keys="availableRowKeys"
:available-col-keys="availableColKeys"
/>
<!-- 悬浮窗组件 -->
<FormulaPopover :formula="formula">
<template #reference>
<el-button>查看公式</el-button>
</template>
</FormulaPopover>
</template>API
FormulaEditor
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| modelValue | CalculateFormula \| null | — | v-model 双向绑定 |
| availableRowKeys | string[] | [] | 行字段 key 列表(补全提示) |
| availableColKeys | string[] | [] | 列字段 key 列表(补全提示) |
| height | string \| number | '400px' | 编辑器高度 |
| readOnly | boolean | false | 只读模式 |
| showToolbar | boolean | true | 显示工具栏 |
| showFieldHints | boolean | true | 显示提取的字段列表 |
| theme | string | 'vs' | Monaco 主题 |
| fontSize | number | 14 | 字号 |
| Emit | 参数 | 说明 |
|------|------|------|
| update:modelValue | CalculateFormula \| null | v-model |
| change | CalculateFormula \| null | 公式变更(300ms 防抖) |
| error | string | 校验错误 |
| Slot | Props | 说明 |
|------|-------|------|
| toolbar-prepend | { title } | 工具栏前缀 |
| toolbar-append | { title, text } | 工具栏后缀 |
| field-hints | { rowKeys, colKeys, availableRowKeys, availableColKeys } | 自定义字段提示 |
| error | { message } | 自定义错误展示 |
| Expose 方法 | 说明 | |-------------|------| | getFormula() | 获取当前公式数据 | | execute(params?) | 沙箱执行公式 | | validate() | 校验公式文本 | | focus() | 聚焦编辑器 | | clear() | 清空编辑器 |
FormulaInput
| Prop | 类型 | 说明 |
|------|------|------|
| formula | CalculateFormula \| null | 公式数据 |
| showValidation | boolean | 是否校验字段存在性 |
| availableRowKeys | string[] | 可用行字段(校验用) |
| availableColKeys | string[] | 可用列字段(校验用) |
FormulaPopover
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| formula | CalculateFormula \| null | — | 公式数据 |
| width | string | '400px' | 弹窗宽度 |
| maxHeight | string | '300px' | 内容最大高度 |
| trigger | 'hover' \| 'click' | 'hover' | 触发方式(hover 模式悬停 1s) |
数据结构
interface CalculateFormula {
title: string // 公式名称
text: string // 公式代码(函数体)
params: {
rowMap: Record<string, unknown> // 行字段 → 值
colMap: Record<string, unknown> // 列字段 → 值
curRow: object // 当前行上下文
}
_useFields: {
rowKeys: string[] // 公式中引用的行字段 ID
colKeys: string[] // 公式中引用的列字段 ID
}
}公式编写示例
// 在编辑器中输入公式(函数体,不需要 function 关键字)
if (curRow.label === '年处理上限') {
return colMap['多宝山_日处理能力'] + colMap['年作业天数'] * 2
}
// 简单的数学运算
return rowMap['单价'] * colMap['数量']
// 使用条件判断
return colMap['状态'] === '启用' ? rowMap['预算'] : 0沙箱安全
公式通过 with + Proxy 在受限环境中执行:
- ✅ 白名单:Math, Date, JSON, Array, Map, Set 等
- ❌ 禁止:window, document, fetch, localStorage, setTimeout 等
- 如需更严格隔离,请在 Web Worker 中执行
License
MIT
