UNPKG

omii-ui

Version:

使用OMII开发的WebComponents库,样式采用bootstrap。可以作为标准的esmodule使用

205 lines (196 loc) 5.8 kB
const { h, classNames } = omii; import uiBase from "../uiBase"; import css from "./index.scss"; import { getCSSStyleSheets } from "../css"; import pictures from "./templates/pictures"; import files from "./templates/files"; import { getExtension, getName } from "../utils"; import { creatPreviewUrl } from "preview-utils"; const Templates = { pictures, files, none: null }; const STATUS = { NONE: "NONE", UPLOADING: "UPLOADING", UPLOADED: "UPLOADED", ERROR: "ERROR", }; export default class extends uiBase { static creatPreviewUrl = creatPreviewUrl; static get STATUS() { return STATUS; } static css = [ () => getCSSStyleSheets( "reboot", "containers", "grid", "card", "utilities", "buttons", "tables" ), css, ]; static defaultProps = { accept: "", action: "", selectText: "选择文件上传", headers: null, //对象或返回对象的方法 multiple: false, autoUpload: false, allowSort: false, //多选,并允许排序时才会有排序功能 limit: false, withCredentials: false, template: "pictures", // file,picture-form,file-form, files: [], //{id,name,size,file,url,ext,type,status} uploadHandler( resource, url, { paramName = "file", withCredentials = false, headers } ) { const file = resource.file; const xhr = new XMLHttpRequest(); const fd = new FormData(); fd.append(paramName, file); xhr.withCredentials = withCredentials; xhr.open("POST", url); if (typeof headers === "function") { headers = headers(); } if (typeof headers === "object") { for (let key in headers) { xhr.setRequestHeader(key, headers[key]); } } resource.status = STATUS.UPLOADING; xhr.onreadystatechange = (args) => { if (xhr.readyState === 4 && xhr.status === 200) { console.log("上传成功"); let data = xhr.responseText; try { data = JSON.parse(data); } catch (exc) { resource.status = STATUS.ERROR; console.error(exc); } resource.status = STATUS.UPLOADED; // Object.assign(file, data); this.fire("uploaded", { resource, data, uploader: this }); this.refresh(); } if (xhr.status > 400) { file.status = STATUS.ERROR; console.log("上传失败", xhr, args); } // else { // file.status = STATUS.ERROR; // console.log("上传失败", xhr, args); // } }; //监听文件上传(xhr.upload)进度 xhr.upload.onprogress = (e) => { if (e.lengthComputable) { let percentage = Math.ceil((e.loaded / e.total) * 100); resource.progress = percentage; this.fire("progress", { resource, loaded: e.loaded, uploader: this }); console.log(percentage + "%"); this.refresh(); } }; xhr.send(fd); }, }; static propTypes = { accept: String, action: String, selectText: String, multiple: Boolean, autoUpload: Boolean, allowSort: Boolean, limit: Number, withCredentials: Boolean, }; #replaceIndex = -1; open(index = -1) { this.#replaceIndex = index; this.$("#files").click(); this.fire("open", { index }); } remove(index) { this.$props.files?.splice(index, 1); this.updateSelf(); this.fire("remove", { index }); } select(files) { let { multiple, files: all, autoUpload } = this.$props; if (files?.length == 0) return false; if (!multiple) all.splice(0, all.length); if (this.#replaceIndex != -1 && files.length >= 1) { let replaceFiles = Array.from(files).map((file) => { return { id: null, name: getName(file.name), ext: getExtension(file.name), size: file.size, type: file.type, lastModified: file.lastModified, file, }; }); all.splice(this.#replaceIndex, 1, ...replaceFiles); this.fire("replaced", { index: this.#replaceIndex, replaceFiles }); } else { let selected = Array.from(files).map((file) => { return { id: null, name: getName(file.name), ext: getExtension(file.name), size: file.size, type: file.type, lastModified: file.lastModified, file, status: STATUS.NONE, }; }); all.push(...selected); this.fire("selected", { selected }); } this.updateSelf(); if (autoUpload === true) this.upload(); } refresh() { this.forceUpdate(); } get uploadHandler() { return this.$props.uploadHandler; } upload() { let { files, action, withCredentials, headers } = this.$props; if (!action) alert("没有设置上传地址"); let index = 0; for (let file of files.filter( (f) => f.file && (!f.status || f.status == STATUS.NONE) )) { file.index = index++; this.uploadHandler.call(this, file, action, { withCredentials, headers }); } } render() { let { multiple, accept, template } = this.$props; return ( <> <slot>{Templates[template]}</slot> <input id="files" type="file" multiple={multiple} accept={accept} onChange={(evt) => { this.select(evt.target.files); evt.target.value = null; }} /> </> ); } }