feat:0666账号密码自动登录刷新Token

This commit is contained in:
2026-11-03 12:13:39 +08:00
parent 4dbec33dbd
commit f69cdc6d8e
12 changed files with 741 additions and 11 deletions
+8
View File
@@ -580,6 +580,10 @@ export interface RockConfig {
auto_purchase_enabled: boolean;
auto_purchase_count: number;
purchase_cooldown_minutes: number;
login_username?: string;
login_password_set?: boolean;
last_token_refresh_at?: string;
last_token_error?: string;
last_purchased_at?: string;
last_heartbeat_at?: string;
}
@@ -786,6 +790,10 @@ export const rockApi = {
request
.post("/platform/rock/test-conn", { bearer_token })
.then((r) => r.data.data),
testLogin: (data: { username?: string; password?: string }) =>
request
.post("/platform/rock/login-test", data)
.then((r) => r.data.data as { username: string; role: string; points: number }),
getStats: () =>
request.get("/platform/rock/stats").then((r) => r.data.data as RockStats),
refreshDashboard: () =>
+26
View File
@@ -31,6 +31,7 @@ export default function PlatformRock() {
const [upstreamStock, setUpstreamStock] = useState<number | null>(null)
const [loadingStats, setLoadingStats] = useState(false)
const [testingConn, setTestingConn] = useState(false)
const [testingLogin, setTestingLogin] = useState(false)
const [savingConfig, setSavingConfig] = useState(false)
const [autoPurchaseEnabled, setAutoPurchaseEnabled] = useState(false)
const [togglingAutoPurchase, setTogglingAutoPurchase] = useState(false)
@@ -81,6 +82,7 @@ export default function PlatformRock() {
auto_delivery_enabled: cfg.auto_delivery_enabled,
base_url: cfg.base_url,
bearer_token: cfg.bearer_token,
login_username: cfg.login_username,
min_points_warning: cfg.min_points_warning,
token_warning_stock: cfg.token_warning_stock,
using_warn_days: cfg.using_warn_days ?? 3,
@@ -188,10 +190,29 @@ export default function PlatformRock() {
}
}
// 测试上游账号密码登录(只验证,不保存 token)
const handleTestLogin = async () => {
const username = form.getFieldValue('login_username') as string | undefined
const password = form.getFieldValue('login_password') as string | undefined
setTestingLogin(true)
try {
const res = await rockApi.testLogin({ username, password })
message.success(`登录成功:${res.username}(${res.role}),积分 ${res.points}`)
} catch (e) {
message.error('测试登录失败: ' + (e instanceof Error ? e.message : '未知错误'))
} finally {
setTestingLogin(false)
}
}
// 保存策略配置
const handleSaveConfig = async () => {
try {
const values = await form.validateFields()
// 密码留空表示不修改,避免每次保存都清空已保存的密文
if (!values.login_password) {
delete values.login_password
}
setSavingConfig(true)
const updated = await rockApi.updateConfig(values)
setConfig(updated)
@@ -369,6 +390,11 @@ export default function PlatformRock() {
autoPurchaseEnabled={autoPurchaseEnabled}
autoPurchaseCoolingSeconds={stats?.auto_purchase_cooldown_seconds ?? 0}
nextAutoPurchaseAt={stats?.next_auto_purchase_at}
loginPasswordSet={config?.login_password_set}
lastTokenRefreshAt={config?.last_token_refresh_at}
lastTokenError={config?.last_token_error}
testingLogin={testingLogin}
onTestLogin={handleTestLogin}
togglingAutoPurchase={togglingAutoPurchase}
testingConn={testingConn}
savingConfig={savingConfig}
@@ -21,6 +21,7 @@ import {
SafetyCertificateOutlined,
ThunderboltOutlined,
} from '@ant-design/icons'
import { formatDateTime } from '../../utils/time'
const { Text } = Typography
@@ -30,6 +31,11 @@ export interface RockStrategyCardProps {
autoPurchaseEnabled: boolean
autoPurchaseCoolingSeconds?: number
nextAutoPurchaseAt?: string
loginPasswordSet?: boolean
lastTokenRefreshAt?: string
lastTokenError?: string
testingLogin: boolean
onTestLogin: () => void
togglingAutoPurchase: boolean
testingConn: boolean
savingConfig: boolean
@@ -45,6 +51,11 @@ export function RockStrategyCard({
autoPurchaseEnabled,
autoPurchaseCoolingSeconds,
nextAutoPurchaseAt,
loginPasswordSet,
lastTokenRefreshAt,
lastTokenError,
testingLogin,
onTestLogin,
togglingAutoPurchase,
testingConn,
savingConfig,
@@ -170,7 +181,7 @@ export function RockStrategyCard({
label={
<Space>
<span>上游商户 Bearer Token (yd_token)</span>
<Tooltip title="0666.pro 采用无密码架构,直接从网页 localStorage 提取 64 位十六进制 Token 即可">
<Tooltip title="Token 失效时自动使用下方账号密码登录刷新;手动粘贴的 Token 会被自动登录覆盖">
<ExclamationCircleOutlined style={{ color: '#94a3b8' }} />
</Tooltip>
</Space>
@@ -196,6 +207,59 @@ export function RockStrategyCard({
/>
</Form.Item>
<Row gutter={12}>
<Col span={12}>
<Form.Item
name="login_username"
label="上游登录账号"
style={{ marginBottom: 12 }}
>
<Input
placeholder="0666.pro 登录账号"
autoComplete="off"
name="upstream_login_username"
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="login_password"
label="上游登录密码"
style={{ marginBottom: 12 }}
extra={
loginPasswordSet
? '已保存密码,留空表示不修改'
: '用于 Token 失效后自动登录'
}
>
<Input.Password
placeholder={loginPasswordSet ? '已保存,留空不修改' : '请输入密码'}
autoComplete="new-password"
name="upstream_login_password"
/>
</Form.Item>
</Col>
</Row>
<Space wrap style={{ marginBottom: 12 }}>
<Button size="small" onClick={onTestLogin} loading={testingLogin}>
测试登录
</Button>
{lastTokenError ? (
<Text type="danger" style={{ fontSize: 12 }}>
Token 刷新失败:{lastTokenError}
</Text>
) : lastTokenRefreshAt ? (
<Text type="secondary" style={{ fontSize: 12 }}>
Token 上次刷新:{formatDateTime(lastTokenRefreshAt)}
</Text>
) : (
<Text type="secondary" style={{ fontSize: 12 }}>
尚未自动刷新 Token
</Text>
)}
</Space>
<div
style={{
background: '#eff6ff',
@@ -206,11 +270,11 @@ export function RockStrategyCard({
color: '#1e40af',
}}
>
💡 <strong>极简提取指引:</strong>登录 0666.pro 网页后,按 F12 打开控制台,在 Console 执行{' '}
💡 <strong>Token 兜底:</strong>自动登录失败时,可登录 0666.pro 网页按 F12 打开控制台,执行{' '}
<Text code copyable={{ text: "localStorage.getItem('yd_token')" }}>
localStorage.getItem('yd_token')
</Text>{' '}
即可一键复制。
手动粘贴到上方。
</div>
</div>
</Col>