web-component-gallery 2.3.13 → 2.3.15
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/ASelectCustom.vue +4 -3
- package/lib/weather/index.vue +234 -58
- package/lib/weather/style/index.less +81 -4
- package/package.json +1 -1
- package/utils/Filter.js +179 -180
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,61 +450,74 @@ 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
|
-
* - [{ fields: ['a', 'b'], type: 'Number', defaultValue: 0 }, { fields: ['c'], type: 'String' }] - 多个对象配置
|
|
468
453
|
* @param {Object} options - 配置选项
|
|
469
454
|
* @returns {*} 转换后的数据
|
|
470
455
|
*/
|
|
471
456
|
function transferDataByFields(data, format, options) {
|
|
457
|
+
// 边界情况处理
|
|
472
458
|
if (data == null || typeof data !== 'object') {
|
|
473
459
|
return data ?? options.defaultValue
|
|
474
460
|
}
|
|
475
461
|
|
|
476
|
-
//
|
|
477
|
-
if (format.length === 0) return data
|
|
462
|
+
// 空配置直接返回
|
|
463
|
+
if (!format || format.length === 0) return data
|
|
478
464
|
|
|
479
|
-
|
|
480
|
-
|
|
465
|
+
// 数组处理:递归处理每个元素(提前到最前面)
|
|
466
|
+
if (Array.isArray(data)) {
|
|
467
|
+
return data.map(item => transferDataByFields(item, format, options))
|
|
468
|
+
}
|
|
481
469
|
|
|
482
|
-
// 对象处理:转换指定字段
|
|
483
470
|
const result = { ...data }
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
if (
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
else if (
|
|
471
|
+
const configType = typeof format[0]
|
|
472
|
+
|
|
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
|
+
}
|
|
481
|
+
}
|
|
482
|
+
} else if (configType === 'object') {
|
|
483
|
+
// 形式 3:对象配置数组
|
|
496
484
|
format.forEach(config => {
|
|
497
|
-
|
|
498
|
-
|
|
485
|
+
const fields = config.fields || []
|
|
486
|
+
const type = config.type || 'Number'
|
|
487
|
+
|
|
488
|
+
for (const field of fields) {
|
|
499
489
|
if (field in result) {
|
|
500
|
-
const
|
|
501
|
-
|
|
490
|
+
const fieldOptions = config.defaultValue !== undefined
|
|
491
|
+
? { ...options, defaultValue: config.defaultValue }
|
|
492
|
+
: options
|
|
493
|
+
|
|
494
|
+
result[field] = transferData(result[field], type, fieldOptions)
|
|
502
495
|
}
|
|
503
496
|
}
|
|
504
497
|
})
|
|
505
498
|
}
|
|
506
499
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
500
|
+
return result
|
|
501
|
+
}
|
|
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' }
|
|
510
511
|
}
|
|
511
512
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
513
|
+
if (Array.isArray(format[0])) {
|
|
514
|
+
return {
|
|
515
|
+
fields: format[0] || [],
|
|
516
|
+
type: format[1] || 'Number'
|
|
515
517
|
}
|
|
516
518
|
}
|
|
517
|
-
|
|
518
|
-
return
|
|
519
|
+
|
|
520
|
+
return { fields: [], type: 'Number' }
|
|
519
521
|
}
|
|
520
522
|
|
|
521
523
|
/**
|
|
@@ -549,18 +551,16 @@ function autoTransferDataInternal(data, options) {
|
|
|
549
551
|
|
|
550
552
|
/**
|
|
551
553
|
* 根据映射对象批量转换数据
|
|
552
|
-
* @param {*} data -
|
|
553
|
-
* @param {Object} formatMap - 转换映射对象
|
|
554
|
+
* @param {*} data - 原始数据
|
|
555
|
+
* @param {Object} formatMap - 转换映射对象
|
|
554
556
|
* @param {Object} options - 配置选项
|
|
555
557
|
* @returns {*} 转换后的数据
|
|
556
558
|
*/
|
|
557
559
|
function transferDataByMap(data, formatMap, options) {
|
|
558
|
-
// 数据为空,返回空对象或原数据
|
|
559
560
|
if (data === null || data === undefined) {
|
|
560
561
|
return options.defaultValue ?? {}
|
|
561
562
|
}
|
|
562
563
|
|
|
563
|
-
// 数组处理:对每个元素应用转换映射
|
|
564
564
|
if (Array.isArray(data)) {
|
|
565
565
|
return data.map(item => {
|
|
566
566
|
if (typeof item !== 'object') return item
|
|
@@ -568,17 +568,14 @@ function transferDataByMap(data, formatMap, options) {
|
|
|
568
568
|
})
|
|
569
569
|
}
|
|
570
570
|
|
|
571
|
-
// 对象处理:根据 formatMap 的 key 进行转换
|
|
572
571
|
const result = {}
|
|
573
572
|
|
|
574
|
-
// 遍历映射表进行类型转换
|
|
575
573
|
for (const key in formatMap) {
|
|
576
574
|
if (Object.hasOwn(formatMap, key)) {
|
|
577
575
|
result[key] = transferData(data[key], formatMap[key], options)
|
|
578
576
|
}
|
|
579
577
|
}
|
|
580
578
|
|
|
581
|
-
// 保留未在映射表中定义的其他属性
|
|
582
579
|
for (const key in data) {
|
|
583
580
|
if (Object.hasOwn(data, key) && !Object.hasOwn(result, key)) {
|
|
584
581
|
result[key] = data[key]
|
|
@@ -592,18 +589,21 @@ function transferDataByMap(data, formatMap, options) {
|
|
|
592
589
|
* 查找字符串中第 n 次出现的位置
|
|
593
590
|
* @param {string} str - 源字符串
|
|
594
591
|
* @param {string} charToFind - 查找字符
|
|
595
|
-
* @param {number} n -
|
|
592
|
+
* @param {number} n - 第几次出现(从 1 开始)
|
|
596
593
|
* @returns {number} 位置索引,未找到返回 -1
|
|
597
594
|
*/
|
|
598
595
|
export function findNthOccurrence(str, charToFind, n) {
|
|
596
|
+
if (n < 1) return -1
|
|
597
|
+
|
|
598
|
+
let index = -1
|
|
599
599
|
let count = 0
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
600
|
+
|
|
601
|
+
while (count < n) {
|
|
602
|
+
index = str.indexOf(charToFind, index + 1)
|
|
603
|
+
if (index === -1) return -1
|
|
604
|
+
count++
|
|
605
605
|
}
|
|
606
|
-
|
|
606
|
+
|
|
607
607
|
return index
|
|
608
608
|
}
|
|
609
609
|
|
|
@@ -619,7 +619,6 @@ export function setFormData(object) {
|
|
|
619
619
|
if (Object.prototype.hasOwnProperty.call(object, key)) {
|
|
620
620
|
const value = object[key]
|
|
621
621
|
|
|
622
|
-
// 处理嵌套对象和数组
|
|
623
622
|
value instanceof Object || Array.isArray(value)
|
|
624
623
|
? formData.append(key, JSON.stringify(value))
|
|
625
624
|
: formData.append(key, value)
|
|
@@ -663,7 +662,7 @@ export function throttle(func, delay = 300) {
|
|
|
663
662
|
/**
|
|
664
663
|
* 数组去重
|
|
665
664
|
* @param {Array} arr - 要去重的数组
|
|
666
|
-
* @param {string} key - 对象去重的键(可选)
|
|
665
|
+
* @param {string} [key] - 对象去重的键(可选)
|
|
667
666
|
* @returns {Array} 去重后的数组
|
|
668
667
|
*/
|
|
669
668
|
export function uniqueArray(arr, key) {
|