统一外部 access_token 存储与轻应用 URL 拼接,修复嵌入会话鉴权隔离。
将 access_token 纳入 scoped storage 迁移,yUserId 登录优先并独立持久化 token;轻应用/按钮管理默认改用 access_token 参数名,支持 hash 路由占位符替换与自动追加。
This commit is contained in:
1 parent
8c6d08d6bf
commit
6378cd33bd
10 files changed
+210
-39
No files matched your search
@@ -49,7 +49,7 @@ interface ServerButton {
|
||||
function toLoginParam(p: ServerLoginParam): TaskButtonLoginParam {
|
||||
return {
|
||||
key: p.key ?? "",
|
||||
source: p.source || "accessToken",
|
||||
source: p.source || "access_token",
|
||||
customValue: p.custom_value ?? "",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
platformTypeChange,
|
||||
} from './GeneralQA.mock';
|
||||
import { requestCrudService } from '@/service/request-axios-service';
|
||||
import { authStorageGet } from '@/core/auth/scoped-storage';
|
||||
|
||||
/**
|
||||
* 通用问答组件
|
||||
@@ -138,7 +139,7 @@ const GeneralQA: React.FC<{
|
||||
const mockSingleRoundStoppedRef = useRef(false);
|
||||
const mockMultiRoundStoppedRef = useRef(false);
|
||||
const chatListRef = useRef<HTMLDivElement | null>(null);
|
||||
const userId = useRef(localStorage.getItem('userId') || '387'); // 用户id
|
||||
const userId = useRef(authStorageGet('userId') || '387'); // 用户id
|
||||
const qaType = useRef('GENERAL'); // 问答类型
|
||||
const chatDataId = useRef(); // 聊天窗口id
|
||||
const compareChatId = useRef(); // 对比对话记录id
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import type { LightApp, LightAppRouteParam } from "@/strategy-components/api/light-apps";
|
||||
import { authStorageGet } from "@/core/auth/scoped-storage";
|
||||
import { normalizeExternalAccessToken } from "@/core/auth/external-access-token";
|
||||
import { readCurrentExternalAccessTokenValue } from "@/core/auth/external-access-token";
|
||||
|
||||
/** iframe 可挂载的父菜单(取自 core/page-layout/sidebar-menu.ts 的现有菜单 id)。 */
|
||||
export const MOUNT_OPTIONS: { label: string; value: string }[] = [
|
||||
@@ -29,7 +29,8 @@ export function mountLabel(value: string | null | undefined): string {
|
||||
* userName / gateDepartName / typeName 取 consumer 接口 userDetailByYuserId 的返回值。
|
||||
*/
|
||||
export const LOGIN_SOURCE_OPTIONS: { label: string; value: string }[] = [
|
||||
{ label: "accessToken", value: "accessToken" },
|
||||
{ label: "access_token", value: "access_token" },
|
||||
{ label: "accessToken(兼容旧配置)", value: "accessToken" },
|
||||
{ label: "yUserId", value: "yUserId" },
|
||||
{ label: "userName", value: "userName" },
|
||||
{ label: "gateDepartName", value: "gateDepartName" },
|
||||
@@ -143,8 +144,8 @@ export function resolveRouteParamValue(
|
||||
}
|
||||
if (param.source) {
|
||||
const value = userInfo[param.source];
|
||||
if (param.source === "accessToken") {
|
||||
return normalizeExternalAccessToken(value);
|
||||
if (param.source === "access_token" || param.source === "accessToken") {
|
||||
return readCurrentExternalAccessTokenValue(userInfo);
|
||||
}
|
||||
return value == null ? "" : String(value);
|
||||
}
|
||||
@@ -157,15 +158,50 @@ export function resolveRouteParamValue(
|
||||
* 兼容 hash 路由地址(如 `https://x#/route`)—— 管理员粘贴完整地址,参数自动追加在末尾,
|
||||
* 落在 hash 路由的 query 上(与现有 XK/PG 页面 `?accessToken=` 拼接方式一致)。
|
||||
*/
|
||||
function appendQueryPairs(url: string, pairs: string[]): string {
|
||||
if (pairs.length === 0) return url;
|
||||
const hashIndex = url.indexOf("#");
|
||||
if (hashIndex >= 0) {
|
||||
const beforeHash = url.slice(0, hashIndex);
|
||||
const hash = url.slice(hashIndex);
|
||||
const sep = hash.includes("?") ? "&" : "?";
|
||||
return `${beforeHash}${hash}${sep}${pairs.join("&")}`;
|
||||
}
|
||||
const sep = url.includes("?") ? "&" : "?";
|
||||
return `${url}${sep}${pairs.join("&")}`;
|
||||
}
|
||||
|
||||
function replaceAccessTokenParam(url: string, accessToken: string): { url: string; replaced: boolean } {
|
||||
if (!accessToken) return { url, replaced: false };
|
||||
let replaced = false;
|
||||
const nextUrl = url.replace(/([?&]access_token)(?:=[^&#]*)?(?=[&#]|$)/g, (match) => {
|
||||
replaced = true;
|
||||
return `${match.split("=")[0]}=${encodeURIComponent(accessToken)}`;
|
||||
});
|
||||
return { url: nextUrl, replaced };
|
||||
}
|
||||
|
||||
export function buildLightAppUrl(
|
||||
app: Pick<LightApp, "url" | "routeParams">,
|
||||
userInfo: Record<string, unknown> = readUserInfo(),
|
||||
theme?: AppThemeColor,
|
||||
): string {
|
||||
const pairs = (app.routeParams ?? [])
|
||||
.filter((p) => p.key)
|
||||
.map((p) => `${encodeURIComponent(p.key)}=${encodeURIComponent(resolveRouteParamValue(p, userInfo, theme))}`);
|
||||
if (pairs.length === 0) return app.url;
|
||||
const sep = app.url.includes("?") ? "&" : "?";
|
||||
return `${app.url}${sep}${pairs.join("&")}`;
|
||||
const routeParams = app.routeParams ?? [];
|
||||
const accessToken = readCurrentExternalAccessTokenValue(userInfo);
|
||||
const tokenUrlResult = replaceAccessTokenParam(app.url, accessToken);
|
||||
const pairs = routeParams
|
||||
.filter((p) => (p.key ?? "").trim())
|
||||
.filter((p) => (p.key ?? "").trim() !== "access_token" || !tokenUrlResult.replaced)
|
||||
.map((p) => {
|
||||
const key = (p.key ?? "").trim();
|
||||
const value = key === "access_token" ? accessToken : resolveRouteParamValue(p, userInfo, theme);
|
||||
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
||||
});
|
||||
const hasAccessTokenParam =
|
||||
tokenUrlResult.replaced ||
|
||||
routeParams.some((p) => (p.key ?? "").trim() === "access_token");
|
||||
if (!hasAccessTokenParam && accessToken) {
|
||||
pairs.push(`${encodeURIComponent("access_token")}=${encodeURIComponent(accessToken)}`);
|
||||
}
|
||||
return appendQueryPairs(tokenUrlResult.url, pairs);
|
||||
}
|
||||
Reference in new issue
Block a user