您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
upload imge to gitlab
当前为
// ==UserScript== // @name uploadImgeToGitlab // @namespace http://tampermonkey.net/ // @version 0.1 // @description upload imge to gitlab // @author shinwoow // @match http://git.rdapp.com/-/ide/project/visulization/project-web-components-store/tree/publish/* // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @grant none // @require https://code.jquery.com/jquery-2.1.4.min.js // @license MIT // ==/UserScript== const imgSub = ['png', 'jpg', 'jpeg', 'tif', 'psd', 'icon'] const preUrl = 'http://newdev.rdapp.com:10066/store/api/coverImages/' const gitPreUrl = 'http://git.rdapp.com/visulization/project-web-components-store/raw/publish/dist/coverImages/' async function sleep(ms){ return new Promise(resolve => setTimeout(() => {console.log('等待' + ms + 'ms');resolve()}, ms)) } function findElByInnerText(el, text) { return Array.prototype.filter.call(el, item => item.innerText.trim() === text).at(0) } function toast(msg) { const toastEl = document.createElement('div') toastEl.className = 'shin-toast' toastEl.innerHTML = ` <div>提示</div> <p>${msg}</p> ` document.body.append(toastEl) setTimeout(() => {toastEl.remove()}, 1000) } // 展开所有 folder async function openImageFolder (level = 0) { const folderList = document.getElementsByClassName('file-row folder') let count = 0 Array.prototype.forEach.call(folderList, item => { if(!item.classList.contains('is-open')){ item.click() count++ } }) if(level < 3 && count) { await sleep(100) await openImageFolder(++level) } } async function uploadImge() { // 等待页面 dom 加载完毕 while(!document.getElementsByClassName('file-row folder')){ await sleep(1000) } await openImageFolder() await sleep(100) const folderElList = document.getElementsByClassName('file-row folder') const imageFolderEl = findElByInnerText(folderElList, 'coverImages') const menuListEl = imageFolderEl.getElementsByClassName('dropdown-menu dropdown-menu-right')[0] const uploadBtn =findElByInnerText(menuListEl.children, '上传文件') const uploadInput = uploadBtn.querySelector('#file-upload') uploadInput.click() async function inputLinsten (...rest) { uploadInput.removeEventListener("input", inputLinsten) // 取消监听 const commitBtn = document.querySelector('.qa-begin-commit-button') try { // 自动提交 await sleep(100) const commitBtn = document.querySelector('.qa-begin-commit-button') commitBtn.click() await sleep(100) const pushBtn = document.querySelector('.qa-commit-button') pushBtn.click() } catch(err) { alert('自动提交失败,请点击左下角手动提交') } } uploadInput.addEventListener("input", inputLinsten) } async function getImgList() { const el = document.getElementsByClassName('file-row folder') const imgEl = findElByInnerText(el, 'coverImages') const parentEl = imgEl?.parentElement || imgEl?.parentNode const imgElList = parentEl.querySelectorAll('.file-row:not(.folder)') const imgNamelist = Array.prototype.map.call(imgElList, item => item.innerText.trim()) .filter(item => imgSub.includes(item.split('.').pop())) // 非图片过滤 return imgNamelist } const getImgItem = (name) => { if(!name) { return '<div style="flex:1;width:0;height:0;"></div>' } return ` <div style="flex: 1;"> <img class="img-item" src="${gitPreUrl}${name}" alt="加载失败,请稍后再试" /> <div style="cursor: pointer;color: rgba(255,255,255,0.8); font-size: 20px;" class="copy-name"> ${name} </div> </div> ` } const copy = (text) => { // 挂载一个不可见元素 const target = document.createElement('input'); target.readOnly = 'readonly'; target.setAttribute('value', text); target.id = 'tempTarget'; target.style.opacity = '0'; target.style.position = 'fixed'; target.style.left = '-9999px'; target.style.top = '0px'; target.style.zIndex = '-9999'; document.body.appendChild(target); if (target.value === '') { console.log('copy 空字符串无法被复制'); toast('空字符串无法被复制') } else { try { // 选中、复制操作 const selected = document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false; target.focus(); target.select(); document.execCommand('copy'); target.setSelectionRange(0, 0); target.blur(); if (selected) { window.getSelection().removeAllRanges(); document.getSelection().addRange(selected); } toast('复制成功') } catch (e) { toast('复制失败') } } // 移除添加的元素 document.body.removeChild(target); } function setStyle () { // 样式 const styleEl = document.createElement('style') styleEl.setAttribute('type', 'text/css') styleEl.innerHTML = ` .shin-scroll-bar::-webkit-scrollbar-track { -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); border-radius: 10px; background-color: #fff; } .shin-scroll-bar::-webkit-scrollbar { width: 5px; height: 5px; background-color: #fff; } .shin-scroll-bar::-webkit-scrollbar-thumb { border-radius: 10px; -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3); background-color: #555; } .img-list { position: fixed; bottom: 0; height: 180px; display: flex; overflow: auto; white-space: nowrap; background: rgba(0,0,0,0.6); padding: 4px; width:100%; } .img-item { width: 200px; height: 120px; display: inline-block; cursor: pointer; border-radius: 4px; } .img-preview { position: relative; margin: 0 55px; height: calc(100% - 180px); } #shin-img-preview { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); max-height: calc(100% - 180px); } .shin-before, .shin-after{ color: rgba(255,255,255,0.6); font-size: 50px; font-weight: 100; margin: auto 0; cursor: pointer; transform: translateY(0px); transition: all .3s; } .shin-before:hover, .shin-after:hover { color: rgba(255,255,255,1); transform: translateY(-3px); } .img-list-content { flex: 1; display: flex; padding: 4px 0; } .shin-toast { position: absolute; left: 50%; top: 50px; transform: translateX(-50%); border: 1px solid #f5f5f5; border-radius: 8px; padding: 4px 24px; z-index: 1080; background: #fff; } .shin-toast div { font-size: 18px; margin-bottom: 4px; } .shin-toast p { margin: 0; } .img-list-wrap { display: flex; flex-wrap: wrap; padding: 24px; height: 100vh; overflow: auto; scrollbar-width: none; // firefox -ms-overflow-style: none; // ie10+ } .img-list-wrap::-webkit-scrollbar { display: none; // chrome safari } .shin-colopse { position: absolute; bottom: 0px; color: #fff; background: rgba(0,0,0,0.6); left: -52px; padding: 4px 8px; border-radius: 2px 2px 0 0; cursor: pointer; } ` document.body.append(styleEl) } async function showImg(arr) { // mask const maskEl = document.createElement('div') maskEl.className = 'modal-backdrop fade show shin-modal' // dialog const wrapEl = document.createElement('div') wrapEl.className = 'modal fade show' wrapEl.style = 'display: block;' const browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; const useWidth = browserWidth - 33.5 * 2 const imgWidth = 200 + 4 // width + margin const maxImgCount = Math.floor(useWidth / imgWidth) // 页码配置 let curPage = 0 const totalPage = Math.ceil(arr.length / maxImgCount) const getImgList = () => { const a = arr.slice(curPage * maxImgCount, (curPage + 1) * maxImgCount) a.push(...new Array(maxImgCount - a.length)) return a } // 展示状态 let displayStatus = 'preview' // 'list' const curImgList = getImgList() const imgListEl = curImgList.reduce((pre, cur) => pre + getImgItem(cur), '') function replaceImgList (index = 0) { const cil = getImgList() const ilEL = cil.reduce((pre, cur) => pre + getImgItem(cur), '') document.querySelector('.img-list-content').innerHTML = ilEL // 替换大图 const imgPreview = document.querySelector('#shin-img-preview') imgPreview.setAttribute('src', gitPreUrl + cil.at(index)) } function addPage () { curPage = curPage >= (totalPage - 1) ? 0 : ++curPage } function subPage() { curPage = curPage <= 0 ? totalPage - 1 : --curPage } function setCurPageByIndex(index) { curPage = Math.floor(index / maxImgCount) } const dialogStr = ` <button aria-label="关闭" type="button" data-dismiss="modal" class="close js-modal-close-action" style="color: #fff; font-size: 100px; font-weight: 100; z-index: 10086;"> <span aria-hidden="true">×</span> </button> <div class="img-preview" style="display: block;"> <img id="shin-img-preview" src="${gitPreUrl}${arr.at(0)}" alt="加载失败,请稍后再试" /> <div class="shin-colopse">展开</div> </div> <div class="img-list" style="display: flex;"> <span class="shin-before"><</span> <div class="img-list-content" > ${imgListEl} </div> <span class="shin-after">></span> </div> <div class="img-list-wrap" style="display: none;"> ${arr.reduce((pre, cur) => pre + getImgItem(cur), '')} </div> ` wrapEl.innerHTML = dialogStr function close () { maskEl.remove() wrapEl.remove() } function changeDisplayState (state) { displayStatus = state switch(displayStatus) { case 'preview': { wrapEl.querySelector('.img-preview').style.display = 'block' wrapEl.querySelector('.img-list').style.display = 'flex' wrapEl.querySelector('.img-list-wrap').style.display = 'none' break; } case 'list': { wrapEl.querySelector('.img-preview').style.display = 'none' wrapEl.querySelector('.img-list').style.display = 'none' wrapEl.querySelector('.img-list-wrap').style.display = 'flex' break; } } } wrapEl.querySelector('.js-modal-close-action').onclick = close wrapEl.querySelector('.img-preview').onclick = function (e) { if(e.target.className === 'img-preview') { close() } e.stopPropagation() e.preventDefault() } wrapEl.querySelector('.shin-before').onclick = function() { // 上一页 subPage() replaceImgList() } wrapEl.querySelector('.shin-after').onclick = function() { // 下一页 addPage() replaceImgList() } wrapEl.querySelector('.img-list').onclick = function(e) { // 点击图片 if(e.target.nodeName === 'IMG') { // 替换大图 const imgPreview = document.querySelector('#shin-img-preview') imgPreview.setAttribute('src', '#') imgPreview.setAttribute('src', e.target.currentSrc) } if(e.target.className === 'copy-name') { // 复制链接 const imgName = e.target.innerText copy(preUrl + imgName) } e.stopPropagation() e.preventDefault() } wrapEl.querySelector('.shin-colopse').onclick = function() { // 展开 changeDisplayState('list') } wrapEl.querySelector('.img-list-wrap').onclick = function(e) { // 点击图片 if(e.target.nodeName === 'IMG') { // 查询、修改页码 const imgName = e.target.currentSrc.split('/').pop() const imgIndex = arr.indexOf(imgName) setCurPageByIndex(imgIndex) replaceImgList(imgIndex % maxImgCount) changeDisplayState('preview') } if(e.target.className === 'copy-name') { // 复制链接 const imgName = e.target.innerText copy(preUrl + imgName) } e.stopPropagation() e.preventDefault() } document.body.append(maskEl) document.body.append(wrapEl) setStyle() } async function showImgeList() { await openImageFolder() await sleep(100) // 等待节点展开 const imgList = await getImgList() showImg(imgList) } function createEl () { const ul = document.getElementsByClassName('navbar-sub-nav')[0]; const uploadBtn = document.createElement('li') uploadBtn.className = 'd-none d-sm-block' const textEl = document.createElement('a') textEl.text = '上传图片' textEl.onclick = uploadImge uploadBtn.append(textEl) ul.append(uploadBtn) const imgDisplayBtn = document.createElement('li') imgDisplayBtn.className = 'd-none d-sm-block' const imgEl = document.createElement('a') imgEl.text = '显示封面图' imgEl.onclick = showImgeList imgDisplayBtn.append(imgEl) ul.append(imgDisplayBtn) } (function() { 'use strict'; createEl() })();