sh-tools 2.1.4 → 2.1.6
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/package.json +1 -1
- package/packages/utils/other.js +14 -6
- package/packages/utils/string.js +54 -227
package/package.json
CHANGED
package/packages/utils/other.js
CHANGED
|
@@ -170,6 +170,8 @@ export default {
|
|
|
170
170
|
}
|
|
171
171
|
// 对于多选获取数组类型值进行解析 赋值
|
|
172
172
|
let oriArray = []
|
|
173
|
+
// 是否需要对原值进行重写 默认为false
|
|
174
|
+
let resetValue = false
|
|
173
175
|
// 进行默认赋值 若没有任何解析原数返回
|
|
174
176
|
rvalue = value
|
|
175
177
|
// 首先提取公式进行公式计算
|
|
@@ -178,7 +180,7 @@ export default {
|
|
|
178
180
|
switch (rname) {
|
|
179
181
|
case '$vInput':
|
|
180
182
|
case '$vMoney':
|
|
181
|
-
if (editable && (
|
|
183
|
+
if (editable && (rname === '$vMoney' || ['integer', 'number', 'float'].includes(type)) && !$vUtils.isNone(value)) {
|
|
182
184
|
if ($vUtils.isNumber(+max) && +value > +max) {
|
|
183
185
|
value = +max
|
|
184
186
|
} else if ($vUtils.isNumber(+min) && +value < +min) {
|
|
@@ -191,14 +193,18 @@ export default {
|
|
|
191
193
|
rvalue = $vUtils.truncate(value, digits)
|
|
192
194
|
}
|
|
193
195
|
if ($vUtils.isString(rvalue)) rvalue = $vUtils.replaceNutrim(rvalue)
|
|
194
|
-
if (
|
|
196
|
+
if (rname === '$vMoney' && !$vUtils.isNone(rvalue)) {
|
|
195
197
|
rtext = $vUtils.truncate($vUtils.divide(rvalue, moneyUnit), digits)
|
|
196
198
|
}
|
|
197
199
|
if (commafy && !bill && bill !== '0') rtext = $vUtils.commafy(rtext, { digits })
|
|
198
200
|
break
|
|
199
201
|
case '$vTime':
|
|
200
202
|
format = format ? format.replace('YYYY', 'yyyy').replace('DD', 'dd').replace('hh', 'HH') : defaultDateFormat[type]
|
|
201
|
-
if (
|
|
203
|
+
if ($vUtils.isNumber(value)) value = String(value)
|
|
204
|
+
if (!$vUtils.isNone(value) && format) {
|
|
205
|
+
rvalue = $vUtils.toDateString(value, format)
|
|
206
|
+
resetValue = true
|
|
207
|
+
}
|
|
202
208
|
break
|
|
203
209
|
case '$vSelect':
|
|
204
210
|
case '$vCheckgroup':
|
|
@@ -230,8 +236,10 @@ export default {
|
|
|
230
236
|
}
|
|
231
237
|
rvalue = oriArray
|
|
232
238
|
} else {
|
|
233
|
-
|
|
234
|
-
|
|
239
|
+
if (options && options.length) {
|
|
240
|
+
let valueOption = options.find(option => $vUtils.isEqual(option[optionValue], value))
|
|
241
|
+
rtext = valueOption ? valueOption[optionLabel] : ''
|
|
242
|
+
}
|
|
235
243
|
rvalue = rname === '$vTree' ? (value ? [value] : []) : value
|
|
236
244
|
}
|
|
237
245
|
if (format) {
|
|
@@ -251,7 +259,7 @@ export default {
|
|
|
251
259
|
break
|
|
252
260
|
}
|
|
253
261
|
if ($vUtils.isString(rvalue)) rvalue = $vUtils.replaceNutrim(rvalue)
|
|
254
|
-
if (formula) {
|
|
262
|
+
if (formula || resetValue) {
|
|
255
263
|
$vUtils.set(rowData, key, rvalue)
|
|
256
264
|
}
|
|
257
265
|
rtext = rtext || rvalue
|
package/packages/utils/string.js
CHANGED
|
@@ -1,227 +1,54 @@
|
|
|
1
|
-
import XEUtils from 'xe-utils'
|
|
2
|
-
|
|
3
|
-
// 数据格式化获取keys
|
|
4
|
-
function getFormatKeys(format) {
|
|
5
|
-
let regR = new RegExp('({[a-zA-Z0-9_.]*})', 'ig')
|
|
6
|
-
let formatStr = String(format)
|
|
7
|
-
return (formatStr.match(regR) || []).map((key, keyIndex) => {
|
|
8
|
-
return key.replace(/{|}/gi, '')
|
|
9
|
-
})
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// 格式化数据结构
|
|
13
|
-
function format(format, data) {
|
|
14
|
-
let keys = getFormatKeys(format)
|
|
15
|
-
let formatStr = String(format)
|
|
16
|
-
keys.map((key, indexkey) => {
|
|
17
|
-
let value = XEUtils.get(data, key) || ''
|
|
18
|
-
formatStr = formatStr.replace(new RegExp('{' + key + '}', 'ig'), value)
|
|
19
|
-
})
|
|
20
|
-
return formatStr
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// 生成随机字符串
|
|
24
|
-
function randomStr(len = 32) {
|
|
25
|
-
const $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
|
|
26
|
-
const maxPos = $chars.length
|
|
27
|
-
let str = ''
|
|
28
|
-
for (let i = 0; i < len; i++) {
|
|
29
|
-
str += $chars.charAt(Math.floor(Math.random() * maxPos))
|
|
30
|
-
}
|
|
31
|
-
return str
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export default {
|
|
35
|
-
randomStr,
|
|
36
|
-
getFormatKeys,
|
|
37
|
-
format,
|
|
38
|
-
replaceNutrim(str) {
|
|
39
|
-
return String(str).replace(/null|undefined|(^\s*)|(\s*$)/gi, '')
|
|
40
|
-
},
|
|
41
|
-
replaceAll(str, from, to) {
|
|
42
|
-
// 替换全部 将str中的所有from替换为to
|
|
43
|
-
return str.replace(new RegExp(from, 'gm'), to)
|
|
44
|
-
},
|
|
45
|
-
filterTag(str) {
|
|
46
|
-
/* 过滤html代码(把<>转换字符串) */
|
|
47
|
-
let me = this
|
|
48
|
-
str = me.replaceAll(str, /&/gi, '&')
|
|
49
|
-
str = me.replaceAll(str, /</gi, '<')
|
|
50
|
-
str = me.replaceAll(str, />/gi, '>')
|
|
51
|
-
str = me.replaceAll(str, ' ', ' ')
|
|
52
|
-
return str
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// 生成水印 推荐 canvas
|
|
56
|
-
class WaterMark {
|
|
57
|
-
constructor(text, settings) {
|
|
58
|
-
this.settings = Object.assign(
|
|
59
|
-
{
|
|
60
|
-
container: document.body,
|
|
61
|
-
id: 'waterMark',
|
|
62
|
-
showType: 'canvas', // div 还是 canvas
|
|
63
|
-
x: 0, // 水印起始位置x轴坐标
|
|
64
|
-
y: 100, // 水印起始位置Y轴坐标
|
|
65
|
-
xSpace: 150, // 水印x轴间隔
|
|
66
|
-
ySpace: 100, // 水印y轴间隔
|
|
67
|
-
color: '#cfcccc', // 水印字体颜色
|
|
68
|
-
alpha: 0.5, // 水印透明度
|
|
69
|
-
fontsize: '15px', // 水印字体大小
|
|
70
|
-
angle: 20, // 水印倾斜度数
|
|
71
|
-
curTime: false // 是否自动拼接当前时间
|
|
72
|
-
},
|
|
73
|
-
settings || {}
|
|
74
|
-
)
|
|
75
|
-
this.globalWidth = this.settings.container.clientWidth
|
|
76
|
-
this.globalHeight = this.settings.container.clientHeight
|
|
77
|
-
this.initCanvas()
|
|
78
|
-
this.draw(text)
|
|
79
|
-
this.insertWaterMark()
|
|
80
|
-
}
|
|
81
|
-
initCanvas() {
|
|
82
|
-
this.renderCanvas = document.createElement('canvas')
|
|
83
|
-
this.renderContext = this.renderCanvas.getContext('2d')
|
|
84
|
-
this.renderCanvas.width = this.globalWidth
|
|
85
|
-
this.renderCanvas.height = this.globalHeight
|
|
86
|
-
this.div = document.createElement('div')
|
|
87
|
-
this.oldData = this.renderContext.getImageData(0, 0, this.globalWidth, this.globalHeight)
|
|
88
|
-
}
|
|
89
|
-
insertWaterMark() {
|
|
90
|
-
const { type, id, alpha, container } = this.settings
|
|
91
|
-
this.WaterMarkEl = this.renderCanvas
|
|
92
|
-
if (type === 'div') {
|
|
93
|
-
this.WaterMarkEl = this.div
|
|
94
|
-
this.WaterMarkEl.style.backgroundImage = 'url(' + this.renderCanvas.toDataURL('image/png') + ')'
|
|
95
|
-
}
|
|
96
|
-
const style = this.WaterMarkEl.style
|
|
97
|
-
style.position = 'absolute'
|
|
98
|
-
style.opacity = alpha
|
|
99
|
-
style.top = style.left = 0
|
|
100
|
-
style.zIndex = '9999'
|
|
101
|
-
style.width = this.globalWidth + 'px'
|
|
102
|
-
style.height = this.globalHeight + 'px'
|
|
103
|
-
style.pointerEvents = 'none'
|
|
104
|
-
this.WaterMarkEl.id = id
|
|
105
|
-
container.append(this.WaterMarkEl)
|
|
106
|
-
}
|
|
107
|
-
draw(waterMarkText, settings) {
|
|
108
|
-
this.settings = Object.assign(this.settings, settings || {})
|
|
109
|
-
let { x, y, xSpace, ySpace, color, fontsize, angle, curTime } = this.settings
|
|
110
|
-
let { globalWidth, globalHeight, renderContext } = this
|
|
111
|
-
let timeStr = ''
|
|
112
|
-
if (curTime) {
|
|
113
|
-
let today = new Date()
|
|
114
|
-
timeStr =
|
|
115
|
-
today.getFullYear() +
|
|
116
|
-
'-' +
|
|
117
|
-
String(today.getMonth() + 1).padStart(2, 0) +
|
|
118
|
-
'-' +
|
|
119
|
-
String(today.getDate()).padStart(2, 0) +
|
|
120
|
-
' ' +
|
|
121
|
-
String(today.getHours()).padStart(2, 0) +
|
|
122
|
-
':' +
|
|
123
|
-
String(today.getMinutes()).padStart(2, 0) +
|
|
124
|
-
':' +
|
|
125
|
-
String(today.getSeconds()).padStart(2, 0)
|
|
126
|
-
}
|
|
127
|
-
waterMarkText = waterMarkText ? waterMarkText + ' ' + timeStr : timeStr
|
|
128
|
-
renderContext.clearRect(0, 0, globalWidth, globalHeight)
|
|
129
|
-
renderContext.font = fontsize + ' microsoft yahei'
|
|
130
|
-
renderContext.fillStyle = color
|
|
131
|
-
renderContext.textAlign = 'left'
|
|
132
|
-
renderContext.textBaseline = 'Middle'
|
|
133
|
-
let measureText = renderContext.measureText(waterMarkText)
|
|
134
|
-
let width = measureText.width
|
|
135
|
-
let height = Math.ceil(width / Math.tan(angle) + 50)
|
|
136
|
-
for (let xx = x; xx < globalWidth; xx += xSpace + width) {
|
|
137
|
-
for (let yy = y; yy < globalHeight; yy += ySpace + height) {
|
|
138
|
-
// 填充文字,x 间距, y 间距
|
|
139
|
-
renderContext.save()
|
|
140
|
-
renderContext.translate(xx, yy)
|
|
141
|
-
renderContext.rotate(0 - (angle * Math.PI) / 180)
|
|
142
|
-
renderContext.fillText(waterMarkText, 0, 0)
|
|
143
|
-
renderContext.restore()
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
// 图片的像素信息里存储着 RGB 的色值,R、G、B 分别为该像素的红、绿、蓝通道,每个通道的分量值范围在 0~255,16 进制则是 00~FF。在 CSS 中经常使用其 16 进制形式,比如指定博客头部背景色为 #A9D5F4。其中 R(红色)的 16 进制值为 A9,换算成十进制为 169。这时候,对 R 分量的值 + 1,即为 170,整个像素 RGB 值为 #AAD5F4,别说你看不出差别,就连火眼金金的“ 像素眼” 设计师都察觉不出来呢。于此同时,修改 G、B 的分量值,也是我们无法察觉的。因此可以得出重要结论:RGB 分量值的小量变动,是肉眼无法分辨的,不影响对图片的识别。
|
|
148
|
-
// 有了这个结论,那就给我们了利用空间,常用手段的就是对二进制最低位进行操作,下面就用 canvas 来演示一下。
|
|
149
|
-
inVisible(ctx, newData, originalData, color = 'R') {
|
|
150
|
-
var oData = originalData.data
|
|
151
|
-
var bit, offset // offset的作用是找到alpha通道值,这里需要大家自己动动脑筋
|
|
152
|
-
switch (color) {
|
|
153
|
-
case 'R':
|
|
154
|
-
bit = 0
|
|
155
|
-
offset = 3
|
|
156
|
-
break
|
|
157
|
-
case 'G':
|
|
158
|
-
bit = 1
|
|
159
|
-
offset = 2
|
|
160
|
-
break
|
|
161
|
-
case 'B':
|
|
162
|
-
bit = 2
|
|
163
|
-
offset = 1
|
|
164
|
-
break
|
|
165
|
-
}
|
|
166
|
-
for (var i = 0; i < oData.length; i++) {
|
|
167
|
-
if (i % 4 === bit) {
|
|
168
|
-
// 只处理目标通道
|
|
169
|
-
if (newData[i + offset] === 0 && oData[i] % 2 === 1) {
|
|
170
|
-
// 没有信息的像素,该通道最低位置0,但不要越界
|
|
171
|
-
if (oData[i] === 255) {
|
|
172
|
-
oData[i]--
|
|
173
|
-
} else {
|
|
174
|
-
oData[i]++
|
|
175
|
-
}
|
|
176
|
-
} else if (newData[i + offset] !== 0 && oData[i] % 2 === 0) {
|
|
177
|
-
// // 有信息的像素,该通道最低位置1,可以想想上面的斑点效果是怎么实现的
|
|
178
|
-
oData[i]++
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
ctx.putImageData(originalData, 0, 0)
|
|
183
|
-
}
|
|
184
|
-
visible(ctx, originalData, color = 'R') {
|
|
185
|
-
var bit, offset // offset的作用是找到alpha通道值,这里需要大家自己动动脑筋
|
|
186
|
-
switch (color) {
|
|
187
|
-
case 'R':
|
|
188
|
-
bit = 0
|
|
189
|
-
offset = 3
|
|
190
|
-
break
|
|
191
|
-
case 'G':
|
|
192
|
-
bit = 1
|
|
193
|
-
offset = 2
|
|
194
|
-
break
|
|
195
|
-
case 'B':
|
|
196
|
-
bit = 2
|
|
197
|
-
offset = 1
|
|
198
|
-
break
|
|
199
|
-
}
|
|
200
|
-
var data = originalData.data
|
|
201
|
-
for (var i = 0; i < data.length; i++) {
|
|
202
|
-
if (i % 4 === bit) {
|
|
203
|
-
// 只处理目标通道
|
|
204
|
-
if (data[i] % 2 === 0) {
|
|
205
|
-
// 没有信息的像素,该通道最低位置0,但不要越界
|
|
206
|
-
if (data[i] % 2 === 0) {
|
|
207
|
-
data[i] = 0
|
|
208
|
-
} else if (i % 4 === 3) {
|
|
209
|
-
// alpha通道不做处理
|
|
210
|
-
continue
|
|
211
|
-
} else {
|
|
212
|
-
// 关闭其他分量,不关闭也不影响答案
|
|
213
|
-
data[i] = 0
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
ctx.putImageData(originalData, 0, 0)
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return new WaterMark(text, settings)
|
|
222
|
-
},
|
|
223
|
-
removeWaterMark(container, id) {
|
|
224
|
-
const body = container || document.body
|
|
225
|
-
body.removeChild(document.getElementById(id || 'waterMark'))
|
|
226
|
-
}
|
|
227
|
-
}
|
|
1
|
+
import XEUtils from 'xe-utils'
|
|
2
|
+
|
|
3
|
+
// 数据格式化获取keys
|
|
4
|
+
function getFormatKeys(format) {
|
|
5
|
+
let regR = new RegExp('({[a-zA-Z0-9_.]*})', 'ig')
|
|
6
|
+
let formatStr = String(format)
|
|
7
|
+
return (formatStr.match(regR) || []).map((key, keyIndex) => {
|
|
8
|
+
return key.replace(/{|}/gi, '')
|
|
9
|
+
})
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// 格式化数据结构
|
|
13
|
+
function format(format, data) {
|
|
14
|
+
let keys = getFormatKeys(format)
|
|
15
|
+
let formatStr = String(format)
|
|
16
|
+
keys.map((key, indexkey) => {
|
|
17
|
+
let value = XEUtils.get(data, key) || ''
|
|
18
|
+
formatStr = formatStr.replace(new RegExp('{' + key + '}', 'ig'), value)
|
|
19
|
+
})
|
|
20
|
+
return formatStr
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// 生成随机字符串
|
|
24
|
+
function randomStr(len = 32) {
|
|
25
|
+
const $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
|
|
26
|
+
const maxPos = $chars.length
|
|
27
|
+
let str = ''
|
|
28
|
+
for (let i = 0; i < len; i++) {
|
|
29
|
+
str += $chars.charAt(Math.floor(Math.random() * maxPos))
|
|
30
|
+
}
|
|
31
|
+
return str
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default {
|
|
35
|
+
randomStr,
|
|
36
|
+
getFormatKeys,
|
|
37
|
+
format,
|
|
38
|
+
replaceNutrim(str) {
|
|
39
|
+
return String(str).replace(/null|undefined|(^\s*)|(\s*$)/gi, '')
|
|
40
|
+
},
|
|
41
|
+
replaceAll(str, from, to) {
|
|
42
|
+
// 替换全部 将str中的所有from替换为to
|
|
43
|
+
return str.replace(new RegExp(from, 'gm'), to)
|
|
44
|
+
},
|
|
45
|
+
filterTag(str) {
|
|
46
|
+
/* 过滤html代码(把<>转换字符串) */
|
|
47
|
+
let me = this
|
|
48
|
+
str = me.replaceAll(str, /&/gi, '&')
|
|
49
|
+
str = me.replaceAll(str, /</gi, '<')
|
|
50
|
+
str = me.replaceAll(str, />/gi, '>')
|
|
51
|
+
str = me.replaceAll(str, ' ', ' ')
|
|
52
|
+
return str
|
|
53
|
+
}
|
|
54
|
+
}
|