Yapi接口数据一键复制
目前為
// ==UserScript==
// @name YapiCopy
// @namespace http://tampermonkey.net/
// @version 0.2.7
// @description Yapi接口数据一键复制
// @author Enjoy
// @icon https://foruda.gitee.com/avatar/1671100286067517749/4867929_enjoy_li_1671100285.png!avatar60
// @match *://yapi.*.com/project/*/interface/api/*
// @grant GM_addElement
// @grant GM_addStyle
// @grant GM_setClipboard
// @license GPL License
// ==/UserScript==
//ES6+ =>ES5 https://babel.docschina.org/repl/
run(document)
function run(document) {
createBtn()
window.cellecteParamsTxt = cellecteParamsTxt
return
function createBtn(options = {}) {
let { selector = 'YapiCopy' } = options
let btnDom = document.querySelector(`#${selector}`)
if (btnDom) return btnDom
btnDom = document.createElement('div')
btnDom.innerHTML = `
<div title='api 一键复制'>'</div>
<div title='params 一键复制'></div>
<div title='response 一键复制'></div>
<style>
#YapiCopy {
width: 15px;
height: 105px;
opacity: 0.15;
background: #0b7d1e;
font-weight: 800;
border-radius: 5px 0 0 5px;
cursor: pointer;
color: #fff;
transition: all 0.2s;
font-size: 18px;
position: fixed;
right: 0;
top: 50vh;
}
#YapiCopy:hover {
opacity: 0.5;
width: 35px;
height: 105px;
}
#YapiCopy>div {
height: 35px;
line-height: 35px;
text-align: center;
border-radius: 5px 0 0 5px;
}
#YapiCopy>div:hover {
background-color: #777d0b;
}
</style>
`
btnDom.setAttribute('id',selector)
document.body.appendChild(btnDom)
btnDom.addEventListener('click',(e) => {
if (e.target.title === 'api 一键复制') {
doCopy(cellecteApiTxt())
} else if (e.target.title === 'params 一键复制') {
doCopy(cellecteParamsTxt('参数格式说明',1))
} else {
doCopy(cellecteParamsTxt('响应数据结构',2))
}
})
}
function doCopy(newValue,selector = 'textarea') {
let textarea = document.querySelector(`#${selector}`)
if (!textarea) {
textarea = document.createElement('textarea')
textarea.style.cssText = 'position: absolute;left: -500px;top: -500px;max-width: 50px;opacity: 0;'
document.body.appendChild(textarea)
}
textarea.value = newValue
textarea.select()
setTimeout(() => {
document.execCommand('Copy')
},200)
}
function cellecteApiTxt() {
let desc = document.querySelector('.colName').innerText || ''
let pageUrl = location.href
let values = document.querySelectorAll('.colValue')
let method = values[3]?.innerText.toLocaleLowerCase() || ''
let apiUrl = values[4]?.innerText || ''
let template = `/**
* @description ${desc}
* @see ${decodeURIComponent(pageUrl)}
* @param { data } data
*/
export function ${apiUrl.replace(/^.*\//,'')}(data) {
return http.${method}('${apiUrl}',data)
}`
console.log(template)
return template
}
function cellecteParamsTxt(desc = '参数说明',index = 1) {
let tableDom = document.querySelectorAll('table')?.[index]
if (!tableDom) return ''
let keys = getCellContent(tableDom,1)
let values = getCellContent(tableDom,2)
let descs = getCellContent(tableDom,5)
let maps = {
"integer": '00',
"string": "''",
'boolean': 'true',
"object": "{}",
"integer []": "[]",
"string []": "['']",
"object []": "[{}]"
}
let temp = '\n'
let tagStack = []
keys.forEach((item,idx) => {
let valStart = ''
let flag = maps[values[idx]]
if (item.includes('<<')) {
valStart = flag.slice(0,flag.length / 2)
tagStack.push(flag.slice(-1 * flag.length / 2) + ',\n')
flag = valStart ? valStart : (flag + ',')
item = item.replace('<<','')
} else if (item.includes('>>')) {
item = tagStack.pop() + item.replace('>>','')
flag = flag + ','
} else {
flag = flag + ','
}
temp += `${item}:${flag} ${descs[idx] ? '//' + descs[idx] : ''}\n`
})
let template = `// ${desc}
let data = {${temp}}`
console.log(template)
return template
}
function getCellContent(tableDom,selectorIndex) {
let levelStack = []
let classPrefix = 'ant-table-row-indent indent-level-'
let res = [...tableDom.querySelectorAll(`tbody td:nth-child(${selectorIndex})`)].map((item) => {
let childNodes = item.childNodes
console.log(`childNodes => %O `,childNodes);
let extraStrStart = ''
if (childNodes[1]?.classList?.value?.includes('ant-table-row-expanded')) {
extraStrStart = '<<'
levelStack.push(childNodes[0].classList.value.replace(new RegExp(`${classPrefix}(\\d+)`,'g'),'$1'))
} else if (levelStack.length && childNodes[0]?.classList?.value.includes(levelStack.at(-1))) {
extraStrStart = '>>'
levelStack.pop()
}
return (extraStrStart + item.innerText) || ''
})
return res
}
}