web-component-gallery 2.3.12 → 2.3.14
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/index.umd.js +1 -1
- package/dist/js.umd.js +1 -1
- package/dist/style.css +75 -3
- package/lib/form-comp/ACascaderMultiple.vue +19 -1
- package/lib/form-comp/ASelectCustom.vue +1 -1
- package/lib/form-comp/style/ACascaderMultiple.less +9 -2
- package/lib/model/Model.js +126 -87
- package/lib/model/utils/render.js +33 -52
- package/lib/weather/index.vue +234 -58
- package/lib/weather/style/index.less +208 -5
- package/package.json +1 -1
- package/utils/Filter.js +182 -176
package/utils/Filter.js
CHANGED
|
@@ -1,16 +1,98 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 格式化日期
|
|
3
|
+
* @param {string|number|Date} time - 时间
|
|
4
|
+
* @param {string} cFormat - 格式化模板
|
|
5
|
+
* {y}年 {m}月 {d}日 {h}时 {i}分 {s}秒 {a}星期 {q}季度
|
|
6
|
+
* @returns {string|null} 格式化后的日期字符串
|
|
7
|
+
*/
|
|
8
|
+
export function formatDate(time, cFormat) {
|
|
9
|
+
if (arguments.length === 0 || !time) return null
|
|
10
|
+
|
|
11
|
+
const format = cFormat || "{y}-{m}-{d} {h}:{i}:{s}"
|
|
12
|
+
let date
|
|
13
|
+
|
|
14
|
+
if (typeof time === "object") {
|
|
15
|
+
date = time
|
|
16
|
+
} else {
|
|
17
|
+
let timestamp = time
|
|
18
|
+
|
|
19
|
+
if (typeof timestamp === "string") {
|
|
20
|
+
timestamp = /^[0-9]+$/.test(timestamp)
|
|
21
|
+
? parseInt(timestamp)
|
|
22
|
+
: timestamp.replace(/-/g, "/")
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (typeof timestamp === "number" && timestamp.toString().length === 10) {
|
|
26
|
+
timestamp *= 1000
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
date = new Date(timestamp)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (isNaN(date.getTime())) {
|
|
33
|
+
console.warn('无效的日期格式')
|
|
34
|
+
return null
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const formatObj = {
|
|
38
|
+
y: date.getFullYear(),
|
|
39
|
+
m: date.getMonth() + 1,
|
|
40
|
+
d: date.getDate(),
|
|
41
|
+
h: date.getHours(),
|
|
42
|
+
i: date.getMinutes(),
|
|
43
|
+
s: date.getSeconds(),
|
|
44
|
+
a: date.getDay(),
|
|
45
|
+
q: Math.floor((date.getMonth() + 3) / 3),
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const timeStr = format.replace(/{([ymdhisaq])+}/g, (result, key) => {
|
|
49
|
+
const value = formatObj[key]
|
|
50
|
+
|
|
51
|
+
if (key === "a") {
|
|
52
|
+
return ["日", "一", "二", "三", "四", "五", "六"][value]
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return String(value).padStart(2, "0")
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
return timeStr
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 获取相对时间(通用函数)
|
|
3
63
|
* @param {number} n - 数量
|
|
64
|
+
* @param {string} unit - 单位:'days'|'hours'|'minutes'|'seconds'
|
|
65
|
+
* @param {boolean} isBefore - 是否之前
|
|
4
66
|
* @param {string|Date} baseTime - 基准时间(可选)
|
|
5
67
|
* @param {string} cFormat - 格式化模板
|
|
6
68
|
* @returns {string} 格式化日期
|
|
7
69
|
*/
|
|
8
|
-
export function
|
|
70
|
+
export function getRelativeTime(n, unit = 'days', isBefore = true, baseTime = null, cFormat) {
|
|
9
71
|
const base = baseTime ? new Date(baseTime) : new Date()
|
|
10
|
-
const
|
|
72
|
+
const multipliers = {
|
|
73
|
+
days: 24 * 60 * 60 * 1000,
|
|
74
|
+
hours: 60 * 60 * 1000,
|
|
75
|
+
minutes: 60 * 1000,
|
|
76
|
+
seconds: 1000
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const diff = n * (multipliers[unit] || multipliers.days)
|
|
80
|
+
const targetTime = new Date(base.getTime() + (isBefore ? -diff : diff))
|
|
81
|
+
|
|
11
82
|
return formatDate(targetTime, cFormat)
|
|
12
83
|
}
|
|
13
84
|
|
|
85
|
+
/**
|
|
86
|
+
* 获取 n 天前的时间
|
|
87
|
+
* @param {number} n - 数量
|
|
88
|
+
* @param {string|Date} baseTime - 基准时间(可选)
|
|
89
|
+
* @param {string} cFormat - 格式化模板
|
|
90
|
+
* @returns {string} 格式化日期
|
|
91
|
+
*/
|
|
92
|
+
export function getNDaysBefore(n, baseTime = null, cFormat) {
|
|
93
|
+
return getRelativeTime(n, 'days', true, baseTime, cFormat)
|
|
94
|
+
}
|
|
95
|
+
|
|
14
96
|
/**
|
|
15
97
|
* 获取 n 小时前的时间
|
|
16
98
|
* @param {number} n - 小时数
|
|
@@ -19,9 +101,7 @@ export function getNDaysBefore(n, baseTime = null, cFormat) {
|
|
|
19
101
|
* @returns {string} 格式化日期
|
|
20
102
|
*/
|
|
21
103
|
export function getNHoursBefore(n, baseTime = null, cFormat) {
|
|
22
|
-
|
|
23
|
-
const targetTime = new Date(base.getTime() - n * 60 * 60 * 1000)
|
|
24
|
-
return formatDate(targetTime, cFormat)
|
|
104
|
+
return getRelativeTime(n, 'hours', true, baseTime, cFormat)
|
|
25
105
|
}
|
|
26
106
|
|
|
27
107
|
/**
|
|
@@ -32,9 +112,7 @@ export function getNHoursBefore(n, baseTime = null, cFormat) {
|
|
|
32
112
|
* @returns {string} 格式化日期
|
|
33
113
|
*/
|
|
34
114
|
export function getNMinutesBefore(n, baseTime = null, cFormat) {
|
|
35
|
-
|
|
36
|
-
const targetTime = new Date(base.getTime() - n * 60 * 1000)
|
|
37
|
-
return formatDate(targetTime, cFormat)
|
|
115
|
+
return getRelativeTime(n, 'minutes', true, baseTime, cFormat)
|
|
38
116
|
}
|
|
39
117
|
|
|
40
118
|
/**
|
|
@@ -45,9 +123,7 @@ export function getNMinutesBefore(n, baseTime = null, cFormat) {
|
|
|
45
123
|
* @returns {string} 格式化日期
|
|
46
124
|
*/
|
|
47
125
|
export function getNSecondsBefore(n, baseTime = null, cFormat) {
|
|
48
|
-
|
|
49
|
-
const targetTime = new Date(base.getTime() - n * 1000)
|
|
50
|
-
return formatDate(targetTime, cFormat)
|
|
126
|
+
return getRelativeTime(n, 'seconds', true, baseTime, cFormat)
|
|
51
127
|
}
|
|
52
128
|
|
|
53
129
|
/**
|
|
@@ -58,9 +134,7 @@ export function getNSecondsBefore(n, baseTime = null, cFormat) {
|
|
|
58
134
|
* @returns {string} 格式化日期
|
|
59
135
|
*/
|
|
60
136
|
export function getNDaysAfter(n, baseTime = null, cFormat) {
|
|
61
|
-
|
|
62
|
-
const targetTime = new Date(base.getTime() + n * 24 * 60 * 60 * 1000)
|
|
63
|
-
return formatDate(targetTime, cFormat)
|
|
137
|
+
return getRelativeTime(n, 'days', false, baseTime, cFormat)
|
|
64
138
|
}
|
|
65
139
|
|
|
66
140
|
/**
|
|
@@ -71,75 +145,7 @@ export function getNDaysAfter(n, baseTime = null, cFormat) {
|
|
|
71
145
|
* @returns {string} 格式化日期
|
|
72
146
|
*/
|
|
73
147
|
export function getNHoursAfter(n, baseTime = null, cFormat) {
|
|
74
|
-
|
|
75
|
-
const targetTime = new Date(base.getTime() + n * 60 * 60 * 1000)
|
|
76
|
-
return formatDate(targetTime, cFormat)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* 格式化日期
|
|
81
|
-
* @param {string|number|Date} time - 时间
|
|
82
|
-
* @param {string} cFormat - 格式化模板
|
|
83
|
-
* {y}年 {m}月 {d}日 {h}时 {i}分 {s}秒 {a}星期 {q}季度
|
|
84
|
-
* @returns {string|null} 格式化后的日期字符串
|
|
85
|
-
*/
|
|
86
|
-
export function formatDate(time, cFormat) {
|
|
87
|
-
if (arguments.length === 0 || !time) return null
|
|
88
|
-
|
|
89
|
-
const format = cFormat || "{y}-{m}-{d} {h}:{i}:{s}"
|
|
90
|
-
let date
|
|
91
|
-
|
|
92
|
-
// 处理不同类型的输入
|
|
93
|
-
if (typeof time === "object") {
|
|
94
|
-
date = time
|
|
95
|
-
} else {
|
|
96
|
-
let timestamp = time
|
|
97
|
-
|
|
98
|
-
// 字符串处理
|
|
99
|
-
if (typeof timestamp === "string") {
|
|
100
|
-
timestamp = /^[0-9]+$/.test(timestamp)
|
|
101
|
-
? parseInt(timestamp)
|
|
102
|
-
: timestamp.replace(/-/g, "/")
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// 10 位时间戳转毫秒
|
|
106
|
-
if (typeof timestamp === "number" && timestamp.toString().length === 10) {
|
|
107
|
-
timestamp *= 1000
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
date = new Date(timestamp)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// 验证日期有效性
|
|
114
|
-
if (isNaN(date.getTime())) {
|
|
115
|
-
console.warn('无效的日期格式')
|
|
116
|
-
return null
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const formatObj = {
|
|
120
|
-
y: date.getFullYear(),
|
|
121
|
-
m: date.getMonth() + 1,
|
|
122
|
-
d: date.getDate(),
|
|
123
|
-
h: date.getHours(),
|
|
124
|
-
i: date.getMinutes(),
|
|
125
|
-
s: date.getSeconds(),
|
|
126
|
-
a: date.getDay(),
|
|
127
|
-
q: Math.floor((date.getMonth() + 3) / 3), // 季度
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const timeStr = format.replace(/{([ymdhisaq])+}/g, (result, key) => {
|
|
131
|
-
const value = formatObj[key]
|
|
132
|
-
|
|
133
|
-
// 星期处理
|
|
134
|
-
if (key === "a") {
|
|
135
|
-
return ["日", "一", "二", "三", "四", "五", "六"][value]
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// 补零处理
|
|
139
|
-
return String(value).padStart(2, "0")
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
return timeStr
|
|
148
|
+
return getRelativeTime(n, 'hours', false, baseTime, cFormat)
|
|
143
149
|
}
|
|
144
150
|
|
|
145
151
|
/**
|
|
@@ -151,7 +157,6 @@ export function formatDate(time, cFormat) {
|
|
|
151
157
|
export function formatTimestamp(timestamp, format) {
|
|
152
158
|
if (!timestamp) return null
|
|
153
159
|
|
|
154
|
-
// 10 位时间戳转毫秒
|
|
155
160
|
if (String(timestamp).length === 10) {
|
|
156
161
|
timestamp *= 1000
|
|
157
162
|
}
|
|
@@ -163,7 +168,7 @@ export function formatTimestamp(timestamp, format) {
|
|
|
163
168
|
* 计算两个日期之间的差异
|
|
164
169
|
* @param {string|Date} date1 - 日期 1
|
|
165
170
|
* @param {string|Date} date2 - 日期 2
|
|
166
|
-
* @returns {Object} 差异对象
|
|
171
|
+
* @returns {Object} 差异对象
|
|
167
172
|
*/
|
|
168
173
|
export function dateDiff(date1, date2) {
|
|
169
174
|
const d1 = new Date(date1)
|
|
@@ -204,28 +209,27 @@ export function getDaysInMonth(year, month) {
|
|
|
204
209
|
/**
|
|
205
210
|
* 颜色十六进制转 RGB/RGBA
|
|
206
211
|
* @param {string} sHex - 十六进制色值
|
|
207
|
-
* @param {number} alpha -
|
|
208
|
-
* @returns {string} rgba(r,g,b,a) 格式字符串
|
|
212
|
+
* @param {number} [alpha] - 透明度(0-1)
|
|
213
|
+
* @returns {string} rgba(r,g,b,a) 或 rgb(r,g,b) 格式字符串
|
|
209
214
|
*/
|
|
210
215
|
export function colorRgba(sHex, alpha) {
|
|
211
216
|
const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
|
|
212
217
|
let sColor = sHex.toLowerCase()
|
|
213
218
|
|
|
214
219
|
if (sColor && reg.test(sColor)) {
|
|
215
|
-
// 简写形式转为完整形式 #fff -> #ffffff
|
|
216
220
|
if (sColor.length === 4) {
|
|
217
221
|
sColor = "#" + [1, 2, 3].map(i =>
|
|
218
222
|
sColor.slice(i, i + 1).repeat(2)
|
|
219
223
|
).join("")
|
|
220
224
|
}
|
|
221
225
|
|
|
222
|
-
// 提取 RGB 值
|
|
223
226
|
const rgbValues = []
|
|
224
227
|
for (let i = 1; i < 7; i += 2) {
|
|
225
228
|
rgbValues.push(parseInt(`0x${sColor.slice(i, i + 2)}`))
|
|
226
229
|
}
|
|
227
230
|
|
|
228
|
-
|
|
231
|
+
// 修复:使用 alpha == null 检查(同时排除 undefined 和 null)
|
|
232
|
+
return (alpha != null)
|
|
229
233
|
? `rgba(${rgbValues.join(",")},${alpha})`
|
|
230
234
|
: `rgb(${rgbValues.join(",")})`
|
|
231
235
|
}
|
|
@@ -258,7 +262,6 @@ export function randomColor(full = false) {
|
|
|
258
262
|
return '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0')
|
|
259
263
|
}
|
|
260
264
|
|
|
261
|
-
// 生成柔和的彩色
|
|
262
265
|
const hue = Math.floor(Math.random() * 360)
|
|
263
266
|
const saturation = 70 + Math.floor(Math.random() * 20)
|
|
264
267
|
const lightness = 60 + Math.floor(Math.random() * 20)
|
|
@@ -305,14 +308,12 @@ export function hslToHex(h, s, l) {
|
|
|
305
308
|
* @returns {Array} [百分比数组,数值数组]
|
|
306
309
|
*/
|
|
307
310
|
export function produceDataSeriesEx(segment, total, baseValue) {
|
|
308
|
-
// 生成分段百分比
|
|
309
311
|
const percentArray = new Array(segment).fill(0)
|
|
310
312
|
for (let i = 0; i < total; i++) {
|
|
311
313
|
const randomIndex = Math.floor(Math.random() * segment)
|
|
312
314
|
percentArray[randomIndex]++
|
|
313
315
|
}
|
|
314
316
|
|
|
315
|
-
// 计算对应数值
|
|
316
317
|
const valueArray = percentArray.map(percent =>
|
|
317
318
|
Math.floor(percent / 100 * baseValue)
|
|
318
319
|
)
|
|
@@ -321,7 +322,7 @@ export function produceDataSeriesEx(segment, total, baseValue) {
|
|
|
321
322
|
}
|
|
322
323
|
|
|
323
324
|
/**
|
|
324
|
-
*
|
|
325
|
+
* 深拷贝(增强版)
|
|
325
326
|
* @param {*} obj - 要拷贝的对象
|
|
326
327
|
* @returns {*} 深拷贝后的结果
|
|
327
328
|
*/
|
|
@@ -334,6 +335,10 @@ export function deepClone(obj) {
|
|
|
334
335
|
return new Date(obj.getTime())
|
|
335
336
|
}
|
|
336
337
|
|
|
338
|
+
if (obj instanceof RegExp) {
|
|
339
|
+
return new RegExp(obj.source, obj.flags)
|
|
340
|
+
}
|
|
341
|
+
|
|
337
342
|
if (obj instanceof Array) {
|
|
338
343
|
return obj.reduce((arr, item) => {
|
|
339
344
|
arr.push(deepClone(item))
|
|
@@ -347,55 +352,43 @@ export function deepClone(obj) {
|
|
|
347
352
|
return newObj
|
|
348
353
|
}, {})
|
|
349
354
|
}
|
|
355
|
+
|
|
356
|
+
return obj
|
|
350
357
|
}
|
|
351
358
|
|
|
352
359
|
/**
|
|
353
360
|
* 数据类型转换工具函数
|
|
354
361
|
* @param {*} data - 原始数据
|
|
355
|
-
* @param {string|Object|null} format -
|
|
362
|
+
* @param {string|Object|null} format - 目标类型或转换配置
|
|
356
363
|
* - 字符串:'String'|'Number'|'Boolean'|'Array'|'Object'
|
|
357
|
-
* -
|
|
358
|
-
* -
|
|
364
|
+
* - 对象:映射配置 {key: type}
|
|
365
|
+
* - 数组:字段配置 [{ fields: ['a'], type: 'Number' }]
|
|
366
|
+
* - null:智能转换
|
|
359
367
|
* @param {Object} options - 配置选项
|
|
360
|
-
* @param {
|
|
361
|
-
* @param {*} options.defaultValue - 自定义默认值(可选)
|
|
368
|
+
* @param {*} options.defaultValue - 自定义默认值
|
|
362
369
|
* @returns {*} 转换后的数据
|
|
363
370
|
*
|
|
364
371
|
* @example
|
|
365
|
-
* //
|
|
366
|
-
* transferData('123')
|
|
367
|
-
* transferData('true')
|
|
368
|
-
* transferData(
|
|
369
|
-
* transferData('
|
|
370
|
-
*
|
|
371
|
-
* //
|
|
372
|
-
* transferData('
|
|
373
|
-
* transferData(
|
|
374
|
-
*
|
|
375
|
-
* //
|
|
376
|
-
* transferData({a:'1',
|
|
377
|
-
* // {a: 1, b: 2}
|
|
378
|
-
*
|
|
379
|
-
* // 配置选项
|
|
380
|
-
* transferData('abc', 'Number') // NaN
|
|
381
|
-
* transferData('abc', 'Number', { defaultValue: -1 }) // -1
|
|
372
|
+
* transferData('123') // 智能转换:123
|
|
373
|
+
* transferData('123', 'Number') // Number:123
|
|
374
|
+
* transferData('true', 'Boolean') // Boolean:true
|
|
375
|
+
* transferData(123, 'String') // String:'123'
|
|
376
|
+
* transferData('[1,2]', 'Array') // Array:[1,2]
|
|
377
|
+
* transferData('{"a":1}', 'Object') // Object:{a:1}
|
|
378
|
+
* transferData({a:'1'}, ['a']) // 批量转 Number:{a:1}
|
|
379
|
+
* transferData({a:'1'}, [['a'],'Number']) // 指定类型:{a:1}
|
|
380
|
+
* transferData({a:'1'}, [{fields:['a'],type:'Number'}]) // 对象配置:{a:1}
|
|
381
|
+
* transferData({a:null}, ['a'], {defaultValue:0}) // 带默认值:{a:0}
|
|
382
|
+
* transferData([{a:'1'},{a:'2'}], ['a']) // 数组递归:[{a:1},{a:2}]
|
|
383
|
+
* transferData({a:'1',b:'2'}, {a:'Number'}) // 对象映射:{a:1,b:'2'}
|
|
382
384
|
*/
|
|
383
385
|
export function transferData(data, format, options = {}) {
|
|
384
|
-
// 智能转换模式
|
|
385
386
|
if (!format) return autoTransferDataInternal(data, options)
|
|
386
387
|
|
|
387
|
-
const { defaultValue } = options
|
|
388
|
-
|
|
389
|
-
// 数组模式:支持两种形式
|
|
390
|
-
// 1. ['a', 'b', 'c'] - 转换为 Number
|
|
391
|
-
// 2. [['a', 'b'], 'Number'] - 指定类型
|
|
392
|
-
// 3. [{ fields: ['a', 'b'], type: 'Number' }] - 对象配置
|
|
393
388
|
if (Array.isArray(format)) return transferDataByFields(data, format, options)
|
|
394
389
|
|
|
395
|
-
// 对象映射模式
|
|
396
390
|
if (typeof format === 'object') return transferDataByMap(data, format, options)
|
|
397
391
|
|
|
398
|
-
// 默认值配置
|
|
399
392
|
const defaults = {
|
|
400
393
|
Number: 0,
|
|
401
394
|
Boolean: false,
|
|
@@ -404,12 +397,10 @@ export function transferData(data, format, options = {}) {
|
|
|
404
397
|
Object: {}
|
|
405
398
|
}
|
|
406
399
|
|
|
407
|
-
const defaultVal = defaultValue ?? defaults[format]
|
|
400
|
+
const defaultVal = options.defaultValue ?? defaults[format]
|
|
408
401
|
|
|
409
|
-
// 空值处理
|
|
410
402
|
if (data == null) return defaultVal
|
|
411
403
|
|
|
412
|
-
// 复杂类型处理 (Array/Object)
|
|
413
404
|
if (format === 'Array' || format === 'Object') {
|
|
414
405
|
const isTargetType = (format === 'Array' && Array.isArray(data)) ||
|
|
415
406
|
(format === 'Object' && typeof data === 'object' && !Array.isArray(data))
|
|
@@ -424,7 +415,6 @@ export function transferData(data, format, options = {}) {
|
|
|
424
415
|
}
|
|
425
416
|
}
|
|
426
417
|
|
|
427
|
-
// 基础类型转换
|
|
428
418
|
try {
|
|
429
419
|
switch (format) {
|
|
430
420
|
case 'Number': {
|
|
@@ -439,7 +429,6 @@ export function transferData(data, format, options = {}) {
|
|
|
439
429
|
return Boolean(data)
|
|
440
430
|
}
|
|
441
431
|
case 'String': {
|
|
442
|
-
// 对象/数组转为 JSON 字符串
|
|
443
432
|
if (typeof data === 'object') {
|
|
444
433
|
try {
|
|
445
434
|
return JSON.stringify(data)
|
|
@@ -461,56 +450,76 @@ export function transferData(data, format, options = {}) {
|
|
|
461
450
|
* 根据字段数组批量转换数据
|
|
462
451
|
* @param {*} data - 原始数据
|
|
463
452
|
* @param {Array} format - 格式配置
|
|
464
|
-
* - ['a', 'b', 'c'] - 默认转为 Number
|
|
465
|
-
* - [['a', 'b'], 'Number'] - 指定类型
|
|
466
|
-
* - [{ fields: ['a', 'b'], type: 'Number' }] - 对象配置
|
|
467
453
|
* @param {Object} options - 配置选项
|
|
468
454
|
* @returns {*} 转换后的数据
|
|
469
455
|
*/
|
|
470
456
|
function transferDataByFields(data, format, options) {
|
|
457
|
+
// 边界情况处理
|
|
471
458
|
if (data == null || typeof data !== 'object') {
|
|
472
459
|
return data ?? options.defaultValue
|
|
473
460
|
}
|
|
474
461
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
// 解析数组配置
|
|
479
|
-
if (format.length === 0) return data
|
|
480
|
-
|
|
481
|
-
// 形式 1: ['a', 'b', 'c'] - 默认转 Number
|
|
482
|
-
if (typeof format[0] === 'string') {
|
|
483
|
-
fields = format
|
|
484
|
-
}
|
|
485
|
-
// 形式 2: [['a', 'b'], 'Number'] - [fields, type]
|
|
486
|
-
else if (Array.isArray(format[0])) {
|
|
487
|
-
fields = format[0]
|
|
488
|
-
if (format[1]) type = format[1]
|
|
489
|
-
}
|
|
490
|
-
// 形式 3: [{ fields: ['a', 'b'], type: 'Number' }] - 对象配置
|
|
491
|
-
else if (typeof format[0] === 'object') {
|
|
492
|
-
const config = format[0]
|
|
493
|
-
fields = config.fields || []
|
|
494
|
-
type = config.type || 'Number'
|
|
495
|
-
}
|
|
462
|
+
// 空配置直接返回
|
|
463
|
+
if (!format || format.length === 0) return data
|
|
496
464
|
|
|
497
|
-
//
|
|
465
|
+
// 数组处理:递归处理每个元素(提前到最前面)
|
|
498
466
|
if (Array.isArray(data)) {
|
|
499
467
|
return data.map(item => transferDataByFields(item, format, options))
|
|
500
468
|
}
|
|
501
469
|
|
|
502
|
-
// 对象处理:转换指定字段
|
|
503
470
|
const result = { ...data }
|
|
471
|
+
const configType = typeof format[0]
|
|
504
472
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
473
|
+
if (configType === 'string' || Array.isArray(format[0])) {
|
|
474
|
+
// 形式 1 和形式 2:统一解析
|
|
475
|
+
const { fields, type } = parseFormatConfig(format)
|
|
476
|
+
|
|
477
|
+
for (const field of fields) {
|
|
478
|
+
if (field in result) {
|
|
479
|
+
result[field] = transferData(result[field], type, options)
|
|
480
|
+
}
|
|
508
481
|
}
|
|
482
|
+
} else if (configType === 'object') {
|
|
483
|
+
// 形式 3:对象配置数组
|
|
484
|
+
format.forEach(config => {
|
|
485
|
+
const fields = config.fields || []
|
|
486
|
+
const type = config.type || 'Number'
|
|
487
|
+
|
|
488
|
+
for (const field of fields) {
|
|
489
|
+
if (field in result) {
|
|
490
|
+
const fieldOptions = config.defaultValue !== undefined
|
|
491
|
+
? { ...options, defaultValue: config.defaultValue }
|
|
492
|
+
: options
|
|
493
|
+
|
|
494
|
+
result[field] = transferData(result[field], type, fieldOptions)
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
})
|
|
509
498
|
}
|
|
510
499
|
|
|
511
500
|
return result
|
|
512
501
|
}
|
|
513
502
|
|
|
503
|
+
/**
|
|
504
|
+
* 解析传统格式配置
|
|
505
|
+
* @param {Array} format - 格式配置
|
|
506
|
+
* @returns {{fields: Array, type: string}} 解析后的配置
|
|
507
|
+
*/
|
|
508
|
+
function parseFormatConfig(format) {
|
|
509
|
+
if (typeof format[0] === 'string') {
|
|
510
|
+
return { fields: format, type: 'Number' }
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (Array.isArray(format[0])) {
|
|
514
|
+
return {
|
|
515
|
+
fields: format[0] || [],
|
|
516
|
+
type: format[1] || 'Number'
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
return { fields: [], type: 'Number' }
|
|
521
|
+
}
|
|
522
|
+
|
|
514
523
|
/**
|
|
515
524
|
* 智能数据类型转换(内部函数)
|
|
516
525
|
* @param {*} data - 原始数据
|
|
@@ -542,18 +551,16 @@ function autoTransferDataInternal(data, options) {
|
|
|
542
551
|
|
|
543
552
|
/**
|
|
544
553
|
* 根据映射对象批量转换数据
|
|
545
|
-
* @param {*} data -
|
|
546
|
-
* @param {Object} formatMap - 转换映射对象
|
|
554
|
+
* @param {*} data - 原始数据
|
|
555
|
+
* @param {Object} formatMap - 转换映射对象
|
|
547
556
|
* @param {Object} options - 配置选项
|
|
548
557
|
* @returns {*} 转换后的数据
|
|
549
558
|
*/
|
|
550
559
|
function transferDataByMap(data, formatMap, options) {
|
|
551
|
-
// 数据为空,返回空对象或原数据
|
|
552
560
|
if (data === null || data === undefined) {
|
|
553
561
|
return options.defaultValue ?? {}
|
|
554
562
|
}
|
|
555
563
|
|
|
556
|
-
// 数组处理:对每个元素应用转换映射
|
|
557
564
|
if (Array.isArray(data)) {
|
|
558
565
|
return data.map(item => {
|
|
559
566
|
if (typeof item !== 'object') return item
|
|
@@ -561,17 +568,14 @@ function transferDataByMap(data, formatMap, options) {
|
|
|
561
568
|
})
|
|
562
569
|
}
|
|
563
570
|
|
|
564
|
-
// 对象处理:根据 formatMap 的 key 进行转换
|
|
565
571
|
const result = {}
|
|
566
572
|
|
|
567
|
-
// 遍历映射表进行类型转换
|
|
568
573
|
for (const key in formatMap) {
|
|
569
574
|
if (Object.hasOwn(formatMap, key)) {
|
|
570
575
|
result[key] = transferData(data[key], formatMap[key], options)
|
|
571
576
|
}
|
|
572
577
|
}
|
|
573
578
|
|
|
574
|
-
// 保留未在映射表中定义的其他属性
|
|
575
579
|
for (const key in data) {
|
|
576
580
|
if (Object.hasOwn(data, key) && !Object.hasOwn(result, key)) {
|
|
577
581
|
result[key] = data[key]
|
|
@@ -585,18 +589,21 @@ function transferDataByMap(data, formatMap, options) {
|
|
|
585
589
|
* 查找字符串中第 n 次出现的位置
|
|
586
590
|
* @param {string} str - 源字符串
|
|
587
591
|
* @param {string} charToFind - 查找字符
|
|
588
|
-
* @param {number} n -
|
|
592
|
+
* @param {number} n - 第几次出现(从 1 开始)
|
|
589
593
|
* @returns {number} 位置索引,未找到返回 -1
|
|
590
594
|
*/
|
|
591
595
|
export function findNthOccurrence(str, charToFind, n) {
|
|
596
|
+
if (n < 1) return -1
|
|
597
|
+
|
|
598
|
+
let index = -1
|
|
592
599
|
let count = 0
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
600
|
+
|
|
601
|
+
while (count < n) {
|
|
602
|
+
index = str.indexOf(charToFind, index + 1)
|
|
603
|
+
if (index === -1) return -1
|
|
604
|
+
count++
|
|
598
605
|
}
|
|
599
|
-
|
|
606
|
+
|
|
600
607
|
return index
|
|
601
608
|
}
|
|
602
609
|
|
|
@@ -612,7 +619,6 @@ export function setFormData(object) {
|
|
|
612
619
|
if (Object.prototype.hasOwnProperty.call(object, key)) {
|
|
613
620
|
const value = object[key]
|
|
614
621
|
|
|
615
|
-
// 处理嵌套对象和数组
|
|
616
622
|
value instanceof Object || Array.isArray(value)
|
|
617
623
|
? formData.append(key, JSON.stringify(value))
|
|
618
624
|
: formData.append(key, value)
|
|
@@ -656,7 +662,7 @@ export function throttle(func, delay = 300) {
|
|
|
656
662
|
/**
|
|
657
663
|
* 数组去重
|
|
658
664
|
* @param {Array} arr - 要去重的数组
|
|
659
|
-
* @param {string} key - 对象去重的键(可选)
|
|
665
|
+
* @param {string} [key] - 对象去重的键(可选)
|
|
660
666
|
* @returns {Array} 去重后的数组
|
|
661
667
|
*/
|
|
662
668
|
export function uniqueArray(arr, key) {
|