feat: node info, build info and acrylic web theme
Squash of recent dev work: return_session login, backend switcher, line detail timeline, overview strips, node platform/country/ISP info with flags and icons, build info (version, tag, time) behind site.show_build, and the acrylic display theme.
This commit is contained in:
1 parent
10634bdd80
commit
14b0de3544
95 files changed
+5524
-528
No files matched your search
+46
-3
@@ -1,7 +1,50 @@
|
||||
// 同时启动展示端(5173)和管理端(5174/admin/);Ctrl+C 一起退出。
|
||||
// 同时启动展示端(5173)和管理端(5175,经展示端的 /admin/ 访问);Ctrl+C 一起退出。
|
||||
// 不经过 shell:直接用 node 跑各自目录下的 vite,输出带前缀,端口被占时直接报错。
|
||||
import { spawn } from 'node:child_process'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const children = ['display', 'admin'].map((name) => spawn('npm', ['run', 'dev', '-w', name], { stdio: 'inherit', shell: true }))
|
||||
const stop = () => children.forEach((c) => c.kill())
|
||||
const vite = fileURLToPath(new URL('./node_modules/vite/bin/vite.js', import.meta.url))
|
||||
|
||||
// 颜色:和 Vite 自己的输出一致(绿色的 ➜、青色/蓝色的链接);设了 NO_COLOR 就不上色
|
||||
const color = !process.env.NO_COLOR
|
||||
const paint = (code, text) => (color ? `[${code}m${text}[0m` : text)
|
||||
const bold = (t) => paint('1', t)
|
||||
const dim = (t) => paint('2', t)
|
||||
const green = (t) => paint('32', t)
|
||||
const cyan = (t) => paint('36', t)
|
||||
const magenta = (t) => paint('35', t)
|
||||
const link = (url) => paint('36;4', url)
|
||||
|
||||
const apps = [
|
||||
{ name: 'display', tint: cyan, cwd: fileURLToPath(new URL('./display/', import.meta.url)) },
|
||||
{ name: 'admin ', tint: magenta, cwd: fileURLToPath(new URL('./admin/', import.meta.url)) },
|
||||
]
|
||||
|
||||
console.log('')
|
||||
console.log(` ${green('➜')} ${bold('展示端')} ${link('http://localhost:5173/')}`)
|
||||
console.log(` ${green('➜')} ${bold('管理端')} ${link('http://localhost:5173/admin/')} ${dim('(也可以直接开 http://localhost:5175/admin/)')}`)
|
||||
console.log('')
|
||||
|
||||
const children = apps.map(({ name, tint, cwd }) => {
|
||||
const child = spawn(process.execPath, [vite], { cwd, stdio: ['inherit', 'pipe', 'pipe'], env: { ...process.env, ...(color ? { FORCE_COLOR: '1' } : {}) } })
|
||||
const prefix = (stream, out) =>
|
||||
stream.on('data', (chunk) => {
|
||||
for (const line of String(chunk).split(/\r?\n/)) if (line.trim()) out.write(`${tint(`[${name}]`)} ${line}\n`)
|
||||
})
|
||||
prefix(child.stdout, process.stdout)
|
||||
prefix(child.stderr, process.stderr)
|
||||
child.on('exit', (code) => {
|
||||
if (code) {
|
||||
console.error(`${tint(`[${name}]`)} ${paint('31', `退出了(${code}),一起停掉`)}`)
|
||||
stop()
|
||||
process.exitCode = code
|
||||
}
|
||||
})
|
||||
return child
|
||||
})
|
||||
|
||||
function stop() {
|
||||
for (const c of children) c.kill()
|
||||
}
|
||||
process.on('SIGINT', stop)
|
||||
process.on('exit', stop)
|
||||
Reference in new issue
Block a user