adtec-core-package 3.2.9 → 3.3.1
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adtec-core-package",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -102,6 +102,7 @@
|
|
|
102
102
|
"smooth-signature": "1.0.15",
|
|
103
103
|
"socket.io-client": "^2.3.1",
|
|
104
104
|
"tdesign-vue-next": "1.18.2",
|
|
105
|
+
"ts-md5": "^1.3.1",
|
|
105
106
|
"uuid": "^11.0.3",
|
|
106
107
|
"vue": "^3.5.13",
|
|
107
108
|
"vue-demi": "^0.14.10",
|
|
@@ -82,6 +82,28 @@ ElSelect.props.fitInputWidth = {
|
|
|
82
82
|
type: Boolean,
|
|
83
83
|
default: false,
|
|
84
84
|
}
|
|
85
|
+
const isWujieSubApp =
|
|
86
|
+
typeof window !== 'undefined' && !!(window as Window & { __POWERED_BY_WUJIE__?: boolean }).__POWERED_BY_WUJIE__
|
|
87
|
+
/**
|
|
88
|
+
* 无界 iframe 内 Popper 坐标修正。
|
|
89
|
+
* ElSelect / ElDatePicker 等须保持 teleported 默认 true(vxe 单元格挂 body + popperClass 防 clearEdit),
|
|
90
|
+
* 仅通过 strategy/modifiers 修正偏移,避免各子应用逐页 v-bind。
|
|
91
|
+
*/
|
|
92
|
+
const wujiePopperOptions = {
|
|
93
|
+
strategy: 'fixed' as const,
|
|
94
|
+
modifiers: [
|
|
95
|
+
{
|
|
96
|
+
name: 'computeStyles',
|
|
97
|
+
options: { adaptive: false, gpuAcceleration: false },
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
}
|
|
101
|
+
if (isWujieSubApp) {
|
|
102
|
+
ElSelect.props.popperOptions = { type: Object, default: () => wujiePopperOptions }
|
|
103
|
+
ElDatePicker.props.popperOptions = { type: Object, default: () => wujiePopperOptions }
|
|
104
|
+
ElTreeSelect.props.popperOptions = { type: Object, default: () => wujiePopperOptions }
|
|
105
|
+
ElCascader.props.popperOptions = { type: Object, default: () => wujiePopperOptions }
|
|
106
|
+
}
|
|
85
107
|
ElSelect.props.popperClass = {
|
|
86
108
|
type: String,
|
|
87
109
|
default: VXE_IGNORE_CLEAR_POPPER,
|
|
@@ -7,6 +7,39 @@ import { storeToRefs } from 'pinia'
|
|
|
7
7
|
import { userInfoStore } from '../stores/userInfoStore.ts'
|
|
8
8
|
import frameworkUtils from '../utils/FrameworkUtils.ts'
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* 后端在带 orgId 且 Redis 未命中时,可能返回带 parentId 的扁平列表(未 buildTree)。
|
|
12
|
+
* 前端按 parentId 重建 children,恢复领域/项目类型等树形字典。
|
|
13
|
+
*/
|
|
14
|
+
const ensureDictTree = (list?: ISysDictDataCacheVo[]): ISysDictDataCacheVo[] => {
|
|
15
|
+
if (!list?.length) return list ?? []
|
|
16
|
+
if (list.some((item) => Array.isArray(item.children) && item.children.length > 0)) {
|
|
17
|
+
return list
|
|
18
|
+
}
|
|
19
|
+
const nodeMap = new Map<string, ISysDictDataCacheVo>()
|
|
20
|
+
list.forEach((item) => {
|
|
21
|
+
if (!item?.id) return
|
|
22
|
+
nodeMap.set(item.id, { ...item, children: undefined })
|
|
23
|
+
})
|
|
24
|
+
if (!nodeMap.size) return list
|
|
25
|
+
|
|
26
|
+
const roots: ISysDictDataCacheVo[] = []
|
|
27
|
+
let linked = 0
|
|
28
|
+
nodeMap.forEach((node) => {
|
|
29
|
+
const parentId = node.parentId
|
|
30
|
+
if (parentId && parentId !== '0' && nodeMap.has(parentId)) {
|
|
31
|
+
const parent = nodeMap.get(parentId)!
|
|
32
|
+
if (!parent.children) parent.children = []
|
|
33
|
+
parent.children.push(node)
|
|
34
|
+
linked += 1
|
|
35
|
+
} else {
|
|
36
|
+
roots.push(node)
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
if (!linked) return list
|
|
40
|
+
return roots
|
|
41
|
+
}
|
|
42
|
+
|
|
10
43
|
export default function useDictHooks(dictTypes?: string[], orgId?: string) {
|
|
11
44
|
const userInfo = userInfoStore()
|
|
12
45
|
const dictStores = dictStore()
|
|
@@ -19,37 +52,133 @@ export default function useDictHooks(dictTypes?: string[], orgId?: string) {
|
|
|
19
52
|
return userInfo.user?.orgId
|
|
20
53
|
}
|
|
21
54
|
|
|
55
|
+
const hasDictList = (list?: ISysDictDataCacheVo[]) => Array.isArray(list) && list.length > 0
|
|
56
|
+
|
|
57
|
+
const hasDictCache = (dictType: string, oid?: string): boolean => {
|
|
58
|
+
if (oid && hasDictList(dictMap.value[`${oid}:${dictType}`])) return true
|
|
59
|
+
if (hasDictList(dictMap.value[dictType])) return true
|
|
60
|
+
return Object.keys(dictMap.value).some(
|
|
61
|
+
(key) => key.endsWith(`:${dictType}`) && hasDictList(dictMap.value[key]),
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const resolveDictMapKey = (dictType: string, orgId?: string): string | undefined => {
|
|
66
|
+
const tenantOrgId = resolveOrgId()
|
|
67
|
+
const scopedOrgId = orgId ?? tenantOrgId
|
|
68
|
+
if (scopedOrgId && hasDictList(dictMap.value[`${scopedOrgId}:${dictType}`])) {
|
|
69
|
+
return `${scopedOrgId}:${dictType}`
|
|
70
|
+
}
|
|
71
|
+
if (hasDictList(dictMap.value[dictType])) return dictType
|
|
72
|
+
const fallback = Object.keys(dictMap.value).find(
|
|
73
|
+
(key) => key.endsWith(`:${dictType}`) && hasDictList(dictMap.value[key]),
|
|
74
|
+
)
|
|
75
|
+
return fallback
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const resolveDictDataKey = (dictType: string, orgId?: string): string | undefined => {
|
|
79
|
+
const tenantOrgId = resolveOrgId()
|
|
80
|
+
const scopedOrgId = orgId ?? tenantOrgId
|
|
81
|
+
if (scopedOrgId) {
|
|
82
|
+
const scopedKey = `${scopedOrgId}:${dictType}`
|
|
83
|
+
if (dictDataMap.value[scopedKey] && Object.keys(dictDataMap.value[scopedKey]).length) {
|
|
84
|
+
return scopedKey
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (dictDataMap.value[dictType] && Object.keys(dictDataMap.value[dictType]).length) {
|
|
88
|
+
return dictType
|
|
89
|
+
}
|
|
90
|
+
return Object.keys(dictDataMap.value).find(
|
|
91
|
+
(key) => key.endsWith(`:${dictType}`) && Object.keys(dictDataMap.value[key]).length > 0,
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const repairCachedDictTrees = (): boolean => {
|
|
96
|
+
let repaired = false
|
|
97
|
+
for (const key of Object.keys(dictMap.value)) {
|
|
98
|
+
const list = dictMap.value[key]
|
|
99
|
+
if (!hasDictList(list)) continue
|
|
100
|
+
const tree = ensureDictTree(list)
|
|
101
|
+
if (tree !== list && tree.some((item) => item.children?.length)) {
|
|
102
|
+
dictMap.value[key] = tree
|
|
103
|
+
repaired = true
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return repaired
|
|
107
|
+
}
|
|
108
|
+
|
|
22
109
|
const getDict = async (dictTypes?: string[], orgId?: string): Promise<void> => {
|
|
23
110
|
try {
|
|
24
111
|
if (!dictTypes || !dictTypes.length) return
|
|
112
|
+
await userInfo.ensureUserHydrated()
|
|
25
113
|
const tenantOrgId = resolveOrgId(orgId)
|
|
26
|
-
|
|
27
|
-
let
|
|
28
|
-
if (
|
|
29
|
-
const oid = orgId ?? tenantOrgId
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
114
|
+
// orgId 就绪后清理 session 里「有 key 无数据」的脏缓存,避免误判已命中
|
|
115
|
+
let cacheDirty = false
|
|
116
|
+
if (tenantOrgId) {
|
|
117
|
+
const oid = orgId ?? tenantOrgId
|
|
118
|
+
for (const key of Object.keys(dictMap.value)) {
|
|
119
|
+
if (
|
|
120
|
+
(key.startsWith(`${oid}:`) || !key.includes(':')) &&
|
|
121
|
+
Array.isArray(dictMap.value[key]) &&
|
|
122
|
+
dictMap.value[key].length === 0
|
|
123
|
+
) {
|
|
124
|
+
delete dictMap.value[key]
|
|
125
|
+
delete dictDataMap.value[key]
|
|
126
|
+
delete dictDefaultValueMap.value[key]
|
|
127
|
+
cacheDirty = true
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// 修复「扁平但含 parentId」的脏缓存(带 orgId 后后端未 buildTree 的历史数据)
|
|
132
|
+
if (repairCachedDictTrees()) {
|
|
133
|
+
cacheDirty = true
|
|
33
134
|
}
|
|
135
|
+
if (cacheDirty) {
|
|
136
|
+
dictStores.publishToSharedCache()
|
|
137
|
+
}
|
|
138
|
+
const uncachedDictTypes = dictTypes.filter(
|
|
139
|
+
(dictType) => !hasDictCache(dictType, orgId ?? tenantOrgId),
|
|
140
|
+
)
|
|
34
141
|
if (!uncachedDictTypes.length) return
|
|
35
142
|
const data = await SysDictCacheApi.batchGetSysDictDataCacheVo(uncachedDictTypes, orgId ?? tenantOrgId)
|
|
36
|
-
|
|
37
|
-
|
|
143
|
+
const normalized: typeof data = {}
|
|
144
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
145
|
+
if (!value?.length) return
|
|
146
|
+
const tree = ensureDictTree(value)
|
|
147
|
+
normalized[key] = tree
|
|
148
|
+
const colon = key.indexOf(':')
|
|
149
|
+
if (colon > 0) {
|
|
150
|
+
const bare = key.slice(colon + 1)
|
|
151
|
+
if (!normalized[bare]?.length) {
|
|
152
|
+
normalized[bare] = tree
|
|
153
|
+
}
|
|
154
|
+
} else if (tenantOrgId) {
|
|
155
|
+
const scoped = `${tenantOrgId}:${key}`
|
|
156
|
+
if (!normalized[scoped]?.length) {
|
|
157
|
+
normalized[scoped] = tree
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
dictMap.value = { ...dictMap.value, ...normalized }
|
|
162
|
+
const nextDataMap = { ...dictDataMap.value }
|
|
163
|
+
const nextDefaultMap = { ...dictDefaultValueMap.value }
|
|
164
|
+
const promises = Object.keys(normalized).map(async (item: string) => {
|
|
38
165
|
const dataMap: dictDataMapVoType = {}
|
|
39
166
|
const defaultList: ISysDictDataCacheVo[] = []
|
|
40
|
-
await packageDictDataMap(dataMap, defaultList,
|
|
167
|
+
await packageDictDataMap(dataMap, defaultList, normalized[item])
|
|
41
168
|
return { item, dataMap, defaultList }
|
|
42
169
|
})
|
|
43
170
|
const results = await Promise.allSettled(promises)
|
|
44
171
|
results.forEach((result, index) => {
|
|
45
172
|
if (result.status === 'fulfilled') {
|
|
46
173
|
const { item, dataMap, defaultList } = result.value
|
|
47
|
-
|
|
48
|
-
|
|
174
|
+
nextDataMap[item] = dataMap
|
|
175
|
+
nextDefaultMap[item] = defaultList
|
|
49
176
|
} else {
|
|
50
|
-
ElMessage.error(`处理键 ${Object.keys(
|
|
177
|
+
ElMessage.error(`处理键 ${Object.keys(normalized)[index]} 时出错:`, result.reason)
|
|
51
178
|
}
|
|
52
179
|
})
|
|
180
|
+
dictDataMap.value = nextDataMap
|
|
181
|
+
dictDefaultValueMap.value = nextDefaultMap
|
|
53
182
|
dictStores.publishToSharedCache()
|
|
54
183
|
} catch (error: any) {
|
|
55
184
|
frameworkUtils.messageError(error)
|
|
@@ -75,13 +204,8 @@ export default function useDictHooks(dictTypes?: string[], orgId?: string) {
|
|
|
75
204
|
}
|
|
76
205
|
|
|
77
206
|
const getDictName = (value?: string, dictType?: string, orgId?: string): string | undefined => {
|
|
78
|
-
|
|
79
|
-
if (dictDataMap.value[key
|
|
80
|
-
const tenantOrgId = resolveOrgId()
|
|
81
|
-
if (tenantOrgId) {
|
|
82
|
-
key = `${tenantOrgId}:${dictType}`
|
|
83
|
-
if (dictDataMap.value[key!]) return dictDataMap.value[key!][value!]?.label || value
|
|
84
|
-
}
|
|
207
|
+
const key = resolveDictDataKey(dictType!, orgId)
|
|
208
|
+
if (key && dictDataMap.value[key]) return dictDataMap.value[key][value!]?.label || value
|
|
85
209
|
return value
|
|
86
210
|
}
|
|
87
211
|
|
|
@@ -90,52 +214,59 @@ export default function useDictHooks(dictTypes?: string[], orgId?: string) {
|
|
|
90
214
|
dictType: string,
|
|
91
215
|
orgId?: string,
|
|
92
216
|
): ISysDictDataCacheVo | {} => {
|
|
93
|
-
|
|
94
|
-
if (dictDataMap.value[key
|
|
95
|
-
return dictDataMap.value[key!][value!]
|
|
96
|
-
const tenantOrgId = resolveOrgId()
|
|
97
|
-
if (tenantOrgId) {
|
|
98
|
-
key = `${tenantOrgId}:${dictType}`
|
|
99
|
-
if (dictDataMap.value[key!] && dictDataMap.value[key!][value!])
|
|
100
|
-
return dictDataMap.value[key!][value!]
|
|
101
|
-
}
|
|
217
|
+
const key = resolveDictDataKey(dictType, orgId)
|
|
218
|
+
if (key && dictDataMap.value[key]?.[value]) return dictDataMap.value[key][value]
|
|
102
219
|
return {}
|
|
103
220
|
}
|
|
104
221
|
const getDictDefaultValue = (
|
|
105
222
|
dictType: string,
|
|
106
223
|
orgId?: string
|
|
107
224
|
): ISysDictDataCacheVo[] => {
|
|
108
|
-
let key = orgId ? `${orgId}:${dictType}` : dictType
|
|
109
|
-
if (dictDefaultValueMap.value[key!]) return dictDefaultValueMap.value[key!]
|
|
110
225
|
const tenantOrgId = resolveOrgId()
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
226
|
+
const scopedOrgId = orgId ?? tenantOrgId
|
|
227
|
+
if (scopedOrgId) {
|
|
228
|
+
const scoped = dictDefaultValueMap.value[`${scopedOrgId}:${dictType}`]
|
|
229
|
+
if (scoped?.length) return scoped
|
|
114
230
|
}
|
|
115
|
-
return []
|
|
231
|
+
return dictDefaultValueMap.value[dictType] ?? []
|
|
116
232
|
}
|
|
117
233
|
const getDictTypeData = (dictType: string, orgId?: string): ISysDictDataCacheVo[] => {
|
|
118
|
-
|
|
119
|
-
if (
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
234
|
+
const key = resolveDictMapKey(dictType, orgId)
|
|
235
|
+
if (!key) return []
|
|
236
|
+
const list = dictMap.value[key]
|
|
237
|
+
const tree = ensureDictTree(list)
|
|
238
|
+
if (tree !== list && tree.some((item) => item.children?.length)) {
|
|
239
|
+
dictMap.value[key] = tree
|
|
240
|
+
const bare = key.includes(':') ? key.slice(key.indexOf(':') + 1) : key
|
|
241
|
+
const tenantOrgId = resolveOrgId(orgId)
|
|
242
|
+
if (tenantOrgId && !key.includes(':')) {
|
|
243
|
+
dictMap.value[`${tenantOrgId}:${bare}`] = tree
|
|
244
|
+
} else if (key.includes(':') && !dictMap.value[bare]?.some((i) => i.children?.length)) {
|
|
245
|
+
dictMap.value[bare] = tree
|
|
246
|
+
}
|
|
124
247
|
}
|
|
125
|
-
return
|
|
248
|
+
return tree
|
|
126
249
|
}
|
|
127
250
|
const clearDict = (dictType?: string[], orgId?: string, all?: Boolean) => {
|
|
128
251
|
clearDictCache(dictType, resolveOrgId(), orgId, all)
|
|
129
252
|
}
|
|
253
|
+
const userReady = ref(!dictTypes?.length)
|
|
130
254
|
const dictReady = ref(!dictTypes?.length)
|
|
131
255
|
if (dictTypes?.length) {
|
|
132
|
-
|
|
256
|
+
void (async () => {
|
|
257
|
+
await userInfo.ensureUserHydrated()
|
|
258
|
+
userReady.value = true
|
|
259
|
+
await getDict(dictTypes, orgId)
|
|
133
260
|
dictReady.value = true
|
|
134
|
-
})
|
|
261
|
+
})()
|
|
135
262
|
}
|
|
136
263
|
return {
|
|
137
264
|
getDict,
|
|
265
|
+
userReady,
|
|
138
266
|
dictReady,
|
|
267
|
+
dictMap,
|
|
268
|
+
dictDataMap,
|
|
269
|
+
dictDefaultValueMap,
|
|
139
270
|
getDictName,
|
|
140
271
|
getDictData,
|
|
141
272
|
getDictTypeData,
|
package/src/stores/dictStore.ts
CHANGED
|
@@ -47,7 +47,7 @@ function getRootWindow(): Window {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
function hydrateCacheFromSessionStorage(cache: SharedDictCache) {
|
|
50
|
-
const raw = sessionStorage.getItem(DICT_STORAGE_KEY)
|
|
50
|
+
const raw = getRootWindow().sessionStorage.getItem(DICT_STORAGE_KEY)
|
|
51
51
|
if (!raw) return
|
|
52
52
|
try {
|
|
53
53
|
const parsed = JSON.parse(Base64.parse(raw).toString(Utf8)) as {
|
|
@@ -70,14 +70,15 @@ function hydrateCacheFromSessionStorage(cache: SharedDictCache) {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
function persistCacheToSessionStorage(cache: SharedDictCache) {
|
|
73
|
-
if (typeof
|
|
73
|
+
if (typeof window === 'undefined') return
|
|
74
|
+
const storage = getRootWindow().sessionStorage
|
|
74
75
|
try {
|
|
75
76
|
const payload = JSON.stringify({
|
|
76
77
|
dictMap: cache.dictMap,
|
|
77
78
|
dictDataMap: cache.dictDataMap,
|
|
78
79
|
dictDefaultValueMap: cache.dictDefaultValueMap,
|
|
79
80
|
})
|
|
80
|
-
|
|
81
|
+
storage.setItem(DICT_STORAGE_KEY, Base64.stringify(Utf8.parse(payload)))
|
|
81
82
|
} catch {
|
|
82
83
|
// ignore quota / privacy errors
|
|
83
84
|
}
|
|
@@ -8,6 +8,12 @@ import { defineStore } from 'pinia'
|
|
|
8
8
|
import type { IUserPermissionVo } from '../interface/IUserPermissionVo'
|
|
9
9
|
import { readUserInfoFromSessionStorage } from '../utils/userSessionStorage'
|
|
10
10
|
|
|
11
|
+
let hydratePromise: Promise<IUserPermissionVo | null> | null = null
|
|
12
|
+
|
|
13
|
+
function resetHydratePromise() {
|
|
14
|
+
hydratePromise = null
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
export const userInfoStore = defineStore({
|
|
12
18
|
id: 'userInfoStore',
|
|
13
19
|
state: () => ({
|
|
@@ -16,34 +22,52 @@ export const userInfoStore = defineStore({
|
|
|
16
22
|
}),
|
|
17
23
|
getters: {
|
|
18
24
|
getUserInfo(): IUserPermissionVo {
|
|
19
|
-
|
|
20
|
-
const hydrated = readUserInfoFromSessionStorage()
|
|
21
|
-
if (hydrated) {
|
|
22
|
-
//@ts-ignore
|
|
23
|
-
this.user = hydrated
|
|
24
|
-
}
|
|
25
|
-
}
|
|
25
|
+
this.hydrateFromRootSession()
|
|
26
26
|
return this.user as IUserPermissionVo
|
|
27
27
|
},
|
|
28
28
|
},
|
|
29
29
|
actions: {
|
|
30
30
|
/** 无界子应用从宿主 sessionStorage 恢复登录态(与 dictStore 同源策略) */
|
|
31
31
|
hydrateFromRootSession(): IUserPermissionVo | null {
|
|
32
|
-
if (this.user) {
|
|
32
|
+
if (this.user?.orgId) {
|
|
33
33
|
return this.user
|
|
34
34
|
}
|
|
35
35
|
const hydrated = readUserInfoFromSessionStorage()
|
|
36
|
-
if (hydrated) {
|
|
36
|
+
if (hydrated?.orgId) {
|
|
37
37
|
//@ts-ignore
|
|
38
38
|
this.user = hydrated
|
|
39
39
|
}
|
|
40
40
|
return this.user
|
|
41
41
|
},
|
|
42
|
+
/** 等待宿主 sessionStorage 写入 userInfo(无界子应用首次进入菜单页) */
|
|
43
|
+
async ensureUserHydrated(maxWaitMs = 3000): Promise<IUserPermissionVo | null> {
|
|
44
|
+
if (this.user?.orgId) {
|
|
45
|
+
return this.user
|
|
46
|
+
}
|
|
47
|
+
if (!hydratePromise) {
|
|
48
|
+
hydratePromise = (async () => {
|
|
49
|
+
const deadline = Date.now() + maxWaitMs
|
|
50
|
+
while (Date.now() < deadline) {
|
|
51
|
+
const hydrated = this.hydrateFromRootSession()
|
|
52
|
+
if (hydrated?.orgId) {
|
|
53
|
+
return hydrated
|
|
54
|
+
}
|
|
55
|
+
await new Promise((resolve) => setTimeout(resolve, 50))
|
|
56
|
+
}
|
|
57
|
+
return this.user
|
|
58
|
+
})().finally(() => {
|
|
59
|
+
hydratePromise = null
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
return hydratePromise
|
|
63
|
+
},
|
|
42
64
|
setUserInfo(userInfo: IUserPermissionVo) {
|
|
65
|
+
resetHydratePromise()
|
|
43
66
|
//@ts-ignore
|
|
44
67
|
this.user = userInfo
|
|
45
68
|
},
|
|
46
69
|
clear() {
|
|
70
|
+
resetHydratePromise()
|
|
47
71
|
//@ts-ignore
|
|
48
72
|
this.user = null
|
|
49
73
|
},
|
|
@@ -14,8 +14,18 @@ export function getRootWindow(): Window {
|
|
|
14
14
|
/** 从 pinia-plugin-store 持久化的 sessionStorage 恢复用户信息 */
|
|
15
15
|
export function readUserInfoFromSessionStorage(storage?: Storage): IUserPermissionVo | null {
|
|
16
16
|
if (typeof window === 'undefined') return null
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
let store: Storage
|
|
18
|
+
try {
|
|
19
|
+
store = storage ?? getRootWindow().sessionStorage
|
|
20
|
+
} catch {
|
|
21
|
+
return null
|
|
22
|
+
}
|
|
23
|
+
let raw: string | null
|
|
24
|
+
try {
|
|
25
|
+
raw = store.getItem(USER_INFO_STORAGE_KEY)
|
|
26
|
+
} catch {
|
|
27
|
+
return null
|
|
28
|
+
}
|
|
19
29
|
if (!raw) return null
|
|
20
30
|
try {
|
|
21
31
|
const parsed = JSON.parse(Base64.parse(raw).toString(Utf8)) as {
|