af-mobile-client-vue3 1.3.53 → 1.3.55
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/package.json +115 -115
- package/src/api/user/index.ts +45 -45
- package/src/router/external-routes.ts +69 -69
- package/src/router/guards.ts +131 -131
- package/src/router/routes.ts +421 -421
- package/src/services/api/Login.ts +6 -6
- package/src/stores/modules/user.ts +1 -1
- package/src/styles/login.less +109 -109
- package/src/types/platform.ts +194 -194
- package/src/utils/environment.ts +10 -10
- package/src/utils/platform-auth.ts +150 -150
- package/src/utils/routerUtil.ts +81 -2
- package/src/utils/wechat.ts +297 -297
- package/src/views/component/XOlMapView/XLocationPicker/index.vue +118 -118
- package/src/views/loading/AuthLoading.vue +378 -378
- package/src/views/user/register/index.vue +1 -1
- package/vite.config.ts +114 -114
- package/certs/127.0.0.1+2-key.pem +0 -28
- package/certs/127.0.0.1+2.pem +0 -27
|
@@ -1,150 +1,150 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 统一平台认证工具类
|
|
3
|
-
* 合并了 wechatUtil.ts, wechat.ts 和 auth-platform.ts 的功能
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { RouteLocationNormalized } from 'vue-router'
|
|
7
|
-
import { PLATFORM_ROUTE_MAP, PlatformType } from '@af-mobile-client-vue3/types/platform'
|
|
8
|
-
import { detectEnvironment } from '@af-mobile-client-vue3/utils/environment'
|
|
9
|
-
/**
|
|
10
|
-
* 认证参数接口
|
|
11
|
-
*/
|
|
12
|
-
export interface AuthParams {
|
|
13
|
-
/** 授权码 */
|
|
14
|
-
code?: string
|
|
15
|
-
/** 状态参数 */
|
|
16
|
-
state?: string
|
|
17
|
-
/** 租户名称 */
|
|
18
|
-
tenantName?: string
|
|
19
|
-
/** 平台类型 */
|
|
20
|
-
platformType?: PlatformType
|
|
21
|
-
/** 错误信息 */
|
|
22
|
-
error?: string
|
|
23
|
-
/** 错误描述 */
|
|
24
|
-
error_description?: string
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* 微信回调参数接口(向后兼容)
|
|
29
|
-
*/
|
|
30
|
-
export interface WechatCallbackParams extends AuthParams { }
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* 外部用户检测结果接口
|
|
34
|
-
*/
|
|
35
|
-
export interface ExternalUserResult {
|
|
36
|
-
/** 是否为外部用户 */
|
|
37
|
-
isExternal: boolean
|
|
38
|
-
/** 认证参数(仅当 isExternal 为 true 且有授权参数时存在) */
|
|
39
|
-
authParams?: {
|
|
40
|
-
code?: string
|
|
41
|
-
state?: string
|
|
42
|
-
tenantName?: string
|
|
43
|
-
platformType?: string
|
|
44
|
-
platformUserId?: string
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* 统一的外部用户检测函数
|
|
50
|
-
* 这是系统中唯一的用户类型检测入口,仅在路由守卫中调用
|
|
51
|
-
* 集成了用户类型检测和认证参数解析功能
|
|
52
|
-
*
|
|
53
|
-
* @param to 目标路由对象
|
|
54
|
-
* @returns 外部用户检测结果,包含是否为外部用户和认证参数
|
|
55
|
-
*/
|
|
56
|
-
export function isExternalUser(to: RouteLocationNormalized): ExternalUserResult {
|
|
57
|
-
console.log('[Platform Detection] 开始检测外部用户环境', { path: to.path, query: to.query })
|
|
58
|
-
|
|
59
|
-
// 第一层检测:URL参数检测(最高优先级)判断公众号登录逻辑
|
|
60
|
-
// 检查路由查询参数中是否有授权参数(code + state)
|
|
61
|
-
const { code, state, appData } = to.query
|
|
62
|
-
if (code && state) {
|
|
63
|
-
// 解析认证参数
|
|
64
|
-
const authParams = {
|
|
65
|
-
code: code as string,
|
|
66
|
-
state: state as string,
|
|
67
|
-
tenantName: state as string,
|
|
68
|
-
platformUserId: code as string,
|
|
69
|
-
platformType: PlatformType.WECHAT_OFFICIAL,
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
isExternal: true,
|
|
74
|
-
authParams,
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// 第二层检测:User-Agent环境检测
|
|
79
|
-
// 检查浏览器环境是否为第三方平台
|
|
80
|
-
const env = detectEnvironment()
|
|
81
|
-
// 微信小程序
|
|
82
|
-
if (env.isMiniprogram && appData) {
|
|
83
|
-
const authParams = {
|
|
84
|
-
platformType: PlatformType.WECHAT_MINI,
|
|
85
|
-
appData,
|
|
86
|
-
}
|
|
87
|
-
// 暂未实现 后续需要增加登陆参数
|
|
88
|
-
return {
|
|
89
|
-
isExternal: true,
|
|
90
|
-
authParams,
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
// 微信环境检测
|
|
94
|
-
if (env.isWechat) {
|
|
95
|
-
console.log('[Platform Detection] 检测到微信环境,判定为外部用户(无授权参数)')
|
|
96
|
-
return {
|
|
97
|
-
isExternal: true,
|
|
98
|
-
authParams: Object.assign(to.query, {
|
|
99
|
-
platformType: PlatformType.WECHAT_OFFICIAL,
|
|
100
|
-
tenantName: to.query.state as string || '',
|
|
101
|
-
}),
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// 支付宝环境检测
|
|
106
|
-
if (env.isAlipayClient) {
|
|
107
|
-
// 暂未实现 后续需要增加登陆参数
|
|
108
|
-
return {
|
|
109
|
-
isExternal: true,
|
|
110
|
-
authParams: {
|
|
111
|
-
platformType: PlatformType.ALIPAY,
|
|
112
|
-
},
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// 钉钉环境检测
|
|
117
|
-
if (env.isDingTalk) {
|
|
118
|
-
// 暂未实现 后续需要增加登陆参数
|
|
119
|
-
return {
|
|
120
|
-
isExternal: true,
|
|
121
|
-
authParams: {
|
|
122
|
-
platformType: PlatformType.DINGTALK,
|
|
123
|
-
},
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// 第三层检测:路由前缀检测
|
|
128
|
-
// 检查路径是否以外部用户路由前缀开头
|
|
129
|
-
const platformPrefixes = Object.values(PLATFORM_ROUTE_MAP)
|
|
130
|
-
const isExternalRoute = platformPrefixes.some(prefix => to.path.startsWith(prefix)) || to.path.startsWith('/ex/')
|
|
131
|
-
if (isExternalRoute) {
|
|
132
|
-
// 暂未实现 后续需要增加登陆参数
|
|
133
|
-
return {
|
|
134
|
-
isExternal: true,
|
|
135
|
-
authParams: Object.assign(to.query, {
|
|
136
|
-
platformType: PlatformType.WECHAT_OFFICIAL,
|
|
137
|
-
tenantName: to.query.state as string || '',
|
|
138
|
-
}),
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// [Platform Detection] 未检测到外部用户环境,判定为内部用户
|
|
143
|
-
return { isExternal: false }
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// 兼容性导出 - 保持向后兼容
|
|
147
|
-
export function isWechat(): boolean {
|
|
148
|
-
const ua = navigator.userAgent.toLowerCase()
|
|
149
|
-
return /micromessenger/i.test(ua)
|
|
150
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* 统一平台认证工具类
|
|
3
|
+
* 合并了 wechatUtil.ts, wechat.ts 和 auth-platform.ts 的功能
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { RouteLocationNormalized } from 'vue-router'
|
|
7
|
+
import { PLATFORM_ROUTE_MAP, PlatformType } from '@af-mobile-client-vue3/types/platform'
|
|
8
|
+
import { detectEnvironment } from '@af-mobile-client-vue3/utils/environment'
|
|
9
|
+
/**
|
|
10
|
+
* 认证参数接口
|
|
11
|
+
*/
|
|
12
|
+
export interface AuthParams {
|
|
13
|
+
/** 授权码 */
|
|
14
|
+
code?: string
|
|
15
|
+
/** 状态参数 */
|
|
16
|
+
state?: string
|
|
17
|
+
/** 租户名称 */
|
|
18
|
+
tenantName?: string
|
|
19
|
+
/** 平台类型 */
|
|
20
|
+
platformType?: PlatformType
|
|
21
|
+
/** 错误信息 */
|
|
22
|
+
error?: string
|
|
23
|
+
/** 错误描述 */
|
|
24
|
+
error_description?: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 微信回调参数接口(向后兼容)
|
|
29
|
+
*/
|
|
30
|
+
export interface WechatCallbackParams extends AuthParams { }
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 外部用户检测结果接口
|
|
34
|
+
*/
|
|
35
|
+
export interface ExternalUserResult {
|
|
36
|
+
/** 是否为外部用户 */
|
|
37
|
+
isExternal: boolean
|
|
38
|
+
/** 认证参数(仅当 isExternal 为 true 且有授权参数时存在) */
|
|
39
|
+
authParams?: {
|
|
40
|
+
code?: string
|
|
41
|
+
state?: string
|
|
42
|
+
tenantName?: string
|
|
43
|
+
platformType?: string
|
|
44
|
+
platformUserId?: string
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 统一的外部用户检测函数
|
|
50
|
+
* 这是系统中唯一的用户类型检测入口,仅在路由守卫中调用
|
|
51
|
+
* 集成了用户类型检测和认证参数解析功能
|
|
52
|
+
*
|
|
53
|
+
* @param to 目标路由对象
|
|
54
|
+
* @returns 外部用户检测结果,包含是否为外部用户和认证参数
|
|
55
|
+
*/
|
|
56
|
+
export function isExternalUser(to: RouteLocationNormalized): ExternalUserResult {
|
|
57
|
+
console.log('[Platform Detection] 开始检测外部用户环境', { path: to.path, query: to.query })
|
|
58
|
+
|
|
59
|
+
// 第一层检测:URL参数检测(最高优先级)判断公众号登录逻辑
|
|
60
|
+
// 检查路由查询参数中是否有授权参数(code + state)
|
|
61
|
+
const { code, state, appData } = to.query
|
|
62
|
+
if (code && state) {
|
|
63
|
+
// 解析认证参数
|
|
64
|
+
const authParams = {
|
|
65
|
+
code: code as string,
|
|
66
|
+
state: state as string,
|
|
67
|
+
tenantName: state as string,
|
|
68
|
+
platformUserId: code as string,
|
|
69
|
+
platformType: PlatformType.WECHAT_OFFICIAL,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
isExternal: true,
|
|
74
|
+
authParams,
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 第二层检测:User-Agent环境检测
|
|
79
|
+
// 检查浏览器环境是否为第三方平台
|
|
80
|
+
const env = detectEnvironment()
|
|
81
|
+
// 微信小程序
|
|
82
|
+
if (env.isMiniprogram && appData) {
|
|
83
|
+
const authParams = {
|
|
84
|
+
platformType: PlatformType.WECHAT_MINI,
|
|
85
|
+
appData,
|
|
86
|
+
}
|
|
87
|
+
// 暂未实现 后续需要增加登陆参数
|
|
88
|
+
return {
|
|
89
|
+
isExternal: true,
|
|
90
|
+
authParams,
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// 微信环境检测
|
|
94
|
+
if (env.isWechat) {
|
|
95
|
+
console.log('[Platform Detection] 检测到微信环境,判定为外部用户(无授权参数)')
|
|
96
|
+
return {
|
|
97
|
+
isExternal: true,
|
|
98
|
+
authParams: Object.assign(to.query, {
|
|
99
|
+
platformType: PlatformType.WECHAT_OFFICIAL,
|
|
100
|
+
tenantName: to.query.state as string || '',
|
|
101
|
+
}),
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 支付宝环境检测
|
|
106
|
+
if (env.isAlipayClient) {
|
|
107
|
+
// 暂未实现 后续需要增加登陆参数
|
|
108
|
+
return {
|
|
109
|
+
isExternal: true,
|
|
110
|
+
authParams: {
|
|
111
|
+
platformType: PlatformType.ALIPAY,
|
|
112
|
+
},
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// 钉钉环境检测
|
|
117
|
+
if (env.isDingTalk) {
|
|
118
|
+
// 暂未实现 后续需要增加登陆参数
|
|
119
|
+
return {
|
|
120
|
+
isExternal: true,
|
|
121
|
+
authParams: {
|
|
122
|
+
platformType: PlatformType.DINGTALK,
|
|
123
|
+
},
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// 第三层检测:路由前缀检测
|
|
128
|
+
// 检查路径是否以外部用户路由前缀开头
|
|
129
|
+
const platformPrefixes = Object.values(PLATFORM_ROUTE_MAP)
|
|
130
|
+
const isExternalRoute = platformPrefixes.some(prefix => to.path.startsWith(prefix)) || to.path.startsWith('/ex/')
|
|
131
|
+
if (isExternalRoute) {
|
|
132
|
+
// 暂未实现 后续需要增加登陆参数
|
|
133
|
+
return {
|
|
134
|
+
isExternal: true,
|
|
135
|
+
authParams: Object.assign(to.query, {
|
|
136
|
+
platformType: PlatformType.WECHAT_OFFICIAL,
|
|
137
|
+
tenantName: to.query.state as string || '',
|
|
138
|
+
}),
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// [Platform Detection] 未检测到外部用户环境,判定为内部用户
|
|
143
|
+
return { isExternal: false }
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 兼容性导出 - 保持向后兼容
|
|
147
|
+
export function isWechat(): boolean {
|
|
148
|
+
const ua = navigator.userAgent.toLowerCase()
|
|
149
|
+
return /micromessenger/i.test(ua)
|
|
150
|
+
}
|
package/src/utils/routerUtil.ts
CHANGED
|
@@ -105,14 +105,93 @@ function loadRoutes(routesConfig?: any) {
|
|
|
105
105
|
const newRoutes = parseRoutes(routesConfig, routes)
|
|
106
106
|
// 设置路由首页
|
|
107
107
|
newRoutes[0].redirect = '/'
|
|
108
|
-
|
|
108
|
+
let finalRoutes = mergeRoutes(routes, newRoutes)
|
|
109
109
|
formatRoutes(finalRoutes)
|
|
110
|
+
const duplicates = checkDuplicateRouteNames(finalRoutes)
|
|
111
|
+
if (duplicates.length > 0) {
|
|
112
|
+
// 可以选择在这里处理重复的路由名称
|
|
113
|
+
finalRoutes = deduplicateRouteNames(finalRoutes)
|
|
114
|
+
}
|
|
110
115
|
finalRoutes.forEach((row) => {
|
|
111
116
|
router.addRoute(row)
|
|
112
117
|
})
|
|
113
118
|
}
|
|
114
119
|
}
|
|
115
120
|
|
|
121
|
+
function checkDuplicateRouteNames(routes) {
|
|
122
|
+
const names = new Set()
|
|
123
|
+
const duplicates = []
|
|
124
|
+
|
|
125
|
+
function check(route) {
|
|
126
|
+
if (route.name) {
|
|
127
|
+
if (names.has(`${route.name}_${route.path}`)) {
|
|
128
|
+
duplicates.push(`${route.name}_${route.path}`)
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
names.add(`${route.name}_${route.path}`)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (route.children) {
|
|
135
|
+
route.children.forEach(check)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
routes.forEach(check)
|
|
140
|
+
return duplicates
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 处理重复路由名称的函数
|
|
144
|
+
function deduplicateRouteNames(routes) {
|
|
145
|
+
const namePathMap = new Map() // 存储 name_path 组合
|
|
146
|
+
const nameCountMap = new Map() // 存储仅 name 的计数
|
|
147
|
+
|
|
148
|
+
function deduplicate(route) {
|
|
149
|
+
if (!route)
|
|
150
|
+
return null
|
|
151
|
+
|
|
152
|
+
if (route.name) {
|
|
153
|
+
const namePathKey = `${route.name}_${route.path}`
|
|
154
|
+
const nameKey = route.name
|
|
155
|
+
|
|
156
|
+
// 检查 name 和 path 是否都重复
|
|
157
|
+
if (namePathMap.has(namePathKey)) {
|
|
158
|
+
// 完全重复的路由,直接移除
|
|
159
|
+
// console.log(`移除重复路由: name=${route.name}, path=${route.path}`)
|
|
160
|
+
return null
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
// 记录这个 name 和 path 的组合
|
|
164
|
+
namePathMap.set(namePathKey, route)
|
|
165
|
+
|
|
166
|
+
// 检查是否只有 name 重复
|
|
167
|
+
if (nameCountMap.has(nameKey)) {
|
|
168
|
+
const count = nameCountMap.get(nameKey) + 1
|
|
169
|
+
nameCountMap.set(nameKey, count)
|
|
170
|
+
// 修改路由名称,添加计数后缀
|
|
171
|
+
route.name = `${nameKey}_${count}`
|
|
172
|
+
// console.log(`重命名重复路由: ${nameKey} -> ${route.name}`)
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
nameCountMap.set(nameKey, 1)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// 递归处理子路由
|
|
181
|
+
if (route.children && route.children.length) {
|
|
182
|
+
route.children = route.children
|
|
183
|
+
.map(child => deduplicate({ ...child }))
|
|
184
|
+
.filter(child => child !== null) // 移除返回 null 的子路由
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return route
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// 处理所有路由并过滤掉返回 null 的路由
|
|
191
|
+
return routes
|
|
192
|
+
.map(route => deduplicate({ ...route }))
|
|
193
|
+
.filter(route => route !== null)
|
|
194
|
+
}
|
|
116
195
|
/**
|
|
117
196
|
* 合并路由
|
|
118
197
|
* @param target
|
|
@@ -219,7 +298,7 @@ function parsefunc(func) {
|
|
|
219
298
|
params: undefined,
|
|
220
299
|
children: undefined,
|
|
221
300
|
}
|
|
222
|
-
if (row
|
|
301
|
+
if (row?.link?.includes('$')) {
|
|
223
302
|
route.router = row.link.split('$')[1]
|
|
224
303
|
route.params = row.link.split('$')[0]
|
|
225
304
|
}
|