wy-editor 1.0.0 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/demo.html +1 -0
- package/dist/fonts/element-icons.f1a45d74.ttf +0 -0
- package/dist/fonts/element-icons.ff18efd1.woff +0 -0
- package/dist/wy-editor.common.js +109385 -0
- package/dist/wy-editor.common.js.map +1 -0
- package/dist/wy-editor.css +1 -0
- package/dist/wy-editor.umd.js +109396 -0
- package/dist/wy-editor.umd.js.map +1 -0
- package/dist/wy-editor.umd.min.js +47 -0
- package/dist/wy-editor.umd.min.js.map +1 -0
- package/package.json +9 -4
- package/.browserslistrc +0 -3
- package/babel.config.js +0 -5
- package/jsconfig.json +0 -19
- package/public/favicon.ico +0 -0
- package/public/index.html +0 -17
- package/src/App.vue +0 -127
- package/src/assets/logo.png +0 -0
- package/src/components/FieldVariable.vue +0 -104
- package/src/components/FormulaList.vue +0 -132
- package/src/core/calculate.js +0 -90
- package/src/core/functionCore.js +0 -92
- package/src/core/index.js +0 -249
- package/src/formula/base.js +0 -11
- package/src/formula/frequentlyUse/formula.json +0 -30
- package/src/formula/frequentlyUse/index.js +0 -13
- package/src/formula/index.js +0 -12
- package/src/formula/mathFormula/formula.json +0 -142
- package/src/formula/mathFormula/index.js +0 -13
- package/src/formula/statistics/formula.json +0 -30
- package/src/formula/statistics/index.js +0 -13
- package/src/formula/stringData/formula.json +0 -93
- package/src/formula/stringData/index.js +0 -13
- package/src/index.js +0 -5
- package/src/index.vue +0 -219
- package/src/main.js +0 -14
- package/src/router/index.js +0 -14
- package/src/utils/index.js +0 -35
- package/vue.config.js +0 -4
package/package.json
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wy-editor",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"private": false,
|
|
5
|
+
"description": "公式配置",
|
|
6
|
+
"main": "dist/wy-editor.umd.min.js",
|
|
7
|
+
"module": "dist/wy-editor.common.js",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
5
11
|
"scripts": {
|
|
6
12
|
"dev": "vue-cli-service serve",
|
|
7
|
-
"build": "vue-cli-service build"
|
|
13
|
+
"build": "vue-cli-service build --target lib --name wy-editor ./src/main.js",
|
|
14
|
+
"build:app": "vue-cli-service build"
|
|
8
15
|
},
|
|
9
16
|
"dependencies": {
|
|
10
17
|
"core-js": "^3.8.3",
|
|
@@ -21,8 +28,6 @@
|
|
|
21
28
|
"less-loader": "^12.2.0",
|
|
22
29
|
"vue-template-compiler": "^2.6.14"
|
|
23
30
|
},
|
|
24
|
-
"description": "公式配置",
|
|
25
|
-
"main": "babel.config.js",
|
|
26
31
|
"author": "",
|
|
27
32
|
"license": "ISC"
|
|
28
33
|
}
|
package/.browserslistrc
DELETED
package/babel.config.js
DELETED
package/jsconfig.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "es5",
|
|
4
|
-
"module": "esnext",
|
|
5
|
-
"baseUrl": "./",
|
|
6
|
-
"moduleResolution": "node",
|
|
7
|
-
"paths": {
|
|
8
|
-
"@/*": [
|
|
9
|
-
"src/*"
|
|
10
|
-
]
|
|
11
|
-
},
|
|
12
|
-
"lib": [
|
|
13
|
-
"esnext",
|
|
14
|
-
"dom",
|
|
15
|
-
"dom.iterable",
|
|
16
|
-
"scripthost"
|
|
17
|
-
]
|
|
18
|
-
}
|
|
19
|
-
}
|
package/public/favicon.ico
DELETED
|
Binary file
|
package/public/index.html
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8">
|
|
5
|
-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
-
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
7
|
-
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
|
8
|
-
<title><%= htmlWebpackPlugin.options.title %></title>
|
|
9
|
-
</head>
|
|
10
|
-
<body>
|
|
11
|
-
<noscript>
|
|
12
|
-
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
|
13
|
-
</noscript>
|
|
14
|
-
<div id="app"></div>
|
|
15
|
-
<!-- built files will be auto injected -->
|
|
16
|
-
</body>
|
|
17
|
-
</html>
|
package/src/App.vue
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div id="app">
|
|
3
|
-
<el-button type="text" @click="dialogVisible = true">配置公式</el-button>
|
|
4
|
-
<!-- <el-form ref="form" :model="formData">
|
|
5
|
-
<el-form-item label="名称">
|
|
6
|
-
<el-input v-model="formData.name"></el-input>
|
|
7
|
-
</el-form-item>
|
|
8
|
-
<el-form-item label="描述">
|
|
9
|
-
<el-input type="textarea" v-model="formData.desc"></el-input>
|
|
10
|
-
</el-form-item>
|
|
11
|
-
</el-form> -->
|
|
12
|
-
<div>结果:{{ result }}</div>
|
|
13
|
-
<el-dialog title="配置公式" :visible.sync="dialogVisible" width="800px">
|
|
14
|
-
<editorIndex
|
|
15
|
-
:formulaList="list"
|
|
16
|
-
ref="formulaEditor"
|
|
17
|
-
:formulaConf="formulaConf"
|
|
18
|
-
:loading="true"
|
|
19
|
-
:fieldList="fieldList"/>
|
|
20
|
-
<!-- <FormulaEditor
|
|
21
|
-
:formulaList="list"
|
|
22
|
-
ref="formulaEditor"
|
|
23
|
-
:formulaConf="formulaConf"
|
|
24
|
-
:loading="true"
|
|
25
|
-
:fieldList="fieldList"></FormulaEditor> -->
|
|
26
|
-
<span slot="footer" class="dialog-footer">
|
|
27
|
-
<el-button @click="onCancel">取 消</el-button>
|
|
28
|
-
<el-button type="primary" @click="onConfirm">确 定</el-button>
|
|
29
|
-
</span>
|
|
30
|
-
</el-dialog>
|
|
31
|
-
</div>
|
|
32
|
-
</template>
|
|
33
|
-
<script>
|
|
34
|
-
import formulaObj from './formula'
|
|
35
|
-
import editorIndex from './index'
|
|
36
|
-
import { calculate, formulaWatcher, FormulaEditor } from 'vue-formula-editor'
|
|
37
|
-
|
|
38
|
-
export default {
|
|
39
|
-
name: 'HomeView',
|
|
40
|
-
components: {
|
|
41
|
-
FormulaEditor,
|
|
42
|
-
editorIndex
|
|
43
|
-
},
|
|
44
|
-
data() {
|
|
45
|
-
return {
|
|
46
|
-
dialogVisible: true,
|
|
47
|
-
formData: {
|
|
48
|
-
name: '',
|
|
49
|
-
desc: '',
|
|
50
|
-
},
|
|
51
|
-
result: 0,
|
|
52
|
-
list: [],
|
|
53
|
-
formulaConf: {},
|
|
54
|
-
watchData: null,
|
|
55
|
-
fieldList: [
|
|
56
|
-
{
|
|
57
|
-
fullName: '名称',
|
|
58
|
-
value: 'string',
|
|
59
|
-
enCode: 'name',
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
fullName: '描述',
|
|
63
|
-
value: 'string',
|
|
64
|
-
enCode: 'desc',
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
fullName: '名称1',
|
|
68
|
-
value: 'string',
|
|
69
|
-
enCode: 'name1',
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
fullName: '描述1',
|
|
73
|
-
value: 'string',
|
|
74
|
-
enCode: 'desc1',
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
fullName: '名称2',
|
|
78
|
-
value: 'string',
|
|
79
|
-
enCode: 'name2',
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
fullName: '描述2',
|
|
83
|
-
value: 'string',
|
|
84
|
-
enCode: 'desc2',
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
}
|
|
88
|
-
},
|
|
89
|
-
computed: {
|
|
90
|
-
nodes() {
|
|
91
|
-
return this.list?.flatMap(o => o.formula) || []
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
mounted() {
|
|
95
|
-
this.list = formulaObj.map(ObjInstance => new ObjInstance())
|
|
96
|
-
},
|
|
97
|
-
methods: {
|
|
98
|
-
onConfirm() {
|
|
99
|
-
const data = this.$refs.formulaEditor.getData()
|
|
100
|
-
this.result = data.text;
|
|
101
|
-
this.dialogVisible = false
|
|
102
|
-
return;
|
|
103
|
-
this.formulaConf = data
|
|
104
|
-
this.dialogVisible = false
|
|
105
|
-
|
|
106
|
-
this.watchData?.()
|
|
107
|
-
// 自动监听form表单的值
|
|
108
|
-
this.watchData = formulaWatcher(
|
|
109
|
-
this,
|
|
110
|
-
{ key: 'formData', value: this.formData },
|
|
111
|
-
this.formulaConf,
|
|
112
|
-
data => {
|
|
113
|
-
this.result = data
|
|
114
|
-
}
|
|
115
|
-
)
|
|
116
|
-
},
|
|
117
|
-
onCancel() {
|
|
118
|
-
this.dialogVisible = false
|
|
119
|
-
},
|
|
120
|
-
resetFormula() {
|
|
121
|
-
this.$refs.formulaEditor.reset()
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
}
|
|
125
|
-
</script>
|
|
126
|
-
|
|
127
|
-
<style></style>
|
package/src/assets/logo.png
DELETED
|
Binary file
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<el-scrollbar style="height: 240px;" class="field-variable">
|
|
3
|
-
|
|
4
|
-
<div class="field-search">
|
|
5
|
-
<el-input placeholder="搜索变量" prefix-icon="el-icon-search" v-model="searchVariable" clearable />
|
|
6
|
-
</div>
|
|
7
|
-
<div class="field-item" @click="$emit('fieldSelect', item)" v-for="item in filterFieldList" :key="item.enCode">
|
|
8
|
-
<span>{{ item.fullName }}</span>
|
|
9
|
-
<span :field-type="item.value" class="text-tag">
|
|
10
|
-
{{ type[item.value] }}
|
|
11
|
-
</span>
|
|
12
|
-
</div>
|
|
13
|
-
|
|
14
|
-
</el-scrollbar>
|
|
15
|
-
|
|
16
|
-
</template>
|
|
17
|
-
|
|
18
|
-
<script>
|
|
19
|
-
|
|
20
|
-
export default {
|
|
21
|
-
name: 'FieldVariable',
|
|
22
|
-
props: {
|
|
23
|
-
fieldList: {
|
|
24
|
-
type: Array,
|
|
25
|
-
default: () => [],
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
components: {},
|
|
29
|
-
data() {
|
|
30
|
-
const type = {
|
|
31
|
-
string: '字符串',
|
|
32
|
-
number: '数字',
|
|
33
|
-
array: '数组',
|
|
34
|
-
}
|
|
35
|
-
return {
|
|
36
|
-
type,
|
|
37
|
-
// 搜索值
|
|
38
|
-
searchVariable: '',
|
|
39
|
-
// 过滤后的变量
|
|
40
|
-
filterFieldList: [],
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
computed: {},
|
|
44
|
-
watch: {
|
|
45
|
-
searchVariable(val, old) {
|
|
46
|
-
this.filterFieldList = this.fieldList.filter(({ fullName }) => fullName.includes(val))
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
methods: {},
|
|
50
|
-
async created() { },
|
|
51
|
-
mounted() {
|
|
52
|
-
this.filterFieldList = this.fieldList
|
|
53
|
-
},
|
|
54
|
-
}
|
|
55
|
-
</script>
|
|
56
|
-
<style lang="less" scoped>
|
|
57
|
-
/deep/ .el-scrollbar__wrap {
|
|
58
|
-
overflow-x: hidden;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
.field-variable {
|
|
62
|
-
max-width: 255px;
|
|
63
|
-
border: 1px solid #eee;
|
|
64
|
-
border-radius: 5px;
|
|
65
|
-
margin-right: 10px;
|
|
66
|
-
.field-search{
|
|
67
|
-
width:95%;
|
|
68
|
-
margin: 5px auto;
|
|
69
|
-
}
|
|
70
|
-
.field-item {
|
|
71
|
-
display: flex;
|
|
72
|
-
justify-content: space-between;
|
|
73
|
-
align-items: center;
|
|
74
|
-
cursor: pointer;
|
|
75
|
-
padding: 8px;
|
|
76
|
-
user-select: none;
|
|
77
|
-
|
|
78
|
-
&:hover {
|
|
79
|
-
background-color: #f0f1f4;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
.text-tag {
|
|
83
|
-
padding: 2px 6px;
|
|
84
|
-
border-radius: 4px;
|
|
85
|
-
color: #fff;
|
|
86
|
-
|
|
87
|
-
&[field-type='string'] {
|
|
88
|
-
color: #409eff;
|
|
89
|
-
background-color: #ecf5ff;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
&[field-type='number'] {
|
|
93
|
-
color: #67c23a;
|
|
94
|
-
background-color: #f0f9eb;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
&[field-type='array'] {
|
|
98
|
-
color: #e6a23c;
|
|
99
|
-
background-color: #fdf6ec;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
</style>
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<el-scrollbar style="height: 240px;" wrap-class="no-x-scrollbar" class="formula-list">
|
|
3
|
-
<div class="field-search">
|
|
4
|
-
<el-input placeholder='搜索函数' prefix-icon="el-icon-search" v-model="searchTreeVariable" clearable></el-input>
|
|
5
|
-
</div>
|
|
6
|
-
<div class="treeContainer" @mouseleave="leaveTree">
|
|
7
|
-
<Tree :data="filterData" :default-expanded-keys="['frequentlyUse']" :props="props"
|
|
8
|
-
:current-node-key="currentKeyNode.enCode" node-key="enCode" @node-click="nodeClick" highlight-current>
|
|
9
|
-
<span class="info-container" @mouseenter="enterInfo(data)" slot-scope="{ data }">
|
|
10
|
-
<span>{{ data.name }}</span>
|
|
11
|
-
<span v-if="data.tip" class="tip">
|
|
12
|
-
{{ data.tip }}
|
|
13
|
-
</span>
|
|
14
|
-
</span>
|
|
15
|
-
</Tree>
|
|
16
|
-
</div>
|
|
17
|
-
</el-scrollbar>
|
|
18
|
-
|
|
19
|
-
</template>
|
|
20
|
-
|
|
21
|
-
<script>
|
|
22
|
-
import 'element-ui/lib/theme-chalk/index.css'
|
|
23
|
-
import { Tree } from 'element-ui'
|
|
24
|
-
|
|
25
|
-
export default {
|
|
26
|
-
name: 'FormulaList',
|
|
27
|
-
components: { Tree },
|
|
28
|
-
props: {
|
|
29
|
-
nodes: {
|
|
30
|
-
type: Array,
|
|
31
|
-
default: () => [],
|
|
32
|
-
},
|
|
33
|
-
props: {
|
|
34
|
-
type: Object,
|
|
35
|
-
default: () => ({
|
|
36
|
-
children: 'formula',
|
|
37
|
-
label: 'name',
|
|
38
|
-
}),
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
data() {
|
|
42
|
-
return {
|
|
43
|
-
searchTreeVariable: "",
|
|
44
|
-
// 选中的节点
|
|
45
|
-
currentKeyNode: {},
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
computed: {
|
|
49
|
-
filterData() {
|
|
50
|
-
if (!this.searchTreeVariable) {
|
|
51
|
-
return this.nodes
|
|
52
|
-
}
|
|
53
|
-
return this.filterTreeData(this.nodes)
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
watch: {},
|
|
57
|
-
methods: {
|
|
58
|
-
nodeClick(o) {
|
|
59
|
-
const currentKeyNode = this.currentKeyNode
|
|
60
|
-
// 目录情况
|
|
61
|
-
if (o.formula) {
|
|
62
|
-
if (currentKeyNode && currentKeyNode.enCode) {
|
|
63
|
-
this.currentKeyNode = {}
|
|
64
|
-
}
|
|
65
|
-
return
|
|
66
|
-
}
|
|
67
|
-
this.currentKeyNode = o
|
|
68
|
-
this.$emit('formulaClick', o)
|
|
69
|
-
},
|
|
70
|
-
filterTreeData(nodes) {
|
|
71
|
-
// 找到nodes树中包含searchTreeVariable的节点但只有一层的结果
|
|
72
|
-
return nodes.reduce((pre, cur) => {
|
|
73
|
-
if (cur.name.toLowerCase().includes(this.searchTreeVariable)) {
|
|
74
|
-
pre.push({ ...cur })
|
|
75
|
-
}
|
|
76
|
-
if (cur.formula) {
|
|
77
|
-
pre.push(...this.filterTreeData(cur.formula))
|
|
78
|
-
}
|
|
79
|
-
return pre
|
|
80
|
-
}, [])
|
|
81
|
-
},
|
|
82
|
-
enterInfo(data) {
|
|
83
|
-
if (data.formula) return
|
|
84
|
-
this.$emit('enterInfo', data)
|
|
85
|
-
},
|
|
86
|
-
leaveTree() {
|
|
87
|
-
if (this.currentKeyNode && this.currentKeyNode.enCode) {
|
|
88
|
-
this.$emit('enterInfo', this.currentKeyNode)
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
created() { },
|
|
93
|
-
mounted() { },
|
|
94
|
-
}
|
|
95
|
-
</script>
|
|
96
|
-
<style lang="less" scoped>
|
|
97
|
-
/deep/ .el-scrollbar__wrap {
|
|
98
|
-
overflow-x: hidden;
|
|
99
|
-
}
|
|
100
|
-
.no-x-scrollbar .el-scrollbar__wrap {
|
|
101
|
-
overflow-x: hidden;
|
|
102
|
-
}
|
|
103
|
-
.field-search{
|
|
104
|
-
width:95%;
|
|
105
|
-
margin: 5px auto;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
.formula-list {
|
|
109
|
-
border-radius: 5px;
|
|
110
|
-
border: 1px solid #eee;
|
|
111
|
-
margin-right: 10px;
|
|
112
|
-
.info-container {
|
|
113
|
-
width: 100%;
|
|
114
|
-
display: flex;
|
|
115
|
-
flex-direction: column;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
::v-deep .el-tree-node__content {
|
|
119
|
-
height: 100%;
|
|
120
|
-
// margin-top: 6px;
|
|
121
|
-
padding: 6px 0;
|
|
122
|
-
user-select: none;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
.tip {
|
|
126
|
-
font-size: 12px;
|
|
127
|
-
color: #999;
|
|
128
|
-
margin-top: 1px;
|
|
129
|
-
line-height: 1.2;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
</style>
|
package/src/core/calculate.js
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import functionCore from './functionCore'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 计算公式
|
|
5
|
-
* @param {{text: string, marks: Array, value: Object}} params
|
|
6
|
-
* @returns
|
|
7
|
-
*/
|
|
8
|
-
function calculate(params) {
|
|
9
|
-
const { text, marks = [], value = {} } = params
|
|
10
|
-
|
|
11
|
-
if (!text) return new Error('非法公式')
|
|
12
|
-
try {
|
|
13
|
-
let str = text
|
|
14
|
-
let offset = 0 // 偏移量
|
|
15
|
-
marks.sort((a, b) => a.from.ch - b.from.ch)
|
|
16
|
-
for (const mark of marks) {
|
|
17
|
-
const { enCode, from, to, uuid } = mark
|
|
18
|
-
|
|
19
|
-
let data = value[enCode] || value[uuid]
|
|
20
|
-
// 子表情况
|
|
21
|
-
if (enCode.indexOf('.') > -1) {
|
|
22
|
-
const [key, subKey] = enCode.split('.')
|
|
23
|
-
if (value[key]) data = value[key].map(o => o[subKey])
|
|
24
|
-
}
|
|
25
|
-
if (data !== undefined) {
|
|
26
|
-
data = JSON.stringify(data)
|
|
27
|
-
// 替换字符串的指定部分
|
|
28
|
-
const startIndex = from.ch + offset
|
|
29
|
-
const endIndex = to.ch + offset
|
|
30
|
-
|
|
31
|
-
str = str.slice(0, startIndex) + data.toString() + str.slice(endIndex)
|
|
32
|
-
|
|
33
|
-
// 更新偏移量
|
|
34
|
-
offset += data.toString().length - (to.ch - from.ch)
|
|
35
|
-
} else {
|
|
36
|
-
return undefined
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
const result = functionCore.executeFunction(str)
|
|
40
|
-
return result
|
|
41
|
-
} catch (e) {
|
|
42
|
-
const errorTypes = {
|
|
43
|
-
TypeError: () => '类型错误',
|
|
44
|
-
RangeError: () => '范围错误',
|
|
45
|
-
SyntaxError: () => '语法错误',
|
|
46
|
-
ReferenceError: () => {
|
|
47
|
-
const regex = /^(\w+)\s+is\s+not\s+defined$/
|
|
48
|
-
const match = e.message.match(regex)
|
|
49
|
-
return match ? `${match[1]} 未定义` : '未定义的变量'
|
|
50
|
-
},
|
|
51
|
-
}
|
|
52
|
-
const errorType = errorTypes[e.constructor.name]
|
|
53
|
-
const errorMessage = errorType?.() || `其他错误: ${e.message}`
|
|
54
|
-
return {
|
|
55
|
-
error: true,
|
|
56
|
-
message: errorMessage,
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* 动态监听并返回计算结果
|
|
63
|
-
* @param {VueContentInstance} vm 当前Vue实例
|
|
64
|
-
* @param {Object} formData 计算公式所需的数据
|
|
65
|
-
* @param {Object} formulaConf 计算公式配置
|
|
66
|
-
* @param {Function} fn 回调函数
|
|
67
|
-
* @returns {Function} 取消监听函数
|
|
68
|
-
*/
|
|
69
|
-
function formulaWatcher(vm, formData, formulaConf, fn) {
|
|
70
|
-
const watchList = []
|
|
71
|
-
const { key, value } = formData
|
|
72
|
-
|
|
73
|
-
const toCalculate = () => {
|
|
74
|
-
const data = calculate({
|
|
75
|
-
value,
|
|
76
|
-
marks: formulaConf.marks,
|
|
77
|
-
text: formulaConf.text,
|
|
78
|
-
})
|
|
79
|
-
fn(data)
|
|
80
|
-
}
|
|
81
|
-
formulaConf.marks.forEach(mark => {
|
|
82
|
-
const [preCode] = mark.enCode.split('.')
|
|
83
|
-
const watchItem = vm.$watch(`${key}.${preCode}`, toCalculate)
|
|
84
|
-
watchList.push(watchItem)
|
|
85
|
-
})
|
|
86
|
-
// 初始化计算
|
|
87
|
-
toCalculate()
|
|
88
|
-
return () => watchList.forEach(watchItem => watchItem())
|
|
89
|
-
}
|
|
90
|
-
export { calculate, formulaWatcher }
|
package/src/core/functionCore.js
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import * as FormulaFunc from '@formulajs/formulajs'
|
|
2
|
-
|
|
3
|
-
class FunctionCore {
|
|
4
|
-
constructor() {
|
|
5
|
-
Object.assign(FunctionCore.prototype, FormulaFunc)
|
|
6
|
-
|
|
7
|
-
// 为了兼容不同的函数命名(如 Ceiling / CEILING / ceiling),对导入的函数创建大小写别名
|
|
8
|
-
Object.keys(FormulaFunc).forEach(key => {
|
|
9
|
-
const fn = FormulaFunc[key]
|
|
10
|
-
if (typeof fn !== 'function') return
|
|
11
|
-
|
|
12
|
-
const lower = key.toLowerCase()
|
|
13
|
-
const upper = key.toUpperCase()
|
|
14
|
-
const capitalized = key.charAt(0).toUpperCase() + key.slice(1).toLowerCase()
|
|
15
|
-
|
|
16
|
-
if (!FunctionCore.prototype[lower]) FunctionCore.prototype[lower] = fn
|
|
17
|
-
if (!FunctionCore.prototype[upper]) FunctionCore.prototype[upper] = fn
|
|
18
|
-
if (!FunctionCore.prototype[capitalized]) FunctionCore.prototype[capitalized] = fn
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
// 若 formulajs 中没有一些常用的字符串函数(或命名差异),提供后备实现
|
|
22
|
-
const fallbackStringFuncs = {
|
|
23
|
-
TOLOWER: s => (s == null ? '' : String(s).toLowerCase()),
|
|
24
|
-
TOUPPER: s => (s == null ? '' : String(s).toUpperCase()),
|
|
25
|
-
CONCAT: (...args) => args.map(a => (a == null ? '' : String(a))).join(''),
|
|
26
|
-
LENGTH: s => (s == null ? 0 : String(s).length),
|
|
27
|
-
SUBSTRING: (s, start, len) => {
|
|
28
|
-
const str = s == null ? '' : String(s)
|
|
29
|
-
const st = Number(start) || 0
|
|
30
|
-
if (len === undefined) return str.slice(st - 1)
|
|
31
|
-
return str.substr(st - 1, Number(len) || 0)
|
|
32
|
-
},
|
|
33
|
-
TRIM: s => (s == null ? '' : String(s).trim()),
|
|
34
|
-
REPLACE: (s, oldText, newText) => (s == null ? '' : String(s).split(oldText).join(newText)),
|
|
35
|
-
INDEXOF: (s, sub) => {
|
|
36
|
-
const idx = (s == null ? '' : String(s)).indexOf(sub == null ? '' : String(sub))
|
|
37
|
-
return idx === -1 ? 0 : idx + 1
|
|
38
|
-
},
|
|
39
|
-
CONTAINS: (s, sub) => (s == null ? false : String(s).includes(sub == null ? '' : String(sub))),
|
|
40
|
-
STARTSWITH: (s, pre) => (s == null ? false : String(s).startsWith(pre == null ? '' : String(pre))),
|
|
41
|
-
ENDSWITH: (s, suf) => (s == null ? false : String(s).endsWith(suf == null ? '' : String(suf))),
|
|
42
|
-
FORMAT: (template, ...args) => {
|
|
43
|
-
const tpl = template == null ? '' : String(template)
|
|
44
|
-
return tpl.replace(/\{(\d+)\}/g, (m, i) => (args[i] == null ? '' : String(args[i])))
|
|
45
|
-
},
|
|
46
|
-
TOSTRING: v => (v == null ? '' : String(v)),
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
Object.keys(fallbackStringFuncs).forEach(k => {
|
|
50
|
-
if (!FunctionCore.prototype[k]) FunctionCore.prototype[k] = fallbackStringFuncs[k]
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
// 后备数学函数(避免 Truncate 等未定义)
|
|
54
|
-
const fallbackMathFuncs = {
|
|
55
|
-
Truncate: n => {
|
|
56
|
-
if (n == null) return 0
|
|
57
|
-
const num = Number(n)
|
|
58
|
-
if (Number.isNaN(num)) return 0
|
|
59
|
-
if (typeof Math.trunc === 'function') return Math.trunc(num)
|
|
60
|
-
return num < 0 ? Math.ceil(num) : Math.floor(num)
|
|
61
|
-
},
|
|
62
|
-
ACos: n => {
|
|
63
|
-
if (n == null) return 0
|
|
64
|
-
const num = Number(n)
|
|
65
|
-
if (Number.isNaN(num)) return 0
|
|
66
|
-
return Math.acos(num)
|
|
67
|
-
},
|
|
68
|
-
Pow: (base, exp) => {
|
|
69
|
-
const b = Number(base)
|
|
70
|
-
const e = Number(exp)
|
|
71
|
-
if (Number.isNaN(b) || Number.isNaN(e)) return 0
|
|
72
|
-
return Math.pow(b, e)
|
|
73
|
-
},
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
Object.keys(fallbackMathFuncs).forEach(k => {
|
|
77
|
-
if (!FunctionCore.prototype[k]) FunctionCore.prototype[k] = fallbackMathFuncs[k]
|
|
78
|
-
})
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
executeFunction(str) { // 执行函数
|
|
82
|
-
const fn = new Function(
|
|
83
|
-
'with(this) { return ' + str + '; }' // 使用 `with` 来确保从当前实例中查找函数
|
|
84
|
-
).bind(this)
|
|
85
|
-
|
|
86
|
-
return fn()
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
// 单例对象,保证全局只有一个实例
|
|
90
|
-
const functionCore = new FunctionCore()
|
|
91
|
-
|
|
92
|
-
export default functionCore
|