tang-ui-x 1.3.4 → 1.3.5
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/components/TIcon/index.uvue +16 -16
- package/locales/en-US/examples.json +17 -7
- package/locales/zh-CN/examples.json +17 -7
- package/locales/zh-TW/examples.json +17 -7
- package/package.json +1 -1
- package/utils/functions/index.uts +1 -0
- package/utils/functions/modules/clipboard.uts +113 -0
- package/utils/functions/modules/date.uts +13 -0
- package/utils/functions/modules/function.uts +42 -0
- package/utils/functions/modules/index.uts +10 -0
- package/utils/functions/modules/number.uts +44 -0
- package/utils/functions/modules/object.uts +74 -0
- package/utils/functions/modules/storage.uts +91 -0
- package/utils/functions/modules/string.uts +38 -0
- package/utils/functions/modules/type.uts +47 -0
- package/utils/functions/modules/upload.uts +130 -0
- package/utils/functions/modules/validate.uts +461 -0
- package/utils/request/index.uts +394 -0
- package/utils/request/type.uts +107 -0
- package/utils/storage/config.uts +233 -0
- package/utils/storage/index.uts +602 -0
- package/utils/storage/types.uts +119 -0
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
})
|
|
31
31
|
|
|
32
32
|
// 计算图标样式
|
|
33
|
-
const iconStyle = computed(() : string => {
|
|
34
|
-
const styles : string[] = []
|
|
33
|
+
const iconStyle = computed(() : string => {
|
|
34
|
+
const styles : string[] = []
|
|
35
35
|
|
|
36
36
|
styles.push(`font-size: ${iconSize.value}`)
|
|
37
37
|
styles.push(`color: ${props.color}`)
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
styles.push('font-weight: bold')
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
if (props.customStyle !== '') {
|
|
44
|
-
styles.push(props.customStyle)
|
|
45
|
-
}
|
|
43
|
+
if (props.customStyle !== '') {
|
|
44
|
+
styles.push(props.customStyle)
|
|
45
|
+
}
|
|
46
46
|
|
|
47
47
|
return styles.join('; ')
|
|
48
48
|
})
|
|
@@ -51,18 +51,18 @@
|
|
|
51
51
|
const iconClass = computed(() : string => {
|
|
52
52
|
const classes : string[] = ['inline-block', 'leading-none', 'iconfont']
|
|
53
53
|
|
|
54
|
-
if (props.name.length > 0) {
|
|
55
|
-
// 支持传入 icon-xxx 或直接传入 xxx
|
|
56
|
-
if (props.name.indexOf('icon-') == 0) {
|
|
57
|
-
classes.push(props.name)
|
|
58
|
-
} else {
|
|
59
|
-
classes.push(`icon-${props.name}`)
|
|
54
|
+
if (props.name.length > 0) {
|
|
55
|
+
// 支持传入 icon-xxx 或直接传入 xxx
|
|
56
|
+
if (props.name.indexOf('icon-') == 0) {
|
|
57
|
+
classes.push(props.name)
|
|
58
|
+
} else {
|
|
59
|
+
classes.push(`icon-${props.name}`)
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
if (props.customClass !== '') {
|
|
64
|
-
classes.push(props.customClass)
|
|
65
|
-
}
|
|
63
|
+
if (props.customClass !== '') {
|
|
64
|
+
classes.push(props.customClass)
|
|
65
|
+
}
|
|
66
66
|
|
|
67
67
|
return classes.join(' ')
|
|
68
68
|
})
|
|
@@ -84,10 +84,10 @@
|
|
|
84
84
|
|
|
85
85
|
<style lang="scss" scoped>
|
|
86
86
|
/* 导入字体图标 */
|
|
87
|
-
@import '
|
|
87
|
+
@import '../../static/font/iconfont.css';
|
|
88
88
|
|
|
89
89
|
.t-icon {
|
|
90
90
|
display: inline-block;
|
|
91
91
|
line-height: 1;
|
|
92
92
|
}
|
|
93
|
-
</style>
|
|
93
|
+
</style>
|
|
@@ -214,10 +214,20 @@
|
|
|
214
214
|
"enName": "NavBar",
|
|
215
215
|
"description": "Top navigation bar"
|
|
216
216
|
},
|
|
217
|
-
"I18nDemo": {
|
|
218
|
-
"name": "I18n Demo",
|
|
219
|
-
"enName": "I18n",
|
|
220
|
-
"description": "Internationalization demo"
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
|
|
217
|
+
"I18nDemo": {
|
|
218
|
+
"name": "I18n Demo",
|
|
219
|
+
"enName": "I18n",
|
|
220
|
+
"description": "Internationalization demo"
|
|
221
|
+
},
|
|
222
|
+
"Request": {
|
|
223
|
+
"name": "Request",
|
|
224
|
+
"enName": "Request",
|
|
225
|
+
"description": "HttpRequest wrapper, interceptor, and response handling demo"
|
|
226
|
+
},
|
|
227
|
+
"Utils": {
|
|
228
|
+
"name": "Utils",
|
|
229
|
+
"enName": "Utils",
|
|
230
|
+
"description": "Common utility functions and storage wrapper demo"
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
@@ -214,10 +214,20 @@
|
|
|
214
214
|
"enName": "NavBar",
|
|
215
215
|
"description": "顶部导航栏"
|
|
216
216
|
},
|
|
217
|
-
"I18nDemo": {
|
|
218
|
-
"name": "多语言测试",
|
|
219
|
-
"enName": "I18n",
|
|
220
|
-
"description": "国际化多语言功能演示"
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
|
|
217
|
+
"I18nDemo": {
|
|
218
|
+
"name": "多语言测试",
|
|
219
|
+
"enName": "I18n",
|
|
220
|
+
"description": "国际化多语言功能演示"
|
|
221
|
+
},
|
|
222
|
+
"Request": {
|
|
223
|
+
"name": "请求封装",
|
|
224
|
+
"enName": "Request",
|
|
225
|
+
"description": "HttpRequest 请求封装、拦截器与响应处理示例"
|
|
226
|
+
},
|
|
227
|
+
"Utils": {
|
|
228
|
+
"name": "工具方法",
|
|
229
|
+
"enName": "Utils",
|
|
230
|
+
"description": "常用工具函数与 storage 封装示例"
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
@@ -214,10 +214,20 @@
|
|
|
214
214
|
"enName": "NavBar",
|
|
215
215
|
"description": "頂部導航欄"
|
|
216
216
|
},
|
|
217
|
-
"I18nDemo": {
|
|
218
|
-
"name": "多語言測試",
|
|
219
|
-
"enName": "I18n",
|
|
220
|
-
"description": "國際化多語言功能演示"
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
|
|
217
|
+
"I18nDemo": {
|
|
218
|
+
"name": "多語言測試",
|
|
219
|
+
"enName": "I18n",
|
|
220
|
+
"description": "國際化多語言功能演示"
|
|
221
|
+
},
|
|
222
|
+
"Request": {
|
|
223
|
+
"name": "請求封裝",
|
|
224
|
+
"enName": "Request",
|
|
225
|
+
"description": "HttpRequest 請求封裝、攔截器與響應處理示例"
|
|
226
|
+
},
|
|
227
|
+
"Utils": {
|
|
228
|
+
"name": "工具方法",
|
|
229
|
+
"enName": "Utils",
|
|
230
|
+
"description": "常用工具函數與 storage 封裝示例"
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './modules/index'
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 复制文本到剪贴板(跨平台支持)
|
|
3
|
+
* @param text 要复制的文本
|
|
4
|
+
* @param success 成功回调
|
|
5
|
+
* @param fail 失败回调
|
|
6
|
+
*/
|
|
7
|
+
export function copyToClipboard(text: string, success?: () => void, fail?: (error?: any) => void) {
|
|
8
|
+
if (text == '') {
|
|
9
|
+
fail && fail('文本不能为空')
|
|
10
|
+
return
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* eslint-disable no-unreachable */
|
|
14
|
+
// #ifdef H5
|
|
15
|
+
try {
|
|
16
|
+
const textarea = document.createElement('textarea')
|
|
17
|
+
textarea.value = text
|
|
18
|
+
textarea.style.position = 'fixed'
|
|
19
|
+
textarea.style.top = '-9999px'
|
|
20
|
+
textarea.style.left = '-9999px'
|
|
21
|
+
document.body.appendChild(textarea)
|
|
22
|
+
textarea.select()
|
|
23
|
+
textarea.setSelectionRange(0, text.length)
|
|
24
|
+
|
|
25
|
+
const successful = document.execCommand('copy')
|
|
26
|
+
document.body.removeChild(textarea)
|
|
27
|
+
|
|
28
|
+
if (successful) {
|
|
29
|
+
uni.showToast({
|
|
30
|
+
title: '复制成功',
|
|
31
|
+
icon: 'success',
|
|
32
|
+
duration: 2000,
|
|
33
|
+
})
|
|
34
|
+
success && success()
|
|
35
|
+
} else {
|
|
36
|
+
throw new Error('复制失败')
|
|
37
|
+
}
|
|
38
|
+
return
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error('H5 复制失败:', error)
|
|
41
|
+
uni.showToast({
|
|
42
|
+
title: '复制失败',
|
|
43
|
+
icon: 'error',
|
|
44
|
+
duration: 2000,
|
|
45
|
+
})
|
|
46
|
+
fail && fail(error)
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
// #endif
|
|
50
|
+
|
|
51
|
+
// #ifdef APP-ANDROID || APP-IOS || APP-HARMONY
|
|
52
|
+
uni.setClipboardData({
|
|
53
|
+
data: text,
|
|
54
|
+
success: () => {
|
|
55
|
+
uni.showToast({
|
|
56
|
+
title: '复制成功',
|
|
57
|
+
icon: 'success',
|
|
58
|
+
duration: 2000,
|
|
59
|
+
})
|
|
60
|
+
success && success()
|
|
61
|
+
},
|
|
62
|
+
fail: (error) => {
|
|
63
|
+
console.error('App 复制失败:', error)
|
|
64
|
+
uni.showToast({
|
|
65
|
+
title: '复制失败',
|
|
66
|
+
icon: 'error',
|
|
67
|
+
duration: 2000,
|
|
68
|
+
})
|
|
69
|
+
fail && fail(error)
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
return
|
|
73
|
+
// #endif
|
|
74
|
+
|
|
75
|
+
// #ifdef MP-WEIXIN || MP-ALIPAY || MP-BAIDU || MP-QQ || MP-TOUTIAO || MP-KUAISHOU
|
|
76
|
+
uni.setClipboardData({
|
|
77
|
+
data: text,
|
|
78
|
+
success: () => {
|
|
79
|
+
uni.showToast({
|
|
80
|
+
title: '复制成功',
|
|
81
|
+
icon: 'success',
|
|
82
|
+
duration: 2000,
|
|
83
|
+
})
|
|
84
|
+
success && success()
|
|
85
|
+
},
|
|
86
|
+
fail: (error) => {
|
|
87
|
+
console.error('小程序复制失败:', error)
|
|
88
|
+
uni.showToast({
|
|
89
|
+
title: '复制失败',
|
|
90
|
+
icon: 'error',
|
|
91
|
+
duration: 2000,
|
|
92
|
+
})
|
|
93
|
+
fail && fail(error)
|
|
94
|
+
},
|
|
95
|
+
})
|
|
96
|
+
// #endif
|
|
97
|
+
/* eslint-enable no-unreachable */
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 复制文本到剪贴板(Promise 版本,跨平台支持)
|
|
102
|
+
* @param text 要复制的文本
|
|
103
|
+
* @returns Promise<void>
|
|
104
|
+
*/
|
|
105
|
+
export function copyToClipboardAsync(text: string): Promise<void> {
|
|
106
|
+
return new Promise((resolve, reject) => {
|
|
107
|
+
copyToClipboard(
|
|
108
|
+
text,
|
|
109
|
+
() => resolve(),
|
|
110
|
+
(error) => reject(error)
|
|
111
|
+
)
|
|
112
|
+
})
|
|
113
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 格式化时间为上午/下午格式
|
|
3
|
+
* @param date 日期对象
|
|
4
|
+
* @returns 格式化后的时间字符串,如 "上午 8:10"
|
|
5
|
+
*/
|
|
6
|
+
export function formatChatTime(date: Date): string {
|
|
7
|
+
const hours = date.getHours()
|
|
8
|
+
const minutes = date.getMinutes()
|
|
9
|
+
const period = hours < 12 ? '上午' : '下午'
|
|
10
|
+
const h = hours % 12 === 0 ? 12 : hours % 12
|
|
11
|
+
const m = minutes < 10 ? '0' + minutes : minutes.toString()
|
|
12
|
+
return `${period} ${h}:${m}`
|
|
13
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 防抖函数
|
|
3
|
+
* @param func 要执行的函数
|
|
4
|
+
* @param delay 延迟时间(ms)
|
|
5
|
+
* @returns 防抖后的函数
|
|
6
|
+
*/
|
|
7
|
+
export function debounce(
|
|
8
|
+
func: (...args: Array<any>) => void,
|
|
9
|
+
delay: number
|
|
10
|
+
): (...args: Array<any>) => void {
|
|
11
|
+
let timer: number | null = null
|
|
12
|
+
|
|
13
|
+
return function (...args: Array<any>): void {
|
|
14
|
+
if (timer != null) {
|
|
15
|
+
clearTimeout(timer)
|
|
16
|
+
}
|
|
17
|
+
timer = setTimeout(() => {
|
|
18
|
+
func(...args)
|
|
19
|
+
}, delay)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 节流函数
|
|
25
|
+
* @param func 要执行的函数
|
|
26
|
+
* @param delay 延迟时间(ms)
|
|
27
|
+
* @returns 节流后的函数
|
|
28
|
+
*/
|
|
29
|
+
export function throttle(
|
|
30
|
+
func: (...args: Array<any>) => void,
|
|
31
|
+
delay: number
|
|
32
|
+
): (...args: Array<any>) => void {
|
|
33
|
+
let last: number = 0
|
|
34
|
+
|
|
35
|
+
return function (...args: Array<any>): void {
|
|
36
|
+
const now = Date.now()
|
|
37
|
+
if (now - last >= delay) {
|
|
38
|
+
last = now
|
|
39
|
+
func(...args)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './clipboard'
|
|
2
|
+
export * from './date'
|
|
3
|
+
export * from './function'
|
|
4
|
+
export * from './number'
|
|
5
|
+
export * from './object'
|
|
6
|
+
export * from './storage'
|
|
7
|
+
export * from './string'
|
|
8
|
+
export * from './type'
|
|
9
|
+
export * from './validate'
|
|
10
|
+
export * from './upload'
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 格式化数字(添加千分位分隔符)
|
|
3
|
+
* @param num 数字
|
|
4
|
+
* @returns 格式化后的字符串
|
|
5
|
+
*/
|
|
6
|
+
export function formatNumber(num: number | string): string {
|
|
7
|
+
const text = `${num}`
|
|
8
|
+
const n = parseFloat(text)
|
|
9
|
+
if (isNaN(n)) return text
|
|
10
|
+
|
|
11
|
+
const parts = text.split('.')
|
|
12
|
+
const integerPart = parts[0]
|
|
13
|
+
const decimalPart = parts.length > 1 ? '.' + parts[1] : ''
|
|
14
|
+
const negative = integerPart.length > 0 && integerPart.charAt(0) == '-'
|
|
15
|
+
const digits = negative ? integerPart.substring(1) : integerPart
|
|
16
|
+
let formatted = ''
|
|
17
|
+
let count = 0
|
|
18
|
+
|
|
19
|
+
for (let i = digits.length - 1; i >= 0; i--) {
|
|
20
|
+
formatted = digits.charAt(i) + formatted
|
|
21
|
+
count++
|
|
22
|
+
if (i > 0 && count % 3 == 0) {
|
|
23
|
+
formatted = ',' + formatted
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return (negative ? '-' : '') + formatted + decimalPart
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 将字节转换为可读大小
|
|
32
|
+
* @param bytes 字节数
|
|
33
|
+
* @param decimals 小数位数
|
|
34
|
+
* @returns 可读大小字符串
|
|
35
|
+
*/
|
|
36
|
+
export function formatBytes(bytes: number, decimals: number = 2): string {
|
|
37
|
+
if (bytes === 0) return '0 B'
|
|
38
|
+
|
|
39
|
+
const k: number = 1024
|
|
40
|
+
const sizes: Array<string> = ['B', 'KB', 'MB', 'GB', 'TB']
|
|
41
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
|
42
|
+
|
|
43
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(decimals))} ${sizes[i]}`
|
|
44
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 安全获取对象属性
|
|
3
|
+
* @param obj 对象
|
|
4
|
+
* @param path 属性路径,如 'a.b.c'
|
|
5
|
+
* @param defaultValue 默认值
|
|
6
|
+
* @returns 属性值
|
|
7
|
+
*/
|
|
8
|
+
export function get(obj: any, path: string, defaultValue: any | null = null): any | null {
|
|
9
|
+
const keys: Array<string> = path.split('.')
|
|
10
|
+
let result: any = obj
|
|
11
|
+
|
|
12
|
+
for (const key of keys) {
|
|
13
|
+
if (result == null || typeof result !== 'object') {
|
|
14
|
+
return defaultValue
|
|
15
|
+
}
|
|
16
|
+
result = result[key]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return result == null ? defaultValue : result
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 深拷贝对象
|
|
24
|
+
* @param obj 要拷贝的对象
|
|
25
|
+
* @returns 拷贝后的对象
|
|
26
|
+
*/
|
|
27
|
+
export function deepClone<T>(obj: T): T {
|
|
28
|
+
if (obj == null || typeof obj !== 'object') {
|
|
29
|
+
return obj
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (obj instanceof Date) {
|
|
33
|
+
return new Date(obj.getTime()) as any
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (obj instanceof Array) {
|
|
37
|
+
return obj.map((item) => deepClone(item)) as any
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const source = obj as UTSJSONObject
|
|
41
|
+
const cloned = {} as UTSJSONObject
|
|
42
|
+
for (const key in source) {
|
|
43
|
+
cloned[key] = deepClone(source[key])
|
|
44
|
+
}
|
|
45
|
+
return cloned as T
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 将对象转换为 Query 字符串
|
|
50
|
+
* @param obj 要转换的对象
|
|
51
|
+
* @param prefix 前缀
|
|
52
|
+
* @returns Query 字符串
|
|
53
|
+
*/
|
|
54
|
+
export function toQueryString(obj: UTSJSONObject, prefix: string = ''): string {
|
|
55
|
+
const parts: Array<string> = []
|
|
56
|
+
|
|
57
|
+
for (const key in obj) {
|
|
58
|
+
const value = obj[key]
|
|
59
|
+
const fullKey = prefix != '' ? `${prefix}[${key}]` : key
|
|
60
|
+
|
|
61
|
+
if (value == null) {
|
|
62
|
+
parts.push(`${encodeURIComponent(fullKey)}=`)
|
|
63
|
+
continue
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
67
|
+
parts.push(toQueryString(value as UTSJSONObject, fullKey))
|
|
68
|
+
} else {
|
|
69
|
+
parts.push(`${encodeURIComponent(fullKey)}=${encodeURIComponent(`${value}`)}`)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return parts.join('&')
|
|
74
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 设置本地缓存
|
|
3
|
+
* @param key 缓存键
|
|
4
|
+
* @param value 缓存值
|
|
5
|
+
* @returns 是否设置成功
|
|
6
|
+
*/
|
|
7
|
+
export function setStorage(key: string, value: any): boolean {
|
|
8
|
+
if (key == '') {
|
|
9
|
+
return false
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
uni.setStorageSync(key, value)
|
|
14
|
+
return true
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.error('setStorage failed:', error)
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 获取本地缓存
|
|
23
|
+
* @param key 缓存键
|
|
24
|
+
* @param defaultValue 默认值
|
|
25
|
+
* @returns 缓存值或默认值
|
|
26
|
+
*/
|
|
27
|
+
export function getStorage(key: string, defaultValue: any | null = null): any | null {
|
|
28
|
+
if (key == '') {
|
|
29
|
+
return defaultValue
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
const value = uni.getStorageSync(key)
|
|
34
|
+
return value == '' ? defaultValue : value
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error('getStorage failed:', error)
|
|
37
|
+
return defaultValue
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 判断本地缓存是否存在
|
|
43
|
+
* @param key 缓存键
|
|
44
|
+
* @returns 是否存在
|
|
45
|
+
*/
|
|
46
|
+
export function hasStorage(key: string): boolean {
|
|
47
|
+
if (key == '') {
|
|
48
|
+
return false
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const value = uni.getStorageSync(key)
|
|
53
|
+
return value != ''
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error('hasStorage failed:', error)
|
|
56
|
+
return false
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 移除本地缓存
|
|
62
|
+
* @param key 缓存键
|
|
63
|
+
* @returns 是否移除成功
|
|
64
|
+
*/
|
|
65
|
+
export function removeStorage(key: string): boolean {
|
|
66
|
+
if (key == '') {
|
|
67
|
+
return false
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
uni.removeStorageSync(key)
|
|
72
|
+
return true
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error('removeStorage failed:', error)
|
|
75
|
+
return false
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* 清空全部本地缓存
|
|
81
|
+
* @returns 是否清空成功
|
|
82
|
+
*/
|
|
83
|
+
export function clearStorage(): boolean {
|
|
84
|
+
try {
|
|
85
|
+
uni.clearStorageSync()
|
|
86
|
+
return true
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.error('clearStorage failed:', error)
|
|
89
|
+
return false
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 截取字符串并添加省略号
|
|
3
|
+
* @param str 字符串
|
|
4
|
+
* @param length 最大长度
|
|
5
|
+
* @returns 截取后的字符串
|
|
6
|
+
*/
|
|
7
|
+
export function truncate(str: string, length: number): string {
|
|
8
|
+
if (str == '') return ''
|
|
9
|
+
if (str.length <= length) return str
|
|
10
|
+
return str.substring(0, length) + '...'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 生成随机字符串
|
|
15
|
+
* @param length 长度
|
|
16
|
+
* @returns 随机字符串
|
|
17
|
+
*/
|
|
18
|
+
export function randomString(length: number = 8): string {
|
|
19
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
|
20
|
+
let result = ''
|
|
21
|
+
for (let i = 0; i < length; i++) {
|
|
22
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length))
|
|
23
|
+
}
|
|
24
|
+
return result
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 生成UUID
|
|
29
|
+
* @returns UUID字符串
|
|
30
|
+
*/
|
|
31
|
+
export function generateUUID(): string {
|
|
32
|
+
const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
33
|
+
const r = (Math.random() * 16) | 0
|
|
34
|
+
const v = c == 'x' ? r : (r & 0x3) | 0x8
|
|
35
|
+
return v.toString(16)
|
|
36
|
+
})
|
|
37
|
+
return uuid
|
|
38
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 检查值是否为空
|
|
3
|
+
* @param value 要检查的值
|
|
4
|
+
* @returns 是否为空
|
|
5
|
+
*/
|
|
6
|
+
export function isEmpty(value: any): boolean {
|
|
7
|
+
if (value == null) return true
|
|
8
|
+
if (typeof value === 'string') return value.trim().length === 0
|
|
9
|
+
if (Array.isArray(value)) return value.length === 0
|
|
10
|
+
if (typeof value === 'object') {
|
|
11
|
+
const obj = value as UTSJSONObject
|
|
12
|
+
for (const key in obj) {
|
|
13
|
+
return false
|
|
14
|
+
}
|
|
15
|
+
return true
|
|
16
|
+
}
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 检查值是否有效(非空)
|
|
22
|
+
* @param value 要检查的值
|
|
23
|
+
* @returns 是否有效
|
|
24
|
+
*/
|
|
25
|
+
export function isValid(value: any): boolean {
|
|
26
|
+
return value != null
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 验证手机号
|
|
31
|
+
* @param phone 手机号
|
|
32
|
+
* @returns 是否有效
|
|
33
|
+
*/
|
|
34
|
+
export function isValidPhone(phone: string): boolean {
|
|
35
|
+
const phoneRegex = /^1[3-9]\d{9}$/
|
|
36
|
+
return phoneRegex.test(phone)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 验证邮箱
|
|
41
|
+
* @param email 邮箱
|
|
42
|
+
* @returns 是否有效
|
|
43
|
+
*/
|
|
44
|
+
export function isValidEmail(email: string): boolean {
|
|
45
|
+
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
|
|
46
|
+
return emailRegex.test(email)
|
|
47
|
+
}
|