omii-ui
Version:
使用OMII开发的WebComponents库,样式采用bootstrap。可以作为标准的esmodule使用
205 lines (196 loc) • 5.8 kB
JSX
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;
}}
/>
</>
);
}
}