adtec-core-package 3.0.4 → 3.0.7

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.
@@ -1,35 +1,59 @@
1
+ /** TipTap focus 选项:不触发 ProseMirror scrollIntoView */
2
+ export const FOCUS_WITHOUT_SCROLL = { scrollIntoView: false }
3
+
4
+ function pushScrollPosition(positions, seen, el) {
5
+ if (!el || seen.has(el)) return
6
+ seen.add(el)
7
+ positions.push({
8
+ el,
9
+ top: el.scrollTop,
10
+ left: el.scrollLeft,
11
+ })
12
+ }
13
+
1
14
  /**
2
- * 保存/恢复编辑器及外层滚动位置,避免 setBlockType 等命令触发 scrollIntoView 导致页面跳动。
15
+ * 保存/恢复编辑器及外层滚动位置,避免 toolbar focus / setBlockType 等触发 scrollIntoView 导致页面跳动。
3
16
  */
4
17
  export function captureScrollPositions(container) {
5
18
  const positions = []
19
+ const seen = new Set()
6
20
  const pageContainer = document.querySelector(
7
21
  `${container} .umo-zoomable-container`,
8
22
  )
9
- if (pageContainer) {
10
- positions.push({
11
- el: pageContainer,
12
- top: pageContainer.scrollTop,
13
- left: pageContainer.scrollLeft,
14
- })
15
- }
23
+ pushScrollPosition(positions, seen, pageContainer)
16
24
 
17
- let node = pageContainer?.parentElement ?? null
25
+ let node =
26
+ pageContainer?.parentElement ??
27
+ document.querySelector(container)?.parentElement ??
28
+ null
18
29
  while (node && node !== document.documentElement) {
19
30
  if (node.classList?.contains('el-scrollbar__wrap')) {
20
- positions.push({
21
- el: node,
22
- top: node.scrollTop,
23
- left: node.scrollLeft,
24
- })
25
- break
31
+ pushScrollPosition(positions, seen, node)
32
+ } else {
33
+ const style = getComputedStyle(node)
34
+ const overflow = `${style.overflow}${style.overflowY}${style.overflowX}`
35
+ if (/auto|scroll/.test(overflow)) {
36
+ pushScrollPosition(positions, seen, node)
37
+ }
26
38
  }
27
39
  node = node.parentElement
28
40
  }
29
41
 
42
+ pushScrollPosition(positions, seen, document.documentElement)
43
+ pushScrollPosition(positions, seen, document.body)
44
+
30
45
  return positions
31
46
  }
32
47
 
48
+ export function runPreservingScroll(container, fn) {
49
+ const scrollPositions = captureScrollPositions(container)
50
+ try {
51
+ return fn()
52
+ } finally {
53
+ restoreScrollPositions(scrollPositions)
54
+ }
55
+ }
56
+
33
57
  export function restoreScrollPositions(positions) {
34
58
  if (!positions.length) return
35
59
  const apply = () => {
@@ -7,14 +7,15 @@
7
7
  <script setup lang="ts">
8
8
  //@ts-ignore
9
9
  import { components, initVxeTableInPage } from 'adtec-core-package/src/config/VxeTableConfig'
10
- // 导入默认的语言
11
10
  import { defineComponent, getCurrentInstance, h } from 'vue'
11
+
12
12
  const { VxeGrid } = components
13
13
  defineComponent({
14
14
  components: {
15
15
  VxeGrid,
16
16
  },
17
17
  })
18
+
18
19
  const { renderComponent = { enableElementPlus: true, enableExcel: false, enablePdf: false } } =
19
20
  defineProps<{
20
21
  renderComponent?: {
@@ -24,12 +25,18 @@ const { renderComponent = { enableElementPlus: true, enableExcel: false, enableP
24
25
  }
25
26
  }>()
26
27
 
27
- initVxeTableInPage(renderComponent.enableExcel,renderComponent.enablePdf)
28
+ initVxeTableInPage(
29
+ renderComponent.enableExcel,
30
+ renderComponent.enablePdf,
31
+ renderComponent.enableElementPlus ?? true,
32
+ )
28
33
 
29
34
  const vm = getCurrentInstance()
30
35
 
31
- const changeRef = (exposed: any) => {
32
- vm && (vm.exposed = exposed)
36
+ const changeRef = (exposed: unknown) => {
37
+ if (vm) {
38
+ vm.exposed = exposed
39
+ }
33
40
  }
34
41
  </script>
35
42
 
@@ -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,
@@ -1,6 +1,9 @@
1
1
  import { defineStore } from 'pinia'
2
- import { ref } from 'vue'
2
+ import { ref, type Ref } from 'vue'
3
+ import Base64 from 'crypto-js/enc-base64'
4
+ import Utf8 from 'crypto-js/enc-utf8'
3
5
  import type { ISysDictDataCacheVo } from '../interface/ISysDictDataCacheVo'
6
+
4
7
  // 定义包含map的整体类型
5
8
  export interface dictMapType {
6
9
  [key: string]: ISysDictDataCacheVo[]
@@ -14,12 +17,168 @@ export interface dictDataMapType {
14
17
  [key: string]: { [key: string]: ISysDictDataCacheVo }
15
18
  }
16
19
 
20
+ const DICT_STORAGE_KEY = 'dictStore'
21
+ const DICT_CACHE_UPDATE_EVENT = 'adtec-dict-cache-update'
22
+
23
+ /** 跨应用共享的 plain 缓存(非 Vue ref,避免 wujie 子应用与宿主 ref 响应式隔离) */
24
+ export interface SharedDictCache {
25
+ dictMap: dictMapType
26
+ dictDataMap: dictDataMapType
27
+ dictDefaultValueMap: dictMapType
28
+ }
29
+
30
+ declare global {
31
+ interface Window {
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
+ }
39
+ }
40
+ }
41
+
42
+ /** wujie 子应用走 parent,宿主/独立 dev 走自身 window */
43
+ function getRootWindow(): Window {
44
+ if (typeof window === 'undefined') return window
45
+ const w = window as Window & { __POWERED_BY_WUJIE__?: boolean }
46
+ return w.__POWERED_BY_WUJIE__ ? window.parent : window
47
+ }
48
+
49
+ function hydrateCacheFromSessionStorage(cache: SharedDictCache) {
50
+ const raw = sessionStorage.getItem(DICT_STORAGE_KEY)
51
+ if (!raw) return
52
+ try {
53
+ const parsed = JSON.parse(Base64.parse(raw).toString(Utf8)) as {
54
+ dictMap?: dictMapType
55
+ dictDataMap?: dictDataMapType
56
+ dictDefaultValueMap?: dictMapType
57
+ }
58
+ if (parsed.dictMap) {
59
+ Object.assign(cache.dictMap, parsed.dictMap)
60
+ }
61
+ if (parsed.dictDataMap) {
62
+ mergeDictDataMap(cache.dictDataMap, parsed.dictDataMap)
63
+ }
64
+ if (parsed.dictDefaultValueMap) {
65
+ Object.assign(cache.dictDefaultValueMap, parsed.dictDefaultValueMap)
66
+ }
67
+ } catch {
68
+ // ignore corrupt session data
69
+ }
70
+ }
71
+
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)
116
+ const root = getRootWindow()
117
+ if (root !== window) {
118
+ try {
119
+ root.dispatchEvent(new CustomEvent(DICT_CACHE_UPDATE_EVENT))
120
+ } catch {
121
+ // cross-origin parent
122
+ }
123
+ }
124
+ }
125
+
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())
138
+ }
139
+
17
140
  export const dictStore = defineStore('dictStore', () => {
18
- const dictMap = ref<dictMapType>({})
19
- const dictDataMap = ref<dictDataMapType>({})
20
- const dictDefaultValueMap = ref<dictMapType>({})
141
+ const sharedCache = getSharedDictCache()
142
+
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
+ }
21
161
 
22
- const clearDictCache = (dictType?: string[],userOrgId?: string, orgId?: string, all?: Boolean) => {
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
+ ) => {
23
182
  if (dictType && dictType.length > 0) {
24
183
  dictType.forEach((item) => {
25
184
  if (orgId) {
@@ -27,6 +186,9 @@ export const dictStore = defineStore('dictStore', () => {
27
186
  delete dictMap.value[key]
28
187
  delete dictDataMap.value[key]
29
188
  delete dictDefaultValueMap.value[key]
189
+ delete sharedCache.dictMap[key]
190
+ delete sharedCache.dictDataMap[key]
191
+ delete sharedCache.dictDefaultValueMap[key]
30
192
  } else {
31
193
  delete dictMap.value[item]
32
194
  delete dictDataMap.value[item]
@@ -34,18 +196,32 @@ export const dictStore = defineStore('dictStore', () => {
34
196
  delete dictMap.value[`${userOrgId}:${item}`]
35
197
  delete dictDataMap.value[`${userOrgId}:${item}`]
36
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}`]
37
205
  }
38
206
  })
207
+ publishToSharedCache()
39
208
  } else if (all) {
40
209
  dictMap.value = {}
41
210
  dictDataMap.value = {}
42
211
  dictDefaultValueMap.value = {}
212
+ sharedCache.dictMap = {}
213
+ sharedCache.dictDataMap = {}
214
+ sharedCache.dictDefaultValueMap = {}
215
+ publishToSharedCache()
43
216
  }
44
217
  }
218
+
45
219
  return {
46
220
  dictMap,
47
221
  dictDataMap,
48
222
  dictDefaultValueMap,
49
223
  clearDictCache,
224
+ syncFromSharedCache,
225
+ publishToSharedCache,
50
226
  }
51
227
  })