adtec-core-package 3.0.5 → 3.0.8
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,4 +1,5 @@
|
|
|
1
1
|
import { ElMessage } from 'element-plus'
|
|
2
|
+
import { ref } from 'vue'
|
|
2
3
|
import SysDictCacheApi from '../api/SysDictCacheApi'
|
|
3
4
|
import type { ISysDictDataCacheVo } from '../interface/ISysDictDataCacheVo'
|
|
4
5
|
import { type dictDataMapVoType, dictStore } from '../stores/dictStore'
|
|
@@ -46,6 +47,7 @@ export default function useDictHooks(dictTypes?: string[], orgId?: string) {
|
|
|
46
47
|
ElMessage.error(`处理键 ${Object.keys(data)[index]} 时出错:`, result.reason)
|
|
47
48
|
}
|
|
48
49
|
})
|
|
50
|
+
dictStores.publishToSharedCache()
|
|
49
51
|
} catch (error: any) {
|
|
50
52
|
frameworkUtils.messageError(error)
|
|
51
53
|
}
|
|
@@ -114,10 +116,16 @@ export default function useDictHooks(dictTypes?: string[], orgId?: string) {
|
|
|
114
116
|
const clearDict = (dictType?: string[], orgId?: string, all?: Boolean) => {
|
|
115
117
|
clearDictCache(dictType, userInfo.getUserInfo.orgId, orgId, all)
|
|
116
118
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
+
/** 构造函数传入的 dictTypes 是否已全部加载(缓存命中也会立即置 true) */
|
|
120
|
+
const dictReady = ref(!dictTypes?.length)
|
|
121
|
+
if (dictTypes?.length) {
|
|
122
|
+
getDict(dictTypes, orgId).finally(() => {
|
|
123
|
+
dictReady.value = true
|
|
124
|
+
})
|
|
125
|
+
}
|
|
119
126
|
return {
|
|
120
127
|
getDict,
|
|
128
|
+
dictReady,
|
|
121
129
|
getDictName,
|
|
122
130
|
getDictData,
|
|
123
131
|
getDictTypeData,
|
package/src/stores/dictStore.ts
CHANGED
|
@@ -18,27 +18,35 @@ export interface dictDataMapType {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
const DICT_STORAGE_KEY = 'dictStore'
|
|
21
|
+
const DICT_CACHE_UPDATE_EVENT = 'adtec-dict-cache-update'
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
/** 跨应用共享的 plain 缓存(非 Vue ref,避免 wujie 子应用与宿主 ref 响应式隔离) */
|
|
24
|
+
export interface SharedDictCache {
|
|
25
|
+
dictMap: dictMapType
|
|
26
|
+
dictDataMap: dictDataMapType
|
|
27
|
+
dictDefaultValueMap: dictMapType
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
declare global {
|
|
29
31
|
interface Window {
|
|
30
|
-
|
|
32
|
+
__ADTEC_SHARED_DICT_CACHE__?: SharedDictCache
|
|
33
|
+
/** @deprecated 3.0.7 起改用 __ADTEC_SHARED_DICT_CACHE__ */
|
|
34
|
+
__ADTEC_SHARED_DICT__?: {
|
|
35
|
+
dictMap: Ref<dictMapType>
|
|
36
|
+
dictDataMap: Ref<dictDataMapType>
|
|
37
|
+
dictDefaultValueMap: Ref<dictMapType>
|
|
38
|
+
}
|
|
31
39
|
}
|
|
32
40
|
}
|
|
33
41
|
|
|
34
|
-
/** wujie 子应用走 parent,宿主/独立 dev 走自身 window
|
|
42
|
+
/** wujie 子应用走 parent,宿主/独立 dev 走自身 window */
|
|
35
43
|
function getRootWindow(): Window {
|
|
36
44
|
if (typeof window === 'undefined') return window
|
|
37
45
|
const w = window as Window & { __POWERED_BY_WUJIE__?: boolean }
|
|
38
46
|
return w.__POWERED_BY_WUJIE__ ? window.parent : window
|
|
39
47
|
}
|
|
40
48
|
|
|
41
|
-
function
|
|
49
|
+
function hydrateCacheFromSessionStorage(cache: SharedDictCache) {
|
|
42
50
|
const raw = sessionStorage.getItem(DICT_STORAGE_KEY)
|
|
43
51
|
if (!raw) return
|
|
44
52
|
try {
|
|
@@ -48,45 +56,129 @@ function hydrateFromSessionStorage(state: SharedDictState) {
|
|
|
48
56
|
dictDefaultValueMap?: dictMapType
|
|
49
57
|
}
|
|
50
58
|
if (parsed.dictMap) {
|
|
51
|
-
|
|
59
|
+
Object.assign(cache.dictMap, parsed.dictMap)
|
|
52
60
|
}
|
|
53
61
|
if (parsed.dictDataMap) {
|
|
54
|
-
|
|
62
|
+
mergeDictDataMap(cache.dictDataMap, parsed.dictDataMap)
|
|
55
63
|
}
|
|
56
64
|
if (parsed.dictDefaultValueMap) {
|
|
57
|
-
|
|
58
|
-
...parsed.dictDefaultValueMap,
|
|
59
|
-
...state.dictDefaultValueMap.value,
|
|
60
|
-
}
|
|
65
|
+
Object.assign(cache.dictDefaultValueMap, parsed.dictDefaultValueMap)
|
|
61
66
|
}
|
|
62
67
|
} catch {
|
|
63
68
|
// ignore corrupt session data
|
|
64
69
|
}
|
|
65
70
|
}
|
|
66
71
|
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
function persistCacheToSessionStorage(cache: SharedDictCache) {
|
|
73
|
+
if (typeof sessionStorage === 'undefined') return
|
|
74
|
+
try {
|
|
75
|
+
const payload = JSON.stringify({
|
|
76
|
+
dictMap: cache.dictMap,
|
|
77
|
+
dictDataMap: cache.dictDataMap,
|
|
78
|
+
dictDefaultValueMap: cache.dictDefaultValueMap,
|
|
79
|
+
})
|
|
80
|
+
sessionStorage.setItem(DICT_STORAGE_KEY, Base64.stringify(Utf8.parse(payload)))
|
|
81
|
+
} catch {
|
|
82
|
+
// ignore quota / privacy errors
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function mergeDictDataMap(target: dictDataMapType, source: dictDataMapType) {
|
|
87
|
+
Object.keys(source).forEach((key) => {
|
|
88
|
+
target[key] = { ...target[key], ...source[key] }
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function cloneDictDataMap(source: dictDataMapType): dictDataMapType {
|
|
93
|
+
const clone: dictDataMapType = {}
|
|
94
|
+
mergeDictDataMap(clone, source)
|
|
95
|
+
return clone
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** 宿主 window 单例 plain 缓存:alive 子应用与宿主共享数据,但不共享 Vue ref */
|
|
99
|
+
export function getSharedDictCache(): SharedDictCache {
|
|
100
|
+
const root = getRootWindow()
|
|
101
|
+
if (!root.__ADTEC_SHARED_DICT_CACHE__) {
|
|
102
|
+
root.__ADTEC_SHARED_DICT_CACHE__ = {
|
|
103
|
+
dictMap: {},
|
|
104
|
+
dictDataMap: {},
|
|
105
|
+
dictDefaultValueMap: {},
|
|
106
|
+
}
|
|
107
|
+
hydrateCacheFromSessionStorage(root.__ADTEC_SHARED_DICT_CACHE__)
|
|
108
|
+
}
|
|
109
|
+
return root.__ADTEC_SHARED_DICT_CACHE__
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function broadcastDictCacheUpdate() {
|
|
113
|
+
if (typeof window === 'undefined') return
|
|
114
|
+
const event = new CustomEvent(DICT_CACHE_UPDATE_EVENT)
|
|
115
|
+
window.dispatchEvent(event)
|
|
69
116
|
const root = getRootWindow()
|
|
70
|
-
if (
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
117
|
+
if (root !== window) {
|
|
118
|
+
try {
|
|
119
|
+
root.dispatchEvent(new CustomEvent(DICT_CACHE_UPDATE_EVENT))
|
|
120
|
+
} catch {
|
|
121
|
+
// cross-origin parent
|
|
75
122
|
}
|
|
76
|
-
hydrateFromSessionStorage(root.__ADTEC_SHARED_DICT__)
|
|
77
123
|
}
|
|
78
|
-
return root.__ADTEC_SHARED_DICT__
|
|
79
124
|
}
|
|
80
125
|
|
|
81
|
-
/** @deprecated
|
|
82
|
-
export function
|
|
83
|
-
|
|
126
|
+
/** @deprecated 3.0.7 起请使用 getSharedDictCache */
|
|
127
|
+
export function getSharedDictRefs() {
|
|
128
|
+
return getSharedDictCache() as unknown as {
|
|
129
|
+
dictMap: Ref<dictMapType>
|
|
130
|
+
dictDataMap: Ref<dictDataMapType>
|
|
131
|
+
dictDefaultValueMap: Ref<dictMapType>
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** @deprecated 已由 getSharedDictCache 在初始化时 hydrate */
|
|
136
|
+
export function syncDictFromSessionStorage(_target?: unknown) {
|
|
137
|
+
hydrateCacheFromSessionStorage(getSharedDictCache())
|
|
84
138
|
}
|
|
85
139
|
|
|
86
140
|
export const dictStore = defineStore('dictStore', () => {
|
|
87
|
-
const
|
|
141
|
+
const sharedCache = getSharedDictCache()
|
|
88
142
|
|
|
89
|
-
|
|
143
|
+
/** 当前应用 Pinia 内的 ref,保证与本应用 Vue 响应式连通 */
|
|
144
|
+
const dictMap = ref<dictMapType>({ ...sharedCache.dictMap })
|
|
145
|
+
const dictDataMap = ref<dictDataMapType>(cloneDictDataMap(sharedCache.dictDataMap))
|
|
146
|
+
const dictDefaultValueMap = ref<dictMapType>({ ...sharedCache.dictDefaultValueMap })
|
|
147
|
+
|
|
148
|
+
const syncFromSharedCache = () => {
|
|
149
|
+
dictMap.value = { ...dictMap.value, ...sharedCache.dictMap }
|
|
150
|
+
mergeDictDataMap(dictDataMap.value, sharedCache.dictDataMap)
|
|
151
|
+
dictDefaultValueMap.value = { ...dictDefaultValueMap.value, ...sharedCache.dictDefaultValueMap }
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const publishToSharedCache = () => {
|
|
155
|
+
Object.assign(sharedCache.dictMap, dictMap.value)
|
|
156
|
+
mergeDictDataMap(sharedCache.dictDataMap, dictDataMap.value)
|
|
157
|
+
Object.assign(sharedCache.dictDefaultValueMap, dictDefaultValueMap.value)
|
|
158
|
+
persistCacheToSessionStorage(sharedCache)
|
|
159
|
+
broadcastDictCacheUpdate()
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (typeof window !== 'undefined') {
|
|
163
|
+
window.addEventListener(DICT_CACHE_UPDATE_EVENT, syncFromSharedCache)
|
|
164
|
+
const root = getRootWindow()
|
|
165
|
+
if (root !== window) {
|
|
166
|
+
try {
|
|
167
|
+
root.addEventListener(DICT_CACHE_UPDATE_EVENT, syncFromSharedCache)
|
|
168
|
+
} catch {
|
|
169
|
+
// cross-origin parent
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
syncFromSharedCache()
|
|
175
|
+
|
|
176
|
+
const clearDictCache = (
|
|
177
|
+
dictType?: string[],
|
|
178
|
+
userOrgId?: string,
|
|
179
|
+
orgId?: string,
|
|
180
|
+
all?: Boolean,
|
|
181
|
+
) => {
|
|
90
182
|
if (dictType && dictType.length > 0) {
|
|
91
183
|
dictType.forEach((item) => {
|
|
92
184
|
if (orgId) {
|
|
@@ -94,6 +186,9 @@ export const dictStore = defineStore('dictStore', () => {
|
|
|
94
186
|
delete dictMap.value[key]
|
|
95
187
|
delete dictDataMap.value[key]
|
|
96
188
|
delete dictDefaultValueMap.value[key]
|
|
189
|
+
delete sharedCache.dictMap[key]
|
|
190
|
+
delete sharedCache.dictDataMap[key]
|
|
191
|
+
delete sharedCache.dictDefaultValueMap[key]
|
|
97
192
|
} else {
|
|
98
193
|
delete dictMap.value[item]
|
|
99
194
|
delete dictDataMap.value[item]
|
|
@@ -101,18 +196,32 @@ export const dictStore = defineStore('dictStore', () => {
|
|
|
101
196
|
delete dictMap.value[`${userOrgId}:${item}`]
|
|
102
197
|
delete dictDataMap.value[`${userOrgId}:${item}`]
|
|
103
198
|
delete dictDefaultValueMap.value[`${userOrgId}:${item}`]
|
|
199
|
+
delete sharedCache.dictMap[item]
|
|
200
|
+
delete sharedCache.dictDataMap[item]
|
|
201
|
+
delete sharedCache.dictDefaultValueMap[item]
|
|
202
|
+
delete sharedCache.dictMap[`${userOrgId}:${item}`]
|
|
203
|
+
delete sharedCache.dictDataMap[`${userOrgId}:${item}`]
|
|
204
|
+
delete sharedCache.dictDefaultValueMap[`${userOrgId}:${item}`]
|
|
104
205
|
}
|
|
105
206
|
})
|
|
207
|
+
publishToSharedCache()
|
|
106
208
|
} else if (all) {
|
|
107
209
|
dictMap.value = {}
|
|
108
210
|
dictDataMap.value = {}
|
|
109
211
|
dictDefaultValueMap.value = {}
|
|
212
|
+
sharedCache.dictMap = {}
|
|
213
|
+
sharedCache.dictDataMap = {}
|
|
214
|
+
sharedCache.dictDefaultValueMap = {}
|
|
215
|
+
publishToSharedCache()
|
|
110
216
|
}
|
|
111
217
|
}
|
|
218
|
+
|
|
112
219
|
return {
|
|
113
220
|
dictMap,
|
|
114
221
|
dictDataMap,
|
|
115
222
|
dictDefaultValueMap,
|
|
116
223
|
clearDictCache,
|
|
224
|
+
syncFromSharedCache,
|
|
225
|
+
publishToSharedCache,
|
|
117
226
|
}
|
|
118
227
|
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type ObjectWithHasOwn = typeof Object & {
|
|
2
|
+
hasOwn?: (object: object, property: PropertyKey) => boolean
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/** 旧浏览器 / 部分 WebView 无 Object.hasOwn,需在业务 bundle 之前注入 */
|
|
6
|
+
export function applyObjectHasOwnPolyfill(target: typeof globalThis = globalThis) {
|
|
7
|
+
const objectCtor = target.Object as ObjectWithHasOwn
|
|
8
|
+
if (typeof objectCtor.hasOwn === 'function') {
|
|
9
|
+
return
|
|
10
|
+
}
|
|
11
|
+
objectCtor.hasOwn = function (object, property) {
|
|
12
|
+
return objectCtor.prototype.hasOwnProperty.call(object, property)
|
|
13
|
+
}
|
|
14
|
+
}
|