af-mobile-client-vue3 1.3.54 → 1.3.57

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.
Files changed (56) hide show
  1. package/package.json +115 -115
  2. package/public/favicon.svg +4 -4
  3. package/scripts/verifyCommit.js +19 -19
  4. package/src/App.vue +1 -1
  5. package/src/api/user/index.ts +45 -45
  6. package/src/components/data/UserDetail/types.ts +1 -1
  7. package/src/components/data/XReportGrid/XAddReport/index.ts +1 -1
  8. package/src/components/data/XReportGrid/XReportDrawer/index.ts +1 -1
  9. package/src/components/data/XTag/index.vue +10 -10
  10. package/src/components/layout/TabBarLayout/index.vue +40 -40
  11. package/src/font-style/Inter-Bold.woff2 +0 -0
  12. package/src/font-style/Inter-Medium.woff2 +0 -0
  13. package/src/font-style/Inter-Regular.woff2 +0 -0
  14. package/src/font-style/Inter-SemiBold.woff2 +0 -0
  15. package/src/font-style/PingFangSC-Medium.subset.woff2 +0 -0
  16. package/src/font-style/PingFangSC-Medium.woff2 +0 -0
  17. package/src/font-style/PingFangSC-Regular.subset.woff2 +0 -0
  18. package/src/font-style/PingFangSC-Semibold.subset.woff2 +0 -0
  19. package/src/font-style/PingFangSC-Semibold.woff2 +0 -0
  20. package/src/font-style/font.css +59 -2
  21. package/src/hooks/useCommon.ts +9 -9
  22. package/src/plugins/AppData.ts +38 -38
  23. package/src/router/external-routes.ts +69 -69
  24. package/src/router/guards.ts +131 -131
  25. package/src/router/invoiceRoutes.ts +33 -33
  26. package/src/router/routes.ts +421 -421
  27. package/src/services/api/Login.ts +6 -6
  28. package/src/services/api/common.ts +109 -109
  29. package/src/services/api/manage.ts +8 -8
  30. package/src/services/api/search.ts +16 -16
  31. package/src/services/restTools.ts +56 -56
  32. package/src/services/v3Api.ts +11 -11
  33. package/src/stores/modules/user.ts +1 -1
  34. package/src/styles/login.less +109 -109
  35. package/src/types/platform.ts +194 -194
  36. package/src/utils/authority-utils.ts +84 -84
  37. package/src/utils/crypto.ts +39 -39
  38. package/src/utils/environment.ts +10 -10
  39. package/src/utils/platform-auth.ts +150 -150
  40. package/src/utils/routerUtil.ts +81 -2
  41. package/src/utils/runEvalFunction.ts +13 -13
  42. package/src/utils/wechat.ts +297 -297
  43. package/src/views/component/EvaluateRecordView/index.vue +40 -40
  44. package/src/views/component/XCellDetailView/index.vue +217 -217
  45. package/src/views/component/XReportFormIframeView/index.vue +47 -47
  46. package/src/views/component/XReportFormView/index.vue +13 -13
  47. package/src/views/component/XSignatureView/index.vue +50 -50
  48. package/src/views/component/notice.vue +46 -46
  49. package/src/views/component/topNav.vue +36 -36
  50. package/src/views/invoiceShow/index.vue +61 -61
  51. package/src/views/loading/AuthLoading.vue +378 -378
  52. package/src/views/user/login/index.vue +22 -22
  53. package/src/views/user/register/index.vue +1 -1
  54. package/vite.config.ts +114 -114
  55. package/certs/127.0.0.1+2-key.pem +0 -28
  56. package/certs/127.0.0.1+2.pem +0 -27
@@ -1,84 +1,84 @@
1
- /**
2
- * 判断是否有路由的权限
3
- * @param authority 路由权限配置
4
- * @param permissions 用户权限集合
5
- */
6
- function hasPermission(authority: any, permissions: any): boolean {
7
- let required: string = '*'
8
- if (typeof authority === 'string')
9
- required = authority
10
- else if (Array.isArray(authority))
11
- required = authority.toString()
12
- else if (typeof authority === 'object')
13
- required = authority.permission
14
-
15
- return required === '*' || hasAnyItem(required, permissions, (r, t) => !!(r === t || r === t.id))
16
- }
17
-
18
- /**
19
- * 判断是否有路由需要的角色
20
- * @param authority 路由权限配置
21
- * @param roles 用户角色集合
22
- */
23
- function hasRole(authority, roles) {
24
- let required
25
- if (typeof authority === 'object')
26
- required = authority.role
27
-
28
- return authority === '*' || hasAnyItem(required, roles, (r, t) => !!(r === t || r === t.id))
29
- }
30
-
31
- /**
32
- * 判断目标数组是否有所需元素
33
- * @param {string | string[]}required 所需元素,数组或单个元素
34
- * @param {string[] | object[]} source 目标数组
35
- * @param {Function} filter 匹配条件
36
- * (r: String, s: String|Object) => boolean
37
- */
38
- function hasAnyItem(required, source, filter): boolean {
39
- if (!required)
40
- return false
41
-
42
- const checkedList = Array.isArray(required) ? required : [required]
43
- return !!source.find(s => checkedList.find(r => filter(r, s)))
44
- }
45
-
46
- /**
47
- * 路由权限校验
48
- * @param route 路由
49
- * @param permissions 用户权限集合
50
- * @param roles 用户角色集合
51
- */
52
- function hasAuthority(route, permissions, roles) {
53
- // TODO 此处判断可能有问题
54
- if (!route.meta.pAuthorities)
55
- return true
56
-
57
- const authorities = [...route.meta.pAuthorities, route.meta.authority]
58
- for (const authority of authorities) {
59
- if (!hasPermission(authority, permissions) && !hasRole(authority, roles))
60
- return false
61
- }
62
- return true
63
- }
64
-
65
- /**
66
- * 根据权限配置过滤菜单数据
67
- * @param menuData
68
- * @param permissions
69
- * @param roles
70
- */
71
- function filterMenu(menuData, permissions, roles) {
72
- return menuData.filter((menu) => {
73
- if (menu.meta && menu.meta.invisible === undefined) {
74
- if (!hasAuthority(menu, permissions, roles))
75
- return false
76
- }
77
- if (menu.children && menu.children.length > 0)
78
- menu.children = filterMenu(menu.children, permissions, roles)
79
-
80
- return true
81
- })
82
- }
83
-
84
- export { filterMenu, hasAuthority }
1
+ /**
2
+ * 判断是否有路由的权限
3
+ * @param authority 路由权限配置
4
+ * @param permissions 用户权限集合
5
+ */
6
+ function hasPermission(authority: any, permissions: any): boolean {
7
+ let required: string = '*'
8
+ if (typeof authority === 'string')
9
+ required = authority
10
+ else if (Array.isArray(authority))
11
+ required = authority.toString()
12
+ else if (typeof authority === 'object')
13
+ required = authority.permission
14
+
15
+ return required === '*' || hasAnyItem(required, permissions, (r, t) => !!(r === t || r === t.id))
16
+ }
17
+
18
+ /**
19
+ * 判断是否有路由需要的角色
20
+ * @param authority 路由权限配置
21
+ * @param roles 用户角色集合
22
+ */
23
+ function hasRole(authority, roles) {
24
+ let required
25
+ if (typeof authority === 'object')
26
+ required = authority.role
27
+
28
+ return authority === '*' || hasAnyItem(required, roles, (r, t) => !!(r === t || r === t.id))
29
+ }
30
+
31
+ /**
32
+ * 判断目标数组是否有所需元素
33
+ * @param {string | string[]}required 所需元素,数组或单个元素
34
+ * @param {string[] | object[]} source 目标数组
35
+ * @param {Function} filter 匹配条件
36
+ * (r: String, s: String|Object) => boolean
37
+ */
38
+ function hasAnyItem(required, source, filter): boolean {
39
+ if (!required)
40
+ return false
41
+
42
+ const checkedList = Array.isArray(required) ? required : [required]
43
+ return !!source.find(s => checkedList.find(r => filter(r, s)))
44
+ }
45
+
46
+ /**
47
+ * 路由权限校验
48
+ * @param route 路由
49
+ * @param permissions 用户权限集合
50
+ * @param roles 用户角色集合
51
+ */
52
+ function hasAuthority(route, permissions, roles) {
53
+ // TODO 此处判断可能有问题
54
+ if (!route.meta.pAuthorities)
55
+ return true
56
+
57
+ const authorities = [...route.meta.pAuthorities, route.meta.authority]
58
+ for (const authority of authorities) {
59
+ if (!hasPermission(authority, permissions) && !hasRole(authority, roles))
60
+ return false
61
+ }
62
+ return true
63
+ }
64
+
65
+ /**
66
+ * 根据权限配置过滤菜单数据
67
+ * @param menuData
68
+ * @param permissions
69
+ * @param roles
70
+ */
71
+ function filterMenu(menuData, permissions, roles) {
72
+ return menuData.filter((menu) => {
73
+ if (menu.meta && menu.meta.invisible === undefined) {
74
+ if (!hasAuthority(menu, permissions, roles))
75
+ return false
76
+ }
77
+ if (menu.children && menu.children.length > 0)
78
+ menu.children = filterMenu(menu.children, permissions, roles)
79
+
80
+ return true
81
+ })
82
+ }
83
+
84
+ export { filterMenu, hasAuthority }
@@ -1,39 +1,39 @@
1
- import AesEncryptJS from 'crypto-js'
2
-
3
- export default {
4
- /**
5
- * AES加密
6
- *
7
- * @param word
8
- * @param encryKey
9
- */
10
- AESEncrypt(word: string, encryKey: string): string {
11
- const key = AesEncryptJS.enc.Utf8.parse(encryKey)
12
- const srcs = AesEncryptJS.enc.Utf8.parse(word)
13
- const encrypted = AesEncryptJS.AES.encrypt(srcs, key, {
14
- mode: AesEncryptJS.mode.ECB,
15
- padding: AesEncryptJS.pad.Pkcs7,
16
- })
17
- return encrypted.toString()
18
- },
19
- /**
20
- * AES解密
21
- *
22
- * @param word
23
- * @param encryKey
24
- */
25
- AESDecrypt(word: string, encryKey: string): any {
26
- const key = AesEncryptJS.enc.Utf8.parse(encryKey)
27
- const decrypt = AesEncryptJS.AES.decrypt(word, key, {
28
- mode: AesEncryptJS.mode.ECB,
29
- padding: AesEncryptJS.pad.Pkcs7,
30
- })
31
- const ret = AesEncryptJS.enc.Utf8.stringify(decrypt).toString()
32
- try {
33
- return JSON.parse(ret)
34
- }
35
- catch {
36
- return ret
37
- }
38
- },
39
- }
1
+ import AesEncryptJS from 'crypto-js'
2
+
3
+ export default {
4
+ /**
5
+ * AES加密
6
+ *
7
+ * @param word
8
+ * @param encryKey
9
+ */
10
+ AESEncrypt(word: string, encryKey: string): string {
11
+ const key = AesEncryptJS.enc.Utf8.parse(encryKey)
12
+ const srcs = AesEncryptJS.enc.Utf8.parse(word)
13
+ const encrypted = AesEncryptJS.AES.encrypt(srcs, key, {
14
+ mode: AesEncryptJS.mode.ECB,
15
+ padding: AesEncryptJS.pad.Pkcs7,
16
+ })
17
+ return encrypted.toString()
18
+ },
19
+ /**
20
+ * AES解密
21
+ *
22
+ * @param word
23
+ * @param encryKey
24
+ */
25
+ AESDecrypt(word: string, encryKey: string): any {
26
+ const key = AesEncryptJS.enc.Utf8.parse(encryKey)
27
+ const decrypt = AesEncryptJS.AES.decrypt(word, key, {
28
+ mode: AesEncryptJS.mode.ECB,
29
+ padding: AesEncryptJS.pad.Pkcs7,
30
+ })
31
+ const ret = AesEncryptJS.enc.Utf8.stringify(decrypt).toString()
32
+ try {
33
+ return JSON.parse(ret)
34
+ }
35
+ catch {
36
+ return ret
37
+ }
38
+ },
39
+ }
@@ -29,17 +29,17 @@ function getPlatformFromClient(): string {
29
29
 
30
30
  function inferPlatformFromUserAgent(userAgent: string): string {
31
31
  const ua = (userAgent || '').toLowerCase()
32
- if (ua.includes('windows'))
32
+ if (ua.includes('windows'))
33
33
  return 'windows'
34
- if (ua.includes('mac os x') || ua.includes('macintosh') || ua.includes('mac os'))
34
+ if (ua.includes('mac os x') || ua.includes('macintosh') || ua.includes('mac os'))
35
35
  return 'macos'
36
- if (ua.includes('android'))
36
+ if (ua.includes('android'))
37
37
  return 'android'
38
- if (ua.includes('iphone') || ua.includes('ipad') || ua.includes('ipod') || ua.includes('ios'))
38
+ if (ua.includes('iphone') || ua.includes('ipad') || ua.includes('ipod') || ua.includes('ios'))
39
39
  return 'ios'
40
- if (ua.includes('cros'))
40
+ if (ua.includes('cros'))
41
41
  return 'chrome os'
42
- if (ua.includes('linux'))
42
+ if (ua.includes('linux'))
43
43
  return 'linux'
44
44
  return 'unknown'
45
45
  }
@@ -89,13 +89,13 @@ export function detectEnvironment(): EnvironmentInfo {
89
89
  export function getCurrentScene(): 'wechat' | 'browser' | 'miniprogram' | 'app' | 'unknown' {
90
90
  const env = detectEnvironment()
91
91
 
92
- if (env.isMiniprogram)
92
+ if (env.isMiniprogram)
93
93
  return 'miniprogram'
94
- if (env.isWechat)
94
+ if (env.isWechat)
95
95
  return 'wechat'
96
- if (env.isApp)
96
+ if (env.isApp)
97
97
  return 'app'
98
- if (env.isBrowser)
98
+ if (env.isBrowser)
99
99
  return 'browser'
100
100
 
101
101
  return 'unknown'
@@ -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
+ }