fix: 修复分享链接路由与登录回跳

- 统一生成包含部署基路径和 Hash 路由的知识库、工作流分享地址

- 未登录访问分享页时保留目标地址,并在登录成功后自动回跳

- 限定分享密钥作用域并补充失效、加载失败及回归测试
This commit is contained in:
2026-07-24 16:00:57 +08:00
parent 41545fcef0
commit 526e16163b
15 changed files with 465 additions and 71 deletions

View File

@@ -1,4 +1,5 @@
import { api } from '#/api/request';
import { readScopedRouteQueryParam } from '#/utils/share-route-context';
const EXPIRED_ERROR_CODES = new Set([4601, 4602]);
const SHARE_ERROR_REASON: Record<number, string> = {
@@ -8,8 +9,8 @@ const SHARE_ERROR_REASON: Record<number, string> = {
const APP_BASE_PATH = (import.meta.env.BASE_URL || '/').replace(/\/$/, '');
function getShareParams() {
const params = new URLSearchParams(window.location.search);
const shareKey = params.get('shareKey') || '';
const shareKey =
readScopedRouteQueryParam('/share/knowledge', 'shareKey') || '';
return { shareKey };
}
@@ -36,9 +37,12 @@ function redirectIfExpired(response: any) {
return response;
}
const reason = SHARE_ERROR_REASON[errorCode] || 'expired';
window.location.assign(
`${APP_BASE_PATH}/share/knowledge/expired?reason=${reason}`,
);
const route = `/share/knowledge/expired?reason=${encodeURIComponent(reason)}`;
const target =
import.meta.env.VITE_ROUTER_HISTORY === 'hash'
? `${APP_BASE_PATH}/#${route}`
: `${APP_BASE_PATH}${route}`;
window.location.assign(target);
return response;
}

View File

@@ -20,6 +20,7 @@ import { events } from 'fetch-event-stream';
import { useAuthStore } from '#/store';
import {
isWorkflowShareRequest,
readWorkflowShareKey,
withWorkflowShareHeader,
WORKFLOW_SHARE_HEADER,
@@ -101,7 +102,10 @@ function createRequestClient(baseURL: string, options?: RequestClientOptions) {
config.headers['easyflow-token'] = formatToken(accessStore.accessToken);
config.headers['Accept-Language'] = preferences.app.locale;
const workflowShareKey = readWorkflowShareKey();
if (workflowShareKey) {
if (
workflowShareKey &&
isWorkflowShareRequest(config.url, config.method)
) {
config.headers[WORKFLOW_SHARE_HEADER] = workflowShareKey;
}
return config;
@@ -196,7 +200,7 @@ export class SseClient {
const res = await fetch(apiURL + url, {
method: 'POST',
signal, // 使用局部变量 signal
headers: this.getHeaders(options?.headers),
headers: this.getHeaders(url, options?.headers),
body: JSON.stringify(data),
});
@@ -265,7 +269,7 @@ export class SseClient {
}
}
private getHeaders(extraHeaders?: HeadersInit) {
private getHeaders(requestUrl: string, extraHeaders?: HeadersInit) {
const accessStore = useAccessStore();
const headers: Record<string, string> = {
Accept: 'text/event-stream',
@@ -277,7 +281,10 @@ export class SseClient {
headers[key] = value;
});
}
return withWorkflowShareHeader(headers);
return withWorkflowShareHeader(headers, {
requestMethod: 'POST',
requestUrl,
});
}
}