一、uni-app、微信小程序、钉钉开发相关api的区别
1、uni.chooseFile不支持微信小程序与支付宝小程序
2、wx.chooseMessageFile 可从客户端会话选择文件
支持类型type有:
all | 从所有文件选择 |
video | 只能选择视频文件 |
image | 只能选择图片文件 |
file | 可以选择除了图片和视频之外的其它的文件 |
3、钉钉应用开发没有选择文件api,只有
- 调用dd.chooseImage从本地相册选择图片;
- 调用dd.chooseVideo拍摄视频或从手机相册中选视频;
- 调用dd.uploadAttachmentToDingTalk上传附件到钉盘,或从钉盘选择文件
针对以上三点,对选择文件进行封封装处理
二、代码
choose-file.js
import Vue from 'vue'
// 目前支持两种 wx 和 钉钉
export const chooseFile = async (options) => {
console.log(options,'......')
let _fn
// #ifdef MP-WEIXIN
_fn = () => new Promise((reslove, reject) => {
wx.chooseMessageFile({
count: 1,
type: 'file',
success: reslove,
fail: reject,
...options
})
})
// #endif
// #ifdef MP-ALIPAY
const instance = Vue.prototype.$initDingFileChoose({
onSelect: options.onSelect || (() => {}),
...options
})
_fn = () => new Promise((reslove, reject) => {
instance.show()
})
// #endif
await _fn()
}
DingChooseFile.vue
<template>
<popup
title="选择文件"
v-model="visible"
:clickMaskToClose="true"
@cancelFn="visible = false"
>
<view class="optionsContent" slot="content">
<view v-for="selectType in types" :key="selectType.value">
<view
class="optionItem"
@tap="onSelect(selectType)"
v-if="chooseType(selectType.value)"
>
<view class="paddingArea">
<view class="optionValue">{{ selectType.name }}</view>
<view class="optionIcon" />
</view>
</view>
</view>
</view>
</popup>
</template>
<script>
import Vue from "vue";
import { apiGetAttachSpaceId } from "@/services/seal";
import { uploadFile } from "@/utils/uploadFile";
export default {
name: "DingChooseFile",
props: {
data: {
type: Object,
default: null,
},
limit: {
type: Number,
default: null,
},
},
data() {
return {
visible: false,
types: [
{ name: "照片", value: "photo" },
{ name: "视频", value: "video" },
{ name: "钉盘", value: "space" },暂时不考虑钉盘接入,无权限
],
outSideSelectHandler: () => {},
optionDing: {},
optionType: "",
};
},
async mounted() {
Vue.prototype.$initDingFileChoose = (arg) => {
let { onSelect, type, ...rest } = arg;
this.optionType = type;
this.optionDing = rest;
this.outSideSelectHandler = onSelect || (() => {});
return {
show: () => (this.visible = true),
close: () => (this.visible = false),
};
};
},
computed: {},
methods: {
/*判断钉钉上传文件类型 */
// type有space和photo、video三种
chooseType(type) {
if (!this.optionType || this.optionType === "all") return true;
if (this.optionType == "file") {
this.optionType = "space";
}
if (this.optionType == "image") {
this.optionType = "photo";
}
return this.optionType === type ? true : false;
},
async onSelect(selectType) {
let _this = this;
const chooseImage = () =>
new Promise((reslove, reject) => {
dd.chooseImage({
success: (res) => {
res.selectType = selectType;
reslove(res);
},
fail: reject,
..._this.optionDing,
});
});
const chooseVideo = () =>
new Promise((reslove, reject) => {
dd.chooseVideo({
...this.optionDing,
success: (res) => {
res.selectType = selectType;
reslove(res);
},
fail: reject,
});
});
const chooseDingDisk = async () => {
// 获取spaceId
let result = await apiGetAttachSpaceId();
return new Promise((reslove, reject) => {
dd.uploadAttachmentToDingTalk({
space: { spaceId: result.data, isCopy: 1, max: 9 },
image: {
spaceId: result.data,
multiple: true,
compress: false,
max: 9,
},
file: { spaceId: result.data, max: 1 },
types: ["space"], //PC端仅支持["photo","file","space"] space代表支持钉盘
success: (res) => {
res.selectType = selectType;
// debugger;
reslove(res);
},
fail: reject,
// ..._this.optionDing,
});
});
};
const fnMap = {
photo: chooseImage,
video: chooseVideo,
// dingDisk: chooseDingDisk,
space: chooseDingDisk,
};
const res = await fnMap[selectType.value](); //res是图片等等地址
this.outSideSelectHandler(res); //调用onselect方法
},
handleSuccess(res, callback) {
this.$showLoading();
let tempFilePaths;
let arr = [];
switch (res.selectType.value) {
case "photo":
tempFilePaths = res.files;
tempFilePaths.forEach((item) => {
arr.push({
fileType:
res.selectType.value === "photo"
? "image"
: res.selectType.value,
file_type: item.fileType,
path: item.path,
file_name: item.fileName || `用印文件.${item.fileType}`,//钉钉上传图片成功的返回值无name字段
file_size: item.size || "",
});
});
break;
case "space":
tempFilePaths = res.data;
tempFilePaths.forEach((item) => {
arr.push({
selectType: res.selectType.value, //'space'
fileType: res.type,
// file_type:
// item.fileName.split(".")[item.fileName.split(".").length - 1],
file_type: item.fileType,
file_id: item.fileId,
space_id: item.spaceId,
file_name: item.fileName,
file_size: item.fileSize || "",
});
});
break;
case "video":
tempFilePaths = res.filePath;
arr.push({
fileType: res.selectType.value,
path: res.filePath,
file_size: res.size,
file_height: res.height,
file_width: res.width,
file_name:
res.fileName ||
res.filePath.split(".")[res.filePath.split(".").length - 1],
file_duration: res.duration,
});
break;
}
callback(arr);
this.visible = false;
},
// 预览钉钉 钉盘上传文件
handlePreviewArea(listData) {
dd.previewFileInDingTalk({
spaceId: listData.data[0].spaceId,
fileId: listData.data[0].fileId,
fileName: listData.data[0].fileName,
fileType: listData.data[0].fileType,
fileSize: listData.data[0].fileSize,
success: (res) => {
console.log(res, "预览成功");
},
fail: (err) => {
console.log(err, "预览失败");
},
});
},
},
};
</script>
<style lang="less" scoped>
.optionsContent {
flex-grow: 1;
overflow: auto;
.optionItem {
display: flex;
align-items: center;
justify-content: space-between;
padding-left: 32rpx;
height: 112rpx;
.paddingArea {
height: 112rpx;
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 0.6px solid #e7e7e7;
}
.optionValue {
flex: 1;
width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 32rpx;
color: rgba(0, 0, 0, 0.9);
margin-right: 20rpx;
}
}
}
</style>
选择文件的使用
// 选择文件
async handleChooseFile() {
let res;
let pathMap = "OSS_SEAL_FILE_PATH";
let _this = this;
// 钉钉上传文件图片要成功时的回调
function callback(arr) {
uploadFile(arr, pathMap, (resp) => {
resp.forEach((item) => {
(item.attach_url = encodeURI(item.fileKey)), //encode转化
(item.attach_name = item.file_name);
});
// 关闭loading状态
_this.$closeLoading();
_this.$emit(
"changeValue",
_this.data.tmpValue.concat(resp),
"",
true
);
});
}
let options = {
// #ifdef MP-ALIPAY
onSelect(_res) {
res = _res;
_this.spaceList = _res;
if (!_this.limit) {
this.handleSuccess(res, callback);
return;
}
//选择上传图片
let size;
if (res.files) {
size = res.files.every((item) => {
return item.size <= 1024 * 1000 * _this.limit;
});
}
// 判断图片大小
if (!size) {
dd.showToast({
type: "fail",
content: "上传图片不能大于10M",
});
} else {
this.handleSuccess(res, callback);
}
},
// #endif
// #ifdef MP-WEIXIN
success: (res) => {
if (!this.limit) {
this.handleSuccess(res);
return;
}
let size = res.tempFiles.every((item) => {
//限制上传图片大小为2M,所有图片少于2M才能上传
return item.size <= 1024 * 1000 * this.limit;
});
if (!size) {
wx.showToast({
title: "上传图片不能大于10M!",
icon: "none",
});
} else {
this.handleSuccess(res);
}
},
// #endif
count: 9,
type: "all", //暂时不考虑钉盘接入
types: ["file", "space"], //types是钉盘上传支持的类型
};
chooseFile(options);
// #endif
},