feat:0666账号密码自动登录刷新Token
This commit is contained in:
@@ -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: () =>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user