站酷网下载按钮

提供站酷网原图下载功能

// ==UserScript==
// @name         站酷网下载按钮
// @namespace    zhanku-download
// @version      1.0.2
// @icon         https://static.zcool.cn/git_z/z/site/favicon.ico?version=1618914637608
// @description  提供站酷网原图下载功能
// @author       sertraline
// @match        http*://www.zcool.com.cn/work/*
// @require      https://cdn.staticfile.org/jquery/3.6.2/jquery.min.js
// @grant    GM_openInTab
// @grant    GM_download
// ==/UserScript==
const IMG_SELECTOR = '.photoImage'
const IMG_BOX_SELECTOR = '.photoInformationContent'
const DOWNLOAD_BOX_SELECTOR = '.imageCollectIcons'
const DOWNLOAD_ALL_BOX_SELECTOR = '.detailNavBox'
const INDEX_MODAL_SELECTOR = '.ReactModalPortal'
const NAMESPACE = GM_info.script.namespace
const DOWNLOAD_ICON = `<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path d="M229.4 452.7l258.5 195.1a39.9 39.9 0 0 0 48.2 0l258.5-195.1c12.2-9.2 5.7-28.7-9.6-28.7H612.9V168a40 40 0 0 0-40-40H451.1a40 40 0 0 0-40 40v256H239c-15.3 0-21.8 19.5-9.6 28.7zM856 656H619.6a4.4 4.4 0 0 0-2.5.8l-47.3 35.7a95.8 95.8 0 0 1-115.6 0l-47.3-35.7a4.4 4.4 0 0 0-2.5-.8H168a40 40 0 0 0-40 40v160a40 40 0 0 0 40 40h688a40 40 0 0 0 40-40V696a40 40 0 0 0-40-40zM688 808a32 32 0 1 1 32-32 32 32 0 0 1-32 32zm120 0a32 32 0 1 1 32-32 32 32 0 0 1-32 32z"/></svg>`
function uuid() {
    return Math.random().toString(36).substr(2)
}
function namespace(str) {
    return `${NAMESPACE}-${str}`
}
let toasts = [];
let $toastContainer;
const TOAST_CONTAINER_SELECTOR = `#${namespace("toast")}`;
function initToast() {
    if (!$toastContainer) {
        $toastContainer = $(TOAST_CONTAINER_SELECTOR);
        if (!$toastContainer.length) {
            const toast = `
                <div id="${namespace("toast")}" class="${namespace("toast")}">
                </div>
            `;
            $toastContainer = $(toast);
            $("body").append($toastContainer);
        }
    }
}

function createBtn({ id, text, callback, parent = "body", cls = "btns-item" }) {
    const _id = namespace(`${uuid()}-${id}`)
    if (document.getElementById(_id)) return
    const btn = `<div id="${_id}" class="${namespace(cls)}">${text}</div>`
    $(parent).append(btn)
    $(`#${_id}`).click(callback)
}

function openToast(text, duration = 2000) {
    if (!text) return;

    initToast();
    const id = namespace(uuid + "toast")
    const toast = {
        id,
        element: $.parseHTML(`
            <div id="${id}" class="${namespace("toast__item")}">
                ${text}
            </div>
        `),
    };
    toasts.push(toast);

    $toastContainer.append(toast.element);
    setTimeout(() => {
        $(toast.element).remove();
        toasts = toasts.filter((t) => t.id !== toast.id);
    }, duration);
}

function getNameFromUrl(url) {
    const SPLIT_REGEXP = /\/|\?/
    return new URL(url).pathname.split(SPLIT_REGEXP).pop()
}
function getFileTypeFromUrl(url) {
    const name = getNameFromUrl(url)
    const SPLIT_REGEXP = /\./
    const res = name.split(SPLIT_REGEXP)[1]
    return res ? res.toUpperCase() : null
}
function downloadFile(url) {
    const name = getNameFromUrl(url)
    GM_download({
        url,
        name,
        saveAs: true,
        onload: () => {
            openToast('下载成功')
        },
        onerror: () => {
            openToast('下载失败')
        }
    })
}
function main() {
    const sourceImgEls = document.querySelectorAll(IMG_BOX_SELECTOR)
    sourceImgEls.forEach(el => {
        const src = el.querySelector(IMG_SELECTOR).src
        const _src = src.split('?')[0]
        createBtn({
            id: 'download',
            text: `${DOWNLOAD_ICON}下载原图`,
            callback() {
                downloadFile(_src)
            },
            parent: el.querySelector(DOWNLOAD_BOX_SELECTOR)

        })
    })
    createBtn({
        id: 'download-all',
        text: DOWNLOAD_ICON,
        callback() {
            const imgs = Array.from(sourceImgEls).map(el => el.querySelector(IMG_SELECTOR).src.split('?')[0])
            openToast(`开始下载${imgs.length}张图片`)
            imgs.forEach(img => {
                downloadFile(img)
            })
        },
        parent: document.querySelector(DOWNLOAD_ALL_BOX_SELECTOR),
        cls: 'download-all-btns-item'
    })
}
//
; (function ($) {
    initStyles()
    main()
})(jQuery)
function initStyles() {
    const styles = `
          <style>
            .imageCollectIcons{
                width:auto !important;
            }
            .${namespace('toast')}{
                position: fixed;
                top: 50px;
                left: 50%;
                transform: translateX(-50%);
                display: flex;
                flex-direction: column;
                align-items: center;
                z-index: 99999999;
            }
            .${namespace('toast__item')}{
                padding: 10px 20px;
                background: rgba(0,0,0,0.5);
                color: #fff;
                border-radius: 5px;
                margin-bottom: 10px;
            }
            .${namespace('btns-item')} {
                margin-left: 4px;
                padding: 0 10px;
                line-height: 36px;
                font-size: 14px;
                height: 36px;
                border-radius: 4px;
                background-color: rgba(0, 0, 0, 0.6);
                display: flex;
                align-items: center;
                color: #fff;
            }
            .${namespace('btns-item')}:hover {
                color: rgb(255, 242, 0);
            }
            .${namespace('btns-item')} svg {
                margin-right: 4px;
                height: 20px;
                fill: #fff;
            }
            .${namespace('btns-item')}:hover svg{
                fill: rgb(255, 242, 0);
            }
            .${namespace('download-all-btns-item')} {
                width: 50px;
                height: 50px;
                display: inline-flex;
                align-items: center;
                justify-content: center;
                border-radius: 50%;
                box-sizing: border-box;
                position: relative;
                cursor: pointer;
                margin-top: 16px;
                border: 1px solid rgb(237, 237, 237);
                background-color: rgba(255, 255, 255, 0.9);
            }
            .${namespace('download-all-btns-item')} svg{
                height: 24px;
            }
          </style>
      `
    $('head').append(styles)
}