feat(登录): 新增 ?redirect= 参数,登录后跳转指定站内页面

支持 ?redirect=page/strategy/dashboard-agent(可不带前导斜杠、可自带 query),
优先级高于 taskId/goPath 深链与默认首页;仅接受站内相对路径,拒绝绝对/协议相对
URL 与反斜杠以防开放式跳转。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
fengxiangdebaoziandClaude Opus 4.8 committed 2026-06-23 21:51:59 +08:00
1 parent e263d86fc3
commit 8241f8dd6b
1 file changed
+19
+19
View File
@@ -82,6 +82,17 @@ export default function LoginPage() {
// 任务深链:外部系统带 ?taskId=&goPath= 时,登录后拉任务详情并直送对应问答/会商页
const taskId = searchParams.get('taskId')?.trim() ?? '';
const goPath = searchParams.get('goPath')?.trim() ?? '';
// 通用「登录后跳指定页」:?redirect=page/strategy/dashboard-agent(值可不带前导斜杠,
// 也可自带 query,如 page/strategy/dashboard-agent?taskId=1580——记得整体 URL 编码)。
// 优先级最高:显式指定即按它跳,先于 taskId/goPath 深链与默认首页。出于安全只接受**站内
// 相对路径**:拒绝带协议的绝对 URL(http(s):、javascript: 等)、协议相对 URL(//host)与反斜杠,
// 避免开放式跳转;缺前导斜杠时自动补全。
const redirectTo = useMemo(() => {
const raw = searchParams.get('redirect')?.trim() ?? '';
if (!raw) return '';
if (/^[a-z][a-z0-9+.-]*:/i.test(raw) || raw.startsWith('//') || raw.includes('\\')) return '';
return raw.startsWith('/') ? raw : `/${raw}`;
}, [searchParams]);
const externalParams = useMemo(
() => ({
theme: searchParams.get('theme') ?? '',
@@ -186,6 +197,13 @@ export default function LoginPage() {
if (!isEmbed) persistSidebarEnabled(sidebarEnabled);
setStatus('success');
// 通用跳转:显式 ?redirect= 指定站内页面时,登录后直接跳过去(优先级最高,
// 先于 taskId/goPath 深链与默认首页)。value 自带的 query 会被原样保留。
if (redirectTo) {
navigate(redirectTo, { replace: true });
return;
}
// 任务深链:带 taskId + goPath 时拉任务详情并直送对应问答/会商页;
// 任一环节失败(无地址/拉取失败/未配置智能体/goPath 无法识别)都回退默认首页。
if (taskId && goPath) {
@@ -238,6 +256,7 @@ export default function LoginPage() {
gatePassword,
taskId,
goPath,
redirectTo,
isEmbed,
]);