u
This commit is contained in:
1 parent
15e0ae5b67
commit
e434374db5
71 files changed
+5726
-329
No files matched your search
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* 开发期取 token —— 给 AI / 脚本 / 命令行用,不必开浏览器点登录。
|
||||
*
|
||||
* 用法(在仓库根目录执行):
|
||||
* node scripts/dev-login.mjs # 用 web/.env.development 里的账号
|
||||
* node scripts/dev-login.mjs G3HD g3soft # 指定机构码 + 账号
|
||||
* node scripts/dev-login.mjs G3HD g3soft pwd # 再指定密码
|
||||
* node scripts/dev-login.mjs --token-only # 只输出 token 一行,便于 $(...) 取值
|
||||
* node scripts/dev-login.mjs --target http://127.0.0.1:8088
|
||||
*
|
||||
* 直接打后端(默认 127.0.0.1:8088),不经过 Vite 代理。
|
||||
*
|
||||
* ⚠️ 同一账号重复登录会互踢(后端 ActiveSessionRegistry,业务码 40101):
|
||||
* 这个脚本每跑一次就会把该账号上一个会话踢下线。别在别人正用同一账号时跑。
|
||||
*/
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import path from 'node:path'
|
||||
|
||||
const ROOT = fileURLToPath(new URL('..', import.meta.url))
|
||||
const ENV_FILE = path.join(ROOT, 'web', '.env.development')
|
||||
|
||||
/* ---------------- 读取 web/.env.development 作为默认值 ---------------- */
|
||||
|
||||
function readEnvValue(key) {
|
||||
try {
|
||||
for (const line of readFileSync(ENV_FILE, 'utf8').split(/\r?\n/)) {
|
||||
const match = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(line)
|
||||
if (match && match[1] === key) {
|
||||
return match[2].trim().replace(/^(['"])(.*)\1$/, '$2')
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// 文件不存在:回落到内置默认值,下面还会打印提示
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
/* ---------------- 参数 ---------------- */
|
||||
|
||||
const positional = []
|
||||
let target = ''
|
||||
let tokenOnly = false
|
||||
|
||||
const args = process.argv.slice(2)
|
||||
for (let i = 0; i < args.length; i += 1) {
|
||||
if (args[i] === '--target') {
|
||||
target = args[i + 1] ?? ''
|
||||
i += 1
|
||||
} else if (args[i] === '--token-only') {
|
||||
tokenOnly = true
|
||||
} else {
|
||||
positional.push(args[i])
|
||||
}
|
||||
}
|
||||
|
||||
const base = (target || process.env.VITE_PROXY_TARGET || 'http://127.0.0.1:8088').replace(/\/+$/, '')
|
||||
const orgId = positional[0] || readEnvValue('VITE_DEV_ORG') || 'G3HD'
|
||||
const account = positional[1] || readEnvValue('VITE_DEV_ACCOUNT') || 'g3soft'
|
||||
const password = positional[2] ?? readEnvValue('VITE_DEV_PASSWORD')
|
||||
|
||||
/* ---------------- 登录 ---------------- */
|
||||
|
||||
let body
|
||||
try {
|
||||
const response = await fetch(`${base}/api/auth/login`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ orgid: orgId, userid: account, password }),
|
||||
})
|
||||
body = await response.json()
|
||||
} catch (error) {
|
||||
console.error(`连不上后端 ${base}:${error.message}`)
|
||||
console.error('先在 server/ 下起后端(legacy TLS 用这条):')
|
||||
console.error(' mvn "-Dspring-boot.run.jvmArguments=-Djava.security.properties=./config/legacy-tls.security" spring-boot:run')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
/* 后端鉴权失败返回 HTTP 200 + body.code=401(不是 HTTP 401),两个都要判。 */
|
||||
if (body?.code !== 0 || !body?.data?.token) {
|
||||
console.error(`登录失败(code=${body?.code}):${body?.message || '响应里没有 token'}`)
|
||||
console.error(`用的账号:机构码 ${orgId} / 账号 ${account}${password ? ' / 密码已填' : ' / 密码为空'}`)
|
||||
console.error('账号密码来自 web/.env.development 的 VITE_DEV_*,也可命令行覆盖。')
|
||||
console.error('超管 g3soft 的密码在库里是空串;若你的库不是,传第三个参数指定密码。')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const { token, user } = body.data
|
||||
|
||||
/* ---------------- 输出 ---------------- */
|
||||
|
||||
if (tokenOnly) {
|
||||
process.stdout.write(`${token}\n`)
|
||||
} else {
|
||||
console.log(`已登录:${orgId}/${account}(${user?.name || '未命名'})`)
|
||||
console.log('')
|
||||
console.log('token:')
|
||||
console.log(token)
|
||||
console.log('')
|
||||
console.log('直接调业务接口(浏览器里不用这个,开发期页面已自动登录):')
|
||||
console.log(` curl -H "Authorization: Bearer ${token}" ${base}/api/data/loaddata`)
|
||||
}
|
||||
Reference in new issue
Block a user