您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
self mode
// ==UserScript== // @name qianmo_job // @version 0.0.3 // @include http://newqianmo.baidu.com/404 // @description self mode // @run-at document-start // @namespace https://gf.qytechs.cn/users/164996 // ==/UserScript== const head = `<meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>job</title> <style> body { user-select: none; cursor: pointer; margin: 0; } #table { display: grid; grid-template-columns: repeat(9, auto); grid-column-gap: 1em; } #node { #width: fit-content; display: grid; grid-template-columns: repeat(6, auto); grid-column-gap: 1em; color: #9E9E9E; } div.running { color: #2196F3; } div.other { color: #9E9E9E; } div.cancelled { color: #FF5722; } div.failed { color: #E91E63; } div.completed { color: #673AB7; } div.pending { color: #FF9800; } div.preempted { color: #3f51b5; } #disconnect{ display: none; color: #bbb; position: fixed; left: 50%; transform: translateX(-50%); } span.button{ user-select:none; cursor:pointer; } div.section{ grid-column: 1 / -1; } iframe{ display: none; } </style>` const body = `<div id="app"> <div id='disconnect'>disconnect</div> <div id="node"></div> <div id="table"></div> <iframe src="http://newqianmo.baidu.com/index.jsp#/console"></iframe> </div>` document.head.innerHTML = head document.body.innerHTML = body const timeout = 10000 const app = document.querySelector('#app') const node = document.querySelector('#node') const table = document.querySelector('#table') const disconnect = document.querySelector('#disconnect') const copy = text => { const textArea = document.createElement('textarea') textArea.value = text document.body.appendChild(textArea) textArea.select() document.execCommand('copy') document.body.removeChild(textArea) } const parse = s => { const t = document.implementation.createHTMLDocument() t.body.innerHTML = s return t } const fetchWithTimeout = (url, options) => { return Promise.race([ fetch(url, options), new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeout)) ]) } const fetchList = async url => { let data = await fetchWithTimeout(url) data = await data.json() data = data.retData.rows return data } const fetchResource = async () => { const url = 'http://newqianmo.baidu.com/action/gpu/queryGpuResource?pageNum=1&pageSize=5&isPersonal=1' return await fetchList(url) } const fetchTask = async (type = '', size = 20) => { const url = `http://newqianmo.baidu.com/action/gpu/queryGpuJobListPerson?pageNum=1&pageSize=${size}&isProjectList=0&jobId=&jobName=&queueName=&status=` return await fetchList(url + type) } const main = async () => { let data try { data = (await Promise.all([ fetchTask('RUNNING'), fetchTask('PENDING', 5), fetchTask('FAILED', 5), fetchTask('PREEMPTED', 5), fetchTask('CANCELLED', 5) //fetchTask('COMPLETED', 5), ])) .filter(i => i) .flat() } catch (err) { disconnect.style.display = 'block' return } disconnect.style.display = 'none' let type_pre = '' let b = data.reduce((a, c) => { let url = '' try { url = new URL(c.jobLogUrl) url.pathname = '' url.port = 8825 } catch {} const link = `<a target="_blank" href="${url}">tb</a> <a target="_blank" href="${c.jobLogUrl}">job</a> <a target="_blank" href="${c.workspaceUrl}">workspace</a>` url = url.hostname const ssh_action = `ssh slurm@${url} -t 'cd job/tmp/job-${c.slurmId};bash'` const rsync_action = `rsync -av slurm@${url}:job/tmp/job-${c.slurmId}/cdsr/runs .` const action = `<span class=button data-copy="${ssh_action}">ssh</span> <span class=button data-copy="${rsync_action}">rsync</span> <span class=button data-copy="deljob -j${c.jobId}">deljob</span>` const list = [ c.jobName, c.jobId, c.priority, c.queueName, c.ncpus, c.gpuRatio, c.elapsed, action, link ] const type = c.status.toLowerCase() if (type !== type_pre) { type_pre = type a += `<div class="section ${type}">${type}</div>` } const row = list.map(i => `<div class=${type}>` + i + '</div>').join('') return a + row }, '') // node data = await fetchResource() let d = data.reduce((a, c) => { const list = [ c.queueName, c.gpuType + ' x ' + c.gpuPerNode, Number(c.quota) - Number(c.used) ] const row = list.map(i => `<div>` + i + '</div>').join('') return a + row }, '') requestAnimationFrame(() => { node.innerHTML = d table.innerHTML = b }) } main() let timer = setInterval(main, timeout) let changeTimer document.addEventListener('click', e => { const type = e.target.textContent const target = e.target let text = '' if (['ssh', 'rsync', 'deljob'].includes(type)) { text = target.dataset.copy } else if (target.children.length === 0) { text = target.textContent.trim() } if (text.length === 0) return copy(text) }) document.addEventListener('visibilitychange', () => { clearTimeout(changeTimer) if (document.hidden) { changeTimer = setTimeout(() => clearInterval(timer), timeout) } else { main() clearInterval(timer) timer = setInterval(main, timeout) } }) const frame = document.querySelector('iframe') setInterval(() => { frame.contentWindow.location.reload() }, 1000 * 3600)
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址