初始提交
This commit is contained in:
400
pages/workFlow/comment/comment-file/index.vue
Normal file
400
pages/workFlow/comment/comment-file/index.vue
Normal file
@@ -0,0 +1,400 @@
|
||||
<template>
|
||||
<view class="jnpf-file">
|
||||
<view class="jnpf-file-box" :style="{textAlign:align}">
|
||||
<view v-if="!detailed &&!disabled " class="jnpf-file-box-line">
|
||||
<!-- #ifndef APP-HARMONY -->
|
||||
<CommentLsjUpload :ref="lsjUpload" :childId="childId" :width="width" :height="height" :option="option"
|
||||
:size="fileSize" :formats="getFormats" :instantly="instantly" @uploadEnd="onuploadEnd"
|
||||
:lsjUpload="lsjUpload" v-if="!disabled" :currentCount="currentCount">
|
||||
<view class="icon-ym icon-ym-comment-file" size="mini"></view>
|
||||
</CommentLsjUpload>
|
||||
<view class="icon-ym icon-ym-comment-file" size="mini" v-else @click="onCountOver"></view>
|
||||
<!-- #endif -->
|
||||
|
||||
|
||||
<!-- #ifdef APP-HARMONY -->
|
||||
<view @click="chooseFile">
|
||||
<view class="icon-ym icon-ym-comment-file" size="mini"></view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
</view>
|
||||
<view class="icon-ym icon-ym-comment-file" size="mini" v-if="disabled" @click="onCountOver"></view>
|
||||
<view class="tipText u-p-l-20">
|
||||
{{tipText}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CommentLsjUpload from './lsj-upload/lsj-upload.vue'
|
||||
|
||||
import {
|
||||
getDownloadUrl
|
||||
} from '@/api/common'
|
||||
import jnpf from '@/utils/jnpf'
|
||||
const units = {
|
||||
KB: 1024,
|
||||
MB: 1024 * 1024,
|
||||
GB: 1024 * 1024 * 1024,
|
||||
};
|
||||
const imgTypeList = ['png', 'jpg', 'jpeg', 'bmp', 'gif']
|
||||
export default {
|
||||
components: {
|
||||
CommentLsjUpload
|
||||
},
|
||||
name: 'jnpf-upload-img',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: () => ([])
|
||||
},
|
||||
limit: {
|
||||
type: [Number, String],
|
||||
default: 9
|
||||
},
|
||||
fileSize: {
|
||||
type: Number,
|
||||
default: 10
|
||||
},
|
||||
sizeUnit: {
|
||||
type: String,
|
||||
default: 'MB'
|
||||
},
|
||||
accept: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
pathType: {
|
||||
type: String,
|
||||
default: 'defaultPath'
|
||||
},
|
||||
tipText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isAccount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
folder: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
vModel: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
detailed: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
align: {
|
||||
type: String,
|
||||
default: 'right'
|
||||
},
|
||||
currentCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
percent: '',
|
||||
fileList: [],
|
||||
// 上传接口参数
|
||||
option: {},
|
||||
params: {
|
||||
pathType: this.pathType,
|
||||
isAccount: this.isAccount,
|
||||
folder: this.folder
|
||||
},
|
||||
// 选择文件后是否立即自动上传,true=选择后立即上传
|
||||
instantly: true,
|
||||
size: 30,
|
||||
list: [],
|
||||
deletable: false,
|
||||
childId: 'upload' + this.$u.guid(3, false, 2),
|
||||
lsjUpload: 'lsjUpload' + this.$u.guid(3, false, 2),
|
||||
width: '48rpx',
|
||||
height: '48rpx',
|
||||
disabled: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
},
|
||||
comUploadUrl() {
|
||||
return this.define.comUploadUrl
|
||||
},
|
||||
getFormats() {
|
||||
let formats = this.accept
|
||||
formats = formats.replace("image/*", 'png,jpg,jpeg,bmp,gif,webp,psd,svg,tiff')
|
||||
formats = formats.replace("video/*", 'avi,wmv,mpg,mpeg,mov,rm,ram,swf,flv,mp4,wma,rm,rmvb,flv,mpg,mkv')
|
||||
formats = formats.replace("audio/*", 'mp3,wav,aif,midi,m4a')
|
||||
return formats
|
||||
},
|
||||
},
|
||||
created() {
|
||||
const token = uni.getStorageSync('token')
|
||||
this.option = {
|
||||
url: this.baseURL + '/api/file/Uploader/annex',
|
||||
name: 'file',
|
||||
header: {
|
||||
'Authorization': token,
|
||||
'uid': '27682',
|
||||
'client': 'app',
|
||||
'accountid': 'DP',
|
||||
},
|
||||
data: this.params
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
modelValue: {
|
||||
handler(val) {
|
||||
this.fileList = JSON.parse(JSON.stringify(val));
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 鸿蒙上传附件
|
||||
chooseFile() {
|
||||
if (this.limit === this.fileList.length) return this.toast(`只允许上传${this.limit}个文件`);
|
||||
uni.chooseFile({
|
||||
count: 1, //默认100
|
||||
success: (res) => {
|
||||
const tempFilePaths = res.tempFilePaths;
|
||||
const token = uni.getStorageSync('token')
|
||||
const file = res.tempFiles[0]
|
||||
// 限制文件大小
|
||||
if (file.size > units[this.sizeUnit] * Math.abs(this.fileSize)) {
|
||||
this.toast(`文件大小超过${this.fileSize}${this.sizeUnit}`)
|
||||
return;
|
||||
}
|
||||
uni.uploadFile({
|
||||
url: this.baseURL + '/api/file/Uploader/annex',
|
||||
filePath: tempFilePaths[0],
|
||||
name: 'file',
|
||||
formData: {
|
||||
...this.params,
|
||||
fileName: file.name
|
||||
},
|
||||
header: {
|
||||
'Authorization': token,
|
||||
'uid': '27682',
|
||||
'client': 'app',
|
||||
'accountid': 'DP',
|
||||
},
|
||||
success: (response) => {
|
||||
let item = JSON.parse(response.data)
|
||||
this.fileList.push({
|
||||
name: res.tempFiles[0].name,
|
||||
fileId: item.data.name,
|
||||
url: item.data.url,
|
||||
fileExtension: item.data.fileExtension,
|
||||
fileSize: item.data.fileSize
|
||||
})
|
||||
this.$emit('update:modelValue', this.fileList)
|
||||
this.$emit('change', this.fileList)
|
||||
this.$forceUpdate();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
onCountOver() {
|
||||
uni.showToast({
|
||||
title: `最多可以上传${this.limit}个文件`,
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
},
|
||||
// 某文件上传结束回调(成功失败都回调)
|
||||
onuploadEnd(item) {
|
||||
if (this.currentCount >= this.limit) {
|
||||
// this.disabled = true;
|
||||
return this.$u.toast('最多可以上传' + this.limit + '个文件')
|
||||
}
|
||||
if (item['responseText']) {
|
||||
let response = JSON.parse(item.responseText)
|
||||
let count = this.fileList.length
|
||||
if (count >= this.limit) {
|
||||
// this.disabled = true;
|
||||
return this.$u.toast('最多可以上传' + this.limit + '个文件')
|
||||
}
|
||||
if (response.code != 200) return this.$u.toast(response.msg)
|
||||
this.fileList.push({
|
||||
name: item.name,
|
||||
fileId: response.data.name,
|
||||
url: response.data.url,
|
||||
fileExtension: response.data.fileExtension,
|
||||
fileSize: response.data.fileSize
|
||||
})
|
||||
this.$emit('update:modelValue', this.fileList)
|
||||
this.$emit('change', this.fileList)
|
||||
}
|
||||
this.$forceUpdate();
|
||||
},
|
||||
downLoad(item) {
|
||||
if (item.fileExtension && imgTypeList.includes(item.fileExtension)) return this.previewImage(item)
|
||||
// #ifdef MP
|
||||
this.previewFile(item)
|
||||
// #endif
|
||||
// #ifndef MP
|
||||
getDownloadUrl('annex', item.fileId).then(res => {
|
||||
const fileUrl = this.baseURL + res.data.url + '&name=' + item.name;
|
||||
// #ifdef H5
|
||||
window.location.href = fileUrl;
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
this.downloadFile(res.data.url);
|
||||
// #endif
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
// 移除某个文件
|
||||
delFile(files) {
|
||||
this.fileList = files
|
||||
// if(this.fileList.length >= this.limit) {
|
||||
// this.disabled = true
|
||||
// }else{
|
||||
// this.disabled = false
|
||||
// }
|
||||
},
|
||||
previewFile(item) {
|
||||
let fileTypes = ['doc', 'xls', 'ppt', 'pdf', 'docx', 'xlsx', 'pptx']
|
||||
let url = item.url
|
||||
let fileType = url.split('.')[1]
|
||||
if (fileTypes.includes(fileType)) {
|
||||
uni.downloadFile({
|
||||
url: this.baseURL + url,
|
||||
success: (res) => {
|
||||
var filePath = res.tempFilePath;
|
||||
uni.openDocument({
|
||||
filePath: encodeURI(filePath),
|
||||
showMenu: true,
|
||||
fileType: fileType,
|
||||
success: (res) => {
|
||||
console.log('打开文档成功');
|
||||
},
|
||||
fail(err) {
|
||||
console.log('小程序', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.$u.toast(
|
||||
'该文件类型无法打开'
|
||||
)
|
||||
}
|
||||
},
|
||||
previewImage(item) {
|
||||
if (!item.url) return
|
||||
const url = jnpf.getAuthImgUrl(item.url)
|
||||
uni.previewImage({
|
||||
urls: [url],
|
||||
current: url,
|
||||
success: () => {},
|
||||
fail: () => {
|
||||
uni.showToast({
|
||||
title: '预览图片失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
downloadFile(url) {
|
||||
uni.downloadFile({
|
||||
url: this.baseURL + url,
|
||||
success: res => {
|
||||
if (res.statusCode === 200) {
|
||||
uni.saveFile({
|
||||
tempFilePath: res.tempFilePath,
|
||||
success: red => {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
mask: true,
|
||||
title: '文件已保存:' + red.savedFilePath, //保存路径
|
||||
duration: 3000,
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.openDocument({
|
||||
filePath: red.savedFilePath,
|
||||
success: ress => {},
|
||||
fail(err) {}
|
||||
});
|
||||
}, 500)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.icon-ym {
|
||||
font-size: 48rpx;
|
||||
}
|
||||
|
||||
.jnpf-file {
|
||||
width: 100%;
|
||||
|
||||
.jnpf-file-box {
|
||||
|
||||
.jnpf-file-box-line {
|
||||
height: 70rpx;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tipText {
|
||||
color: #606266;
|
||||
word-break: break-all;
|
||||
line-height: 48rpx;
|
||||
}
|
||||
|
||||
.jnpf-file-item {
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
|
||||
.jnpf-file-item-txt {
|
||||
width: 230rpx;
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
.showLeft {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.closeBox {
|
||||
height: 60rpx;
|
||||
align-items: flex-end;
|
||||
justify-content: space-evenly;
|
||||
flex: 0.2;
|
||||
|
||||
.closeTxt {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #fa3534;
|
||||
color: #FFFFFF;
|
||||
font-size: 20rpx;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
432
pages/workFlow/comment/comment-file/lsj-upload/LsjFile.js
Normal file
432
pages/workFlow/comment/comment-file/lsj-upload/LsjFile.js
Normal file
@@ -0,0 +1,432 @@
|
||||
export class LsjFile {
|
||||
constructor(data) {
|
||||
this.dom = null;
|
||||
// files.type = waiting(等待上传)|| loading(上传中)|| success(成功) || fail(失败)
|
||||
this.files = new Map();
|
||||
this.debug = data.debug || false;
|
||||
this.id = data.id;
|
||||
this.width = data.width;
|
||||
this.height = data.height;
|
||||
this.option = data.option;
|
||||
this.instantly = data.instantly;
|
||||
this.prohibited = data.prohibited;
|
||||
this.onchange = data.onchange;
|
||||
this.onprogress = data.onprogress;
|
||||
this.uploadHandle = this._uploadHandle;
|
||||
// #ifdef MP-WEIXIN
|
||||
this.uploadHandle = this._uploadHandleWX;
|
||||
// #endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建File节点
|
||||
* @param {string}path webview地址
|
||||
*/
|
||||
create(path) {
|
||||
if (!this.dom) {
|
||||
// #ifdef H5
|
||||
let dom = document.createElement('input');
|
||||
dom.type = 'file'
|
||||
dom.value = ''
|
||||
dom.style.height = this.height
|
||||
dom.style.width = this.width
|
||||
dom.style.position = 'absolute'
|
||||
dom.style.top = 0
|
||||
dom.style.left = 0
|
||||
dom.style.right = 0
|
||||
dom.style.bottom = 0
|
||||
dom.style.opacity = 0
|
||||
dom.style.zIndex = 900
|
||||
dom.accept = this.prohibited.accept;
|
||||
if (this.prohibited.multiple) {
|
||||
dom.multiple = 'multiple';
|
||||
}
|
||||
dom.onchange = event => {
|
||||
for (let file of event.target.files) {
|
||||
if (this.files.size >= this.prohibited.count) {
|
||||
this.toast(`最多可以上传${this.prohibited.count}个文件`);
|
||||
this.dom.value = '';
|
||||
break;
|
||||
}
|
||||
this.addFile(file);
|
||||
}
|
||||
|
||||
this._uploadAfter();
|
||||
|
||||
this.dom.value = '';
|
||||
};
|
||||
this.dom = dom;
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
let styles = {
|
||||
top: '-200px',
|
||||
left: 0,
|
||||
width: '1px',
|
||||
height: '200px',
|
||||
background: 'transparent'
|
||||
};
|
||||
let extras = {
|
||||
debug: this.debug,
|
||||
instantly: this.instantly,
|
||||
prohibited: this.prohibited,
|
||||
}
|
||||
this.dom = plus.webview.create(path, this.id, styles, extras);
|
||||
this.setData(this.option);
|
||||
this._overrideUrlLoading();
|
||||
// #endif
|
||||
return this.dom;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置上传参数
|
||||
* @param {object|string}name 上传参数,支持a.b 和 a[b]
|
||||
*/
|
||||
setData() {
|
||||
let [name, value = ''] = arguments;
|
||||
if (typeof name === 'object') {
|
||||
Object.assign(this.option, name);
|
||||
} else {
|
||||
this._setValue(this.option, name, value);
|
||||
}
|
||||
|
||||
this.debug && console.log(JSON.stringify(this.option));
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
this.dom.evalJS(`vm.setData('${JSON.stringify(this.option)}')`);
|
||||
// #endif
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传
|
||||
* @param {string}name 文件名称
|
||||
*/
|
||||
async upload(name = '') {
|
||||
if (!this.option.url) {
|
||||
throw Error('未设置上传地址');
|
||||
}
|
||||
|
||||
// #ifndef APP-PLUS
|
||||
if (name && this.files.has(name)) {
|
||||
await this.uploadHandle(this.files.get(name));
|
||||
} else {
|
||||
for (let item of this.files.values()) {
|
||||
if (item.type === 'waiting' || item.type === 'fail') {
|
||||
await this.uploadHandle(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
this.dom && this.dom.evalJS(`vm.upload('${name}')`);
|
||||
// #endif
|
||||
}
|
||||
|
||||
// 选择文件change
|
||||
addFile(file, isCallChange) {
|
||||
|
||||
let name = file.name;
|
||||
this.debug && console.log('文件名称', name, '大小', file.size);
|
||||
|
||||
if (file) {
|
||||
// 限制文件格式
|
||||
let path = '';
|
||||
let suffix = name.substring(name.lastIndexOf(".") + 1).toLowerCase();
|
||||
let formats = this.prohibited.formats.toLowerCase();
|
||||
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
path = URL.createObjectURL(file);
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
path = file.path;
|
||||
// #endif
|
||||
if (formats && !formats.includes(suffix)) {
|
||||
this.toast(`不支持上传${suffix.toUpperCase()}格式文件`);
|
||||
return false;
|
||||
}
|
||||
// 限制文件大小
|
||||
if (file.size > 1024 * 1024 * Math.abs(this.prohibited.size)) {
|
||||
this.toast(`文件大小超过${this.prohibited.size}MB`)
|
||||
return false;
|
||||
}
|
||||
this.files.set(file.name, {
|
||||
file,
|
||||
path,
|
||||
name: file.name,
|
||||
size: file.size,
|
||||
progress: 0,
|
||||
type: 'waiting'
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除文件
|
||||
* @param {string}name 不传name默认移除所有文件,传入name移除指定name的文件
|
||||
*/
|
||||
clear(name = '') {
|
||||
// #ifdef APP-PLUS
|
||||
this.dom && this.dom.evalJS(`vm.clear('${name}')`);
|
||||
// #endif
|
||||
|
||||
if (!name) {
|
||||
this.files.clear();
|
||||
} else {
|
||||
this.files.delete(name);
|
||||
}
|
||||
return this.onchange(this.files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提示框
|
||||
* @param {string}msg 轻提示内容
|
||||
*/
|
||||
toast(msg) {
|
||||
uni.showToast({
|
||||
title: msg,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信小程序选择文件
|
||||
* @param {number}count 可选择文件数量
|
||||
*/
|
||||
chooseMessageFile(type, count) {
|
||||
wx.chooseMessageFile({
|
||||
count: count,
|
||||
type: type,
|
||||
success: ({
|
||||
tempFiles
|
||||
}) => {
|
||||
for (let file of tempFiles) {
|
||||
this.addFile(file);
|
||||
}
|
||||
this._uploadAfter();
|
||||
},
|
||||
fail: () => {
|
||||
this.toast(`打开失败`);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
_copyObject(obj) {
|
||||
if (typeof obj !== "undefined") {
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
} else {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动根据字符串路径设置对象中的值 支持.和[]
|
||||
* @param {Object} dataObj 数据源
|
||||
* @param {String} name 支持a.b 和 a[b]
|
||||
* @param {String} value 值
|
||||
* setValue(dataObj, name, value);
|
||||
*/
|
||||
_setValue(dataObj, name, value) {
|
||||
// 通过正则表达式 查找路径数据
|
||||
let dataValue;
|
||||
if (typeof value === "object") {
|
||||
dataValue = this._copyObject(value);
|
||||
} else {
|
||||
dataValue = value;
|
||||
}
|
||||
let regExp = new RegExp("([\\w$]+)|\\[(:\\d)\\]", "g");
|
||||
const patten = name.match(regExp);
|
||||
// 遍历路径 逐级查找 最后一级用于直接赋值
|
||||
for (let i = 0; i < patten.length - 1; i++) {
|
||||
let keyName = patten[i];
|
||||
if (typeof dataObj[keyName] !== "object") dataObj[keyName] = {};
|
||||
dataObj = dataObj[keyName];
|
||||
}
|
||||
// 最后一级
|
||||
dataObj[patten[patten.length - 1]] = dataValue;
|
||||
this.debug && console.log('参数更新后', JSON.stringify(this.option));
|
||||
}
|
||||
|
||||
_uploadAfter() {
|
||||
this.onchange(this.files);
|
||||
setTimeout(() => {
|
||||
this.instantly && this.upload();
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
_overrideUrlLoading() {
|
||||
this.dom.overrideUrlLoading({
|
||||
mode: 'reject'
|
||||
}, e => {
|
||||
let {
|
||||
retype,
|
||||
item,
|
||||
files,
|
||||
end
|
||||
} = this._getRequest(
|
||||
e.url
|
||||
);
|
||||
let _this = this;
|
||||
switch (retype) {
|
||||
case 'updateOption':
|
||||
this.dom.evalJS(`vm.setData('${JSON.stringify(_this.option)}')`);
|
||||
break
|
||||
case 'change':
|
||||
try {
|
||||
_this.files = new Map([..._this.files, ...JSON.parse(unescape(files))]);
|
||||
} catch (e) {
|
||||
return console.error('出错了,请检查代码')
|
||||
}
|
||||
_this.onchange(_this.files);
|
||||
break
|
||||
case 'progress':
|
||||
try {
|
||||
item = JSON.parse(unescape(item));
|
||||
} catch (e) {
|
||||
return console.error('出错了,请检查代码')
|
||||
}
|
||||
_this._changeFilesItem(item, end);
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
_getRequest(url) {
|
||||
let theRequest = new Object()
|
||||
let index = url.indexOf('?')
|
||||
if (index != -1) {
|
||||
let str = url.substring(index + 1)
|
||||
let strs = str.split('&')
|
||||
for (let i = 0; i < strs.length; i++) {
|
||||
theRequest[strs[i].split('=')[0]] = unescape(strs[i].split('=')[1])
|
||||
}
|
||||
}
|
||||
return theRequest
|
||||
}
|
||||
|
||||
_changeFilesItem(item, end = false) {
|
||||
this.debug && console.log('onprogress', JSON.stringify(item));
|
||||
this.onprogress(item, end);
|
||||
this.files.set(item.name, item);
|
||||
}
|
||||
|
||||
_uploadHandle(item) {
|
||||
item.type = 'loading';
|
||||
delete item.responseText;
|
||||
return new Promise((resolve, reject) => {
|
||||
this.debug && console.log('option', JSON.stringify(this.option));
|
||||
let {
|
||||
url,
|
||||
name,
|
||||
method = 'POST',
|
||||
header,
|
||||
formData,
|
||||
data
|
||||
} = this.option;
|
||||
let form = new FormData();
|
||||
for (let keys in formData) {
|
||||
form.append(keys, formData[keys])
|
||||
}
|
||||
for (let keys in data) {
|
||||
form.append(keys, data[keys])
|
||||
}
|
||||
form.append(name, item.file);
|
||||
let xmlRequest = new XMLHttpRequest();
|
||||
xmlRequest.open(method, url, true);
|
||||
for (let keys in header) {
|
||||
xmlRequest.setRequestHeader(keys, header[keys])
|
||||
}
|
||||
|
||||
xmlRequest.upload.addEventListener(
|
||||
'progress',
|
||||
event => {
|
||||
if (event.lengthComputable) {
|
||||
let progress = Math.ceil((event.loaded * 100) / event.total)
|
||||
if (progress <= 100) {
|
||||
item.progress = progress;
|
||||
this._changeFilesItem(item);
|
||||
}
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
xmlRequest.ontimeout = () => {
|
||||
console.error('请求超时')
|
||||
item.type = 'fail';
|
||||
this._changeFilesItem(item, true);
|
||||
return resolve(false);
|
||||
}
|
||||
|
||||
xmlRequest.onreadystatechange = ev => {
|
||||
if (xmlRequest.readyState == 4) {
|
||||
if (xmlRequest.status == 200) {
|
||||
this.debug && console.log('上传完成:' + xmlRequest.responseText)
|
||||
item['responseText'] = xmlRequest.responseText;
|
||||
item.type = 'success';
|
||||
this._changeFilesItem(item, true);
|
||||
return resolve(true);
|
||||
} else if (xmlRequest.status == 0) {
|
||||
console.error(
|
||||
'status = 0 :请检查请求头Content-Type与服务端是否匹配,服务端已正确开启跨域,并且nginx未拦截阻止请求')
|
||||
}
|
||||
console.error('--ERROR--:status = ' + xmlRequest.status)
|
||||
item.type = 'fail';
|
||||
this._changeFilesItem(item, true);
|
||||
return resolve(false);
|
||||
}
|
||||
}
|
||||
xmlRequest.send(form)
|
||||
});
|
||||
}
|
||||
|
||||
_uploadHandleWX(item) {
|
||||
item.type = 'loading';
|
||||
delete item.responseText;
|
||||
return new Promise((resolve, reject) => {
|
||||
this.debug && console.log('option', JSON.stringify(this.option));
|
||||
let form = {
|
||||
filePath: item.file.path,
|
||||
...this.option,
|
||||
formData: this.option.data || {},
|
||||
};
|
||||
form['fail'] = ({
|
||||
errMsg = ''
|
||||
}) => {
|
||||
console.error('--ERROR--:' + errMsg)
|
||||
item.type = 'fail';
|
||||
this._changeFilesItem(item, true);
|
||||
return resolve(false);
|
||||
}
|
||||
form['success'] = res => {
|
||||
if (res.statusCode == 200) {
|
||||
this.debug && console.log('上传完成,微信端返回不一定是字符串,根据接口返回格式判断是否需要JSON.parse:' + res.data)
|
||||
item['responseText'] = res.data;
|
||||
item.type = 'success';
|
||||
this._changeFilesItem(item, true);
|
||||
return resolve(true);
|
||||
}
|
||||
item.type = 'fail';
|
||||
this._changeFilesItem(item, true);
|
||||
return resolve(false);
|
||||
}
|
||||
|
||||
let xmlRequest = uni.uploadFile(form);
|
||||
xmlRequest.onProgressUpdate(({
|
||||
progress = 0
|
||||
}) => {
|
||||
if (progress <= 100) {
|
||||
item.progress = progress;
|
||||
this._changeFilesItem(item);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
399
pages/workFlow/comment/comment-file/lsj-upload/lsj-upload.vue
Normal file
399
pages/workFlow/comment/comment-file/lsj-upload/lsj-upload.vue
Normal file
@@ -0,0 +1,399 @@
|
||||
<template>
|
||||
<view class="lsj-file" :style="[getStyles]">
|
||||
<view ref="lsj" class="hFile" :style="[getStyles]" @click="onClick">
|
||||
<slot>
|
||||
<view class="defview" :style="[getStyles]">附件上传</view>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 查看文档:https://ext.dcloud.net.cn/plugin?id=5459
|
||||
import {
|
||||
LsjFile
|
||||
} from './LsjFile.js'
|
||||
export default {
|
||||
name: 'comment-Lsj-upload',
|
||||
props: {
|
||||
currentCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
// 打印日志
|
||||
debug: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 自动上传
|
||||
instantly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 上传接口参数设置
|
||||
option: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
// 文件大小上限
|
||||
size: {
|
||||
type: Number,
|
||||
default: 10
|
||||
},
|
||||
// 文件选择个数上限,超出后不触发点击
|
||||
count: {
|
||||
type: Number,
|
||||
default: 2000
|
||||
},
|
||||
// 是否允许多选文件
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 允许上传的文件格式(多个以逗号隔开)
|
||||
formats: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// input file选择限制
|
||||
accept: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 微信选择文件类型
|
||||
//all=从所有文件选择,
|
||||
//video=只能选择视频文件,
|
||||
//image=只能选择图片文件,
|
||||
//file=可以选择除了图片和视频之外的其它的文件
|
||||
wxFileType: {
|
||||
type: String,
|
||||
default: 'all'
|
||||
},
|
||||
// webviewID需唯一,不同窗口也不要同Id
|
||||
childId: {
|
||||
type: String,
|
||||
default: 'lsjUpload'
|
||||
},
|
||||
// 文件选择触发面宽度
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%'
|
||||
},
|
||||
// 文件选择触发面高度
|
||||
height: {
|
||||
type: String,
|
||||
default: '80rpx'
|
||||
},
|
||||
|
||||
// top,left,bottom,right仅position=absolute时才需要传入
|
||||
top: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
left: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
bottom: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
right: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// nvue不支持跟随窗口滚动
|
||||
position: {
|
||||
type: String,
|
||||
// #ifdef APP-NVUE
|
||||
default: 'absolute',
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
default: 'static',
|
||||
// #endif
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
option(v) {
|
||||
// #ifdef APP-PLUS
|
||||
this.lsjFile && this.show();
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
updated() {
|
||||
// #ifdef APP-PLUS
|
||||
if (this.isShow) {
|
||||
this.lsjFile && this.show();
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
computed: {
|
||||
getStyles() {
|
||||
let styles = {
|
||||
width: this.width,
|
||||
height: this.height
|
||||
}
|
||||
if (this.position == 'absolute') {
|
||||
styles['top'] = this.top
|
||||
styles['bottom'] = this.bottom
|
||||
styles['left'] = this.left
|
||||
styles['right'] = this.right
|
||||
styles['position'] = 'fixed'
|
||||
}
|
||||
|
||||
return styles
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this._size = 0;
|
||||
let WEBID = this.childId + new Date().getTime();
|
||||
this.lsjFile = new LsjFile({
|
||||
id: WEBID,
|
||||
debug: this.debug,
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
option: this.option,
|
||||
instantly: this.instantly,
|
||||
// 限制条件
|
||||
prohibited: {
|
||||
// 大小
|
||||
size: this.size,
|
||||
// 允许上传的格式
|
||||
formats: this.formats,
|
||||
// 限制选择的格式
|
||||
accept: this.accept,
|
||||
count: this.count,
|
||||
// 是否多选
|
||||
multiple: this.multiple,
|
||||
},
|
||||
onchange: this.onchange,
|
||||
onprogress: this.onprogress,
|
||||
});
|
||||
this.create();
|
||||
// 需判断是否当前页显示
|
||||
uni.$on('lsjShow', this.show);
|
||||
},
|
||||
beforeDestroy() {
|
||||
uni.$off('lsjShow', this.show);
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
this.lsjFile.dom.close();
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
setFiles(array) {
|
||||
if (array instanceof Map) {
|
||||
for (let [key, item] of array) {
|
||||
item['progress'] = 100;
|
||||
item['type'] = 'success';
|
||||
this.lsjFile.files.set(key, item);
|
||||
}
|
||||
} else if (Array.isArray(array)) {
|
||||
array.forEach(item => {
|
||||
if (item.name) {
|
||||
item['progress'] = 100;
|
||||
item['type'] = 'success';
|
||||
this.lsjFile.files.set(item.name, item);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.onchange(this.lsjFile.files);
|
||||
},
|
||||
setData() {
|
||||
this.lsjFile && this.lsjFile.setData(...arguments);
|
||||
},
|
||||
getDomStyles(callback) {
|
||||
// #ifndef APP-NVUE
|
||||
let view = uni
|
||||
.createSelectorQuery()
|
||||
.in(this)
|
||||
.select('.lsj-file')
|
||||
view.fields({
|
||||
size: true,
|
||||
rect: true
|
||||
},
|
||||
({
|
||||
height,
|
||||
width,
|
||||
top,
|
||||
left,
|
||||
right,
|
||||
bottom
|
||||
}) => {
|
||||
uni.createSelectorQuery()
|
||||
.selectViewport()
|
||||
.scrollOffset(({
|
||||
scrollTop
|
||||
}) => {
|
||||
return callback({
|
||||
top: parseInt(top) + parseInt(scrollTop) + 'px',
|
||||
left: parseInt(left) + 'px',
|
||||
width: parseInt(width) + 'px',
|
||||
height: parseInt(height) + 'px'
|
||||
})
|
||||
})
|
||||
.exec()
|
||||
}
|
||||
).exec()
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
const dom = weex.requireModule('dom')
|
||||
dom.getComponentRect(this.$refs.lsj, ({
|
||||
size: {
|
||||
height,
|
||||
width,
|
||||
top,
|
||||
left,
|
||||
right,
|
||||
bottom
|
||||
}
|
||||
}) => {
|
||||
return callback({
|
||||
top: parseInt(top) + 'px',
|
||||
left: parseInt(left) + 'px',
|
||||
width: parseInt(width) + 'px',
|
||||
height: parseInt(height) + 'px',
|
||||
right: parseInt(right) + 'px',
|
||||
bottom: parseInt(bottom) + 'px'
|
||||
})
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
show() {
|
||||
if (this._size && (this._size >= this.count)) {
|
||||
return;
|
||||
}
|
||||
this.isShow = true;
|
||||
// #ifdef APP-PLUS
|
||||
this.lsjFile && this.getDomStyles(styles => {
|
||||
this.lsjFile.dom.setStyle(styles)
|
||||
});
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
this.lsjFile.dom.style.display = 'inline'
|
||||
// #endif
|
||||
},
|
||||
hide() {
|
||||
this.isShow = false;
|
||||
// #ifdef APP-PLUS
|
||||
this.lsjFile && this.lsjFile.dom.setStyle({
|
||||
top: '-100px',
|
||||
left: '0px',
|
||||
width: '1px',
|
||||
height: '100px',
|
||||
});
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
this.lsjFile.dom.style.display = 'none'
|
||||
// #endif
|
||||
},
|
||||
/**
|
||||
* 手动提交上传
|
||||
* @param {string}name 文件名称,不传则上传所有type等于waiting和fail的文件
|
||||
*/
|
||||
upload(name) {
|
||||
this.lsjFile && this.lsjFile.upload(name);
|
||||
},
|
||||
/**
|
||||
* @returns {Map} 已选择的文件Map集
|
||||
*/
|
||||
onchange(files) {
|
||||
// this.$emit('change',files);
|
||||
this._size = files.size;
|
||||
return files.size >= this.count ? this.hide() : this.show();
|
||||
},
|
||||
/**
|
||||
* @returns {object} 当前上传中的对象
|
||||
*/
|
||||
onprogress(item, end = false) {
|
||||
this.$emit('progress', item);
|
||||
if (end) {
|
||||
setTimeout(() => {
|
||||
this.$emit('uploadEnd', item);
|
||||
}, 0);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 移除组件内缓存的某条数据
|
||||
* @param {string}name 文件名称,不指定默认清除所有文件
|
||||
*/
|
||||
clear(name) {
|
||||
this.lsjFile.clear(name);
|
||||
},
|
||||
// 创建选择器
|
||||
create() {
|
||||
// 若iOS端服务端处理不了跨域就将hybrid目录内的html放到服务端去,并将此处path改成服务器上的地址
|
||||
let path = '/uni_modules/lsj-upload/hybrid/html/uploadFile.html?sourceflag=comment';
|
||||
let dom = this.lsjFile.create(path);
|
||||
// #ifdef H5
|
||||
this.$refs.lsj.$el.appendChild(dom);
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
this.show();
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
dom.setStyle({
|
||||
position: this.position
|
||||
});
|
||||
dom.loadURL(path);
|
||||
setTimeout(() => {
|
||||
// #ifdef APP-NVUE
|
||||
plus.webview.currentWebview().append(dom);
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
this.$root.$scope.$getAppWebview().append(dom);
|
||||
// #endif
|
||||
this.show();
|
||||
}, 300)
|
||||
// #endif
|
||||
},
|
||||
// 点击选择附件
|
||||
onClick() {
|
||||
/*if (this.currentCount >= 9) {
|
||||
this.toast(`最多可以上传9个文件`);
|
||||
return;
|
||||
}*/
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
if (!this.isShow) {
|
||||
return;
|
||||
}
|
||||
let count = this.count - this._size;
|
||||
this.lsjFile.chooseMessageFile(this.wxFileType, count);
|
||||
// #endif
|
||||
},
|
||||
toast(msg) {
|
||||
uni.showToast({
|
||||
title: msg,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.lsj-file {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.defview {
|
||||
background-color: #007aff;
|
||||
color: #fff;
|
||||
border-radius: 10rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.hFile {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user