1
0
forked from dyf/APP

合并线上代码

This commit is contained in:
liub
2025-11-07 12:16:10 +08:00
parent 2493bb7113
commit 623a47466a
41 changed files with 5293 additions and 119 deletions

View File

@ -0,0 +1,285 @@
<!-- eslint-disable -->
<template>
<view>
<!-- #ifdef APP-PLUS -->
<view class="xe-upload" v-html="renderInput" :props="mergeProps" :change:props="XeUpload.renderProps"></view>
<!-- #endif -->
</view>
</template>
<script>
import {
chooseMedia,
chooseFile,
chooseMessageFile,
uploadFile,
} from '../../tools/apis';
import {
deepMerge,
awaitWrap,
base64ToPath,
isArray,
} from '../../tools/tools';
export default {
name: 'XeUpload',
props: {
options: {
default: () => ({}),
type: Object,
},
},
data() {
return {
id: 0, // APP上传框ID
renderInput: '', // APP上传框
};
},
computed: {
mergeOptions({ options = {} }) {
const tmpOptions = {
name: 'file',
};
return deepMerge(tmpOptions, options);
},
mergeProps({ id, renderInput, mergeOptions }) {
return {
id,
renderInput,
upload: mergeOptions,
};
},
},
methods: {
// 上传事件
async upload(type, config = {}) {
let tmpResult = [];
if (['image', 'video'].includes(type)) {
const [err, res] = await chooseMedia(type, config);
if (err) return this.handleError(err);
tmpResult = res?.tempFiles || [];
}
// H5 || APP-PLUS || MP-WEIXIN
if (['file'].includes(type)) {
let tmpFiles = {};
let tmpErr = null;
// #ifdef H5
[tmpErr, tmpFiles] = await chooseFile(config);
// #endif
// #ifdef MP-WEIXIN
[tmpErr, tmpFiles] = await chooseMessageFile(config);
// #endif
// #ifdef APP-PLUS
this.id = Math.floor(Math.random() * 100000000 + 1);
this.initInput(config.extension);
// #endif
if (tmpErr) return this.handleError(tmpErr);
tmpResult = tmpFiles?.tempFiles || [];
}
this.handleUpload(tmpResult);
},
// 初始化上传框
initInput(extension) {
const { id } = this;
let accept = extension;
if (isArray(extension)) {
accept = extension.join(',');
}
this.renderInput = `<input type="file" id="xe-upload-${id}" name="xe-upload" ${accept ? 'accept="' + accept + '"' : ''} />`;
},
// 文件上传没有传入上传url时返回本地链接
async handleUpload(files = []) {
if (files.filter((e) => Boolean(e)).length === 0) return;
const { mergeOptions } = this;
if (!mergeOptions.url) {
return this.handleEmits({
type: 'choose',
data: files,
});
}
const tmpUploads = files.map((e) =>
uploadFile(
{
...mergeOptions,
filePath: e.tempFilePath,
},
e,
)
);
const [err, res] = await awaitWrap(Promise.all(tmpUploads));
if (err) return this.handleError(err);
this.handleEmits({
type: 'success',
data: res,
});
},
// 处理失败事件
handleError(error) {
this.handleEmits({
type: 'warning',
data: error,
});
},
// 处理响应事件
async handleEmits(e) {
// #ifdef APP-PLUS
if (e.type === 'choose') {
// 将base64转为本地链接
for (let i = 0; i < e.data.length; i += 1) {
const item = e.data[i];
if (!item.base64Url) {
continue;
}
const [parseError, parseUrl] = await awaitWrap(base64ToPath(item.base64Url, item.name));
if (!parseError) {
e.data[i].tempFilePath = parseUrl;
} else {
e.data[i].tempFilePath = item.base64Url;
}
delete e.data[i].base64Url;
}
}
// #endif
this.$emit('callback', e);
},
},
};
</script>
<!-- #ifdef APP-PLUS -->
<script module="XeUpload" lang="renderjs">
import {
appUploadFile,
} from '../../tools/apis';
import {
awaitWrap,
fileToBase64,
} from '../../tools/tools';
export default {
data() {
return {
id: 0, // 上传框ID
uploadOptions: {}, // 上传配置
};
},
methods: {
// 处理 XeUpload 传入 renderjs 数据,以及调起上传框
renderProps(info) {
const { id, renderInput, upload } = info;
if (!renderInput) return;
this.id = id;
this.uploadOptions = upload;
this.$nextTick(() => {
const dom = document.getElementById(`xe-upload-${id}`);
dom.addEventListener('change', () => {
this.handleUpload();
});
dom?.click?.();
});
},
// 处理文件上传(没有传入url时返回本地链接)
async handleUpload() {
const {
url,
name,
header = {},
formData = {},
} = this.uploadOptions || {};
const dom = document.getElementById(`xe-upload-${this.id}`);
if (!dom.files[0]) return;
const tmpFileList = Array.from(dom.files);
const tmpUploads = [];
for (let i = 0; i < tmpFileList.length; i += 1) {
const e = tmpFileList[i];
let tmpType = 'file';
if (e.type.includes('image')) {
tmpType = 'image';
}
if (e.type.includes('video')) {
tmpType = 'video';
}
const tmpExts = {
size: e.size,
name: e.name,
type: e.type,
fileType: tmpType,
tempFilePath: '',
base64Url: '',
};
// 没有传入上传url时直接返回本地链接
if (!url) {
const [parseError, parseUrl] = await awaitWrap(fileToBase64(dom.files[i]));
if (!parseError) {
tmpExts.base64Url = parseUrl;
}
tmpUploads.push(tmpExts);
continue;
};
const tmpData = new FormData();
tmpData.append(name, dom.files[i], e.name);
for (let key in formData) {
tmpData.append(key, formData[key]);
}
// 上传进度
const onprogress = (ev) => {
if(ev.lengthComputable) {
var result = (ev.loaded / ev.total) * 100;
this.handleRenderEmits({
type: 'onprogress',
data: {
progress: Math.floor(result),
current: i + 1,
total: tmpFileList.length,
},
});
};
}
tmpUploads.push(appUploadFile({
url,
header,
formData: tmpData
}, tmpExts, onprogress ));
}
// 没有传入上传url时直接返回本地链接列表
if (!url) {
return this.handleRenderEmits({
type: 'choose',
data: tmpUploads,
});
}
this.handleRenderEmits({
type: 'onprogress',
data: {
progress: 0,
current: 1,
total: tmpFileList.length,
},
});
// 处理上传文件
const [err, res] = await awaitWrap(Promise.all(tmpUploads));
if (err) {
return this.handleRenderEmits({
type: 'warning',
data: err,
});
}
this.handleRenderEmits({
type: 'success',
data: res,
});
},
// 数据传输到XeUpload组件
handleRenderEmits(data) {
this.$ownerInstance.callMethod('handleEmits', data);
},
},
};
</script>
<!-- #endif -->
<style scoped>
.xe-upload {
display: none;
}
</style>