bangumi图片上传

上传图片到niupic,catbox,管理历史上传记录

// ==UserScript==
// @name         bangumi图片上传
// @namespace    https://github.com/shadowdreamer/jioben
// @version      0.6
// @description  上传图片到niupic,catbox,管理历史上传记录
// @author       dovahkiin
// @include      http*://bgm.tv*
// @include      http*://bangumi.tv*
// @grant        GM_xmlhttpRequest
// @require      https://cdn.bootcss.com/vue/2.6.8/vue.min.js
// @noframes
// ==/UserScript==

(function () {
    const box = document.createElement("div");
    box.setAttribute("id","imgupload")
    box.innerHTML = `<img-uploader></img-uploader>`
    document.body.append(box);
    
    Vue.component('img-uploader',{
        data() {
            return {
                message: "上传文件:",
                file: null,
                url: [],
                open: false,
                openHistory: false,
                urlList: [],
                uploadApi: 'catbox',
            };
        },
        computed: {
            notices() {
                if (!this.file) {
                    return ['拖动或者粘贴文件到此处', '只能粘贴剪贴板图片(如qq截图)', '支持多个文件']
                } else if (this.file == 'dragenter') {
                    return ['松手']
                } else {
                    function renderSize(value) {
                        if (!value) {
                            return "0 Bytes";
                        }
                        var unitArr = new Array("Bytes", "KB", "MB", "GB", "TB");
                        var index = 0;
                        var srcsize = parseFloat(value);
                        index = Math.floor(Math.log(srcsize) / Math.log(1024));
                        var size = srcsize / Math.pow(1024, index);
                        size = size.toFixed(2);//保留的小数位数
                        return size + unitArr[index];
                    }
                    return Array.from(this.file, el => el.name + ',' + renderSize(el.size))
                }
            }
        },
        methods: {
            pushToUpload() {
                if (!this.file) return;
                this.url = Array.from({ length: this.file.length }, () => '')
                Array.prototype.forEach.call(this.file, (el, index) => {
                    this.upload(el, index)
                })
            },
            upload(file, index) {
                const formData = new FormData();
                let api = "";
                switch (this.uploadApi) {
                    case "niupic":
                        api = "https://www.niupic.com/api/upload";
                        formData.append("image_field", file);
                        break;
                    case "catbox":
                        api = "https://catbox.moe/user/api.php";
                        formData.append("fileToUpload", file)
                        formData.append("reqtype", "fileupload")
                        break;
                    case "sm.ms":
                        api = "https://sm.ms/api/upload";
                        formData.append("smfile", file)
                        break;
                }
                new Promise((resove, reject) => {
                    GM_xmlhttpRequest({
                        url: api,
                        method: "post",
                        data: formData,
                        // onprogress:ev=>{
                        //     console.log(ev)
                        // },
                        onload: res => {
                            let resUrl = '';
                            if (res.status == 200) {
                                switch (this.uploadApi) {
                                    case "niupic":
                                        resUrl = JSON.parse(res.responseText).img_puburl
                                        break;
                                    case "catbox":
                                        resUrl = res.responseText
                                        break;
                                    case "sm.ms":
                                        resUrl = JSON.parse(res.responseText).data.url
                                        break;
                                }
                                if (resUrl) {
                                    resove(resUrl)
                                } else {
                                    reject('失败')
                                }
                            } else {
                                reject('失败')
                            }
                        }
                    });
                }).then((url) => {
                    this.$set(this.url, index, url)
                    this.saveToLocal(url);
                }).catch(text => {
                    this.$set(this.url, index, text)
                })
            },
            copyToClipboard(id) {
                let focus = document.getElementById(id);
                focus.select();
                document.execCommand("copy");
            },
            saveToLocal(url) {
                this.urlList.push(url);
                localStorage.setItem("imgUrl", JSON.stringify(this.urlList));
            },
            deleteThisImg(index) {
                this.urlList.splice(index, 1);
                localStorage.setItem("imgUrl", JSON.stringify(this.urlList));
            },
            fileFilt(file){                
                return Array.prototype.filter.call(file,el=> /image/.test(el.type) )
            },
            dodrop(ev) {
                this.file = this.fileFilt(ev.dataTransfer.files)
                this.url = []
            },
            pasteEvt(ev) {
                this.file = this.fileFilt(ev.clipboardData.files)
                this.url = []
            },
            change(ev) {
                this.file = this.fileFilt(ev.target.files)
                this.url = []
            },
        },
        filters: {
            addHttp(url) {
                if (/^http(s)?/.test(url)) {
                    return url
                } else {
                    return "https://" + url
                }
            },
            addWithTag(url) {
                if (!url) return '在传了.....';
                return `[img]${url}[/img]`;
            },
        },
        mounted() {
            if (localStorage.getItem("imgUrl")) {
                this.urlList = JSON.parse(localStorage.getItem("imgUrl"));
            } else {
                localStorage.setItem("imgUrl", "[]");
            }
        },
        template:`<div>
        <div class="openUpload imgupload-toggle" @click="open = !open">upload</div>
        <div class="openHistory imgupload-toggle" @click="openHistory = !openHistory">history</div>
        <transition name="warp">
            <div class="imgupload-warp upload-layout" v-show="open">
                <p>{{message}}</p>
                <span>选择上传网站:</span>
                <select  v-model="uploadApi" >
                    <option value="niupic">niupic</option>
                    <option value="catbox">Catbox</option>
                    <option value="sm.ms">sm.ms</option>
                </select>
    
                <div
                    class = "drop-area"
                    contenteditable="true"
                    @dragenter.stop.prevent = " file = 'dragenter'"
                    @dragover.stop.prevent
                    @drop.stop.prevent = "dodrop($event)"
                    @paste.stop.prevent = "pasteEvt($event)"
                    >
                    <p v-for="notice in notices">{{notice}}</p>
    
                </div>
    
                <input
                    type="file"
                    multiple="multiple"
                    :files = "file"
                    accept="image/gif, image/jpeg, image/jpg, image/png, image/webp"
                    @change="change($event)"
                >
                <input type="button" value="上传" @click="pushToUpload"/>
                &nbsp;&nbsp;&nbsp;&nbsp;
                <input type="button" value="清空" @click="file = null"/>
    
    
                <div class="url-box"  v-for="(imgurl,index) in url"  :key = "index">
                    <input :value="imgurl | addWithTag" :id="'img-url-' + index" readonly>
                    <input type="button" value="点击复制" @click="copyToClipboard('img-url-' + index)">
                </div>
    
    
    
            </div>
        </transition>
        <transition name="warp">
            <div class="imgupload-warp history-layout" v-if="openHistory">
                <ul>
                    <li v-for="(url,index) in urlList" :key="index" class = "img-history-list">
                        <img :src="url | addHttp">
                        <button @click="deleteThisImg(index)" >删除</button>
                    </li>
                </ul>
            </div>
        </transition>
    </div>`
    })
    new Vue({ el: "#imgupload" })


    const style = document.createElement("style");
    const heads = document.getElementsByTagName("head");
    style.setAttribute("type", "text/css");
    style.innerHTML = `
.imgupload-warp {
	position: fixed;
	width: 300px;
	padding: 15px;
	box-sizing: border-box;
	background-color: #eee;
	border-radius: 5px;
	box-shadow: 0 0 15px #aaa;
	z-index: 99;
}
.upload-layout {
	min-height: 100px;
	top: 93px;
	right: 60px;
}
.history-layout {
	height: 300px;
	right: 60px;
	top: 260px;
	overflow-y: scroll;
}
.history-layout img {
	height: 60px;
    vertical-align: middle;

}
.url-box {
	margin: 8px 0px;
}
.imgupload-toggle {
	position: fixed;
	height: 50px;
	width: 50px;
    font-size:12px;
	line-height: 48px;
	text-align: center;
	border-radius: 50%;
	background-color: #fff;
	opacity: 0.7;
	cursor: pointer;
	box-shadow: 0 0 15px #aaa;
	user-select: none;
	z-index: 99;
}
.imgupload-toggle:hover {
	opacity: 1;
}
.openUpload {
	top: 203px;
	right: 10px;
}
.openHistory {
	top: 260px;
	right: 10px;
}
.drop-area{
    min-height: 100px;
    white-space: nowrap;
    border: 1px solid black;
    padding:2px;
    background-color:#fff;
    font-size:10px;
    over-flow:hidden;
}
.img-history-list{
    display:flex;
    justify-content : space-between
}
.img-history-list:nth-of-type(2n+1){
    background-color:#fff;
}
.img-history-list:nth-of-type(2n){
    background-color:#ccc;
}
.warp-enter-active,
.warp-leave-active {
	transition: opacity 0.5s;
}
.warp-enter,
.warp-leave-to {
	opacity: 0;
}
`
    heads[0].append(style)
})();