lgsso-sdk 1.2.7 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lgsso-sdk.cjs +249 -113
- package/dist/lgsso-sdk.esm.js +249 -113
- package/dist/lgsso-sdk.js +249 -113
- package/dist/lgsso-sdk.min.js +1 -1
- package/package.json +1 -1
- package/src/sso.js +213 -98
- package/src/utils.js +36 -15
package/dist/lgsso-sdk.cjs
CHANGED
|
@@ -5,8 +5,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
/*
|
|
6
6
|
* @Author: Robin LEI
|
|
7
7
|
* @Date: 2025-08-21 15:09:15
|
|
8
|
-
* @LastEditTime:
|
|
9
|
-
* @FilePath: \
|
|
8
|
+
* @LastEditTime: 2026-01-23 11:28:26
|
|
9
|
+
* @FilePath: \lims-frontd:\业务代码\中联钢信\五服一管\lg-ssosdk\src\utils.js
|
|
10
10
|
*/
|
|
11
11
|
/**
|
|
12
12
|
* 检查是否在浏览器环境
|
|
@@ -42,38 +42,58 @@ function getQueryParam(name, url) {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
|
-
* 移除URL
|
|
46
|
-
* @param {string}
|
|
45
|
+
* 移除URL中的指定参数(支持单个或多个)
|
|
46
|
+
* @param {string|string[]} names - 要删除的参数名(单个字符串或字符串数组)
|
|
47
47
|
*/
|
|
48
|
-
function removeQueryParam(
|
|
48
|
+
function removeQueryParam(names) {
|
|
49
49
|
if (!isBrowser()) return;
|
|
50
50
|
|
|
51
|
+
// 统一转为数组,兼容单个参数的调用方式
|
|
52
|
+
const paramNames = Array.isArray(names) ? names : [names];
|
|
53
|
+
if (paramNames.length === 0) return; // 无参数需删除时直接返回
|
|
54
|
+
|
|
51
55
|
const url = new URL(window.location.href);
|
|
52
|
-
let
|
|
56
|
+
let newUrl;
|
|
53
57
|
|
|
54
58
|
// 处理hash模式(参数在#之后)
|
|
55
59
|
if (url.hash.includes('?')) {
|
|
56
60
|
const [hashPath, hashQuery] = url.hash.split('?');
|
|
57
|
-
params = new URLSearchParams(hashQuery);
|
|
61
|
+
const params = new URLSearchParams(hashQuery);
|
|
62
|
+
|
|
63
|
+
// 批量删除参数
|
|
64
|
+
paramNames.forEach(name => {
|
|
65
|
+
if (params.has(name)) {
|
|
66
|
+
params.delete(name);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
58
69
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
70
|
+
// 重构hash部分
|
|
71
|
+
const newHash = params.toString() ? `${hashPath}?${params.toString()}` : hashPath;
|
|
72
|
+
if (newHash !== url.hash) { // 只有hash变化时才更新URL
|
|
62
73
|
url.hash = newHash;
|
|
63
74
|
newUrl = url.toString();
|
|
64
75
|
}
|
|
65
76
|
}
|
|
66
77
|
// 处理history模式(参数在?之后)
|
|
67
78
|
else {
|
|
68
|
-
params = new URLSearchParams(url.search);
|
|
69
|
-
|
|
70
|
-
|
|
79
|
+
const params = new URLSearchParams(url.search);
|
|
80
|
+
let hasChanged = false;
|
|
81
|
+
|
|
82
|
+
// 批量删除参数
|
|
83
|
+
paramNames.forEach(name => {
|
|
84
|
+
if (params.has(name)) {
|
|
85
|
+
params.delete(name);
|
|
86
|
+
hasChanged = true;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// 只有参数变化时才更新URL
|
|
91
|
+
if (hasChanged) {
|
|
71
92
|
url.search = params.toString();
|
|
72
93
|
newUrl = url.toString();
|
|
73
94
|
}
|
|
74
95
|
}
|
|
75
|
-
|
|
76
|
-
// 更新URL
|
|
96
|
+
// 更新URL(仅当URL有变化时)
|
|
77
97
|
if (newUrl && newUrl !== window.location.href) {
|
|
78
98
|
window.location.replace(newUrl);
|
|
79
99
|
}
|
|
@@ -96,6 +116,7 @@ function getCurrentUrlWithParams() {
|
|
|
96
116
|
*/
|
|
97
117
|
function mergeConfigs(defaults, options) {
|
|
98
118
|
if (!options) return { ...defaults };
|
|
119
|
+
|
|
99
120
|
const merged = { ...defaults };
|
|
100
121
|
for (const key in options) {
|
|
101
122
|
if (options.hasOwnProperty(key)) {
|
|
@@ -4040,6 +4061,93 @@ async function request(url, {
|
|
|
4040
4061
|
}
|
|
4041
4062
|
}
|
|
4042
4063
|
|
|
4064
|
+
// ===== Cookie操作工具函数 =====
|
|
4065
|
+
/**
|
|
4066
|
+
* 获取指定名称的Cookie值
|
|
4067
|
+
* @param {string} name Cookie名称
|
|
4068
|
+
* @returns {string|null} Cookie值
|
|
4069
|
+
*/
|
|
4070
|
+
function getCookie(name) {
|
|
4071
|
+
if (!isBrowser()) return null;
|
|
4072
|
+
const match = document.cookie.match(new RegExp(`(^| )${name}=([^;]+)`));
|
|
4073
|
+
return match ? decodeURIComponent(match[2]) : null;
|
|
4074
|
+
}
|
|
4075
|
+
|
|
4076
|
+
/**
|
|
4077
|
+
* 设置Cookie(支持指定根域名)
|
|
4078
|
+
* @param {string} name Cookie名称
|
|
4079
|
+
* @param {string} value Cookie值
|
|
4080
|
+
* @param {Object} options 配置(expires: 过期天数/Date, path: 路径, domain: 域名)
|
|
4081
|
+
*/
|
|
4082
|
+
function setCookie(name, value, options = {}) {
|
|
4083
|
+
if (!isBrowser()) return;
|
|
4084
|
+
let cookieStr = `${name}=${encodeURIComponent(value)}`;
|
|
4085
|
+
|
|
4086
|
+
// 路径:默认根路径,确保全站可用
|
|
4087
|
+
cookieStr += `; path=${options.path || '/'}`;
|
|
4088
|
+
|
|
4089
|
+
// 域名:指定根域名.zlgx.com(适配你的场景)
|
|
4090
|
+
// 优先级:用户传入的domain > 默认根域名.zlgx.com
|
|
4091
|
+
const targetDomain = options.domain || '.zlgx.com';
|
|
4092
|
+
cookieStr += `; domain=${targetDomain}`;
|
|
4093
|
+
|
|
4094
|
+
// 过期时间(默认1天)
|
|
4095
|
+
if (options.expires) {
|
|
4096
|
+
const expires = typeof options.expires === 'number'
|
|
4097
|
+
? new Date(Date.now() + options.expires * 86400000)
|
|
4098
|
+
: options.expires;
|
|
4099
|
+
cookieStr += `; expires=${expires.toUTCString()}`;
|
|
4100
|
+
}
|
|
4101
|
+
|
|
4102
|
+
// 可选:HTTPS环境下添加Secure(仅HTTPS传输)
|
|
4103
|
+
if (options.secure || window.location.protocol === 'https:') {
|
|
4104
|
+
cookieStr += '; Secure';
|
|
4105
|
+
}
|
|
4106
|
+
|
|
4107
|
+
// 可选:防止XSS攻击的HttpOnly(注意:HttpOnly的Cookie无法通过JS读取)
|
|
4108
|
+
if (options.httpOnly) {
|
|
4109
|
+
cookieStr += '; HttpOnly';
|
|
4110
|
+
}
|
|
4111
|
+
|
|
4112
|
+
document.cookie = cookieStr;
|
|
4113
|
+
}
|
|
4114
|
+
|
|
4115
|
+
function removeCookie(name, options = {}) {
|
|
4116
|
+
if (!isBrowser()) return;
|
|
4117
|
+
setCookie(
|
|
4118
|
+
name,
|
|
4119
|
+
'',
|
|
4120
|
+
{
|
|
4121
|
+
expires: -1, // 立即过期
|
|
4122
|
+
path: options.path || '/',
|
|
4123
|
+
domain: options.domain || '.zlgx.com' // 必须和设置时一致
|
|
4124
|
+
}
|
|
4125
|
+
);
|
|
4126
|
+
}
|
|
4127
|
+
|
|
4128
|
+
// 调用示例:删除根域名下的platType
|
|
4129
|
+
removeCookie('platType', { domain: '.zlgx.com' });
|
|
4130
|
+
|
|
4131
|
+
/**
|
|
4132
|
+
* 给重定向地址拼接platType参数
|
|
4133
|
+
* @param {string} redirectUrl 原始重定向地址
|
|
4134
|
+
* @param {string} platType platType值
|
|
4135
|
+
* @param {string} platTypeKey 参数名(默认platType)
|
|
4136
|
+
* @returns {string} 拼接后的重定向地址
|
|
4137
|
+
*/
|
|
4138
|
+
function addPlatTypeToRedirectUrl(redirectUrl, platType, platTypeKey = 'platType') {
|
|
4139
|
+
if (!redirectUrl || !platType) return redirectUrl;
|
|
4140
|
+
try {
|
|
4141
|
+
const url = new URL(redirectUrl);
|
|
4142
|
+
url.searchParams.set(platTypeKey, platType);
|
|
4143
|
+
return url.toString();
|
|
4144
|
+
} catch (e) {
|
|
4145
|
+
// 兼容非标准URL的情况(比如相对路径)
|
|
4146
|
+
const separator = redirectUrl.includes('?') ? '&' : '?';
|
|
4147
|
+
return `${redirectUrl}${separator}${platTypeKey}=${platType}`;
|
|
4148
|
+
}
|
|
4149
|
+
}
|
|
4150
|
+
|
|
4043
4151
|
// 默认配置
|
|
4044
4152
|
const DEFAULT_CONFIG = {
|
|
4045
4153
|
accessCodeKey: 'accessCode',
|
|
@@ -4050,13 +4158,14 @@ const DEFAULT_CONFIG = {
|
|
|
4050
4158
|
refreshCodeApi: '',
|
|
4051
4159
|
logoutApi: '',
|
|
4052
4160
|
logOutUrl: '',
|
|
4053
|
-
storage: localStorage,
|
|
4161
|
+
storage: localStorage,
|
|
4054
4162
|
oldPwdKey: 'oldPwd',
|
|
4055
4163
|
newPwdKey: 'newPwd',
|
|
4056
4164
|
changePasswordApi: '',
|
|
4057
4165
|
sendCaptchaCodeApi: '',
|
|
4058
4166
|
typeKey: 'type',
|
|
4059
|
-
codeKey: 'code'
|
|
4167
|
+
codeKey: 'code',
|
|
4168
|
+
platTypeKey: 'platType' // platType参数名配置
|
|
4060
4169
|
};
|
|
4061
4170
|
|
|
4062
4171
|
let config = null;
|
|
@@ -4079,46 +4188,35 @@ function validateConfig(options) {
|
|
|
4079
4188
|
}
|
|
4080
4189
|
|
|
4081
4190
|
/**
|
|
4082
|
-
* 判断是否是iOS
|
|
4191
|
+
* 判断是否是iOS移动端
|
|
4083
4192
|
* @returns {boolean} 是否为iOS环境
|
|
4084
4193
|
*/
|
|
4085
4194
|
function isIOS() {
|
|
4086
|
-
|
|
4087
|
-
// if (!isBrowser()) return false;
|
|
4195
|
+
if (!isBrowser()) return false;
|
|
4088
4196
|
|
|
4089
4197
|
const userAgent = navigator.userAgent.toLowerCase();
|
|
4090
|
-
const platform = navigator.platform.toLowerCase();
|
|
4198
|
+
const platform = navigator.platform.toLowerCase();
|
|
4091
4199
|
const maxTouchPoints = navigator.maxTouchPoints || 0;
|
|
4092
|
-
const screenRatio = screen.width / screen.height;
|
|
4200
|
+
const screenRatio = screen.width / screen.height;
|
|
4093
4201
|
|
|
4094
|
-
// ========== 核心检测规则 ==========
|
|
4095
|
-
// 1. 基础规则:iPhone/iPod 直接命中(无兼容问题)
|
|
4096
4202
|
const isIphoneIpod = /iphone|ipod/.test(userAgent) && !window.MSStream;
|
|
4097
|
-
|
|
4098
|
-
// 2. iPad 专属检测(覆盖所有iPad机型,含iPad Air)
|
|
4099
4203
|
const isIpad = (
|
|
4100
|
-
// 场景1:老版本iPadOS/原生标识(platform含ipad)
|
|
4101
4204
|
platform.includes('ipad') ||
|
|
4102
|
-
// 场景2:iPadOS 13+ 伪装Mac(UA含macintosh + 触摸+ 非Mac平台)
|
|
4103
4205
|
(
|
|
4104
|
-
userAgent.includes('macintosh') &&
|
|
4105
|
-
maxTouchPoints > 0 &&
|
|
4106
|
-
!platform.includes('mac') &&
|
|
4206
|
+
userAgent.includes('macintosh') &&
|
|
4207
|
+
maxTouchPoints > 0 &&
|
|
4208
|
+
!platform.includes('mac') &&
|
|
4107
4209
|
!window.MSStream
|
|
4108
4210
|
) ||
|
|
4109
|
-
// 场景3:新版本iPadOS(UA直接含ipados,如iPad Air搭载的iPadOS 15+)
|
|
4110
4211
|
userAgent.includes('ipados') ||
|
|
4111
|
-
// 场景4:极端场景(第三方浏览器如Chrome for iPad Air)
|
|
4112
4212
|
(
|
|
4113
|
-
maxTouchPoints >= 5 &&
|
|
4114
|
-
!platform.includes('android') &&
|
|
4115
|
-
(screenRatio > 0.7 && screenRatio < 1.4)
|
|
4213
|
+
maxTouchPoints >= 5 &&
|
|
4214
|
+
!platform.includes('android') &&
|
|
4215
|
+
(screenRatio > 0.7 && screenRatio < 1.4)
|
|
4116
4216
|
)
|
|
4117
4217
|
);
|
|
4118
4218
|
|
|
4119
|
-
|
|
4120
|
-
const result = isIphoneIpod || isIpad;
|
|
4121
|
-
return result;
|
|
4219
|
+
return isIphoneIpod || isIpad;
|
|
4122
4220
|
}
|
|
4123
4221
|
|
|
4124
4222
|
/**
|
|
@@ -4138,9 +4236,17 @@ function createSSO() {
|
|
|
4138
4236
|
config = mergeConfigs(DEFAULT_CONFIG, options);
|
|
4139
4237
|
validateConfig(config);
|
|
4140
4238
|
|
|
4239
|
+
// 初始化时检测URL中的platType并存入Cookie
|
|
4240
|
+
if (isBrowser()) {
|
|
4241
|
+
const platTypeFromUrl = getQueryParam(config.platTypeKey);
|
|
4242
|
+
if (platTypeFromUrl) {
|
|
4243
|
+
setCookie(config.platTypeKey, platTypeFromUrl);
|
|
4244
|
+
// 可选:移除URL中的platType(避免重复显示)
|
|
4245
|
+
}
|
|
4246
|
+
}
|
|
4247
|
+
|
|
4141
4248
|
const accessCode = getQueryParam(config.accessCodeKey);
|
|
4142
4249
|
|
|
4143
|
-
// 验证必要的API配置
|
|
4144
4250
|
if (!config.tokenApi) {
|
|
4145
4251
|
return { code: -100, msg: '缺少tokenApi配置', success: false };
|
|
4146
4252
|
}
|
|
@@ -4159,14 +4265,25 @@ function createSSO() {
|
|
|
4159
4265
|
|
|
4160
4266
|
if (result.code === 0 && result.data) {
|
|
4161
4267
|
config.storage.setItem(config.tokenKey, result.data);
|
|
4162
|
-
removeQueryParam(config.accessCodeKey);
|
|
4268
|
+
removeQueryParam([config.accessCodeKey,config.platTypeKey]);
|
|
4163
4269
|
}
|
|
4164
4270
|
return result;
|
|
4165
4271
|
}
|
|
4166
4272
|
// 如果没有token,跳转到登录页
|
|
4167
4273
|
else if (!this.getToken()) {
|
|
4168
4274
|
if (isBrowser() && config.logOutUrl) {
|
|
4169
|
-
|
|
4275
|
+
// ===== 核心修正:platType拼到redirect_uri里 =====
|
|
4276
|
+
const platTypeFromCookie = getCookie(config.platTypeKey);
|
|
4277
|
+
// 1. 获取原始重定向地址
|
|
4278
|
+
let redirectUri = getCurrentUrlWithParams();
|
|
4279
|
+
// 2. 给重定向地址加platType参数
|
|
4280
|
+
if (platTypeFromCookie) {
|
|
4281
|
+
redirectUri = addPlatTypeToRedirectUrl(redirectUri, platTypeFromCookie, config.platTypeKey);
|
|
4282
|
+
}
|
|
4283
|
+
// 3. 构建登录页URL(仅带redirect_uri参数)
|
|
4284
|
+
let loginUrl = new URL(config.logOutUrl);
|
|
4285
|
+
loginUrl.searchParams.set('redirect_uri', encodeURIComponent(redirectUri));
|
|
4286
|
+
window.location.href = loginUrl.toString();
|
|
4170
4287
|
}
|
|
4171
4288
|
}
|
|
4172
4289
|
|
|
@@ -4198,33 +4315,21 @@ function createSSO() {
|
|
|
4198
4315
|
* @returns {Promise<Object>} 接口返回结果
|
|
4199
4316
|
*/
|
|
4200
4317
|
async logout() {
|
|
4201
|
-
// 1. 前置校验:初始化状态
|
|
4202
4318
|
if (!config) {
|
|
4203
4319
|
return { code: -101, msg: '请先调用init方法初始化', success: false };
|
|
4204
4320
|
}
|
|
4205
4321
|
|
|
4206
|
-
// 2. 工具函数:统一构建登录跳转URL(确保完整编码当前URL的所有参数/hash)
|
|
4207
|
-
const buildLoginUrl = () => {
|
|
4208
|
-
if (!config.logOutUrl || !isBrowser()) return '';
|
|
4209
|
-
// 关键:获取当前完整URL(含query、hash)并完整编码,避免参数丢失
|
|
4210
|
-
const currentFullUrl = window.location.href;
|
|
4211
|
-
const encodedRedirectUri = encodeURIComponent(currentFullUrl);
|
|
4212
|
-
return `${config.logOutUrl}?redirect_uri=${encodedRedirectUri}`;
|
|
4213
|
-
};
|
|
4214
|
-
|
|
4215
|
-
// 3. 校验logoutApi配置(仅接口调用时需要,跳转登录页不受此影响)
|
|
4216
4322
|
if (!config.logoutApi) {
|
|
4217
|
-
// 无logoutApi时仍清除token并跳转登录页,保证基础退出逻辑
|
|
4218
|
-
this.removeToken();
|
|
4219
|
-
const loginUrl = buildLoginUrl();
|
|
4220
|
-
if (loginUrl) window.location.href = loginUrl;
|
|
4221
4323
|
return { code: -102, msg: '未配置logoutApi', success: false };
|
|
4222
4324
|
}
|
|
4223
4325
|
|
|
4326
|
+
// 获取并删除Cookie中的platType
|
|
4327
|
+
const platType = getCookie(config.platTypeKey);
|
|
4328
|
+
removeCookie(config.platTypeKey);
|
|
4329
|
+
|
|
4224
4330
|
const token = this.getToken();
|
|
4225
4331
|
if (token) {
|
|
4226
4332
|
try {
|
|
4227
|
-
// 调用退出接口
|
|
4228
4333
|
const result = await request(
|
|
4229
4334
|
config.logoutApi,
|
|
4230
4335
|
{
|
|
@@ -4233,37 +4338,48 @@ function createSSO() {
|
|
|
4233
4338
|
timeout: config.timeout
|
|
4234
4339
|
}
|
|
4235
4340
|
);
|
|
4236
|
-
// 无论接口返回结果如何,都清除token
|
|
4237
4341
|
this.removeToken();
|
|
4238
4342
|
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4343
|
+
if (isBrowser() && config.logOutUrl) {
|
|
4344
|
+
// ===== 核心修正:platType拼到redirect_uri里 =====
|
|
4345
|
+
// 1. 获取原始重定向地址
|
|
4346
|
+
let redirectUri = getCurrentUrlWithParams();
|
|
4347
|
+
// 2. 给重定向地址加platType参数
|
|
4348
|
+
if (platType) {
|
|
4349
|
+
redirectUri = addPlatTypeToRedirectUrl(redirectUri, platType, config.platTypeKey);
|
|
4350
|
+
}
|
|
4351
|
+
// 3. 构建登录页URL
|
|
4352
|
+
let logoutUrl = new URL(config.logOutUrl);
|
|
4353
|
+
logoutUrl.searchParams.set('redirect_uri', encodeURIComponent(redirectUri));
|
|
4354
|
+
window.location.href = logoutUrl.toString();
|
|
4355
|
+
}
|
|
4242
4356
|
return result;
|
|
4243
4357
|
} catch (error) {
|
|
4244
|
-
// 接口调用失败,仍清除token并跳转登录页
|
|
4245
|
-
this.removeToken();
|
|
4246
|
-
const loginUrl = buildLoginUrl();
|
|
4247
|
-
if (loginUrl) window.location.href = loginUrl;
|
|
4248
4358
|
return { code: -103, msg: `退出失败: ${error.message}`, success: false };
|
|
4249
4359
|
}
|
|
4250
4360
|
} else {
|
|
4251
|
-
// 无token时直接清除(兜底)并跳转登录页
|
|
4252
4361
|
this.removeToken();
|
|
4253
|
-
|
|
4254
|
-
|
|
4362
|
+
if (isBrowser() && config.logOutUrl) {
|
|
4363
|
+
// ===== 核心修正:platType拼到redirect_uri里 =====
|
|
4364
|
+
let redirectUri = getCurrentUrlWithParams();
|
|
4365
|
+
if (platType) {
|
|
4366
|
+
redirectUri = addPlatTypeToRedirectUrl(redirectUri, platType, config.platTypeKey);
|
|
4367
|
+
}
|
|
4368
|
+
let logoutUrl = new URL(config.logOutUrl);
|
|
4369
|
+
logoutUrl.searchParams.set('redirect_uri', encodeURIComponent(redirectUri));
|
|
4370
|
+
window.location.href = logoutUrl.toString();
|
|
4371
|
+
}
|
|
4255
4372
|
return { code: 0, msg: '已成功清除token', success: true };
|
|
4256
4373
|
}
|
|
4257
4374
|
},
|
|
4258
4375
|
|
|
4259
4376
|
/**
|
|
4260
4377
|
* 用token换取新accessCode并跳转到指定URL
|
|
4261
|
-
* @param {string} redirectUrl -
|
|
4378
|
+
* @param {string} redirectUrl - 目标跳转地址
|
|
4262
4379
|
* @param {string} target - 当前页面:_self、新页面打开:_blank,默认当前页_self
|
|
4263
4380
|
* @returns {Promise<Object>} 接口返回结果
|
|
4264
4381
|
*/
|
|
4265
4382
|
async toUrl(redirectUrl, target = '_self') {
|
|
4266
|
-
// 1. 前置校验:初始化状态、参数合法性
|
|
4267
4383
|
if (!config) {
|
|
4268
4384
|
return { code: -101, msg: '请先调用init方法初始化', success: false };
|
|
4269
4385
|
}
|
|
@@ -4272,45 +4388,49 @@ function createSSO() {
|
|
|
4272
4388
|
return { code: -104, msg: '请提供跳转地址', success: false };
|
|
4273
4389
|
}
|
|
4274
4390
|
|
|
4275
|
-
//
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
// ========== 保留:platType=screen强制_self逻辑 ==========
|
|
4279
|
-
const isPlatTypeScreen = currentPlatType === 'screen';
|
|
4280
|
-
|
|
4281
|
-
// 2. 处理target参数:platType=screen > iOS > 传入的target
|
|
4282
|
-
const finalTarget = isPlatTypeScreen
|
|
4283
|
-
? '_self' // platType=screen时强制_self
|
|
4284
|
-
: (isIOS() ? '_self' : target); // 否则沿用原iOS判断逻辑
|
|
4285
|
-
|
|
4286
|
-
if (!['_self', '_blank'].includes(finalTarget)) {
|
|
4287
|
-
return { code: -108, msg: 'target参数必须是"_self"或"_blank"', success: false };
|
|
4391
|
+
// iOS强制_self
|
|
4392
|
+
if (isIOS()) {
|
|
4393
|
+
target = '_self';
|
|
4288
4394
|
}
|
|
4289
4395
|
|
|
4290
|
-
//
|
|
4291
|
-
const
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4396
|
+
// platType=screen时强制_self
|
|
4397
|
+
const platType = getCookie(config.platTypeKey);
|
|
4398
|
+
if (platType === 'screen') {
|
|
4399
|
+
target = '_self';
|
|
4400
|
+
}
|
|
4401
|
+
|
|
4402
|
+
// 验证target参数
|
|
4403
|
+
if (!['_self', '_blank'].includes(target)) {
|
|
4404
|
+
return { code: -108, msg: 'target参数必须是"_self"或"_blank"', success: false };
|
|
4405
|
+
}
|
|
4297
4406
|
|
|
4298
|
-
// 4. 校验refreshCodeApi配置
|
|
4299
4407
|
if (!config.refreshCodeApi) {
|
|
4300
4408
|
return { code: -105, msg: '未配置refreshCodeApi', success: false };
|
|
4301
4409
|
}
|
|
4302
4410
|
|
|
4303
|
-
// 5. 获取token,无token则直接跳登录页
|
|
4304
4411
|
const token = this.getToken();
|
|
4305
4412
|
if (!token) {
|
|
4306
4413
|
if (isBrowser() && config.logOutUrl) {
|
|
4307
|
-
|
|
4308
|
-
|
|
4414
|
+
// ===== 核心修正:platType拼到redirect_uri里 =====
|
|
4415
|
+
// 1. 给目标跳转地址加platType
|
|
4416
|
+
let newRedirectUrl = redirectUrl;
|
|
4417
|
+
if (platType) {
|
|
4418
|
+
newRedirectUrl = addPlatTypeToRedirectUrl(newRedirectUrl, platType, config.platTypeKey);
|
|
4419
|
+
}
|
|
4420
|
+
// 2. 构建登录页URL
|
|
4421
|
+
let loginUrl = new URL(config.logOutUrl);
|
|
4422
|
+
loginUrl.searchParams.set('redirect_uri', encodeURIComponent(newRedirectUrl));
|
|
4423
|
+
const loginUrlStr = loginUrl.toString();
|
|
4424
|
+
|
|
4425
|
+
if (target === '_blank') {
|
|
4426
|
+
window.open(loginUrlStr, '_blank');
|
|
4427
|
+
} else {
|
|
4428
|
+
window.location.href = loginUrlStr;
|
|
4429
|
+
}
|
|
4309
4430
|
}
|
|
4310
4431
|
return { code: -106, msg: '未找到有效token', success: false };
|
|
4311
4432
|
}
|
|
4312
4433
|
|
|
4313
|
-
// 6. 有token则尝试换取accessCode并跳转
|
|
4314
4434
|
try {
|
|
4315
4435
|
const result = await request(
|
|
4316
4436
|
config.refreshCodeApi,
|
|
@@ -4322,31 +4442,48 @@ function createSSO() {
|
|
|
4322
4442
|
);
|
|
4323
4443
|
|
|
4324
4444
|
if (result.code === 0 && result.data && isBrowser()) {
|
|
4325
|
-
//
|
|
4445
|
+
// toUrl跳转目标地址时,仅携带accessCode,不携带platType
|
|
4326
4446
|
const url = new URL(redirectUrl);
|
|
4327
|
-
// 1. 如果当前页面有platType,拼接到目标URL(覆盖原有platType)
|
|
4328
|
-
if (currentPlatType) {
|
|
4329
|
-
url.searchParams.set('platType', currentPlatType);
|
|
4330
|
-
}
|
|
4331
|
-
// 2. 拼接accessCode(保留原有逻辑)
|
|
4332
4447
|
url.searchParams.set(config.accessCodeKey, result.data);
|
|
4333
4448
|
const targetUrl = url.toString();
|
|
4334
4449
|
|
|
4335
|
-
|
|
4450
|
+
if (target === '_blank') {
|
|
4451
|
+
window.open(targetUrl, '_blank');
|
|
4452
|
+
} else {
|
|
4453
|
+
window.location.href = targetUrl;
|
|
4454
|
+
}
|
|
4336
4455
|
} else {
|
|
4337
|
-
//
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4456
|
+
// ===== 核心修正:platType拼到redirect_uri里 =====
|
|
4457
|
+
let newRedirectUrl = redirectUrl;
|
|
4458
|
+
if (platType) {
|
|
4459
|
+
newRedirectUrl = addPlatTypeToRedirectUrl(newRedirectUrl, platType, config.platTypeKey);
|
|
4460
|
+
}
|
|
4461
|
+
let loginUrl = new URL(config.logOutUrl);
|
|
4462
|
+
loginUrl.searchParams.set('redirect_uri', encodeURIComponent(newRedirectUrl));
|
|
4463
|
+
const loginUrlStr = loginUrl.toString();
|
|
4464
|
+
|
|
4465
|
+
if (target === '_blank') {
|
|
4466
|
+
window.open(loginUrlStr, '_blank');
|
|
4467
|
+
} else {
|
|
4468
|
+
window.location.href = loginUrlStr;
|
|
4341
4469
|
}
|
|
4342
4470
|
}
|
|
4343
4471
|
|
|
4344
4472
|
return result;
|
|
4345
4473
|
} catch (error) {
|
|
4346
|
-
//
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4474
|
+
// ===== 核心修正:platType拼到redirect_uri里 =====
|
|
4475
|
+
let newRedirectUrl = redirectUrl;
|
|
4476
|
+
if (platType) {
|
|
4477
|
+
newRedirectUrl = addPlatTypeToRedirectUrl(newRedirectUrl, platType, config.platTypeKey);
|
|
4478
|
+
}
|
|
4479
|
+
let loginUrl = new URL(config.logOutUrl);
|
|
4480
|
+
loginUrl.searchParams.set('redirect_uri', encodeURIComponent(newRedirectUrl));
|
|
4481
|
+
const loginUrlStr = loginUrl.toString();
|
|
4482
|
+
|
|
4483
|
+
if (target === '_blank') {
|
|
4484
|
+
window.open(loginUrlStr, '_blank');
|
|
4485
|
+
} else {
|
|
4486
|
+
window.location.href = loginUrlStr;
|
|
4350
4487
|
}
|
|
4351
4488
|
return { code: -107, msg: `跳转失败: ${error.message}`, success: false };
|
|
4352
4489
|
}
|
|
@@ -4385,7 +4522,7 @@ function createSSO() {
|
|
|
4385
4522
|
* @returns {Object|null} 当前配置
|
|
4386
4523
|
*/
|
|
4387
4524
|
getConfig() {
|
|
4388
|
-
return { ...config };
|
|
4525
|
+
return { ...config };
|
|
4389
4526
|
},
|
|
4390
4527
|
|
|
4391
4528
|
async changePassword(fromData = {}) {
|
|
@@ -4414,7 +4551,6 @@ function createSSO() {
|
|
|
4414
4551
|
|
|
4415
4552
|
async getPhoneCode() {
|
|
4416
4553
|
const token = this.getToken();
|
|
4417
|
-
// 修复笔误:sendCaptchaCode → sendCaptchaCodeApi
|
|
4418
4554
|
return request(
|
|
4419
4555
|
config.sendCaptchaCodeApi,
|
|
4420
4556
|
{
|