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,6 +1,6 @@
1
1
  {
2
2
  "name": "adtec-core-package",
3
- "version": "3.0.5",
3
+ "version": "3.0.8",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -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
- getDict(dictTypes, orgId).then(() => {
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,
@@ -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
- export interface SharedDictState {
23
- dictMap: Ref<dictMapType>
24
- dictDataMap: Ref<dictDataMapType>
25
- dictDefaultValueMap: Ref<dictMapType>
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
- __ADTEC_SHARED_DICT__?: SharedDictState
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 —— 全应用共享同一份 ref */
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 hydrateFromSessionStorage(state: SharedDictState) {
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
- state.dictMap.value = { ...parsed.dictMap, ...state.dictMap.value }
59
+ Object.assign(cache.dictMap, parsed.dictMap)
52
60
  }
53
61
  if (parsed.dictDataMap) {
54
- state.dictDataMap.value = { ...parsed.dictDataMap, ...state.dictDataMap.value }
62
+ mergeDictDataMap(cache.dictDataMap, parsed.dictDataMap)
55
63
  }
56
64
  if (parsed.dictDefaultValueMap) {
57
- state.dictDefaultValueMap.value = {
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
- /** 宿主 window 单例:alive 子应用与宿主读写同一组 Vue ref(刷新时仍由 sessionStorage 恢复) */
68
- export function getSharedDictRefs(): SharedDictState {
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 (!root.__ADTEC_SHARED_DICT__) {
71
- root.__ADTEC_SHARED_DICT__ = {
72
- dictMap: ref<dictMapType>({}),
73
- dictDataMap: ref<dictDataMapType>({}),
74
- dictDefaultValueMap: ref<dictMapType>({}),
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 已由 getSharedDictRefs 在初始化时 hydrate;保留兼容旧调用 */
82
- export function syncDictFromSessionStorage(target: SharedDictState) {
83
- hydrateFromSessionStorage(target)
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 { dictMap, dictDataMap, dictDefaultValueMap } = getSharedDictRefs()
141
+ const sharedCache = getSharedDictCache()
88
142
 
89
- const clearDictCache = (dictType?: string[], userOrgId?: string, orgId?: string, all?: Boolean) => {
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
+ }