mirror of
https://gitee.com/vant-contrib/vant-weapp.git
synced 2025-04-06 03:58:05 +08:00
feat(uploader): add new key thumb & standardization file-list (#3673)
fix #3606, fix #3661
This commit is contained in:
parent
8f21b5ed17
commit
36256cd28f
@ -5,7 +5,7 @@ Page({
|
|||||||
fileList1: [],
|
fileList1: [],
|
||||||
fileList2: [
|
fileList2: [
|
||||||
{ url: 'https://img.yzcdn.cn/vant/leaf.jpg' },
|
{ url: 'https://img.yzcdn.cn/vant/leaf.jpg' },
|
||||||
{ url: 'https://img.yzcdn.cn/vant/tree.jpg' }
|
{ url: 'https://img.yzcdn.cn/vant/tree.jpg' },
|
||||||
],
|
],
|
||||||
fileList3: [{ url: 'https://img.yzcdn.cn/vant/sand.jpg' }],
|
fileList3: [{ url: 'https://img.yzcdn.cn/vant/sand.jpg' }],
|
||||||
fileList4: [],
|
fileList4: [],
|
||||||
@ -17,14 +17,14 @@ Page({
|
|||||||
{
|
{
|
||||||
url: 'https://img.yzcdn.cn/vant/leaf.jpg',
|
url: 'https://img.yzcdn.cn/vant/leaf.jpg',
|
||||||
status: 'uploading',
|
status: 'uploading',
|
||||||
message: '上传中'
|
message: '上传中',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
url: 'https://img.yzcdn.cn/vant/tree.jpg',
|
url: 'https://img.yzcdn.cn/vant/tree.jpg',
|
||||||
status: 'failed',
|
status: 'failed',
|
||||||
message: '上传失败'
|
message: '上传失败',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRead(event) {
|
beforeRead(event) {
|
||||||
@ -39,6 +39,7 @@ Page({
|
|||||||
|
|
||||||
afterRead(event) {
|
afterRead(event) {
|
||||||
const { file, name } = event.detail;
|
const { file, name } = event.detail;
|
||||||
|
console.log(JSON.stringify(file, null, 2));
|
||||||
const fileList = this.data[`fileList${name}`];
|
const fileList = this.data[`fileList${name}`];
|
||||||
|
|
||||||
this.setData({ [`fileList${name}`]: fileList.concat(file) });
|
this.setData({ [`fileList${name}`]: fileList.concat(file) });
|
||||||
@ -67,12 +68,12 @@ Page({
|
|||||||
this.uploadFilePromise(`my-photo${index}.png`, file)
|
this.uploadFilePromise(`my-photo${index}.png`, file)
|
||||||
);
|
);
|
||||||
Promise.all(uploadTasks)
|
Promise.all(uploadTasks)
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
wx.showToast({ title: '上传成功', icon: 'none' });
|
wx.showToast({ title: '上传成功', icon: 'none' });
|
||||||
const fileList = data.map(item => ({ url: item.fileID }));
|
const fileList = data.map((item) => ({ url: item.fileID }));
|
||||||
this.setData({ cloudPath: data, fileList6: fileList });
|
this.setData({ cloudPath: data, fileList6: fileList });
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch((e) => {
|
||||||
wx.showToast({ title: '上传失败', icon: 'none' });
|
wx.showToast({ title: '上传失败', icon: 'none' });
|
||||||
console.log(e);
|
console.log(e);
|
||||||
});
|
});
|
||||||
@ -82,7 +83,7 @@ Page({
|
|||||||
uploadFilePromise(fileName, chooseResult) {
|
uploadFilePromise(fileName, chooseResult) {
|
||||||
return wx.cloud.uploadFile({
|
return wx.cloud.uploadFile({
|
||||||
cloudPath: fileName,
|
cloudPath: fileName,
|
||||||
filePath: chooseResult.path
|
filePath: chooseResult.path,
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { isNumber, isPlainObject } from './validator';
|
||||||
|
|
||||||
export function isDef(value: any): boolean {
|
export function isDef(value: any): boolean {
|
||||||
return value !== undefined && value !== null;
|
return value !== undefined && value !== null;
|
||||||
}
|
}
|
||||||
@ -7,10 +9,6 @@ export function isObj(x: any): boolean {
|
|||||||
return x !== null && (type === 'object' || type === 'function');
|
return x !== null && (type === 'object' || type === 'function');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isNumber(value) {
|
|
||||||
return /^\d+(\.\d+)?$/.test(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function range(num: number, min: number, max: number) {
|
export function range(num: number, min: number, max: number) {
|
||||||
return Math.min(Math.max(num, min), max);
|
return Math.min(Math.max(num, min), max);
|
||||||
}
|
}
|
||||||
@ -55,6 +53,20 @@ export function requestAnimationFrame(cb: Function) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function pickExclude(obj: unknown, keys: string[]) {
|
||||||
|
if (!isPlainObject(obj)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.keys(obj).reduce((prev, key) => {
|
||||||
|
if (!keys.includes(key)) {
|
||||||
|
prev[key] = obj[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
return prev;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
export function getRect(
|
export function getRect(
|
||||||
this: WechatMiniprogram.Component.TrivialInstance,
|
this: WechatMiniprogram.Component.TrivialInstance,
|
||||||
selector: string
|
selector: string
|
||||||
|
39
packages/common/validator.ts
Normal file
39
packages/common/validator.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
export function isFunction(val: unknown): val is Function {
|
||||||
|
return typeof val === 'function';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isPlainObject(val: unknown): val is Record<string, unknown> {
|
||||||
|
return val !== null && typeof val === 'object' && !Array.isArray(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isPromise<T = unknown>(val: unknown): val is Promise<T> {
|
||||||
|
return isPlainObject(val) && isFunction(val.then) && isFunction(val.catch);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isDef(value: any): boolean {
|
||||||
|
return value !== undefined && value !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isObj(x: unknown): x is Record<string, unknown> {
|
||||||
|
const type = typeof x;
|
||||||
|
return x !== null && (type === 'object' || type === 'function');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isNumber(value: string) {
|
||||||
|
return /^\d+(\.\d+)?$/.test(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isBoolean(value: unknown): value is boolean {
|
||||||
|
return typeof value === 'boolean';
|
||||||
|
}
|
||||||
|
|
||||||
|
const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i;
|
||||||
|
const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv)/i;
|
||||||
|
|
||||||
|
export function isImageUrl(url: string): boolean {
|
||||||
|
return IMAGE_REGEXP.test(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isVideoUrl(url: string): boolean {
|
||||||
|
return VIDEO_REGEXP.test(url);
|
||||||
|
}
|
@ -27,6 +27,7 @@ Page({
|
|||||||
data: {
|
data: {
|
||||||
fileList: [],
|
fileList: [],
|
||||||
},
|
},
|
||||||
|
|
||||||
afterRead(event) {
|
afterRead(event) {
|
||||||
const { file } = event.detail;
|
const { file } = event.detail;
|
||||||
// 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式
|
// 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式
|
||||||
@ -48,7 +49,7 @@ Page({
|
|||||||
|
|
||||||
### 图片预览
|
### 图片预览
|
||||||
|
|
||||||
通过向组件传入`file-list`属性,可以绑定已经上传的图片列表,并展示图片列表的预览图
|
通过向组件传入`file-list`属性,可以绑定已经上传的图片列表,并展示图片列表的预览图。file-list 的详细结构可见下方。
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<van-uploader file-list="{{ fileList }}" />
|
<van-uploader file-list="{{ fileList }}" />
|
||||||
@ -58,10 +59,14 @@ Page({
|
|||||||
Page({
|
Page({
|
||||||
data: {
|
data: {
|
||||||
fileList: [
|
fileList: [
|
||||||
{ url: 'https://img.yzcdn.cn/vant/leaf.jpg', name: '图片1' },
|
{
|
||||||
|
url: 'https://img.yzcdn.cn/vant/leaf.jpg',
|
||||||
|
name: '图片1',
|
||||||
|
},
|
||||||
// Uploader 根据文件后缀来判断是否为图片文件
|
// Uploader 根据文件后缀来判断是否为图片文件
|
||||||
// 如果图片 URL 中不包含类型信息,可以添加 isImage 标记来声明
|
// 如果图片 URL 中不包含类型信息,可以添加 isImage 标记来声明
|
||||||
{
|
{
|
||||||
|
url: 'http://iph.href.lu?text=default',
|
||||||
url: 'http://iph.href.lu/60x60?text=default',
|
url: 'http://iph.href.lu/60x60?text=default',
|
||||||
name: '图片2',
|
name: '图片2',
|
||||||
isImage: true,
|
isImage: true,
|
||||||
@ -74,7 +79,7 @@ Page({
|
|||||||
|
|
||||||
### 图片编辑状态
|
### 图片编辑状态
|
||||||
|
|
||||||
通过`deletable `可以标识所有图片或者单张图片是否可删除。如果`Props `的全局`deletable `为`false`,则所有图片都不展示删除按钮;如果`Props `的全局`deletable `为`true`,则可通过设置每一个图片对象里的`deletable `来控制每一张图片是否显示删除按钮,如果图片对象里不设置则默认为`true`。
|
通过`deletable`可以标识所有图片或者单张图片是否可删除。如果`Props`的全局`deletable`为`false`,则所有图片都不展示删除按钮;如果`Props`的全局`deletable`为`true`,则可通过设置每一个图片对象里的`deletable`来控制每一张图片是否显示删除按钮,如果图片对象里不设置则默认为`true`。
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<van-uploader file-list="{{ fileList }}" deletable="{{ true }}" />
|
<van-uploader file-list="{{ fileList }}" deletable="{{ true }}" />
|
||||||
@ -153,6 +158,7 @@ Page({
|
|||||||
```html
|
```html
|
||||||
<van-uploader
|
<van-uploader
|
||||||
file-list="{{ fileList }}"
|
file-list="{{ fileList }}"
|
||||||
|
accept="media"
|
||||||
use-before-read
|
use-before-read
|
||||||
bind:before-read="beforeRead"
|
bind:before-read="beforeRead"
|
||||||
bind:after-read="afterRead"
|
bind:after-read="afterRead"
|
||||||
@ -237,13 +243,26 @@ uploadFilePromise(fileName, chooseResult) {
|
|||||||
|
|
||||||
#### accept 的合法值
|
#### accept 的合法值
|
||||||
|
|
||||||
| 参数 | 说明 |
|
| 参数 | 说明 |
|
||||||
| ------- | ------------------------------ |
|
| ------- | ------------------------------------ |
|
||||||
| `media` | 图片和视频 |
|
| `media` | 图片和视频 |
|
||||||
| `image` | 图片 |
|
| `image` | 图片 |
|
||||||
| `video` | 视频 |
|
| `video` | 视频 |
|
||||||
| `file` | 除了图片和视频之外的其它的文件 |
|
| `file` | 从客户端会话选择图片和视频以外的文件 |
|
||||||
| `all` | 所有文件 |
|
| `all` | 从客户端会话选择所有文件 |
|
||||||
|
|
||||||
|
### FileList
|
||||||
|
|
||||||
|
`file-list` 为一个对象数组,数组中的每一个对象包含以下 `key`
|
||||||
|
|
||||||
|
| 参数 | 说明 |
|
||||||
|
| --------- | ------------------------------------------------------ |
|
||||||
|
| `url` | 图片和视频的网络资源地址 |
|
||||||
|
| `name` | 文件名称,视频将在全屏预览时作为标题显示 |
|
||||||
|
| `thumb` | 图片缩略图或视频封面的网络资源地址,仅对图片和视频有效 |
|
||||||
|
| `type` | 文件类型,可选值`image` `video` `file` |
|
||||||
|
| `isImage` | 手动标记图片资源 |
|
||||||
|
| `isVideo` | 手动标记视频资源 |
|
||||||
|
|
||||||
### Slot
|
### Slot
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { VantComponent } from '../common/component';
|
import { VantComponent } from '../common/component';
|
||||||
import { isImageFile, isVideo, chooseFile, isPromise } from './utils';
|
import { isImageFile, chooseFile, isVideoFile } from './utils';
|
||||||
import { chooseImageProps, chooseVideoProps } from './shared';
|
import { chooseImageProps, chooseVideoProps } from './shared';
|
||||||
|
import { isBoolean, isPromise } from '../common/validator';
|
||||||
|
|
||||||
VantComponent({
|
VantComponent({
|
||||||
props: {
|
props: {
|
||||||
@ -73,13 +74,13 @@ VantComponent({
|
|||||||
const { fileList = [], maxCount } = this.data;
|
const { fileList = [], maxCount } = this.data;
|
||||||
const lists = fileList.map((item) => ({
|
const lists = fileList.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
isImage:
|
isImage: isImageFile(item),
|
||||||
typeof item.isImage === 'undefined'
|
isVideo: isVideoFile(item),
|
||||||
? isImageFile(item)
|
deletable: isBoolean(item.deletable) ? item.deletable : true,
|
||||||
: item.isImage,
|
|
||||||
deletable:
|
|
||||||
typeof item.deletable === 'undefined' ? true : item.deletable,
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
console.log(lists);
|
||||||
|
|
||||||
this.setData({ lists, isInCount: lists.length < maxCount });
|
this.setData({ lists, isInCount: lists.length < maxCount });
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -100,18 +101,9 @@ VantComponent({
|
|||||||
maxCount: maxCount - lists.length,
|
maxCount: maxCount - lists.length,
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
let file = null;
|
console.log(res);
|
||||||
|
|
||||||
if (isVideo(res, accept)) {
|
this.onBeforeRead(multiple ? res : res[0]);
|
||||||
file = {
|
|
||||||
path: res.tempFilePath,
|
|
||||||
...res,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
file = multiple ? res.tempFiles : res.tempFiles[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onBeforeRead(file);
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.$emit('error', error);
|
this.$emit('error', error);
|
||||||
@ -120,14 +112,14 @@ VantComponent({
|
|||||||
|
|
||||||
onBeforeRead(file) {
|
onBeforeRead(file) {
|
||||||
const { beforeRead, useBeforeRead } = this.data;
|
const { beforeRead, useBeforeRead } = this.data;
|
||||||
let res: boolean | Promise<any> = true;
|
let res: boolean | Promise<void> = true;
|
||||||
|
|
||||||
if (typeof beforeRead === 'function') {
|
if (typeof beforeRead === 'function') {
|
||||||
res = beforeRead(file, this.getDetail());
|
res = beforeRead(file, this.getDetail());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useBeforeRead) {
|
if (useBeforeRead) {
|
||||||
res = new Promise((resolve, reject) => {
|
res = new Promise<void>((resolve, reject) => {
|
||||||
this.$emit('before-read', {
|
this.$emit('before-read', {
|
||||||
file,
|
file,
|
||||||
...this.getDetail(),
|
...this.getDetail(),
|
||||||
@ -150,7 +142,7 @@ VantComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onAfterRead(file) {
|
onAfterRead(file) {
|
||||||
const { maxSize } = this.data;
|
const { maxSize, afterRead } = this.data;
|
||||||
const oversize = Array.isArray(file)
|
const oversize = Array.isArray(file)
|
||||||
? file.some((item) => item.size > maxSize)
|
? file.some((item) => item.size > maxSize)
|
||||||
: file.size > maxSize;
|
: file.size > maxSize;
|
||||||
@ -160,8 +152,8 @@ VantComponent({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof this.data.afterRead === 'function') {
|
if (typeof afterRead === 'function') {
|
||||||
this.data.afterRead(file, this.getDetail());
|
afterRead(file, this.getDetail());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$emit('after-read', { file, ...this.getDetail() });
|
this.$emit('after-read', { file, ...this.getDetail() });
|
||||||
@ -184,32 +176,28 @@ VantComponent({
|
|||||||
const item = lists[index];
|
const item = lists[index];
|
||||||
|
|
||||||
wx.previewImage({
|
wx.previewImage({
|
||||||
urls: lists
|
urls: lists.filter((item) => isImageFile(item)).map((item) => item.url),
|
||||||
.filter((item) => item.isImage)
|
current: item.url,
|
||||||
.map((item) => item.url || item.path),
|
|
||||||
current: item.url || item.path,
|
|
||||||
fail() {
|
fail() {
|
||||||
wx.showToast({ title: '预览图片失败', icon: 'none' });
|
wx.showToast({ title: '预览图片失败', icon: 'none' });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// fix: accept 为 video 时不能展示视频
|
|
||||||
onPreviewVideo: function (event) {
|
onPreviewVideo(event) {
|
||||||
if (!this.data.previewFullImage) return;
|
if (!this.data.previewFullImage) return;
|
||||||
var index = event.currentTarget.dataset.index;
|
const { index } = event.currentTarget.dataset;
|
||||||
var lists = this.data.lists;
|
const { lists } = this.data;
|
||||||
|
|
||||||
wx.previewMedia({
|
wx.previewMedia({
|
||||||
sources: lists
|
sources: lists
|
||||||
.filter(function (item) {
|
.filter((item) => isVideoFile(item))
|
||||||
return item.isVideo;
|
.map((item) => ({
|
||||||
})
|
...item,
|
||||||
.map(function (item) {
|
type: 'video',
|
||||||
item.type = 'video';
|
})),
|
||||||
item.url = item.url || item.path;
|
|
||||||
return item;
|
|
||||||
}),
|
|
||||||
current: index,
|
current: index,
|
||||||
fail: function () {
|
fail() {
|
||||||
wx.showToast({ title: '预览视频失败', icon: 'none' });
|
wx.showToast({ title: '预览视频失败', icon: 'none' });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
<image
|
<image
|
||||||
wx:if="{{ item.isImage }}"
|
wx:if="{{ item.isImage }}"
|
||||||
mode="{{ imageFit }}"
|
mode="{{ imageFit }}"
|
||||||
src="{{ item.url || item.path }}"
|
src="{{ item.thumb || item.url }}"
|
||||||
alt="{{ item.name || ('图片' + index) }}"
|
alt="{{ item.name || ('图片' + index) }}"
|
||||||
class="van-uploader__preview-image"
|
class="van-uploader__preview-image"
|
||||||
style="width: {{ utils.addUnit(previewSize) }}; height: {{ utils.addUnit(previewSize) }};"
|
style="width: {{ utils.addUnit(previewSize) }}; height: {{ utils.addUnit(previewSize) }};"
|
||||||
@ -23,21 +23,23 @@
|
|||||||
/>
|
/>
|
||||||
<video
|
<video
|
||||||
wx:elif="{{ item.isVideo }}"
|
wx:elif="{{ item.isVideo }}"
|
||||||
src="{{item.url || item.path}}"
|
src="{{ item.url }}"
|
||||||
autoplay="{{item.autoplay}}"
|
title="{{ item.name || ('视频' + index) }}"
|
||||||
|
poster="{{ item.thumb }}"
|
||||||
|
autoplay="{{ item.autoplay }}"
|
||||||
class="van-uploader__preview-image"
|
class="van-uploader__preview-image"
|
||||||
style="width: {{ utils.addUnit(previewSize) }}; height: {{ utils.addUnit(previewSize) }};"
|
style="width: {{ utils.addUnit(previewSize) }}; height: {{ utils.addUnit(previewSize) }};"
|
||||||
data-index="{{ index }}"
|
data-index="{{ index }}"
|
||||||
bind:tap="onPreviewVideo"
|
bind:tap="onPreviewVideo"
|
||||||
>
|
>
|
||||||
</video>
|
</video>
|
||||||
<view
|
<view
|
||||||
wx:else
|
wx:else
|
||||||
class="van-uploader__file"
|
class="van-uploader__file"
|
||||||
style="width: {{ utils.addUnit(previewSize) }}; height: {{ utils.addUnit(previewSize) }};"
|
style="width: {{ utils.addUnit(previewSize) }}; height: {{ utils.addUnit(previewSize) }};"
|
||||||
>
|
>
|
||||||
<van-icon name="description" class="van-uploader__file-icon" />
|
<van-icon name="description" class="van-uploader__file-icon" />
|
||||||
<view class="van-uploader__file-name van-ellipsis">{{ item.name || item.url || item.path }}</view>
|
<view class="van-uploader__file-name van-ellipsis">{{ item.name || item.url }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view
|
||||||
wx:if="{{ item.status === 'uploading' || item.status === 'failed' }}"
|
wx:if="{{ item.status === 'uploading' || item.status === 'failed' }}"
|
||||||
@ -59,7 +61,7 @@
|
|||||||
|
|
||||||
<!-- 上传样式 -->
|
<!-- 上传样式 -->
|
||||||
<block wx:if="{{ isInCount }}">
|
<block wx:if="{{ isInCount }}">
|
||||||
<view class="van-uploader__slot" bind:tap="startUpload">
|
<view class="van-uploader__slot" bindtap="startUpload">
|
||||||
<slot />
|
<slot />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
@ -1,26 +1,24 @@
|
|||||||
|
import { pickExclude } from '../common/utils';
|
||||||
|
import { isImageUrl, isVideoUrl } from '../common/validator';
|
||||||
|
|
||||||
interface File {
|
interface File {
|
||||||
path: string; // 上传临时地址
|
|
||||||
url: string; // 上传临时地址
|
url: string; // 上传临时地址
|
||||||
size: number; // 上传大小
|
size?: number; // 上传大小
|
||||||
name: string; // 上传文件名称,accept="image" 不存在
|
name?: string;
|
||||||
type: string; // 上传类型,accept="image" 不存在
|
type: string; // 上传类型
|
||||||
time: number; // 上传时间,accept="image" 不存在
|
duration?: number; // 上传时间
|
||||||
image: boolean; // 是否为图片
|
time?: number; // 消息文件时间
|
||||||
}
|
isImage?: boolean;
|
||||||
|
isVideo?: boolean;
|
||||||
const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i;
|
|
||||||
|
|
||||||
function isImageUrl(url: string): boolean {
|
|
||||||
return IMAGE_REGEXP.test(url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isImageFile(item: File): boolean {
|
export function isImageFile(item: File): boolean {
|
||||||
if (item.type) {
|
if (item.isImage != null) {
|
||||||
return item.type.indexOf('image') === 0;
|
return item.isImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.path) {
|
if (item.type) {
|
||||||
return isImageUrl(item.path);
|
return item.type === 'image';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.url) {
|
if (item.url) {
|
||||||
@ -30,11 +28,62 @@ export function isImageFile(item: File): boolean {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isVideo(
|
export function isVideoFile(item: File): boolean {
|
||||||
res: any,
|
if (item.isVideo != null) {
|
||||||
accept: string
|
return item.isVideo;
|
||||||
): res is WechatMiniprogram.ChooseVideoSuccessCallbackResult {
|
}
|
||||||
return accept === 'video';
|
|
||||||
|
if (item.type) {
|
||||||
|
return item.type === 'video';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.url) {
|
||||||
|
return isVideoUrl(item.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatImage(
|
||||||
|
res: WechatMiniprogram.ChooseImageSuccessCallbackResult
|
||||||
|
): File[] {
|
||||||
|
return res.tempFiles.map((item) => ({
|
||||||
|
...pickExclude(item, ['path']),
|
||||||
|
type: 'image',
|
||||||
|
url: item.path,
|
||||||
|
thumb: item.path,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatVideo(
|
||||||
|
res: WechatMiniprogram.ChooseVideoSuccessCallbackResult & Record<string, any>
|
||||||
|
) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
...pickExclude(res, ['tempFilePath', 'thumbTempFilePath', 'errMsg']),
|
||||||
|
type: 'video',
|
||||||
|
url: res.tempFilePath,
|
||||||
|
thumb: res.thumbTempFilePath,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatMedia(res: WechatMiniprogram.ChooseMediaSuccessCallbackResult) {
|
||||||
|
return res.tempFiles.map((item) => ({
|
||||||
|
...pickExclude(item, ['fileType', 'thumbTempFilePath', 'tempFilePath']),
|
||||||
|
type: res.type,
|
||||||
|
url: item.tempFilePath,
|
||||||
|
thumb: res.type === 'video' ? item.thumbTempFilePath : item.tempFilePath,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatFile(
|
||||||
|
res: WechatMiniprogram.ChooseMessageFileSuccessCallbackResult
|
||||||
|
) {
|
||||||
|
return res.tempFiles.map((item) => ({
|
||||||
|
...pickExclude(item, ['path']),
|
||||||
|
url: item.path,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function chooseFile({
|
export function chooseFile({
|
||||||
@ -46,66 +95,47 @@ export function chooseFile({
|
|||||||
sizeType,
|
sizeType,
|
||||||
camera,
|
camera,
|
||||||
maxCount,
|
maxCount,
|
||||||
}): Promise<
|
}) {
|
||||||
| WechatMiniprogram.ChooseImageSuccessCallbackResult
|
return new Promise((resolve, reject) => {
|
||||||
| WechatMiniprogram.ChooseMediaSuccessCallbackResult
|
switch (accept) {
|
||||||
| WechatMiniprogram.ChooseVideoSuccessCallbackResult
|
case 'image':
|
||||||
| WechatMiniprogram.ChooseMessageFileSuccessCallbackResult
|
|
||||||
> {
|
|
||||||
switch (accept) {
|
|
||||||
case 'image':
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
wx.chooseImage({
|
wx.chooseImage({
|
||||||
count: multiple ? Math.min(maxCount, 9) : 1, // 最多可以选择的数量,如果不支持多选则数量为1
|
count: multiple ? Math.min(maxCount, 9) : 1,
|
||||||
sourceType: capture, // 选择图片的来源,相册还是相机
|
sourceType: capture,
|
||||||
sizeType,
|
sizeType,
|
||||||
success: resolve,
|
success: (res) => resolve(formatImage(res)),
|
||||||
fail: reject,
|
fail: reject,
|
||||||
});
|
});
|
||||||
});
|
break;
|
||||||
case 'media':
|
case 'media':
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
wx.chooseMedia({
|
wx.chooseMedia({
|
||||||
count: multiple ? Math.min(maxCount, 9) : 1, // 最多可以选择的数量,如果不支持多选则数量为1
|
count: multiple ? Math.min(maxCount, 9) : 1,
|
||||||
sourceType: capture, // 选择图片的来源,相册还是相机
|
sourceType: capture,
|
||||||
maxDuration,
|
maxDuration,
|
||||||
sizeType,
|
sizeType,
|
||||||
camera,
|
camera,
|
||||||
success: resolve,
|
success: (res) => resolve(formatMedia(res)),
|
||||||
fail: reject,
|
fail: reject,
|
||||||
});
|
});
|
||||||
});
|
break;
|
||||||
case 'video':
|
case 'video':
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
wx.chooseVideo({
|
wx.chooseVideo({
|
||||||
sourceType: capture,
|
sourceType: capture,
|
||||||
compressed,
|
compressed,
|
||||||
maxDuration,
|
maxDuration,
|
||||||
camera,
|
camera,
|
||||||
success: resolve,
|
success: (res) => resolve(formatVideo(res)),
|
||||||
fail: reject,
|
fail: reject,
|
||||||
});
|
});
|
||||||
});
|
break;
|
||||||
default:
|
default:
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
wx.chooseMessageFile({
|
wx.chooseMessageFile({
|
||||||
count: multiple ? maxCount : 1, // 最多可以选择的数量,如果不支持多选则数量为1
|
count: multiple ? maxCount : 1,
|
||||||
type: 'file',
|
type: accept,
|
||||||
success: resolve,
|
success: (res) => resolve(formatFile(res)),
|
||||||
fail: reject,
|
fail: reject,
|
||||||
});
|
});
|
||||||
});
|
break;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
export function isFunction(val: unknown): val is Function {
|
|
||||||
return typeof val === 'function';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isObject(val: any): val is Record<any, any> {
|
|
||||||
return val !== null && typeof val === 'object';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isPromise<T = any>(val: unknown): val is Promise<T> {
|
|
||||||
return isObject(val) && isFunction(val.then) && isFunction(val.catch);
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user