UNPKG

nutui-taro-upgrade

Version:

@nutui/nutui-taro 对京东风格组件库的taro4 版本支持

646 lines (645 loc) 23.4 kB
var __defProp = Object.defineProperty; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __publicField = (obj, key, value) => { __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); return value; }; import { toRef, ref, watch, reactive, resolveComponent, openBlock, createElementBlock, renderSlot, createTextVNode, createBlock, createCommentVNode, Fragment, renderList, normalizeClass, createElementVNode, toDisplayString, createVNode, withModifiers } from "vue"; import { c as createComponent } from "../component-669c158a.js"; import { f as funInterceptor } from "../Interceptor-14c4e574.js"; import { Progress as _sfc_main$1 } from "../progress/Progress.js"; import { Button as _sfc_main$2 } from "../button/Button.js"; import Taro from "@tarojs/taro"; import { Photograph, Failure, Loading, Del, Link } from "@nutui/icons-vue-taro"; import { u as useLocale } from "../index-3b6ff56c.js"; import { u as useFormDisabled } from "../common-47b33c3f.js"; import { _ as _export_sfc } from "../_plugin-vue_export-helper-cc2b3d55.js"; import "../util-f26975e1.js"; import "../with-install-783bc31f.js"; import "nutui-taro-upgrade/dist/packages/locale/lang"; import "../useParent-db66af63.js"; class UploadOptions { constructor() { __publicField(this, "url", ""); __publicField(this, "name", "file"); __publicField(this, "fileType", "image"); __publicField(this, "formData"); __publicField(this, "sourceFile"); __publicField(this, "method", "post"); __publicField(this, "xhrState", 200); __publicField(this, "timeout", 30 * 1e3); __publicField(this, "headers", {}); __publicField(this, "withCredentials", false); __publicField(this, "onStart"); __publicField(this, "taroFilePath"); __publicField(this, "onProgress"); __publicField(this, "onSuccess"); __publicField(this, "onFailure"); __publicField(this, "beforeXhrUpload"); } } class Uploader { constructor(options) { __publicField(this, "options"); this.options = options; } upload() { var _a; const options = this.options; const xhr = new XMLHttpRequest(); xhr.timeout = options.timeout; if (xhr.upload) { xhr.upload.addEventListener( "progress", (e) => { var _a2; (_a2 = options.onProgress) == null ? void 0 : _a2.call(options, e, options); }, false ); xhr.onreadystatechange = () => { var _a2, _b; if (xhr.readyState === 4) { if (xhr.status == options.xhrState) { (_a2 = options.onSuccess) == null ? void 0 : _a2.call(options, xhr.responseText, options); } else { (_b = options.onFailure) == null ? void 0 : _b.call(options, xhr.responseText, options); } } }; xhr.withCredentials = options.withCredentials; xhr.open(options.method, options.url, true); for (const [key, value] of Object.entries(options.headers)) { xhr.setRequestHeader(key, value); } (_a = options.onStart) == null ? void 0 : _a.call(options, options); if (options.beforeXhrUpload) { options.beforeXhrUpload(xhr, options); } else { xhr.send(options.formData); } } else { console.warn("浏览器不支持 XMLHttpRequest"); } } } class UploaderTaro extends Uploader { constructor(options) { super(options); } uploadTaro(uploadFile, env) { var _a; const options = this.options; if (env === "WEB") { this.upload(); } else { if (options.beforeXhrUpload) { options.beforeXhrUpload(uploadFile, options); } else { const uploadTask = uploadFile({ url: options.url, filePath: options.taroFilePath, fileType: options.fileType, header: __spreadValues({ "Content-Type": "multipart/form-data" }, options.headers), // formData: options.formData, name: options.name, success(response) { var _a2, _b; if (options.xhrState == response.statusCode) { (_a2 = options.onSuccess) == null ? void 0 : _a2.call(options, response, options); } else { (_b = options.onFailure) == null ? void 0 : _b.call(options, response, options); } }, fail(e) { var _a2; (_a2 = options.onFailure) == null ? void 0 : _a2.call(options, e, options); } }); (_a = options.onStart) == null ? void 0 : _a.call(options, options); uploadTask.progress((res) => { var _a2; (_a2 = options.onProgress) == null ? void 0 : _a2.call(options, res, options); }); } } } } class FileItem { constructor() { __publicField(this, "status", "ready"); __publicField(this, "message", ""); __publicField(this, "uid", (/* @__PURE__ */ new Date()).getTime().toString()); __publicField(this, "name"); __publicField(this, "url"); __publicField(this, "type"); __publicField(this, "path"); __publicField(this, "percentage", 0); __publicField(this, "formData", {}); } } const { create } = createComponent("uploader"); const cN = "NutUploader"; const _sfc_main = create({ components: { NutProgress: _sfc_main$1, NutButton: _sfc_main$2, Photograph, Failure, Loading, Del, Link }, props: { name: { type: String, default: "file" }, url: { type: String, default: "" }, sizeType: { type: Array, default: () => ["original", "compressed"] }, sourceType: { type: Array, default: () => ["album", "camera"] }, mediaType: { type: Array, default: () => ["image", "video", "mix"] }, camera: { type: String, default: "back" }, timeout: { type: [Number, String], default: 1e3 * 30 }, // defaultFileList: { type: Array, default: () => new Array<FileItem>() }, fileList: { type: Array, default: () => [] }, isPreview: { type: Boolean, default: true }, // picture、list listType: { type: String, default: "picture" }, isDeletable: { type: Boolean, default: true }, method: { type: String, default: "post" }, capture: { type: Boolean, default: false }, maximize: { type: [Number, String], default: Number.MAX_VALUE }, maximum: { type: [Number, String], default: 9 }, clearInput: { type: Boolean, default: true }, accept: { type: String, default: "*" }, headers: { type: Object, default: {} }, data: { type: Object, default: {} }, xhrState: { type: [Number, String], default: 200 }, multiple: { type: Boolean, default: true }, disabled: { type: Boolean, default: false }, autoUpload: { type: Boolean, default: true }, maxDuration: { type: Number, default: 10 }, beforeUpload: { type: Function, default: null }, beforeXhrUpload: { type: Function, default: null }, beforeDelete: { type: Function, default: () => { return true; } }, onChange: { type: Function }, mode: { type: String, default: "aspectFit" } }, emits: [ "start", "progress", "oversize", "success", "failure", "change", "delete", "update:fileList", "fileItemClick" ], setup(props, { emit }) { const disabled = useFormDisabled(toRef(props, "disabled")); const translate = useLocale(cN); const fileList = ref(props.fileList); const uploadQueue = ref([]); watch( () => props.fileList, () => { fileList.value = props.fileList; } ); const chooseImage = () => { if (disabled.value) { return; } if (Taro.getEnv() == "WEB") { let el = document.getElementById("taroChooseImage"); if (el) { el == null ? void 0 : el.setAttribute("accept", props.accept); } else { const obj = document.createElement("input"); obj.setAttribute("type", "file"); obj.setAttribute("id", "taroChooseImage"); obj.setAttribute("accept", props.accept); obj.setAttribute("style", "position: fixed; top: -4000px; left: -3000px; z-index: -300;"); document.body.appendChild(obj); } } if (Taro.getEnv() == "WEAPP") { Taro.chooseMedia({ /** 最多可以选择的文件个数 */ count: props.multiple ? Number(props.maximum) - fileList.value.length : 1, /** 文件类型 */ mediaType: props.mediaType, /** 图片和视频选择的来源 */ sourceType: props.sourceType, /** 拍摄视频最长拍摄时间,单位秒。时间范围为 3s 至 30s 之间 */ maxDuration: props.maxDuration, /** 仅对 mediaType 为 image 时有效,是否压缩所选文件 */ sizeType: props.sizeType, /** 仅在 sourceType 为 camera 时生效,使用前置或后置摄像头 */ camera: props.camera, /** 接口调用失败的回调函数 */ fail: (res) => { emit("failure", res); }, /** 接口调用成功的回调函数 */ success: onChangeMedia }); } else { Taro.chooseImage({ // 选择数量 count: props.multiple ? Number(props.maximum) - fileList.value.length : 1, // 可以指定是原图还是压缩图,默认二者都有 sizeType: props.sizeType, sourceType: props.sourceType, success: onChangeImage, fail: (res) => { emit("failure", res); } }); } }; const onChangeMedia = (res) => { const { tempFiles } = res; const _files = filterFiles(tempFiles); if (props.beforeUpload) { props.beforeUpload(new Array().slice.call(_files)).then( (f) => { const _files2 = filterFiles(new Array().slice.call(f)); if (!_files2.length) res.tempFiles = []; readFile(_files2); } ); } else { readFile(_files); } emit("change", { fileList: fileList.value }); }; const onChangeImage = (res) => { const { tempFiles } = res; const _files = filterFiles(tempFiles); if (props.beforeUpload) { props.beforeUpload(new Array().slice.call(_files)).then( (f) => { const _files2 = filterFiles(new Array().slice.call(f)); if (!_files2.length) res.tempFiles = []; readFile(_files2); } ); } else { readFile(_files); } emit("change", { fileList: fileList.value }); }; const fileItemClick = (fileItem) => { emit("fileItemClick", { fileItem }); }; const executeUpload = (fileItem, index) => { const uploadOption = new UploadOptions(); uploadOption.name = props.name; uploadOption.url = props.url; uploadOption.fileType = fileItem.type; uploadOption.formData = fileItem.formData; uploadOption.timeout = props.timeout * 1; uploadOption.method = props.method; uploadOption.xhrState = props.xhrState; uploadOption.method = props.method; uploadOption.headers = props.headers; uploadOption.taroFilePath = fileItem.path; uploadOption.beforeXhrUpload = props.beforeXhrUpload; uploadOption.onStart = (option) => { fileItem.status = "ready"; fileItem.message = translate("readyUpload"); clearUploadQueue(index); emit("start", option); }; uploadOption.onProgress = (event, option) => { fileItem.status = "uploading"; fileItem.message = translate("uploading"); fileItem.percentage = event.progress; emit("progress", { event, option, percentage: fileItem.percentage }); }; uploadOption.onSuccess = (data, option) => { fileItem.status = "success"; fileItem.message = translate("success"); emit("success", { data, responseText: data, option, fileItem }); emit("update:fileList", fileList.value); }; uploadOption.onFailure = (data, option) => { fileItem.status = "error"; fileItem.message = translate("error"); emit("failure", { data, responseText: data, option, fileItem }); }; let task = new UploaderTaro(uploadOption); if (props.autoUpload) { task.uploadTaro(Taro.uploadFile, Taro.getEnv()); } else { uploadQueue.value.push( new Promise((resolve) => { resolve(task); }) ); } }; const clearUploadQueue = (index = -1) => { if (index > -1) { uploadQueue.value.splice(index, 1); } else { uploadQueue.value = []; fileList.value = []; emit("update:fileList", fileList.value); } }; const submit = () => { Promise.all(uploadQueue.value).then((res) => { res.forEach((i) => i.uploadTaro(Taro.uploadFile, Taro.getEnv())); }); }; const readFile = (files) => { files.forEach((file, index) => { var _a, _b; let fileType = file.type; let filepath = file.tempFilePath || file.path; const fileItem = reactive(new FileItem()); fileItem.message = translate("ready"); if (file.fileType) { fileType = file.fileType; } else { const imgReg = /\.(png|jpeg|jpg|webp|gif)$/i; if (!fileType && (imgReg.test(filepath) || filepath.includes("data:image"))) { fileType = "image"; } } fileItem.path = filepath; fileItem.name = filepath; fileItem.status = "ready"; fileItem.message = translate("waitingUpload"); fileItem.type = fileType; if (Taro.getEnv() == "WEB") { const formData = new FormData(); for (const [key, value] of Object.entries(props.data)) { formData.append(key, value); } formData.append(props.name, file.originalFileObj); fileItem.name = (_a = file.originalFileObj) == null ? void 0 : _a.name; fileItem.type = (_b = file.originalFileObj) == null ? void 0 : _b.type; fileItem.formData = formData; } else { fileItem.formData = props.data; } if (props.isPreview) { fileItem.url = fileType == "video" ? file.thumbTempFilePath : filepath; } fileList.value.push(fileItem); executeUpload(fileItem, index); }); }; const filterFiles = (files) => { const maximum = props.maximum * 1; const maximize = props.maximize * 1; const oversizes = new Array(); files = files.filter((file) => { if (file.size > maximize) { oversizes.push(file); return false; } else { return true; } }); if (oversizes.length) { emit("oversize", oversizes); } let currentFileLength = files.length + fileList.value.length; if (currentFileLength > maximum) { files.splice(files.length - (currentFileLength - maximum)); } return files; }; const deleted = (file, index) => { fileList.value.splice(index, 1); emit("delete", { file, fileList: fileList.value, index }); }; const onDelete = (file, index) => { if (disabled.value) return; clearUploadQueue(index); funInterceptor(props.beforeDelete, { args: [file, fileList.value], done: () => deleted(file, index) }); }; return { onDelete, fileList, disabled, chooseImage, fileItemClick, clearUploadQueue, submit }; } }); const _hoisted_1 = { class: "nut-uploader" }; const _hoisted_2 = { key: 0, class: "nut-uploader__slot" }; const _hoisted_3 = { key: 0, class: "nut-uploader__preview-img" }; const _hoisted_4 = { key: 0, class: "nut-uploader__preview__progress" }; const _hoisted_5 = { class: "nut-uploader__preview__progress__msg" }; const _hoisted_6 = ["onClick"]; const _hoisted_7 = ["mode", "src", "onClick"]; const _hoisted_8 = { key: 3, class: "nut-uploader__preview-img__file" }; const _hoisted_9 = ["onClick"]; const _hoisted_10 = { class: "file__name_tips" }; const _hoisted_11 = { class: "tips" }; const _hoisted_12 = { key: 1, class: "nut-uploader__preview-list" }; const _hoisted_13 = ["onClick"]; const _hoisted_14 = { class: "file__name_tips" }; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { const _component_nut_button = resolveComponent("nut-button"); const _component_Failure = resolveComponent("Failure"); const _component_Loading = resolveComponent("Loading"); const _component_Link = resolveComponent("Link"); const _component_Del = resolveComponent("Del"); const _component_nut_progress = resolveComponent("nut-progress"); const _component_Photograph = resolveComponent("Photograph"); return openBlock(), createElementBlock("view", _hoisted_1, [ _ctx.$slots.default ? (openBlock(), createElementBlock("view", _hoisted_2, [ renderSlot(_ctx.$slots, "default"), _cache[0] || (_cache[0] = createTextVNode()), Number(_ctx.maximum) - _ctx.fileList.length ? (openBlock(), createBlock(_component_nut_button, { key: 0, class: "nut-uploader__input", onClick: _ctx.chooseImage }, null, 8, ["onClick"])) : createCommentVNode("", true) ])) : createCommentVNode("", true), _cache[9] || (_cache[9] = createTextVNode()), (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.fileList, (item, index) => { var _a, _b; return openBlock(), createElementBlock("view", { key: item.uid, class: normalizeClass(["nut-uploader__preview", [_ctx.listType]]) }, [ _ctx.listType == "picture" && !_ctx.$slots.default ? (openBlock(), createElementBlock("view", _hoisted_3, [ item.status != "success" ? (openBlock(), createElementBlock("view", _hoisted_4, [ item.status != "ready" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [ item.status == "error" ? (openBlock(), createBlock(_component_Failure, { key: 0, color: "#fff" })) : (openBlock(), createBlock(_component_Loading, { key: 1, name: "loading", color: "#fff" })) ], 64)) : createCommentVNode("", true), _cache[1] || (_cache[1] = createTextVNode()), createElementVNode("view", _hoisted_5, toDisplayString(item.message), 1) ])) : createCommentVNode("", true), _cache[2] || (_cache[2] = createTextVNode()), _ctx.isDeletable ? (openBlock(), createElementBlock("view", { key: 1, class: "close", onClick: ($event) => _ctx.onDelete(item, index) }, [ renderSlot(_ctx.$slots, "delete-icon", {}, () => [ createVNode(_component_Failure) ]) ], 8, _hoisted_6)) : createCommentVNode("", true), _cache[3] || (_cache[3] = createTextVNode()), (((_a = item == null ? void 0 : item.type) == null ? void 0 : _a.includes("image")) || ((_b = item == null ? void 0 : item.type) == null ? void 0 : _b.includes("video"))) && item.url ? (openBlock(), createElementBlock("img", { key: 2, class: "nut-uploader__preview-img__c", mode: _ctx.mode, src: item.url, onClick: ($event) => _ctx.fileItemClick(item) }, null, 8, _hoisted_7)) : (openBlock(), createElementBlock("view", _hoisted_8, [ createElementVNode("view", { class: "nut-uploader__preview-img__file__name", onClick: ($event) => _ctx.fileItemClick(item) }, [ createElementVNode("view", _hoisted_10, toDisplayString(item.name), 1) ], 8, _hoisted_9) ])), _cache[4] || (_cache[4] = createTextVNode()), createElementVNode("view", _hoisted_11, toDisplayString(item.name), 1) ])) : _ctx.listType == "list" ? (openBlock(), createElementBlock("view", _hoisted_12, [ createElementVNode("view", { class: normalizeClass(["nut-uploader__preview-img__file__name", [item.status]]), onClick: ($event) => _ctx.fileItemClick(item) }, [ createVNode(_component_Link, { class: "nut-uploader__preview-img__file__link" }), _cache[5] || (_cache[5] = createTextVNode()), createElementVNode("view", _hoisted_14, toDisplayString(item.name), 1), _cache[6] || (_cache[6] = createTextVNode()), _ctx.isDeletable ? (openBlock(), createBlock(_component_Del, { key: 0, color: "#808080", class: "nut-uploader__preview-img__file__del", onClick: withModifiers(($event) => _ctx.onDelete(item, index), ["stop"]) }, null, 8, ["onClick"])) : createCommentVNode("", true) ], 10, _hoisted_13), _cache[7] || (_cache[7] = createTextVNode()), item.status == "uploading" ? (openBlock(), createBlock(_component_nut_progress, { key: 0, size: "small", percentage: item.percentage, "stroke-color": "linear-gradient(270deg, rgba(18,126,255,1) 0%,rgba(32,147,255,1) 32.815625%,rgba(13,242,204,1) 100%)", "show-text": false }, null, 8, ["percentage"])) : createCommentVNode("", true) ])) : createCommentVNode("", true) ], 2); }), 128)), _cache[10] || (_cache[10] = createTextVNode()), _ctx.listType == "picture" && !_ctx.$slots.default && Number(_ctx.maximum) - _ctx.fileList.length ? (openBlock(), createElementBlock("view", { key: 1, class: normalizeClass(["nut-uploader__upload", [_ctx.listType]]) }, [ renderSlot(_ctx.$slots, "upload-icon", {}, () => [ createVNode(_component_Photograph, { color: "#808080" }) ]), _cache[8] || (_cache[8] = createTextVNode()), createVNode(_component_nut_button, { class: normalizeClass(["nut-uploader__input", { disabled: _ctx.disabled }]), onClick: _ctx.chooseImage }, null, 8, ["class", "onClick"]) ], 2)) : createCommentVNode("", true) ]); } const index_taro = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]); export { index_taro as default };