sh-tools 2.3.10 → 2.3.12
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/README.md +159 -26
- package/package.json +2 -2
- package/packages/expr/index.js +458 -450
- package/packages/index.js +19 -0
- package/packages/utils/number.js +0 -10
- package/packages/utils/other.js +0 -137
- package/packages/utils/string.js +16 -0
package/README.md
CHANGED
|
@@ -1,39 +1,172 @@
|
|
|
1
1
|
# sh-tools
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
{**以下是 Gitee 平台说明,您可以替换此简介**
|
|
5
|
-
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
|
|
6
|
-
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
|
|
3
|
+
## 概述
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
软件架构说明
|
|
5
|
+
SH-Tools 提供了一个强大的表达式求值器模块,支持复杂的数学运算、逻辑判断、函数调用和模板字符串解析。特别适合动态计算、规则引擎和配置化计算场景。
|
|
10
6
|
|
|
7
|
+
## 安装
|
|
8
|
+
npm install sh-tools
|
|
11
9
|
|
|
12
|
-
|
|
10
|
+
## 引入方式
|
|
11
|
+
import { utils, expr } from 'sh-tools'
|
|
13
12
|
|
|
14
|
-
1. xxxx
|
|
15
|
-
2. xxxx
|
|
16
|
-
3. xxxx
|
|
17
13
|
|
|
18
|
-
|
|
14
|
+
## 核心 API
|
|
15
|
+
| 函数名 | 参数 | 返回值 | 描述 | 示例 |
|
|
16
|
+
|--------|------|--------|------|------|
|
|
17
|
+
| `utils.calculate(expression, data?)` | `expression: string` - 表达式字符串<br>`data?: object` - 数据上下文 | `any` - 计算结果 | 计算表达式并返回结果,支持 `{}` 模板 | `utils.calculate("1+2*3")` → `7`<br>`utils.calculate("用户{name}", {name:"张三"})` → `"用户张三"` |
|
|
18
|
+
| `utils.calculateLog(expression, data?)` | `expression: string`<br>`data?: object` | `{result, log, treeLog}` - 结果和日志 | 计算表达式并返回详细执行日志 | `utils.calculateLog("sum([1,2,3])")` → `{result: 6, log: [...], treeLog: [...]}` |
|
|
19
|
+
| `expr.registerFunction(name, fn, override?)` | `name: string\|object` - 函数名或对象<br>`fn: Function` - 函数实现<br>`override?: boolean` - 是否覆盖 | `void` | 注册自定义函数 | `expr.registerFunction('double', x=>x*2)`<br>`expr.registerFunction({square: x=>x*x})` |
|
|
20
|
+
| `expr.extendOperator(symbol, config, override?)` | `symbol: string` - 运算符<br>`config: object` - 配置<br>`override?: boolean` - 是否覆盖 | `void` | 扩展自定义运算符 | `expr.extendOperator('//', {precedence:11, fn:(a,b)=>Math.floor(a/b)})` |
|
|
19
21
|
|
|
20
|
-
1. xxxx
|
|
21
|
-
2. xxxx
|
|
22
|
-
3. xxxx
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
# 内置函数
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
2. 新建 Feat_xxx 分支
|
|
28
|
-
3. 提交代码
|
|
29
|
-
4. 新建 Pull Request
|
|
25
|
+
## 数学函数
|
|
30
26
|
|
|
27
|
+
| 函数名 | 参数 | 返回值 | 描述 | 示例 |
|
|
28
|
+
|--------|------|--------|------|------|
|
|
29
|
+
| `abs` | `x: number` | `number` | 绝对值 | `abs(-10)` → `10` |
|
|
30
|
+
| `ceil` | `x: number` | `number` | 向上取整 | `ceil(3.14)` → `4` |
|
|
31
|
+
| `floor` | `x: number` | `number` | 向下取整 | `floor(3.14)` → `3` |
|
|
32
|
+
| `round` | `x: number` | `number` | 四舍五入 | `round(3.14)` → `3` |
|
|
33
|
+
| `pow` | `base: number, exponent: number` | `number` | 幂运算 | `pow(2, 3)` → `8` |
|
|
34
|
+
| `sqrt` | `x: number` | `number` | 平方根 | `sqrt(9)` → `3` |
|
|
35
|
+
| `sin` | `x: number` | `number` | 正弦 | `sin(0)` → `0` |
|
|
36
|
+
| `cos` | `x: number` | `number` | 余弦 | `cos(0)` → `1` |
|
|
37
|
+
| `tan` | `x: number` | `number` | 正切 | `tan(0)` → `0` |
|
|
38
|
+
| `log` | `x: number` | `number` | 自然对数 | `log(10)` → `2.302...` |
|
|
39
|
+
| `exp` | `x: number` | `number` | e的幂次 | `exp(1)` → `2.718...` |
|
|
40
|
+
| `random` | `min?: number, max?: number` | `number` | 随机数 | `random()` → `0.123`<br>`random(1,10)` → `5` |
|
|
41
|
+
| `min` | `...args: number[]` 或 `arr: number[]` | `number` | 最小值 | `min(5,2,8,1)` → `1`<br>`min([5,2,8,1])` → `1` |
|
|
42
|
+
| `max` | `...args: number[]` 或 `arr: number[]` | `number` | 最大值 | `max(5,2,8,1)` → `8`<br>`max([5,2,8,1])` → `8` |
|
|
43
|
+
| `add` | `a: number, b: number` | `number` | 加法(精确) | `add(0.1, 0.2)` → `0.3` |
|
|
44
|
+
| `subtract` | `a: number, b: number` | `number` | 减法(精确) | `subtract(0.3, 0.1)` → `0.2` |
|
|
45
|
+
| `multiply` | `a: number, b: number` | `number` | 乘法(精确) | `multiply(0.1, 0.2)` → `0.02` |
|
|
46
|
+
| `divide` | `a: number, b: number` | `number` | 除法(精确) | `divide(0.3, 0.1)` → `3` |
|
|
47
|
+
| `toFixed` | `value: number, digits: number` | `string` | 保留小数位 | `toFixed(3.14159, 2)` → `"3.14"` |
|
|
48
|
+
| `toInteger` | `value: any` | `number` | 转整数 | `toInteger("123")` → `123`<br>`toInteger(3.14)` → `3` |
|
|
49
|
+
| `toNumber` | `value: any` | `number` | 转数字 | `toNumber("3.14")` → `3.14`<br>`toNumber("123")` → `123` |
|
|
50
|
+
| `truncate` | `value: number, digits: number` | `number` | 截断小数位 | `truncate(3.14159, 2)` → `3.14` |
|
|
31
51
|
|
|
32
|
-
|
|
52
|
+
## 数组函数
|
|
53
|
+
|
|
54
|
+
| 函数名 | 参数 | 返回值 | 描述 | 示例 |
|
|
55
|
+
|--------|------|--------|------|------|
|
|
56
|
+
| `sum` | `arr: number[]` | `number` | 求和 | `sum([1,2,3])` → `6` |
|
|
57
|
+
| `mean` | `arr: number[]` | `number` | 平均值 | `mean([1,2,3,4])` → `2.5` |
|
|
58
|
+
| `min` | `arr: number[]` | `number` | 最小值 | `min([5,2,8,1])` → `1` |
|
|
59
|
+
| `max` | `arr: number[]` | `number` | 最大值 | `max([5,2,8,1])` → `8` |
|
|
60
|
+
| `flatten` | `arr: any[]` | `any[]` | 扁平化数组 | `flatten([[1,2],[3,4]])` → `[1,2,3,4]` |
|
|
61
|
+
| `uniq` | `arr: any[]` | `any[]` | 数组去重 | `uniq([1,2,2,3,3,3])` → `[1,2,3]` |
|
|
62
|
+
| `includes` | `arr: any[], value: any` | `boolean` | 包含判断 | `includes([1,2,3], 2)` → `true` |
|
|
63
|
+
| `first` | `arr: any[]` | `any` | 第一个元素 | `first([1,2,3])` → `1` |
|
|
64
|
+
| `last` | `arr: any[]` | `any` | 最后一个元素 | `last([1,2,3])` → `3` |
|
|
65
|
+
| `length` | `arr: any[]` | `number` | 数组长度 | `length([1,2,3,4,5])` → `5` |
|
|
66
|
+
| `slice` | `arr: any[], start: number, end?: number` | `any[]` | 切片 | `slice([1,2,3,4,5], 1, 3)` → `[2,3]` |
|
|
67
|
+
| `indexOf` | `arr: any[], value: any, fromIndex?: number` | `number` | 查找索引 | `indexOf([1,2,3,2], 2)` → `1` |
|
|
68
|
+
| `union` | `...arrays: any[][]` | `any[]` | 数组合并并去重 | `union([1,2], [2,3], [3,4])` → `[1,2,3,4]` |
|
|
69
|
+
| `pluck` | `arr: object[], property: string` | `any[]` | 提取属性值 | `pluck([{id:1},{id:2},{id:3}], 'id')` → `[1,2,3]` |
|
|
70
|
+
| `orderBy` | `arr: any[], field: string, order?: 'asc'\|'desc'` | `any[]` | 排序 | `orderBy([{age:30},{age:25}], 'age', 'asc')` → `[{age:25},{age:30}]` |
|
|
71
|
+
| `groupBy` | `arr: any[], field: string` | `object` | 分组 | `groupBy([{type:'A'},{type:'B'},{type:'A'}], 'type')` → `{A:[...], B:[...]}` |
|
|
72
|
+
| `countBy` | `arr: any[], field: string` | `object` | 统计计数 | `countBy([{type:'A'},{type:'B'},{type:'A'}], 'type')` → `{A:2, B:1}` |
|
|
73
|
+
| `toArrayTree` | `arr: any[], options?: object` | `any[]` | 转树形结构 | `toArrayTree([{id:1,pid:0},{id:2,pid:1}])` → `[{id:1,children:[{id:2}]}]` |
|
|
74
|
+
| `toTreeArray` | `tree: any[], options?: object` | `any[]` | 树形转数组 | `toTreeArray([{id:1,children:[{id:2}]}])` → `[{id:1,pid:0},{id:2,pid:1}]` |
|
|
75
|
+
| `invoke` | `arr: any[], methodName: string, ...args: any[]` | `any[]` | 调用方法 | `invoke([[1,2],[3,4]], 'join', ',')` → `['1,2','3,4']` |
|
|
76
|
+
| `unzip` | `arr: any[][]` | `any[][]` | 解压数组 | `unzip([[1,'a'],[2,'b'],[3,'c']])` → `[[1,2,3],['a','b','c']]` |
|
|
77
|
+
| `includeArrays` | `arr1: any[], arr2: any[]` | `boolean` | 数组包含 | `includeArrays([1,2,3,4], [2,3])` → `true` |
|
|
78
|
+
|
|
79
|
+
## 字符串函数
|
|
80
|
+
|
|
81
|
+
| 函数名 | 参数 | 返回值 | 描述 | 示例 |
|
|
82
|
+
|--------|------|--------|------|------|
|
|
83
|
+
| `trim` | `str: string` | `string` | 去除两端空格 | `trim(' hello ')` → `'hello'` |
|
|
84
|
+
| `trimLeft` | `str: string` | `string` | 去除左侧空格 | `trimLeft(' hello')` → `'hello'` |
|
|
85
|
+
| `trimRight` | `str: string` | `string` | 去除右侧空格 | `trimRight('hello ')` → `'hello'` |
|
|
86
|
+
| `camelCase` | `str: string` | `string` | 转驼峰命名 | `camelCase('hello_world')` → `'helloWorld'`<br>`camelCase('hello-world')` → `'helloWorld'` |
|
|
87
|
+
| `kebabCase` | `str: string` | `string` | 转烤串命名 | `kebabCase('helloWorld')` → `'hello-world'`<br>`kebabCase('HelloWorld')` → `'hello-world'` |
|
|
88
|
+
| `startsWith` | `str: string, search: string` | `boolean` | 是否以指定字符串开头 | `startsWith('hello', 'he')` → `true`<br>`startsWith('hello', 'lo')` → `false` |
|
|
89
|
+
| `endsWith` | `str: string, search: string` | `boolean` | 是否以指定字符串结尾 | `endsWith('hello', 'lo')` → `true`<br>`endsWith('hello', 'he')` → `false` |
|
|
90
|
+
| `toValueString` | `value: any` | `string` | 转值字符串 | `toValueString(123)` → `'123'`<br>`toValueString(null)` → `''` |
|
|
91
|
+
| `toNumberString` | `value: any, digits?: number` | `string` | 转数字字符串 | `toNumberString(3.14159, 2)` → `'3.14'` |
|
|
92
|
+
|
|
93
|
+
## 日期函数
|
|
94
|
+
|
|
95
|
+
| 函数名 | 参数 | 返回值 | 描述 | 示例 |
|
|
96
|
+
|--------|------|--------|------|------|
|
|
97
|
+
| `now` | 无 | `number` | 当前时间戳 | `now()` → `1640995200000` |
|
|
98
|
+
| `timestamp` | 无 | `number` | 当前时间戳 | `timestamp()` → `1640995200000` |
|
|
99
|
+
| `toDateString` | `date: any, format?: string` | `string` | 日期格式化 | `toDateString(1640995200000, 'YYYY-MM-DD')` → `'2022-01-01'` |
|
|
100
|
+
| `getYearDiff` | `date1: string\|number, date2: string\|number` | `number` | 年份差 | `getYearDiff('2020-01-01', '2024-01-01')` → `4` |
|
|
101
|
+
| `getMonthDiff` | `date1: string\|number, date2: string\|number` | `number` | 月份差 | `getMonthDiff('2024-01-01', '2024-06-01')` → `5` |
|
|
102
|
+
| `getDayDiff` | `date1: string\|number, date2: string\|number` | `number` | 天数差 | `getDayDiff('2024-01-01', '2024-01-10')` → `9` |
|
|
103
|
+
| `getHourDiff` | `time1: string\|number, time2: string\|number` | `number` | 小时差 | `getHourDiff('2024-01-01 10:00', '2024-01-01 15:30')` → `5.5` |
|
|
104
|
+
| `getMinuteDiff` | `time1: string\|number, time2: string\|number` | `number` | 分钟差 | `getMinuteDiff('10:30', '11:45')` → `75` |
|
|
105
|
+
| `getSecondDiff` | `time1: string\|number, time2: string\|number` | `number` | 秒数差 | `getSecondDiff('12:00:00', '12:01:30')` → `90` |
|
|
106
|
+
| `getDayOfMonth` | `date: string\|number` | `number` | 当月第几天 | `getDayOfMonth('2024-01-15')` → `15` |
|
|
107
|
+
|
|
108
|
+
## 对象函数
|
|
109
|
+
|
|
110
|
+
| 函数名 | 参数 | 返回值 | 描述 | 示例 |
|
|
111
|
+
|--------|------|--------|------|------|
|
|
112
|
+
| `has` | `obj: object, key: string` | `boolean` | 检查属性是否存在 | `has({name:'John'}, 'name')` → `true` |
|
|
113
|
+
| `get` | `obj: object, path: string, defaultValue?: any` | `any` | 深度获取属性值 | `get({user:{name:'John'}}, 'user.name')` → `'John'`<br>`get({}, 'user.name', '默认值')` → `'默认值'` |
|
|
114
|
+
| `assign` | `target: object, ...sources: object[]` | `object` | 对象属性分配 | `assign({}, {a:1}, {b:2})` → `{a:1,b:2}` |
|
|
115
|
+
| `merge` | `...objects: object[]` | `object` | 深度合并对象 | `merge({a:{x:1}}, {a:{y:2}, b:3})` → `{a:{x:1,y:2},b:3}` |
|
|
116
|
+
| `pick` | `obj: object, keys: string[]` | `object` | 选取指定属性 | `pick({name:'John',age:30,city:'NY'}, ['name','age'])` → `{name:'John',age:30}` |
|
|
117
|
+
| `omit` | `obj: object, keys: string[]` | `object` | 排除指定属性 | `omit({x:1,y:2,z:3}, ['z'])` → `{x:1,y:2}` |
|
|
118
|
+
|
|
119
|
+
## 类型判断函数
|
|
120
|
+
|
|
121
|
+
| 函数名 | 参数 | 返回值 | 描述 | 示例 |
|
|
122
|
+
|--------|------|--------|------|------|
|
|
123
|
+
| `isNaN` | `value: any` | `boolean` | 是否是NaN | `isNaN(NaN)` → `true`<br>`isNaN(123)` → `false` |
|
|
124
|
+
| `isArray` | `value: any` | `boolean` | 是否是数组 | `isArray([1,2,3])` → `true`<br>`isArray({})` → `false` |
|
|
125
|
+
| `isFloat` | `value: any` | `boolean` | 是否是浮点数 | `isFloat(3.14)` → `true`<br>`isFloat(3)` → `false` |
|
|
126
|
+
| `isInteger` | `value: any` | `boolean` | 是否是整数 | `isInteger(3)` → `true`<br>`isInteger(3.14)` → `false` |
|
|
127
|
+
| `isBoolean` | `value: any` | `boolean` | 是否是布尔值 | `isBoolean(true)` → `true`<br>`isBoolean('true')` → `false` |
|
|
128
|
+
| `isString` | `value: any` | `boolean` | 是否是字符串 | `isString('hello')` → `true`<br>`isString(123)` → `false` |
|
|
129
|
+
| `isNumber` | `value: any` | `boolean` | 是否是数字 | `isNumber(123)` → `true`<br>`isNumber('123')` → `false` |
|
|
130
|
+
| `isPlainObject` | `value: any` | `boolean` | 是否是纯对象 | `isPlainObject({})` → `true`<br>`isPlainObject([])` → `false` |
|
|
131
|
+
| `isDate` | `value: any` | `boolean` | 是否是日期对象 | `isDate(new Date())` → `true`<br>`isDate('2024-01-01')` → `false` |
|
|
132
|
+
| `isEmpty` | `value: any` | `boolean` | 是否为空 | `isEmpty([])` → `true`<br>`isEmpty({})` → `true`<br>`isEmpty('')` → `true`<br>`isEmpty([1])` → `false` |
|
|
133
|
+
| `isNull` | `value: any` | `boolean` | 是否是null | `isNull(null)` → `true`<br>`isNull(undefined)` → `false` |
|
|
134
|
+
| `isMatch` | `obj: object, source: object` | `boolean` | 是否部分匹配 | `isMatch({a:1,b:2,c:3}, {a:1,b:2})` → `true` |
|
|
135
|
+
| `isEqual` | `value1: any, value2: any` | `boolean` | 深度相等比较 | `isEqual({a:[1,2]}, {a:[1,2]})` → `true`<br>`isEqual({a:1}, {a:1,b:2})` → `false` |
|
|
136
|
+
| `getSize` | `value: any` | `number` | 获取大小 | `getSize([1,2,3])` → `3`<br>`getSize({a:1,b:2})` → `2`<br>`getSize('hello')` → `5` |
|
|
137
|
+
|
|
138
|
+
## 工具函数
|
|
139
|
+
|
|
140
|
+
| 函数名 | 参数 | 返回值 | 描述 | 示例 |
|
|
141
|
+
|--------|------|--------|------|------|
|
|
142
|
+
| `first` | `arr: any[]` 或 `...args: any[]` | `any` | 第一个元素 | `first([1,2,3])` → `1`<br>`first(1,2,3)` → `1` |
|
|
143
|
+
| `last` | `arr: any[]` 或 `...args: any[]` | `any` | 最后一个元素 | `last([1,2,3])` → `3`<br>`last(1,2,3)` → `3` |
|
|
144
|
+
|
|
145
|
+
## 注意事项
|
|
146
|
+
|
|
147
|
+
1. **参数类型**:所有函数参数都经过类型转换,字符串会自动转为数字等
|
|
148
|
+
2. **空值处理**:大部分函数对空值有安全的处理机制
|
|
149
|
+
3. **错误处理**:函数调用出错时会抛出清晰的错误信息
|
|
150
|
+
4. **性能优化**:常用函数做了性能优化,适合高频调用
|
|
151
|
+
|
|
152
|
+
## 使用示例
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
import { utils } from 'sh-tools'
|
|
156
|
+
|
|
157
|
+
// 数学计算
|
|
158
|
+
utils.calculate("abs(-10) + pow(2, 3)") // 18
|
|
159
|
+
|
|
160
|
+
// 数组操作
|
|
161
|
+
utils.calculate("sum([1,2,3,4,5]) / length([1,2,3,4,5])") // 3
|
|
162
|
+
|
|
163
|
+
// 字符串处理
|
|
164
|
+
utils.calculate("trim(' hello ') + ' ' + camelCase('world_test')") // "hello worldTest"
|
|
165
|
+
|
|
166
|
+
// 日期计算
|
|
167
|
+
utils.calculate("getDayDiff('2024-01-01', '2024-01-10') + getHourDiff('10:00', '12:30')") // 12.5
|
|
168
|
+
|
|
169
|
+
// 对象操作
|
|
170
|
+
utils.calculate("merge({a:1}, {b:2}, {c:3})") // {a:1, b:2, c:3}
|
|
171
|
+
```
|
|
33
172
|
|
|
34
|
-
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
|
35
|
-
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
|
|
36
|
-
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
|
|
37
|
-
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
|
|
38
|
-
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
|
39
|
-
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sh-tools",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.12",
|
|
4
4
|
"description": "基于fetch和xe-utils二次封装,支持宏公式计算",
|
|
5
5
|
"main": "packages/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"author": "神秘的sh",
|
|
14
14
|
"license": "ISC",
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"xe-utils": "^
|
|
16
|
+
"xe-utils": "^4.0.0"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@babel/core": "^7.12.16",
|