im-ui-mobile 0.1.16 → 0.1.18
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/im-col/im-col.vue +1 -1
- package/components/im-upload/im-upload.vue +72 -198
- package/components/im-upload/utils/{file-adapter.js → file-adapter.ts} +17 -17
- package/components/im-upload/utils/{file-chooser.js → file-chooser.ts} +17 -15
- package/components/im-upload/utils/{file-validator.js → file-validator.ts} +11 -103
- package/components/im-upload/utils/{upload.js → upload.ts} +11 -10
- package/package.json +1 -1
- package/types/components/upload.d.ts +2 -6
- package/types/index.d.ts +1 -0
- package/utils/datetime.js +8 -8
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
<!-- 按钮类型 -->
|
|
11
11
|
<template v-if="type === 'button'">
|
|
12
12
|
<im-button :type="buttonType" :size="buttonSize" :disabled="disabled" :loading="uploading">
|
|
13
|
-
<view
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
</view>
|
|
13
|
+
<!-- <view> -->
|
|
14
|
+
<text v-if="!uploading" class="im-upload__icon">+</text>
|
|
15
|
+
<text class="im-upload__text">{{ uploading ? '上传中...' : buttonText }}</text>
|
|
16
|
+
<!-- </view> -->
|
|
17
17
|
</im-button>
|
|
18
18
|
</template>
|
|
19
19
|
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
<!-- 头像类型 -->
|
|
30
30
|
<template v-else-if="type === 'avatar'">
|
|
31
31
|
<view class="im-upload__avatar">
|
|
32
|
-
<im-avatar :
|
|
32
|
+
<im-avatar :url="fileList[0]?.url" :size="avatarSize" :radius="avatarRadius">
|
|
33
33
|
<template v-if="!fileList[0]?.url">
|
|
34
|
-
<
|
|
34
|
+
<im-icon name="plus" size="40" color="#8c939d" />
|
|
35
35
|
</template>
|
|
36
36
|
</im-avatar>
|
|
37
37
|
<text class="im-upload__avatar-text">{{ avatarText }}</text>
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
<!-- 图片列表 -->
|
|
58
58
|
<template v-if="listType === 'picture'">
|
|
59
59
|
<view class="im-upload__item-preview">
|
|
60
|
-
<image v-if="file.type?.startsWith('image
|
|
60
|
+
<image v-if="file.type?.startsWith('image')" class="im-upload__item-image" :src="file.url || file.thumbUrl"
|
|
61
61
|
mode="aspectFill" @tap="handlePreview(file)" />
|
|
62
62
|
<view v-else class="im-upload__item-file">
|
|
63
63
|
<text class="im-upload__item-file-icon">📄</text>
|
|
@@ -83,10 +83,6 @@
|
|
|
83
83
|
|
|
84
84
|
<!-- 操作按钮 -->
|
|
85
85
|
<view class="im-upload__item-actions">
|
|
86
|
-
<text v-if="file.status === 'done' && previewable" class="im-upload__item-action"
|
|
87
|
-
@tap="handlePreview(file)">
|
|
88
|
-
👁️
|
|
89
|
-
</text>
|
|
90
86
|
<text v-if="!readonly && removable" class="im-upload__item-action" @tap="handleRemove(file, index)">
|
|
91
87
|
✕
|
|
92
88
|
</text>
|
|
@@ -176,7 +172,7 @@ interface UploadFile {
|
|
|
176
172
|
// 定义 Props
|
|
177
173
|
interface Props {
|
|
178
174
|
// 值
|
|
179
|
-
modelValue?: UploadFile[]
|
|
175
|
+
modelValue?: string | UploadFile[]
|
|
180
176
|
|
|
181
177
|
// 上传类型
|
|
182
178
|
type?: 'button' | 'card' | 'avatar' | 'drag' | undefined
|
|
@@ -241,18 +237,17 @@ interface Props {
|
|
|
241
237
|
|
|
242
238
|
// 定义 Emits
|
|
243
239
|
interface Emits {
|
|
244
|
-
(e: 'update:modelValue', files: UploadFile[]): void
|
|
245
|
-
(e: 'change', files: UploadFile[]): void
|
|
240
|
+
(e: 'update:modelValue', files: string | UploadFile[]): void
|
|
241
|
+
(e: 'change', files: string | UploadFile[]): void
|
|
246
242
|
(e: 'select', file: Object): void
|
|
247
|
-
(e: '
|
|
248
|
-
(e: 'success', response: any, file: UploadFile): void
|
|
243
|
+
(e: 'success', file: UploadFile): void
|
|
249
244
|
(e: 'error', error: Error, file: UploadFile): void
|
|
250
245
|
(e: 'progress', percent: number, file: UploadFile): void
|
|
251
246
|
(e: 'remove', file: UploadFile, index: number): void
|
|
252
247
|
(e: 'preview', file: UploadFile): void
|
|
253
248
|
(e: 'exceed', files: Object[]): void
|
|
254
|
-
(e: '
|
|
255
|
-
(e: '
|
|
249
|
+
(e: 'uploading', file: UploadFile): void
|
|
250
|
+
(e: 'uploaded', file: UploadFile): void
|
|
256
251
|
}
|
|
257
252
|
|
|
258
253
|
// 定义 Props 默认值
|
|
@@ -294,6 +289,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
294
289
|
autoUpload: true,
|
|
295
290
|
|
|
296
291
|
responseFormatter: (response: any) => {
|
|
292
|
+
console.log('responseFormatter', response)
|
|
297
293
|
return {
|
|
298
294
|
url: response?.data?.url || response?.result?.url || response?.url || response?.fileUrl,
|
|
299
295
|
name: response?.data?.fileName || response?.result?.fileName || response?.data?.name || response?.result?.name || response?.name,
|
|
@@ -313,7 +309,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
313
309
|
const emit = defineEmits<Emits>()
|
|
314
310
|
|
|
315
311
|
// 响应式状态
|
|
316
|
-
const fileList = ref<UploadFile[]>(props.modelValue || []
|
|
312
|
+
const fileList = ref<UploadFile[]>([]) //props.modelValue || []
|
|
317
313
|
const dragOver = ref(false)
|
|
318
314
|
const uploadingAll = ref(false)
|
|
319
315
|
|
|
@@ -322,8 +318,19 @@ const uploadTasks = new Map<string, UniApp.UploadTask>()
|
|
|
322
318
|
|
|
323
319
|
// 监听 modelValue 变化
|
|
324
320
|
watch(() => props.modelValue, (val) => {
|
|
325
|
-
if (val)
|
|
326
|
-
|
|
321
|
+
if (!val) return
|
|
322
|
+
|
|
323
|
+
if (isSingleFile()) {
|
|
324
|
+
fileList.value = [{
|
|
325
|
+
url: String(props.modelValue),
|
|
326
|
+
uid: '',
|
|
327
|
+
name: 'single file',
|
|
328
|
+
size: 0,
|
|
329
|
+
status: 'uploading'
|
|
330
|
+
}]
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
fileList.value = val as UploadFile[]
|
|
327
334
|
}
|
|
328
335
|
}, { deep: true })
|
|
329
336
|
|
|
@@ -334,7 +341,7 @@ const uploading = computed(() => {
|
|
|
334
341
|
|
|
335
342
|
// 生成唯一ID
|
|
336
343
|
const generateUid = () => {
|
|
337
|
-
return Date.now() + '-' + Math.random().toString(36).
|
|
344
|
+
return Date.now() + '-' + Math.random().toString(36).substring(2, 9)
|
|
338
345
|
}
|
|
339
346
|
|
|
340
347
|
// 格式化文件大小
|
|
@@ -370,8 +377,13 @@ const handleUploadTap = async () => {
|
|
|
370
377
|
return
|
|
371
378
|
}
|
|
372
379
|
|
|
373
|
-
|
|
374
|
-
|
|
380
|
+
let accept = getFileType(props.accept) // image, video, all
|
|
381
|
+
let maxSelectable = props.multiple ? Math.max(0, props.maxCount! - fileList.value.length) : 1
|
|
382
|
+
|
|
383
|
+
if (props.type === 'avatar') {
|
|
384
|
+
accept = 'image'
|
|
385
|
+
maxSelectable = 1
|
|
386
|
+
}
|
|
375
387
|
|
|
376
388
|
if (maxSelectable <= 0) {
|
|
377
389
|
emit('exceed', [])
|
|
@@ -384,9 +396,10 @@ const handleUploadTap = async () => {
|
|
|
384
396
|
|
|
385
397
|
try {
|
|
386
398
|
const res = await chooseFile({
|
|
387
|
-
count:
|
|
388
|
-
type:
|
|
399
|
+
count: maxSelectable,
|
|
400
|
+
type: accept
|
|
389
401
|
})
|
|
402
|
+
|
|
390
403
|
for (const tempFile of res.tempFiles as Array<any>) {
|
|
391
404
|
await processFile(tempFile)
|
|
392
405
|
}
|
|
@@ -397,25 +410,6 @@ const handleUploadTap = async () => {
|
|
|
397
410
|
icon: 'none'
|
|
398
411
|
})
|
|
399
412
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
// uni.chooseFile({
|
|
403
|
-
// count: maxSelectable,
|
|
404
|
-
// type: getFileType(props.accept),
|
|
405
|
-
// extension: getFileExtensions(props.accept),
|
|
406
|
-
// success: async (res) => {
|
|
407
|
-
// for (const tempFile of res.tempFiles as Array<any>) {
|
|
408
|
-
// await processFile(tempFile)
|
|
409
|
-
// }
|
|
410
|
-
// },
|
|
411
|
-
// fail: (err) => {
|
|
412
|
-
// console.error('选择文件失败:', err)
|
|
413
|
-
// uni.showToast({
|
|
414
|
-
// title: '选择文件失败',
|
|
415
|
-
// icon: 'none'
|
|
416
|
-
// })
|
|
417
|
-
// }
|
|
418
|
-
// })
|
|
419
413
|
}
|
|
420
414
|
|
|
421
415
|
// 获取文件类型
|
|
@@ -425,19 +419,9 @@ const getFileType = (accept: string): 'image' | 'video' | 'all' => {
|
|
|
425
419
|
return 'all'
|
|
426
420
|
}
|
|
427
421
|
|
|
428
|
-
//
|
|
429
|
-
const
|
|
430
|
-
|
|
431
|
-
return undefined
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
const extensions = accept
|
|
435
|
-
.split(',')
|
|
436
|
-
.map(ext => ext.trim())
|
|
437
|
-
.filter(ext => ext.startsWith('.'))
|
|
438
|
-
.map(ext => ext.substring(1))
|
|
439
|
-
|
|
440
|
-
return extensions.length > 0 ? extensions : undefined
|
|
422
|
+
// 是否仅上传单个文件
|
|
423
|
+
const isSingleFile = () => {
|
|
424
|
+
return typeof props.modelValue === 'string' || props.type === 'avatar' || !props.multiple
|
|
441
425
|
}
|
|
442
426
|
|
|
443
427
|
// 处理文件
|
|
@@ -485,7 +469,7 @@ const processFile = async (uniFile: any) => {
|
|
|
485
469
|
status: 'pending',
|
|
486
470
|
progress: 0,
|
|
487
471
|
url: uniFile.path,
|
|
488
|
-
thumbUrl: uniFile.type?.startsWith('image
|
|
472
|
+
thumbUrl: uniFile.type?.startsWith('image') ? uniFile.path : undefined,
|
|
489
473
|
rawFile: uniFile,
|
|
490
474
|
file
|
|
491
475
|
}
|
|
@@ -493,6 +477,7 @@ const processFile = async (uniFile: any) => {
|
|
|
493
477
|
// 添加到文件列表
|
|
494
478
|
if (!props.multiple) {
|
|
495
479
|
fileList.value = [uploadFile]
|
|
480
|
+
|
|
496
481
|
} else {
|
|
497
482
|
fileList.value.push(uploadFile)
|
|
498
483
|
}
|
|
@@ -506,69 +491,13 @@ const processFile = async (uniFile: any) => {
|
|
|
506
491
|
}
|
|
507
492
|
}
|
|
508
493
|
|
|
509
|
-
// // 检查文件类型是否被接受
|
|
510
|
-
// const isFileTypeAccepted = (uniFile: any): boolean => {
|
|
511
|
-
// if (props.accept === '*') return true
|
|
512
|
-
|
|
513
|
-
// const acceptTypes = props.accept.split(',').map(type => type.trim())
|
|
514
|
-
|
|
515
|
-
// for (const acceptType of acceptTypes) {
|
|
516
|
-
// if (acceptType === '*') return true
|
|
517
|
-
|
|
518
|
-
// // 检查 MIME 类型
|
|
519
|
-
// if (acceptType.endsWith('/*')) {
|
|
520
|
-
// const category = acceptType.split('/')[0]
|
|
521
|
-
// if (uniFile.type?.startsWith(category + '/')) {
|
|
522
|
-
// return true
|
|
523
|
-
// }
|
|
524
|
-
// }
|
|
525
|
-
|
|
526
|
-
// // 检查扩展名
|
|
527
|
-
// if (acceptType.startsWith('.')) {
|
|
528
|
-
// const ext = acceptType.substring(1).toLowerCase()
|
|
529
|
-
// const fileName = uniFile.name.toLowerCase()
|
|
530
|
-
// if (fileName.endsWith('.' + ext)) {
|
|
531
|
-
// return true
|
|
532
|
-
// }
|
|
533
|
-
// }
|
|
534
|
-
|
|
535
|
-
// // 检查完整 MIME 类型
|
|
536
|
-
// if (uniFile.type === acceptType) {
|
|
537
|
-
// return true
|
|
538
|
-
// }
|
|
539
|
-
// }
|
|
540
|
-
|
|
541
|
-
// return false
|
|
542
|
-
// }
|
|
543
|
-
|
|
544
|
-
// 从 uniapp 文件创建 File 对象
|
|
545
|
-
// const createFileFromUniFile = (uniFile: any): File => {
|
|
546
|
-
// const file = new File([], uniFile.name, {
|
|
547
|
-
// type: uniFile.type || 'application/octet-stream',
|
|
548
|
-
// lastModified: uniFile.lastModified || Date.now()
|
|
549
|
-
// })
|
|
550
|
-
|
|
551
|
-
// Object.defineProperties(file, {
|
|
552
|
-
// size: {
|
|
553
|
-
// value: uniFile.size,
|
|
554
|
-
// writable: false
|
|
555
|
-
// },
|
|
556
|
-
// path: {
|
|
557
|
-
// value: uniFile.path,
|
|
558
|
-
// writable: false
|
|
559
|
-
// }
|
|
560
|
-
// })
|
|
561
|
-
|
|
562
|
-
// return file
|
|
563
|
-
// }
|
|
564
|
-
|
|
565
494
|
// 开始上传
|
|
566
495
|
const startUpload = async (uploadFile: UploadFile) => {
|
|
567
496
|
uploadFile.status = 'uploading'
|
|
568
497
|
uploadFile.progress = 0
|
|
569
|
-
emit('
|
|
570
|
-
|
|
571
|
-
updateFileList()
|
|
498
|
+
emit('uploading', uploadFile)
|
|
499
|
+
|
|
500
|
+
// updateFileList()
|
|
572
501
|
|
|
573
502
|
try {
|
|
574
503
|
let response: any
|
|
@@ -580,7 +509,7 @@ const startUpload = async (uploadFile: UploadFile) => {
|
|
|
580
509
|
(percent) => {
|
|
581
510
|
uploadFile.progress = percent
|
|
582
511
|
emit('progress', percent, uploadFile)
|
|
583
|
-
updateFileList()
|
|
512
|
+
updateFileList(uploadFile)
|
|
584
513
|
}
|
|
585
514
|
)
|
|
586
515
|
} else if (props.action) {
|
|
@@ -598,7 +527,7 @@ const startUpload = async (uploadFile: UploadFile) => {
|
|
|
598
527
|
uploadFile.response = formattedResponse
|
|
599
528
|
uploadFile.url = formattedResponse.url || uploadFile.url
|
|
600
529
|
|
|
601
|
-
emit('success',
|
|
530
|
+
emit('success', uploadFile)
|
|
602
531
|
} catch (error) {
|
|
603
532
|
uploadFile.status = 'error'
|
|
604
533
|
uploadFile.error = error as Error
|
|
@@ -609,17 +538,21 @@ const startUpload = async (uploadFile: UploadFile) => {
|
|
|
609
538
|
icon: 'none'
|
|
610
539
|
})
|
|
611
540
|
} finally {
|
|
612
|
-
emit('
|
|
613
|
-
updateFileList()
|
|
541
|
+
emit('uploaded', uploadFile)
|
|
542
|
+
updateFileList(uploadFile)
|
|
614
543
|
}
|
|
615
544
|
}
|
|
616
545
|
|
|
617
546
|
// 默认上传实现
|
|
618
547
|
const defaultUpload = (uploadFile: UploadFile): Promise<any> => {
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
548
|
+
let headers = props.headers
|
|
549
|
+
|
|
550
|
+
if (props.accessToken) {
|
|
551
|
+
headers = {
|
|
552
|
+
...headers,
|
|
553
|
+
'Authorization': `Bearer ${props.accessToken}`,
|
|
554
|
+
'AccessToken': props.accessToken,
|
|
555
|
+
}
|
|
623
556
|
}
|
|
624
557
|
|
|
625
558
|
return universalUploadFile({
|
|
@@ -636,43 +569,17 @@ const defaultUpload = (uploadFile: UploadFile): Promise<any> => {
|
|
|
636
569
|
timeout: props.timeout,
|
|
637
570
|
withCredentials: props.withCredentials
|
|
638
571
|
})
|
|
639
|
-
|
|
640
|
-
// return new Promise((resolve, reject) => {
|
|
641
|
-
// uni.uploadFile({
|
|
642
|
-
// url: props.action!,
|
|
643
|
-
// filePath: uploadFile.rawFile.path,
|
|
644
|
-
// name: props.name,
|
|
645
|
-
// formData: {
|
|
646
|
-
// ...props.data,
|
|
647
|
-
// filename: uploadFile.name,
|
|
648
|
-
// size: uploadFile.size,
|
|
649
|
-
// type: uploadFile.type
|
|
650
|
-
// },
|
|
651
|
-
// header: headers,
|
|
652
|
-
// timeout: props.timeout,
|
|
653
|
-
// withCredentials: props.withCredentials,
|
|
654
|
-
// success: (res: any) => {
|
|
655
|
-
// try {
|
|
656
|
-
// const data = typeof res.data === 'string' ? JSON.parse(res.data) : res.data
|
|
657
|
-
// resolve(data)
|
|
658
|
-
// } catch (e: any) {
|
|
659
|
-
// reject(e)
|
|
660
|
-
// }
|
|
661
|
-
// },
|
|
662
|
-
// complete: () => {
|
|
663
|
-
// // 上传完成
|
|
664
|
-
// },
|
|
665
|
-
// fail: (e: any) => {
|
|
666
|
-
// reject(e)
|
|
667
|
-
// }
|
|
668
|
-
// })
|
|
669
|
-
// })
|
|
670
572
|
}
|
|
671
573
|
|
|
672
574
|
// 更新文件列表
|
|
673
|
-
const updateFileList = () => {
|
|
575
|
+
const updateFileList = (uploadFile?: UploadFile) => {
|
|
674
576
|
emit('change', [...fileList.value])
|
|
675
|
-
|
|
577
|
+
|
|
578
|
+
if (isSingleFile()) {
|
|
579
|
+
emit('update:modelValue', String(uploadFile?.url))
|
|
580
|
+
} else {
|
|
581
|
+
emit('update:modelValue', [...fileList.value])
|
|
582
|
+
}
|
|
676
583
|
}
|
|
677
584
|
|
|
678
585
|
// 处理删除
|
|
@@ -713,7 +620,7 @@ const handlePreview = (file: UploadFile) => {
|
|
|
713
620
|
emit('preview', file)
|
|
714
621
|
|
|
715
622
|
// 如果是图片,使用 uni.previewImage
|
|
716
|
-
if (file.url && file.type?.startsWith('image
|
|
623
|
+
if (file.url && file.type?.startsWith('image')) {
|
|
717
624
|
uni.previewImage({
|
|
718
625
|
urls: [file.url],
|
|
719
626
|
current: file.url
|
|
@@ -778,30 +685,6 @@ const handleClearAll = () => {
|
|
|
778
685
|
})
|
|
779
686
|
}
|
|
780
687
|
|
|
781
|
-
// 手动上传文件
|
|
782
|
-
const upload = async (file: File) => {
|
|
783
|
-
const uploadFile: UploadFile = {
|
|
784
|
-
uid: generateUid(),
|
|
785
|
-
name: file.name,
|
|
786
|
-
size: file.size,
|
|
787
|
-
type: file.type,
|
|
788
|
-
status: 'pending',
|
|
789
|
-
progress: 0,
|
|
790
|
-
file: file
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
if (!props.multiple) {
|
|
794
|
-
fileList.value = [uploadFile]
|
|
795
|
-
} else {
|
|
796
|
-
fileList.value.push(uploadFile)
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
emit('select', file)
|
|
800
|
-
updateFileList()
|
|
801
|
-
|
|
802
|
-
await startUpload(uploadFile)
|
|
803
|
-
}
|
|
804
|
-
|
|
805
688
|
// 清空文件列表
|
|
806
689
|
const clearFiles = () => {
|
|
807
690
|
handleClearAll()
|
|
@@ -825,7 +708,6 @@ const abortUpload = (uid: string) => {
|
|
|
825
708
|
|
|
826
709
|
// 暴露方法给父组件
|
|
827
710
|
defineExpose({
|
|
828
|
-
upload,
|
|
829
711
|
clearFiles,
|
|
830
712
|
abortUpload,
|
|
831
713
|
uploadAll: handleUploadAll,
|
|
@@ -905,11 +787,6 @@ defineExpose({
|
|
|
905
787
|
gap: 20rpx;
|
|
906
788
|
}
|
|
907
789
|
|
|
908
|
-
.im-upload__avatar-icon {
|
|
909
|
-
font-size: 40rpx;
|
|
910
|
-
color: #8c939d;
|
|
911
|
-
}
|
|
912
|
-
|
|
913
790
|
.im-upload__avatar-text {
|
|
914
791
|
font-size: 26rpx;
|
|
915
792
|
color: #606266;
|
|
@@ -949,12 +826,15 @@ defineExpose({
|
|
|
949
826
|
}
|
|
950
827
|
|
|
951
828
|
.im-upload__list {
|
|
952
|
-
margin-top:
|
|
829
|
+
// margin-top: 20rpx;
|
|
830
|
+
display: flex;
|
|
831
|
+
flex-wrap: wrap;
|
|
953
832
|
}
|
|
954
833
|
|
|
955
834
|
.im-upload__item {
|
|
956
835
|
&--picture {
|
|
957
|
-
margin-
|
|
836
|
+
margin-top: 20rpx;
|
|
837
|
+
margin-right: 20rpx;
|
|
958
838
|
}
|
|
959
839
|
|
|
960
840
|
&--text {
|
|
@@ -1066,12 +946,6 @@ defineExpose({
|
|
|
1066
946
|
right: 8rpx;
|
|
1067
947
|
display: flex;
|
|
1068
948
|
gap: 8rpx;
|
|
1069
|
-
opacity: 0;
|
|
1070
|
-
transition: opacity 0.3s;
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
.im-upload__item-preview:hover .im-upload__item-actions {
|
|
1074
|
-
opacity: 1;
|
|
1075
949
|
}
|
|
1076
950
|
|
|
1077
951
|
.im-upload__item-action {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
// utils/file-adapter.
|
|
1
|
+
// utils/file-adapter.ts
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 创建统一的文件对象(多平台兼容)
|
|
5
5
|
* @param {Object} rawFile - 原始文件数据
|
|
6
6
|
* @returns {Object} 统一格式的文件对象
|
|
7
7
|
*/
|
|
8
|
-
export const createFileFromUniFile = (rawFile) => {
|
|
8
|
+
export const createFileFromUniFile = (rawFile: any): any => {
|
|
9
9
|
// 检查环境
|
|
10
10
|
// #ifdef H5
|
|
11
11
|
if (rawFile instanceof File) {
|
|
@@ -31,7 +31,7 @@ export const createFileFromUniFile = (rawFile) => {
|
|
|
31
31
|
raw: rawFile,
|
|
32
32
|
|
|
33
33
|
// 方法(模拟 File 对象的部分行为)
|
|
34
|
-
slice(start, end) {
|
|
34
|
+
slice(start: any, end: any) {
|
|
35
35
|
// 小程序环境不支持实际切片,返回一个标记对象
|
|
36
36
|
return {
|
|
37
37
|
path: this.path,
|
|
@@ -44,12 +44,12 @@ export const createFileFromUniFile = (rawFile) => {
|
|
|
44
44
|
|
|
45
45
|
// 转换为 base64(异步)
|
|
46
46
|
toBase64() {
|
|
47
|
-
return new Promise((resolve, reject) => {
|
|
47
|
+
return new Promise((resolve: any, reject: any) => {
|
|
48
48
|
// #ifdef MP-WEIXIN
|
|
49
49
|
wx.getFileSystemManager().readFile({
|
|
50
50
|
filePath: this.path,
|
|
51
51
|
encoding: 'base64',
|
|
52
|
-
success: (res) => resolve(res.data),
|
|
52
|
+
success: (res: any) => resolve(res.data),
|
|
53
53
|
fail: reject
|
|
54
54
|
})
|
|
55
55
|
// #endif
|
|
@@ -62,10 +62,10 @@ export const createFileFromUniFile = (rawFile) => {
|
|
|
62
62
|
// #endif
|
|
63
63
|
|
|
64
64
|
// #ifdef APP-PLUS
|
|
65
|
-
plus.io.resolveLocalFileSystemURL(this.path, (entry) => {
|
|
66
|
-
entry.file((file) => {
|
|
65
|
+
plus.io.resolveLocalFileSystemURL(this.path, (entry: any) => {
|
|
66
|
+
entry.file((file: any) => {
|
|
67
67
|
const reader = new plus.io.FileReader()
|
|
68
|
-
reader.onload = (e) => resolve(e.target.result.split(',')[1])
|
|
68
|
+
reader.onload = (e: any) => resolve(e.target.result.split(',')[1])
|
|
69
69
|
reader.onerror = reject
|
|
70
70
|
reader.readAsDataURL(file)
|
|
71
71
|
})
|
|
@@ -76,11 +76,11 @@ export const createFileFromUniFile = (rawFile) => {
|
|
|
76
76
|
|
|
77
77
|
// 转换为 ArrayBuffer(异步)
|
|
78
78
|
toArrayBuffer() {
|
|
79
|
-
return new Promise((resolve, reject) => {
|
|
79
|
+
return new Promise((resolve: any, reject: any) => {
|
|
80
80
|
// #ifdef MP-WEIXIN
|
|
81
81
|
wx.getFileSystemManager().readFile({
|
|
82
82
|
filePath: this.path,
|
|
83
|
-
success: (res) => resolve(res.data),
|
|
83
|
+
success: (res: any) => resolve(res.data),
|
|
84
84
|
fail: reject
|
|
85
85
|
})
|
|
86
86
|
// #endif
|
|
@@ -132,7 +132,7 @@ export const createFileFromUniFile = (rawFile) => {
|
|
|
132
132
|
/**
|
|
133
133
|
* 从文件路径提取文件名
|
|
134
134
|
*/
|
|
135
|
-
const getFileNameFromPath = (path) => {
|
|
135
|
+
const getFileNameFromPath = (path: any): any => {
|
|
136
136
|
if (!path) return 'unnamed'
|
|
137
137
|
return path.split('/').pop().split('?')[0]
|
|
138
138
|
}
|
|
@@ -140,11 +140,11 @@ const getFileNameFromPath = (path) => {
|
|
|
140
140
|
/**
|
|
141
141
|
* 从文件名获取文件类型
|
|
142
142
|
*/
|
|
143
|
-
const getFileTypeFromPath = (filename) => {
|
|
143
|
+
const getFileTypeFromPath = (filename: any): any => {
|
|
144
144
|
if (!filename) return 'application/octet-stream'
|
|
145
145
|
|
|
146
146
|
const extension = filename.split('.').pop().toLowerCase()
|
|
147
|
-
const typeMap = {
|
|
147
|
+
const typeMap: any = {
|
|
148
148
|
// 图片
|
|
149
149
|
'jpg': 'image/jpeg',
|
|
150
150
|
'jpeg': 'image/jpeg',
|
|
@@ -186,18 +186,18 @@ const getFileTypeFromPath = (filename) => {
|
|
|
186
186
|
/**
|
|
187
187
|
* 批量转换文件对象
|
|
188
188
|
*/
|
|
189
|
-
export const createFilesFromUniFiles = (rawFiles) => {
|
|
189
|
+
export const createFilesFromUniFiles = (rawFiles: any): any => {
|
|
190
190
|
if (!Array.isArray(rawFiles)) {
|
|
191
191
|
rawFiles = [rawFiles]
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
-
return rawFiles.map(file => createFileFromUniFile(file))
|
|
194
|
+
return rawFiles.map((file: any) => createFileFromUniFile(file))
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
/**
|
|
198
198
|
* 环境检测
|
|
199
199
|
*/
|
|
200
|
-
export const isBrowserEnv = () => {
|
|
200
|
+
export const isBrowserEnv = (): any => {
|
|
201
201
|
// #ifdef H5
|
|
202
202
|
return typeof File !== 'undefined'
|
|
203
203
|
// #endif
|
|
@@ -205,7 +205,7 @@ export const isBrowserEnv = () => {
|
|
|
205
205
|
return false
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
-
export const isWeChatEnv = () => {
|
|
208
|
+
export const isWeChatEnv = (): any => {
|
|
209
209
|
// #ifdef MP-WEIXIN
|
|
210
210
|
return true
|
|
211
211
|
// #endif
|
|
@@ -1,34 +1,36 @@
|
|
|
1
|
-
// utils/file-chooser.
|
|
2
|
-
|
|
1
|
+
// utils/file-chooser.ts
|
|
2
|
+
|
|
3
|
+
export const chooseFile = (options: any = {}): any => {
|
|
3
4
|
const defaultOptions = {
|
|
4
5
|
count: 1,
|
|
5
6
|
type: 'image'
|
|
6
7
|
}
|
|
7
|
-
|
|
8
8
|
const config = { ...defaultOptions, ...options }
|
|
9
9
|
|
|
10
|
-
return new Promise((resolve, reject) => {
|
|
10
|
+
return new Promise((resolve: any, reject: any) => {
|
|
11
11
|
// #ifdef H5 || APP-PLUS
|
|
12
12
|
uni.chooseFile({
|
|
13
13
|
...config,
|
|
14
|
-
success: (res) => resolve(res),
|
|
15
|
-
fail: (err) => reject(err)
|
|
14
|
+
success: (res: any) => resolve(res),
|
|
15
|
+
fail: (err: any) => reject(err)
|
|
16
16
|
})
|
|
17
17
|
// #endif
|
|
18
18
|
|
|
19
19
|
// #ifdef MP-WEIXIN
|
|
20
20
|
// 微信小程序需要根据type映射到不同的API
|
|
21
|
-
if (config.type === 'image'
|
|
21
|
+
if (config.type === 'image') {
|
|
22
22
|
wx.chooseImage({
|
|
23
23
|
count: config.count,
|
|
24
|
-
success: (res) => {
|
|
24
|
+
success: (res: any) => {
|
|
25
|
+
const { tempFilePaths, tempFiles } = res
|
|
25
26
|
// 统一返回格式
|
|
26
27
|
const result = {
|
|
27
|
-
tempFilePaths:
|
|
28
|
-
tempFiles:
|
|
28
|
+
tempFilePaths: tempFilePaths,
|
|
29
|
+
tempFiles: tempFiles.map((file: any) => ({
|
|
29
30
|
path: file.path,
|
|
30
31
|
size: file.size,
|
|
31
|
-
type: file.type || 'image'
|
|
32
|
+
type: file.type || 'image',
|
|
33
|
+
name: ''
|
|
32
34
|
}))
|
|
33
35
|
}
|
|
34
36
|
resolve(result)
|
|
@@ -39,9 +41,9 @@ export const chooseFile = (options = {}) => {
|
|
|
39
41
|
wx.chooseMessageFile({
|
|
40
42
|
count: config.count,
|
|
41
43
|
type: config.type === 'video' ? 'video' : 'file',
|
|
42
|
-
success: (res) => {
|
|
44
|
+
success: (res: any) => {
|
|
43
45
|
resolve({
|
|
44
|
-
tempFilePaths: res.tempFiles.map(file => file.path),
|
|
46
|
+
tempFilePaths: res.tempFiles.map((file: any) => file.path),
|
|
45
47
|
tempFiles: res.tempFiles
|
|
46
48
|
})
|
|
47
49
|
},
|
|
@@ -54,10 +56,10 @@ export const chooseFile = (options = {}) => {
|
|
|
54
56
|
// 支付宝小程序处理
|
|
55
57
|
my.chooseImage({
|
|
56
58
|
count: config.count,
|
|
57
|
-
success: (res) => {
|
|
59
|
+
success: (res: any) => {
|
|
58
60
|
resolve({
|
|
59
61
|
tempFilePaths: res.apFilePaths,
|
|
60
|
-
tempFiles: res.apFilePaths.map(path => ({ path }))
|
|
62
|
+
tempFiles: res.apFilePaths.map((path: any) => ({ path }))
|
|
61
63
|
})
|
|
62
64
|
},
|
|
63
65
|
fail: reject
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
// utils/file-validator.
|
|
1
|
+
// utils/file-validator.ts
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 获取文件类型(多平台兼容)
|
|
5
5
|
*/
|
|
6
|
-
const getFileType = (file) => {
|
|
7
|
-
// 优先使用 MIME 类型判断
|
|
8
|
-
if (file.type) {
|
|
9
|
-
return file.type.split('/')[0] // image, video, audio, application
|
|
10
|
-
}
|
|
11
|
-
|
|
6
|
+
const getFileType = (file: any): any => {
|
|
12
7
|
// 通过文件名后缀判断
|
|
13
8
|
const path = file.path || file.name || ''
|
|
14
9
|
const extension = path.split('.').pop().toLowerCase()
|
|
@@ -35,7 +30,7 @@ const getFileType = (file) => {
|
|
|
35
30
|
/**
|
|
36
31
|
* 统一文件类型映射(将自定义类型映射到平台支持的类型)
|
|
37
32
|
*/
|
|
38
|
-
const mapAcceptTypeToPlatform = (accept, platform) => {
|
|
33
|
+
const mapAcceptTypeToPlatform = (accept: string, platform: string): any => {
|
|
39
34
|
const typeMap = {
|
|
40
35
|
image: {
|
|
41
36
|
wx: ['image'],
|
|
@@ -73,7 +68,7 @@ const mapAcceptTypeToPlatform = (accept, platform) => {
|
|
|
73
68
|
* @param {string|Array} accept - 接受的文件类型
|
|
74
69
|
* @returns {boolean}
|
|
75
70
|
*/
|
|
76
|
-
export const isFileTypeAccepted = (file, accept = 'image') => {
|
|
71
|
+
export const isFileTypeAccepted = (file: any, accept: any = 'image'): boolean => {
|
|
77
72
|
if (!file) return false
|
|
78
73
|
|
|
79
74
|
// 如果 accept 是数组,转换为字符串处理
|
|
@@ -83,11 +78,10 @@ export const isFileTypeAccepted = (file, accept = 'image') => {
|
|
|
83
78
|
const fileType = getFileType(file)
|
|
84
79
|
|
|
85
80
|
// 处理 accept 字符串
|
|
86
|
-
const acceptTypes = acceptType.split(',').map(type => type.trim())
|
|
81
|
+
const acceptTypes = acceptType.split(',').map((type: any) => type.trim())
|
|
87
82
|
|
|
88
83
|
// 特殊类型处理
|
|
89
|
-
if (acceptTypes.includes('all')) return true
|
|
90
|
-
if (acceptTypes.includes('*')) return true
|
|
84
|
+
if (acceptTypes.includes('*') || acceptTypes.includes('all')) return true
|
|
91
85
|
|
|
92
86
|
// 检查文件类型
|
|
93
87
|
for (const accepted of acceptTypes) {
|
|
@@ -106,7 +100,7 @@ export const isFileTypeAccepted = (file, accept = 'image') => {
|
|
|
106
100
|
}
|
|
107
101
|
|
|
108
102
|
// 通用类型匹配
|
|
109
|
-
const genericTypes = {
|
|
103
|
+
const genericTypes: any = {
|
|
110
104
|
'image': ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'],
|
|
111
105
|
'video': ['mp4', 'avi', 'mov', 'wmv'],
|
|
112
106
|
'audio': ['mp3', 'wav', 'ogg', 'm4a'],
|
|
@@ -124,7 +118,7 @@ export const isFileTypeAccepted = (file, accept = 'image') => {
|
|
|
124
118
|
/**
|
|
125
119
|
* 获取平台特定的文件选择配置
|
|
126
120
|
*/
|
|
127
|
-
export const getPlatformFileConfig = (options = {}) => {
|
|
121
|
+
export const getPlatformFileConfig = (options: any = {}): any => {
|
|
128
122
|
const { accept = 'image', count = 1 } = options
|
|
129
123
|
|
|
130
124
|
// #ifdef MP-WEIXIN
|
|
@@ -194,8 +188,8 @@ export const getPlatformFileConfig = (options = {}) => {
|
|
|
194
188
|
/**
|
|
195
189
|
* 获取微信小程序支持的扩展名
|
|
196
190
|
*/
|
|
197
|
-
const getWeChatExtensions = (accept) => {
|
|
198
|
-
const extensions = []
|
|
191
|
+
const getWeChatExtensions = (accept: any): any => {
|
|
192
|
+
const extensions: any = []
|
|
199
193
|
|
|
200
194
|
if (accept.includes('image')) {
|
|
201
195
|
extensions.push('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp')
|
|
@@ -217,90 +211,4 @@ const getWeChatExtensions = (accept) => {
|
|
|
217
211
|
}
|
|
218
212
|
|
|
219
213
|
return extensions
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// /**
|
|
223
|
-
// * 统一文件选择方法(整合类型检查)
|
|
224
|
-
// */
|
|
225
|
-
// export const chooseFile = async (options = {}) => {
|
|
226
|
-
// const {
|
|
227
|
-
// accept = 'image',
|
|
228
|
-
// count = 1,
|
|
229
|
-
// sizeLimit, // 文件大小限制(字节)
|
|
230
|
-
// onTypeError, // 类型错误回调
|
|
231
|
-
// onSizeError // 大小错误回调
|
|
232
|
-
// } = options
|
|
233
|
-
|
|
234
|
-
// const platformConfig = getPlatformFileConfig({ accept, count })
|
|
235
|
-
|
|
236
|
-
// return new Promise((resolve, reject) => {
|
|
237
|
-
// // #ifdef MP-WEIXIN
|
|
238
|
-
// const wxApi = wx[platformConfig.api]
|
|
239
|
-
// wxApi({
|
|
240
|
-
// ...platformConfig.config,
|
|
241
|
-
// success: (res) => {
|
|
242
|
-
// // 统一处理返回结果
|
|
243
|
-
// let files = []
|
|
244
|
-
// if (platformConfig.api === 'chooseImage') {
|
|
245
|
-
// files = res.tempFiles.map(file => ({
|
|
246
|
-
// path: file.path,
|
|
247
|
-
// size: file.size,
|
|
248
|
-
// type: 'image'
|
|
249
|
-
// }))
|
|
250
|
-
// } else if (platformConfig.api === 'chooseMessageFile') {
|
|
251
|
-
// files = res.tempFiles
|
|
252
|
-
// }
|
|
253
|
-
|
|
254
|
-
// // 类型检查
|
|
255
|
-
// const filteredFiles = files.filter(file =>
|
|
256
|
-
// isFileTypeAccepted(file, accept)
|
|
257
|
-
// )
|
|
258
|
-
|
|
259
|
-
// // 大小检查
|
|
260
|
-
// if (sizeLimit) {
|
|
261
|
-
// const oversizedFiles = filteredFiles.filter(file => file.size > sizeLimit)
|
|
262
|
-
// if (oversizedFiles.length > 0 && onSizeError) {
|
|
263
|
-
// onSizeError(oversizedFiles)
|
|
264
|
-
// }
|
|
265
|
-
// }
|
|
266
|
-
|
|
267
|
-
// resolve({
|
|
268
|
-
// tempFilePaths: filteredFiles.map(f => f.path),
|
|
269
|
-
// tempFiles: filteredFiles
|
|
270
|
-
// })
|
|
271
|
-
// },
|
|
272
|
-
// fail: reject
|
|
273
|
-
// })
|
|
274
|
-
// // #endif
|
|
275
|
-
|
|
276
|
-
// // #ifdef H5 || APP-PLUS
|
|
277
|
-
// uni.chooseFile({
|
|
278
|
-
// ...platformConfig.config,
|
|
279
|
-
// success: (res) => {
|
|
280
|
-
// // 类型检查
|
|
281
|
-
// const filteredFiles = res.tempFiles.filter(file =>
|
|
282
|
-
// isFileTypeAccepted(file, accept)
|
|
283
|
-
// )
|
|
284
|
-
|
|
285
|
-
// if (filteredFiles.length === 0 && onTypeError) {
|
|
286
|
-
// onTypeError('没有符合类型的文件')
|
|
287
|
-
// }
|
|
288
|
-
|
|
289
|
-
// // 大小检查
|
|
290
|
-
// if (sizeLimit) {
|
|
291
|
-
// const oversizedFiles = filteredFiles.filter(file => file.size > sizeLimit)
|
|
292
|
-
// if (oversizedFiles.length > 0 && onSizeError) {
|
|
293
|
-
// onSizeError(oversizedFiles)
|
|
294
|
-
// }
|
|
295
|
-
// }
|
|
296
|
-
|
|
297
|
-
// resolve({
|
|
298
|
-
// tempFilePaths: filteredFiles.map(f => f.path),
|
|
299
|
-
// tempFiles: filteredFiles
|
|
300
|
-
// })
|
|
301
|
-
// },
|
|
302
|
-
// fail: reject
|
|
303
|
-
// })
|
|
304
|
-
// // #endif
|
|
305
|
-
// })
|
|
306
|
-
// }
|
|
214
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
// utils/upload.
|
|
1
|
+
// utils/upload.ts
|
|
2
|
+
|
|
2
3
|
/**
|
|
3
4
|
* 获取平台特定的上传方法
|
|
4
5
|
*/
|
|
5
|
-
const getPlatformUploadAPI = () => {
|
|
6
|
+
const getPlatformUploadAPI = (): any => {
|
|
6
7
|
// #ifdef H5 || APP-PLUS
|
|
7
8
|
return uni.uploadFile
|
|
8
9
|
// #endif
|
|
@@ -34,11 +35,11 @@ const getPlatformUploadAPI = () => {
|
|
|
34
35
|
/**
|
|
35
36
|
* 获取平台特定的请求头处理
|
|
36
37
|
*/
|
|
37
|
-
const getPlatformHeaders = (headers, platform) => {
|
|
38
|
+
const getPlatformHeaders = (headers: any, platform: any): any => {
|
|
38
39
|
// 微信小程序需要特殊处理
|
|
39
40
|
if (platform === 'wx') {
|
|
40
41
|
// 微信小程序中,header 字段名是小写的
|
|
41
|
-
const wxHeaders = {}
|
|
42
|
+
const wxHeaders: any = {}
|
|
42
43
|
Object.keys(headers).forEach(key => {
|
|
43
44
|
wxHeaders[key.toLowerCase()] = headers[key]
|
|
44
45
|
})
|
|
@@ -51,7 +52,7 @@ const getPlatformHeaders = (headers, platform) => {
|
|
|
51
52
|
/**
|
|
52
53
|
* 获取平台特定的请求配置
|
|
53
54
|
*/
|
|
54
|
-
const getPlatformConfig = (config, platform) => {
|
|
55
|
+
const getPlatformConfig = (config: any, platform: any): any => {
|
|
55
56
|
const baseConfig = {
|
|
56
57
|
url: config.url,
|
|
57
58
|
filePath: config.filePath,
|
|
@@ -107,7 +108,7 @@ const getPlatformConfig = (config, platform) => {
|
|
|
107
108
|
/**
|
|
108
109
|
* 获取当前平台标识
|
|
109
110
|
*/
|
|
110
|
-
const getCurrentPlatform = () => {
|
|
111
|
+
const getCurrentPlatform = (): any => {
|
|
111
112
|
// #ifdef MP-WEIXIN
|
|
112
113
|
return 'wx'
|
|
113
114
|
// #endif
|
|
@@ -142,14 +143,14 @@ const getCurrentPlatform = () => {
|
|
|
142
143
|
/**
|
|
143
144
|
* 多平台兼容的文件上传方法
|
|
144
145
|
*/
|
|
145
|
-
export const universalUploadFile = (config) => {
|
|
146
|
+
export const universalUploadFile = (config: any): any => {
|
|
146
147
|
const platform = getCurrentPlatform()
|
|
147
148
|
const platformConfig = getPlatformConfig(config, platform)
|
|
148
149
|
const uploadAPI = getPlatformUploadAPI()
|
|
149
150
|
|
|
150
|
-
return new Promise((resolve, reject) => {
|
|
151
|
+
return new Promise((resolve: any, reject: any) => {
|
|
151
152
|
// 平台特定的成功回调处理
|
|
152
|
-
const successCallback = (res) => {
|
|
153
|
+
const successCallback = (res: any) => {
|
|
153
154
|
try {
|
|
154
155
|
// 统一处理返回数据格式
|
|
155
156
|
let data = res.data || res
|
|
@@ -181,7 +182,7 @@ export const universalUploadFile = (config) => {
|
|
|
181
182
|
}
|
|
182
183
|
|
|
183
184
|
// 平台特定的失败回调处理
|
|
184
|
-
const failCallback = (err) => {
|
|
185
|
+
const failCallback = (err: any) => {
|
|
185
186
|
const error = {
|
|
186
187
|
errMsg: err.errMsg || 'uploadFile:fail',
|
|
187
188
|
detail: err
|
package/package.json
CHANGED
|
@@ -86,9 +86,6 @@ declare interface UploadProps {
|
|
|
86
86
|
|
|
87
87
|
// 上传组件方法
|
|
88
88
|
declare interface UploadMethods {
|
|
89
|
-
// 手动上传文件
|
|
90
|
-
upload: (file: Object) => Promise<void>
|
|
91
|
-
|
|
92
89
|
// 清空文件列表
|
|
93
90
|
clearFiles: () => void
|
|
94
91
|
|
|
@@ -110,15 +107,14 @@ declare interface _Upload {
|
|
|
110
107
|
'update:modelValue': (files: UploadFile[]) => void
|
|
111
108
|
'change': (files: UploadFile[]) => void
|
|
112
109
|
'select': (file: Object) => void
|
|
113
|
-
'upload': (file: UploadFile) => void
|
|
114
110
|
'success': (response: any, file: UploadFile) => void
|
|
115
111
|
'error': (error: Error, file: UploadFile) => void
|
|
116
112
|
'progress': (percent: number, file: UploadFile) => void
|
|
117
113
|
'remove': (file: UploadFile, index: number) => void
|
|
118
114
|
'preview': (file: UploadFile) => void
|
|
119
115
|
'exceed': (files: Object[]) => void
|
|
120
|
-
'
|
|
121
|
-
'
|
|
116
|
+
'uploading': (file: UploadFile) => void
|
|
117
|
+
'uploaded': (file: UploadFile) => void
|
|
122
118
|
}
|
|
123
119
|
} & UploadMethods
|
|
124
120
|
}
|
package/types/index.d.ts
CHANGED
package/utils/datetime.js
CHANGED
|
@@ -19,18 +19,18 @@ const toTimeText = (timeStamp, simple = false) => {
|
|
|
19
19
|
timeText = Math.floor(timeDiff / 60000) + '分钟前';
|
|
20
20
|
} else if (timeDiff >= 3600000 && timeDiff < 86400000 && !isYesterday(dateTime)) {
|
|
21
21
|
// 今日
|
|
22
|
-
timeText = formatDateTime(dateTime).
|
|
22
|
+
timeText = formatDateTime(dateTime).substring(11, 5);
|
|
23
23
|
} else if (isYesterday(dateTime)) {
|
|
24
24
|
// 昨天
|
|
25
|
-
timeText = '昨天' + formatDateTime(dateTime).
|
|
25
|
+
timeText = '昨天' + formatDateTime(dateTime).substring(11, 5);
|
|
26
26
|
} else if (isYear(dateTime)) {
|
|
27
27
|
// 今年
|
|
28
|
-
timeText = formatDateTime(dateTime).
|
|
28
|
+
timeText = formatDateTime(dateTime).substring(5, simple ? 5 : 14);
|
|
29
29
|
} else {
|
|
30
30
|
// 不属于今年
|
|
31
31
|
timeText = formatDateTime(dateTime);
|
|
32
32
|
if (simple) {
|
|
33
|
-
timeText = timeText.
|
|
33
|
+
timeText = timeText.substring(2, 8);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
return timeText;
|
|
@@ -127,19 +127,19 @@ const toChatTimeText = (timeStamp) => {
|
|
|
127
127
|
|
|
128
128
|
// 今天内的消息
|
|
129
129
|
if (timeDiff < 86400000 && !isYesterday(dateTime)) {
|
|
130
|
-
return formatDateTime(dateTime).
|
|
130
|
+
return formatDateTime(dateTime).substring(11, 5);
|
|
131
131
|
}
|
|
132
132
|
// 昨天的消息
|
|
133
133
|
else if (isYesterday(dateTime)) {
|
|
134
|
-
return '昨天 ' + formatDateTime(dateTime).
|
|
134
|
+
return '昨天 ' + formatDateTime(dateTime).substring(11, 5);
|
|
135
135
|
}
|
|
136
136
|
// 今年内的消息
|
|
137
137
|
else if (isYear(dateTime)) {
|
|
138
|
-
return formatDateTime(dateTime).
|
|
138
|
+
return formatDateTime(dateTime).substring(5, 5); // MM/dd
|
|
139
139
|
}
|
|
140
140
|
// 往年的消息
|
|
141
141
|
else {
|
|
142
|
-
return formatDateTime(dateTime).
|
|
142
|
+
return formatDateTime(dateTime).substring(2, 8); // yy/MM/dd
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
|