After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,2 @@
|
||||
// export const THUHOLE_API_ROOT='//localhost:5001/';
|
||||
export const THUHOLE_API_ROOT = 'https://thuhole.com/' |
@ -0,0 +1,47 @@
|
||||
const DUMP_VER='dump_v1'; |
||||
|
||||
function dump() { |
||||
return JSON.stringify({ |
||||
_dump_ver: DUMP_VER, |
||||
token: localStorage['TOKEN']||null, |
||||
hole_config: localStorage['hole_config']||null, |
||||
}); |
||||
} |
||||
function load(s) { |
||||
console.log('elevator: loading',s); |
||||
let obj=JSON.parse(s); |
||||
if(obj._dump_ver!==DUMP_VER) { |
||||
console.error('elevator: loading version mismatch, current',DUMP_VER,'param',obj._dump_ver); |
||||
return; |
||||
} |
||||
if(localStorage['TOKEN']===undefined && obj.token) { |
||||
console.log('replace token'); |
||||
localStorage['TOKEN']=obj.token; |
||||
} |
||||
if(localStorage['hole_config']===undefined && obj.hole_config) { |
||||
console.log('replace hole config'); |
||||
localStorage['hole_config']=obj.hole_config; |
||||
} |
||||
} |
||||
|
||||
export function elevate() { |
||||
// load
|
||||
// '?foo=fo&bar=ba' -> [["foo","fo"],["bar","ba"]]
|
||||
let params=window.location.search.substr(1).split('&').map((kv)=>kv.split('=')); |
||||
params.forEach((kv)=>{ |
||||
if(kv.length===2 && kv[0]==='_elevator_data') { |
||||
load(decodeURIComponent(kv[1])); |
||||
let url=new URL(window.location.href); |
||||
url.search=''; |
||||
window.history.replaceState('','',url.href); |
||||
} |
||||
}); |
||||
|
||||
// dump
|
||||
if(window.location.protocol==='http:' && window.location.hostname==='pkuhelper.pku.edu.cn') { |
||||
let url=new URL(window.location.href); |
||||
url.protocol='https:'; |
||||
url.search='?_elevator_data='+encodeURIComponent(dump()); |
||||
window.location.replace(url.href); |
||||
} |
||||
} |
@ -0,0 +1,35 @@
|
||||
export function get_json(res) { |
||||
if(!res.ok) throw Error(`网络错误 ${res.status} ${res.statusText}`); |
||||
return ( |
||||
res |
||||
.text() |
||||
.then((t)=>{ |
||||
try { |
||||
return JSON.parse(t); |
||||
} catch(e) { |
||||
console.error('json parse error'); |
||||
console.trace(e); |
||||
console.log(t); |
||||
throw new SyntaxError('JSON Parse Error '+t.substr(0,50)); |
||||
} |
||||
}) |
||||
); |
||||
} |
||||
|
||||
export function listen_darkmode(override) { // override: true/false/undefined
|
||||
function update_color_scheme() { |
||||
if(override===undefined ? window.matchMedia('(prefers-color-scheme: dark)').matches : override) |
||||
document.body.classList.add('root-dark-mode'); |
||||
else |
||||
document.body.classList.remove('root-dark-mode'); |
||||
} |
||||
|
||||
update_color_scheme(); |
||||
window.matchMedia('(prefers-color-scheme: dark)').addListener(()=>{ |
||||
update_color_scheme(); |
||||
}); |
||||
} |
||||
|
||||
export function API_VERSION_PARAM() { |
||||
return '&PKUHelperAPI=3.0&jsapiver='+encodeURIComponent((process.env.REACT_APP_BUILD_INFO||'null')+'-'+(Math.floor(+new Date()/7200000)*2)); |
||||
} |
@ -0,0 +1,37 @@
|
||||
:root { |
||||
--foreground-dark: hsl(0,0%,93%); |
||||
} |
||||
|
||||
body { |
||||
margin: 0; |
||||
padding: 0; |
||||
overflow-x: hidden; |
||||
text-size-adjust: 100%; |
||||
} |
||||
|
||||
body, textarea, pre { |
||||
font-family: 'Segoe UI', '微软雅黑', 'Microsoft YaHei', sans-serif; |
||||
} |
||||
|
||||
* { |
||||
box-sizing: border-box; |
||||
word-wrap: break-word; |
||||
-webkit-overflow-scrolling: touch; |
||||
} |
||||
|
||||
p, pre { |
||||
margin: 0; |
||||
} |
||||
|
||||
a { |
||||
text-decoration: none; |
||||
cursor: pointer; |
||||
} |
||||
|
||||
pre { |
||||
white-space: pre-line; |
||||
} |
||||
|
||||
code { |
||||
font-family: Consolas, Courier, monospace; |
||||
} |
@ -0,0 +1,301 @@
|
||||
.centered-line { |
||||
overflow: hidden; |
||||
text-align: center; |
||||
} |
||||
|
||||
.centered-line::before, |
||||
.centered-line::after { |
||||
background-color: #000; |
||||
content: ""; |
||||
display: inline-block; |
||||
height: 1px; |
||||
position: relative; |
||||
vertical-align: middle; |
||||
width: 50%; |
||||
} |
||||
|
||||
.root-dark-mode .centered-line { |
||||
color: var(--foreground-dark); |
||||
} |
||||
.root-dark-mode .centered-line::before, .root-dark-mode .centered-line::after { |
||||
background-color: var(--foreground-dark); |
||||
} |
||||
|
||||
.centered-line::before { |
||||
right: 1em; |
||||
margin-left: -50%; |
||||
} |
||||
|
||||
.centered-line::after { |
||||
left: 1em; |
||||
margin-right: -50%; |
||||
} |
||||
|
||||
.title-line { |
||||
color: #fff; |
||||
margin-top: 1em; |
||||
} |
||||
.title-line::before, |
||||
.title-line::after { |
||||
background-color: #fff; |
||||
box-shadow: 0 1px 1px #000; |
||||
} |
||||
|
||||
.root-dark-mode .title-line { |
||||
color: var(--foreground-dark); |
||||
} |
||||
.root-dark-mode .title-line::before, .root-dark-mode .title-line::after { |
||||
background-color: var(--foreground-dark); |
||||
} |
||||
|
||||
.app-switcher { |
||||
display: flex; |
||||
height: 2em; |
||||
text-align: center; |
||||
margin: 0 .1em; |
||||
user-select: none; |
||||
} |
||||
.app-switcher-desc { |
||||
margin: 0 .5em; |
||||
flex: 1 1 0; |
||||
opacity: .5; |
||||
height: 2em; |
||||
line-height: 2rem; |
||||
font-size: .8em; |
||||
} |
||||
|
||||
.root-dark-mode .app-switcher-desc { |
||||
color: var(--foreground-dark); |
||||
} |
||||
|
||||
@media screen and (max-width: 570px) { |
||||
.app-switcher-desc { |
||||
flex: 1 1 0; |
||||
display: none; |
||||
} |
||||
.app-switcher-item { |
||||
flex: 1 1 0 !important; |
||||
padding: 0 !important; |
||||
} |
||||
.app-switcher-dropdown-title { |
||||
padding-left: 0 !important; |
||||
padding-right: 0 !important; |
||||
text-align: center !important; |
||||
} |
||||
.app-switcher-dropdown-item { |
||||
margin-left: -2em !important; |
||||
margin-right: 0 !important; |
||||
} |
||||
} |
||||
|
||||
.app-switcher a:hover { /* reset underline from /hole style */ |
||||
border-bottom: unset; |
||||
margin-bottom: unset; |
||||
} |
||||
|
||||
.app-switcher-desc a { |
||||
color: unset; |
||||
} |
||||
|
||||
.app-switcher-left { |
||||
text-align: right; |
||||
} |
||||
.app-switcher-right { |
||||
text-align: left; |
||||
} |
||||
.app-switcher-item { |
||||
flex: 0 0 auto; |
||||
border-radius: 3px; |
||||
height: 1.6em; |
||||
line-height: 1.6em; |
||||
margin: .2em .1em; |
||||
padding: 0 .45em; |
||||
} |
||||
a.app-switcher-item, .app-switcher-item a { |
||||
transition: unset; /* override ant design */ |
||||
color: black; |
||||
} |
||||
.app-switcher-item img { |
||||
width: 1.2rem; |
||||
height: 1.2rem; |
||||
position: relative; |
||||
top: .2rem; |
||||
vertical-align: unset; /* override ant design */ |
||||
} |
||||
.app-switcher-item span:not(:empty) { |
||||
margin-left: .2rem; |
||||
} |
||||
.app-switcher-logo-hover { |
||||
margin-left: -1.2rem; |
||||
} |
||||
|
||||
.app-switcher-item:hover { |
||||
background-color: black; |
||||
color: white !important; |
||||
} |
||||
.app-switcher-item:hover a { |
||||
color: white !important; |
||||
} |
||||
.app-switcher-item-current { |
||||
background-color: rgba(0,0,0,.4); |
||||
text-shadow: 0 0 5px rgba(0,0,0,.5); |
||||
color: white !important; |
||||
} |
||||
.app-switcher-item-current a { |
||||
color: white !important; |
||||
} |
||||
|
||||
.root-dark-mode .app-switcher-item, .root-dark-mode .app-switcher-dropdown-title a { |
||||
color: var(--foreground-dark); |
||||
} |
||||
.root-dark-mode .app-switcher-item:hover, .root-dark-mode .app-switcher-item-current, .root-dark-mode .app-switcher-dropdown-title:hover a { |
||||
background-color: #555; |
||||
color: var(--foreground-dark); |
||||
} |
||||
|
||||
.app-switcher-item:hover .app-switcher-logo-normal, .app-switcher-item-current .app-switcher-logo-normal { |
||||
opacity: 0; |
||||
} |
||||
.app-switcher-item:not(.app-switcher-item-current):not(:hover) .app-switcher-logo-hover { |
||||
opacity: 0; |
||||
} |
||||
|
||||
.root-dark-mode .app-switcher-logo-normal { |
||||
opacity: 0 !important; |
||||
} |
||||
.root-dark-mode .app-switcher-logo-hover { |
||||
opacity: 1 !important; |
||||
} |
||||
|
||||
.app-switcher-dropdown { |
||||
padding: 0; |
||||
text-align: left; |
||||
} |
||||
|
||||
.app-switcher-dropdown:not(:hover) { |
||||
max-height: 1.6rem; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.app-switcher-dropdown-item { |
||||
background-color: hsla(0,0%,35%,.9); |
||||
padding: .125em .25em; |
||||
margin-left: -.75em; |
||||
margin-right: -.75em; |
||||
position: relative; |
||||
z-index: 10; |
||||
cursor: pointer; |
||||
} |
||||
.app-switcher-dropdown-item:hover { |
||||
background-color: rgba(0,0,0,.9); |
||||
} |
||||
.app-switcher-dropdown-item:nth-child(2) { |
||||
border-top-left-radius: 3px; |
||||
border-top-right-radius: 3px; |
||||
} |
||||
.app-switcher-dropdown-item:last-child { |
||||
border-bottom-left-radius: 3px; |
||||
border-bottom-right-radius: 3px; |
||||
} |
||||
|
||||
.app-switcher-dropdown-title { |
||||
padding-bottom: .2em; |
||||
padding-left: .5em; |
||||
padding-right: .25em; |
||||
} |
||||
.app-switcher-dropdown-title a { |
||||
cursor: unset; |
||||
} |
||||
|
||||
.thuhole-login-popup { |
||||
font-size: 1rem; |
||||
background-color: #f7f7f7; |
||||
color: black; |
||||
position: fixed; |
||||
left: 50%; |
||||
top: 50%; |
||||
width: 320px; |
||||
z-index: 114515; |
||||
transform: translateX(-50%) translateY(-50%); |
||||
border-radius: 5px; |
||||
} |
||||
.thuhole-login-popup a { |
||||
color: #00c; |
||||
} |
||||
.thuhole-login-popup p { |
||||
margin: .75em 0; |
||||
text-align: center; |
||||
} |
||||
/* override ant design */ |
||||
.thuhole-login-popup input, .thuhole-login-popup button { |
||||
font-size: .85em; |
||||
vertical-align: middle; |
||||
} |
||||
.thuhole-login-popup input:not([type="checkbox"]) { |
||||
width: 8rem; |
||||
border-radius: 5px; |
||||
border: 1px solid black; |
||||
outline: none; |
||||
margin: 0; |
||||
padding: 0 .5em; |
||||
line-height: 2em; |
||||
} |
||||
.thuhole-login-popup button { |
||||
width: 6rem; |
||||
color: black; |
||||
background-color: rgba(235,235,235,.5); |
||||
border-radius: 5px; |
||||
text-align: center; |
||||
border: 1px solid black; |
||||
line-height: 2em; |
||||
margin: 0 .5rem; |
||||
} |
||||
.thuhole-login-popup button:hover { |
||||
background-color: rgba(255,255,255,.7); |
||||
} |
||||
.thuhole-login-popup button:disabled { |
||||
background-color: rgba(128,128,128,.5); |
||||
} |
||||
.thuhole-login-type { |
||||
display: inline-block; |
||||
width: 6rem; |
||||
margin: 0 .5rem; |
||||
} |
||||
.thuhole-login-popup-shadow { |
||||
opacity: .5; |
||||
background-color: black; |
||||
position: fixed; |
||||
left: 0; |
||||
top: 0; |
||||
height: 100%; |
||||
width: 100%; |
||||
z-index: 114514; |
||||
} |
||||
|
||||
.thuhole-login-popup label.perm-item { |
||||
font-size: .8em; |
||||
vertical-align: .1rem; |
||||
margin-left: .5rem; |
||||
} |
||||
|
||||
.aux-margin { |
||||
width: calc(100% - 2 * 50px); |
||||
margin: 0 50px; |
||||
} |
||||
@media screen and (max-width: 1300px) { |
||||
.aux-margin { |
||||
width: calc(100% - 2 * 10px); |
||||
margin: 0 10px; |
||||
} |
||||
} |
||||
|
||||
.title { |
||||
font-size: 1.5em; |
||||
height: 4rem; |
||||
padding-top: 1rem; |
||||
text-align: center; |
||||
} |
||||
|
||||
.time-str { |
||||
color: #999999; |
||||
} |