UNPKG

@cataract6545/tmui

Version:

tm-vuetify是一个新势力由主题驱动的UI组件库,相比其它优势大,组件全,设计趋势紧跟未来。具有主题生成,主题实时切换,暗黑实时切换,lottie动画,图表等新颖功能,tmui TMUI

399 lines (370 loc) 11.8 kB
//文件上传的状态值 export enum statusCode { //待上传 upload = 0, //上传中 uploading = 1, //上传失败 fail = 2, //上传成功 success = 3, //超过大小限制 max = 4, } //文件对象结构 export interface file { url: string,//当前显示的图片地址,这是个本地临时地址。待上传前,成功后会替换服务器地址。 status?: string,//上传状态文本 progress?: number,//当前文件上传的进度 uid?: string | number,//文件唯一标识id statusCode?: statusCode,//文件状态 response?: any,//上传成功后的回调数据。 name?: string,//文件名称 [propName: string]: any } //上传class对象的配置。 export interface fileConfig { maxSize?: number,//每一个文件上传的最大尺寸,默认为10mb maxFile?: number,//一次选择文件最大数量。 fileType?: Array<string>,//文件选择的类型。 hostUrl?: string,//上传文件的服务器地址 fileList?: Array<file>,//已上传的文件列表。 autoUpload?: Boolean, header?: Object,//头部参数。 formData?: Object,//额外的表单数据。 formName?: string, statusCode?: number,//服务返回成功的状态码标志,默认200表示成功。 } export function getUid(length = 3) { return Number(Number(Math.random().toString().substr(3, length) + Date.now()).toString(8)); } /** * 上传文件。 * 作者:tmzdy * 时间:2022年4月27日 * 联系:zhongjihan@sina.com * @method {Function} beforeChooesefile -- 选择图片上传前执行的勾子。 * @method {Function} chooesefile -- 选择图片上传,弹出层进行选择文件 。 * @method {Function} chooesefileAfter -- 选择图片、视频文件成功后触发。返回选择后的文件。此时还未加入待上传列表,会返回 一个文件列表用于过滤。需要在函数中再返回 一个文件 列表, * @method {Function} chooesefileSuccess -- 文件已经加入到了待上传文件列表,需要返回过滤的文件列表 * @method {Function} beforeAddfile -- 动态加入预计加入文件前执行的勾子,返回true才会正式加入到待上传列表中。 * @method {Function} addFile -- 动态加入预上传的文件。 * @method {Function} progress -- 进度。 * @method {Function} fail -- 失败。服务器出现非200时触发。 * @method {Function} beforeSuccess -- 服务器返回成功,立即执行的勾子。如果此时返回false,则表示文件 上传失败。 * @method {Function} success -- 成功。 * @method {Function} complete -- 单个文件完成。不管上传成功与失败否,都会触发此函数。 * @method {Function} uploadComplete -- 所有文件上传完时触发 * @method {Function} beforeStart -- 开始上传。前的校验勾子。如果返回false,将阻止上传 * @method {Function} start -- 开始上传。 * @method {Function} stop -- 停止上传。中止上传时触发的函数。 */ export class uploadfile { //文件列表。 filelist: Array<file> = []; isStop = false; index = 0; config: fileConfig = {}; uploadobj: UniNamespace.UploadTask | null = null; constructor(config: fileConfig) { let cf: fileConfig = { maxSize: 10 * 1024 * 1024, maxFile: 9, fileType: ['album', 'camera'], fileList: [], autoUpload: true, header: {}, formData: {}, formName: 'file' } cf = { ...cf, ...arguments[0] ?? {} }; //配置{name: 'file', // 上传时的文件key名。默认file,header: {}, // 上传的头部参数。} this.config = cf; this.addFile(cf.fileList); delete this.config.fileList; } async beforeChooesefile() { return true; } async chooesefileAfter(fileList: Array<file>) { return fileList; } async chooesefileSuccess(fileList: Array<file>) { return fileList; } delete(item: file) { let index = this.filelist.findIndex(el => el.uid == item.uid); if (index > -1) { let p = [...this.filelist] p.splice(index, 1) this.filelist = [...p]; } return this.filelist; } async clear() { /** 清清前要选暂停所有正在上传的文件 */ this.stop(); this.filelist = []; } setFileStatus(item: file) { let index = this.filelist.findIndex(el => el.uid == item.uid); if (index > -1) { let p = [...this.filelist] p.splice(index, 1, item) this.filelist = [...p]; } } /** * 成功后返回选择后的图片列表。 */ async chooesefile(): Promise<Array<file>> { let t = this; return new Promise(async (rs, rj) => { let isready = await t.beforeChooesefile(); if (!isready) { rs([]) return; } uni.chooseImage({ count: t.config.maxFile, sourceType: t.config.fileType, fail: (e) => { rj("取消选择"); }, success: async (res) => { if (res.tempFilePaths.length == 0) { rj("未选择") return; } let imgarray = res.tempFilePaths; let fielist = res.tempFiles; let jgsk: Array<file> = []; //0待上传,1上传中,2上传失败,3上传成功。4超过大小限制 imgarray.forEach((item: string, index: number) => { let isMaxsize = fielist[index].size > t.config.maxSize ? true : false; jgsk.push({ url: item, status: isMaxsize ? '超过大小' : "待上传", progress: isMaxsize ? 100 : 0, uid: getUid(), statusCode: isMaxsize ? statusCode.max : statusCode.upload, response: null, name: fielist[index].name ?? "" }) }) let isreadyChoose = await t.chooesefileAfter(jgsk); if (!Array.isArray(isreadyChoose) || typeof isreadyChoose != 'object') { rj("chooesefileAfter:函数过滤,没有返回文件列表。") return; } t.filelist.push(...isreadyChoose) t.chooesefileSuccess(isreadyChoose); rs(isreadyChoose) if (t.config.autoUpload) { setTimeout(function () { t.start(); }, 500); } } }) }) } async chooseMPH5weixinFile() { let t = this; return new Promise((rs, rj) => { var fs = uni.chooseFile; // #ifdef MP-WEIXIN || MP-QQ fs = uni.chooseMessageFile; // #endif var config = { count: t.config.maxfile, type: t.config.type, extension: t.config.extension, } if (!t.config.extension || !Array.isArray(t.config.extension) || t.config.extension?.length == 0) { delete config.extension } fs({ ...config, fail: (e) => { console.error(e); uni.$tm.toast("已取消选择"); rj(e); }, success: (res) => { if (res.tempFiles.length == 0) { uni.$tm.toast("未选择"); return; } let fielist = res.tempFiles; let jgsk = []; //0待上传,1上传中,2上传失败,3上传成功。4超过大小限制 fielist.forEach((item, index) => { let isMaxsize = fielist[index].size > t.config.maxsize ? true : false; let ftype = item.name || "" if (ftype) { ftype = ftype.substr(ftype.lastIndexOf(".") + 1).toLocaleLowerCase(); } jgsk.push({ url: item.path, name: item.name || '默认文件名称', type: ftype, status: isMaxsize ? '超过大小' : "待上传", progress: isMaxsize ? 100 : 0, fileId: guid(), statusCode: isMaxsize ? 4 : 0, data: null,//上传成功后的回调数据。 }) }) t.filelist.push(...jgsk) t.selected(t.filelist); if (t.config.isAuto) { t.start(); } rs(t.filelist) } }) }) } setConfig(config: fileConfig) { this.config = { ...this.config, ...config ?? {} } } /** * 动态加入文件 * @param {Object} filelist */ addFile(filelist: Array<file> = []) { if (typeof filelist !== 'object' && !Array.isArray(filelist)) return; let total_uid = new Set(this.filelist.map(e => e.uid)) let total_url = new Set(this.filelist.map(e => e.url)) let cfilelist = filelist.map(el => { return { ...el, status: el?.status ?? "待上传", statusCode: el?.statusCode ?? statusCode.upload, uid: el?.uid ?? getUid(), progress: el?.progress ?? 0, name: el?.name ?? "", response: el?.response ?? null, url: el?.url ?? "" } }) let filterFIle = cfilelist.filter(item => !total_uid.has(item.uid) && !total_url.has(item.url)) this.filelist.push(...filterFIle) } beforeSuccess(item: file) { return Promise.resolve(true); } beforeStart(item: file) { return Promise.resolve(true); } // 进度。 progress(item: file,index:number) { } // 失败 fail(item: file) { } // 成功 success(item: file, fileList: Array<file>) { } // 完成。 complete(filelist: file) { } uploadComplete(filelist: Array<file>) { } awaitTime() { return new Promise((resolve) => { setTimeout(() => { resolve(true) }, 20) }) } // 开始上传。 async start() { if (this.filelist.length <= 0) { console.error("未选择图片,已取消上传") return; } let t = this; // t重新开始上传从头开始。 this.index = 0; this.isStop = false; async function startupload() { if (t.isStop) return; let item = t.filelist[t.index]; if (!item || typeof item === 'undefined') { // 文件不存在。直接结束。 t.uploadComplete(t.filelist); return; } let canbleStart = await t.beforeStart(item) if (!canbleStart) { item.statusCode = statusCode.fail; item.status = "不允许上传" t.filelist.splice(t.index, 1, item) t.index++; t.setFileStatus(item) t.fail(item) t.complete(item); startupload(); return; } if (item.statusCode == 3 || item.statusCode == 1 || item.statusCode == 4 || item.statusCode == 2) { // 直接跳过。至下一个文件。 t.index++; startupload(); return; } item.statusCode = statusCode.uploading; item.status = "上传中..." t.setFileStatus(item) const upObj = t.uploadobj = uni.uploadFile({ url: String(t.config.hostUrl), name: t.config?.formName ?? 'file', header: t.config?.header ?? {}, filePath: item.url, formData: { name: item.name, ...t.config.formData }, success: async (res) => { if (t.isStop) return item.response = res.data; let isOksuccess = await t.beforeSuccess(item); const statusCode_reonese = t.config?.statusCode ?? 200 if (res.statusCode != statusCode_reonese || !isOksuccess) { item.statusCode = statusCode.fail; item.status = "上传失败"; t.fail(item) t.setFileStatus(item) t.index++; return; } // 上传成功。 item.statusCode = statusCode.success; item.status = "上传成功"; t.setFileStatus(item) t.success(item, t.filelist) t.index++; }, fail: (res) => { if (t.isStop) return item.statusCode = statusCode.fail; item.status = "上传失败"; t.setFileStatus(item) t.fail(item) t.index++; }, complete: async (res) => { if (t.isStop) return await t.awaitTime(); t.complete(item); // 直接下一个文件。 startupload(); } }) if (upObj) { let item = t.filelist[t.index]; upObj.onProgressUpdate(async (res) => { if (t.isStop) return item.progress = res.progress; item.statusCode = statusCode.uploading; item.status = "..."; t.setFileStatus(item) t.progress(item,t.index) }) } } await startupload(); } // 停止上传 stop() { this.isStop = true; if (this.uploadobj != null) { this.uploadobj.abort() } } }