vue2-client 1.10.32 → 1.10.35

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 (27) hide show
  1. package/package.json +1 -1
  2. package/src/App.vue +196 -196
  3. package/src/base-client/components/common/XAddNativeForm/demo.vue +43 -43
  4. package/src/base-client/components/common/XAddReport/XAddReport.vue +1 -1
  5. package/src/base-client/components/common/XConversation/XConversation.vue +12 -0
  6. package/src/base-client/components/common/XDataCard/XDataCard.vue +17 -16
  7. package/src/base-client/components/common/XForm/XFormItem.vue +1248 -1286
  8. package/src/base-client/components/common/XFormCol/XFormCol.vue +157 -157
  9. package/src/base-client/components/common/XFormGroup/XFormGroup.vue +301 -301
  10. package/src/base-client/components/common/XFormTable/XFormTable.vue +12 -0
  11. package/src/base-client/components/common/XFormTable/demo.vue +2 -2
  12. package/src/base-client/components/common/XIntervalPicker/XIntervalPicker.vue +121 -0
  13. package/src/base-client/components/common/XReportDrawer/XReportDrawer.vue +1 -1
  14. package/src/base-client/components/common/XReportGrid/XReport.vue +1079 -1070
  15. package/src/base-client/components/common/XReportGrid/XReportDemo.vue +46 -47
  16. package/src/base-client/components/common/XReportGrid/XReportDesign.vue +628 -628
  17. package/src/base-client/components/common/XReportGrid/XReportJsonRender.vue +380 -380
  18. package/src/base-client/components/common/XReportGrid/XReportTrGroup.vue +1104 -1104
  19. package/src/base-client/components/common/XReportGrid/print.js +184 -184
  20. package/src/base-client/components/common/XTab/XTab.vue +57 -25
  21. package/src/components/cache/AKeepAlive.js +11 -4
  22. package/src/layouts/BlankView.vue +59 -3
  23. package/src/pages/ReportGrid/index.vue +76 -76
  24. package/src/router/async/router.map.js +95 -148
  25. package/src/router/guards.js +260 -263
  26. package/src/utils/microAppUtils.js +49 -40
  27. package/src/utils/routerUtil.js +526 -450
@@ -1,184 +1,184 @@
1
- // print.js
2
-
3
- export function printElement (elementToPrint) {
4
- // 创建一个新的浏览器窗口
5
- const printWindow = window.open('', '_blank', 'height=1024,width=768')
6
- // 设置新窗口的文档内容
7
- printWindow.document.write(`
8
- <html>
9
- <head>
10
- <title>Print</title>
11
- <style>
12
- @page {
13
- size: auto;
14
- margin: 0mm;
15
- }
16
- html, body {
17
- margin: 0;
18
- padding: 0;
19
- width: 100%;
20
- height: 100%;
21
- }
22
- #print-container {
23
- display: none
24
- }
25
- .img{
26
- width: 95%;
27
- height: 180px;
28
- object-fit: cover;
29
- }
30
- .reportMain {
31
- text-align: center;
32
- margin: 0 auto;
33
- font-size: 16px;
34
- color: #000;
35
- background-color: #fff;
36
- border-radius: 8px;
37
-
38
- .reportTitle {
39
- font-weight: bold;
40
- }
41
-
42
- .subTitle {
43
- display: flex;
44
- justify-content: space-between;
45
- margin-bottom: 1%;
46
-
47
- .subTitleItems {
48
- max-width: 30%;
49
- }
50
- }
51
-
52
- .inputsDiv {
53
- display: flex;
54
- justify-content: space-between;
55
- .inputsDivItem {
56
- display: flex;
57
- align-items: center;
58
- padding: 0 4px;
59
- white-space: nowrap;
60
- .inputsDivItemLabel {
61
- padding: 0 4px;
62
- }
63
- }
64
- }
65
-
66
- .reportTable {
67
- width: 100%;
68
- border-collapse: collapse;
69
- table-layout:fixed;
70
- word-break:break-all;
71
- text-align: center;
72
- }
73
- }
74
- .reportMainForDisplay {
75
- text-align: center;
76
- margin: 10% auto;
77
- font-size: 16px;
78
- color: #000;
79
- background-color: #fff;
80
- border-radius: 8px;
81
-
82
- .reportTitle {
83
- font-weight: bold;
84
- }
85
-
86
- .subTitle {
87
- display: flex;
88
- justify-content: space-between;
89
-
90
- .subTitleItems {
91
- max-width: 30%;
92
- }
93
- }
94
-
95
- .inputsDiv {
96
- display: flex;
97
- justify-content: space-around;
98
- .inputsDivItem {
99
- display: flex;
100
- align-items: center;
101
- padding: 0 4px;
102
- white-space: nowrap;
103
- .inputsDivItemLabel {
104
- padding: 0 4px;
105
- }
106
- }
107
- }
108
-
109
- .reportTable {
110
- width: 100%;
111
- border-collapse: collapse;
112
- table-layout:fixed;
113
- word-break:break-all;
114
- }
115
- }
116
- .reportMainNoPadding {
117
- text-align: center;
118
- margin: 0 auto;
119
- font-size: 16px;
120
- color: #000;
121
- background-color: #fff;
122
- border-radius: 8px;
123
-
124
- .reportTitle {
125
- font-weight: bold;
126
- }
127
-
128
- .subTitle {
129
- display: flex;
130
- justify-content: space-between;
131
-
132
- .subTitleItems {
133
- max-width: 30%;
134
- }
135
- }
136
-
137
- .inputsDiv {
138
- display: flex;
139
- justify-content: space-between;
140
- .inputsDivItem {
141
- display: flex;
142
- align-items: center;
143
- padding: 0 4px;
144
- white-space: nowrap;
145
- .inputsDivItemLabel {
146
- padding: 0 4px;
147
- }
148
- }
149
- }
150
-
151
- .reportTable {
152
- width: 100%;
153
- border-collapse: collapse;
154
- table-layout:fixed;
155
- word-break:break-all;
156
- }
157
- }
158
- .tools{
159
- position: fixed;
160
- right: 2%;
161
- text-align: right;
162
- width: 60%;
163
- cursor: pointer;
164
- .toolsItem{
165
- width: 15%;
166
- margin-right: 3%;
167
- display: inline-block;
168
- }
169
- }
170
- </style>
171
- </head>
172
- <body>
173
- <!-- 将需要打印的元素内容复制到新窗口中 -->
174
- ${elementToPrint.innerHTML}
175
- </body>
176
- </html>
177
- `)
178
- // 延迟执行打印,以确保新窗口的内容已加载完成
179
- printWindow.document.close() // 关闭文档流,确保内容完全加载
180
- setTimeout(() => {
181
- printWindow.print() // 调用打印方法
182
- printWindow.close()
183
- }, 500) // 延迟500毫秒后执行打印
184
- }
1
+ // print.js
2
+
3
+ export function printElement (elementToPrint) {
4
+ // 创建一个新的浏览器窗口
5
+ const printWindow = window.open('', '_blank', 'height=1024,width=768')
6
+ // 设置新窗口的文档内容
7
+ printWindow.document.write(`
8
+ <html>
9
+ <head>
10
+ <title>Print</title>
11
+ <style>
12
+ @page {
13
+ size: auto;
14
+ margin: 0mm;
15
+ }
16
+ html, body {
17
+ margin: 0;
18
+ padding: 0;
19
+ width: 100%;
20
+ height: 100%;
21
+ }
22
+ #print-container {
23
+ display: none
24
+ }
25
+ .img{
26
+ width: 95%;
27
+ height: 180px;
28
+ object-fit: cover;
29
+ }
30
+ .reportMain {
31
+ text-align: center;
32
+ margin: 0 auto;
33
+ font-size: 16px;
34
+ color: #000;
35
+ background-color: #fff;
36
+ border-radius: 8px;
37
+
38
+ .reportTitle {
39
+ font-weight: bold;
40
+ }
41
+
42
+ .subTitle {
43
+ display: flex;
44
+ justify-content: space-between;
45
+ margin-bottom: 1%;
46
+
47
+ .subTitleItems {
48
+ max-width: 30%;
49
+ }
50
+ }
51
+
52
+ .inputsDiv {
53
+ display: flex;
54
+ justify-content: space-between;
55
+ .inputsDivItem {
56
+ display: flex;
57
+ align-items: center;
58
+ padding: 0 4px;
59
+ white-space: nowrap;
60
+ .inputsDivItemLabel {
61
+ padding: 0 4px;
62
+ }
63
+ }
64
+ }
65
+
66
+ .reportTable {
67
+ width: 100%;
68
+ border-collapse: collapse;
69
+ table-layout:fixed;
70
+ word-break:break-all;
71
+ text-align: center;
72
+ }
73
+ }
74
+ .reportMainForDisplay {
75
+ text-align: center;
76
+ margin: 10% auto;
77
+ font-size: 16px;
78
+ color: #000;
79
+ background-color: #fff;
80
+ border-radius: 8px;
81
+
82
+ .reportTitle {
83
+ font-weight: bold;
84
+ }
85
+
86
+ .subTitle {
87
+ display: flex;
88
+ justify-content: space-between;
89
+
90
+ .subTitleItems {
91
+ max-width: 30%;
92
+ }
93
+ }
94
+
95
+ .inputsDiv {
96
+ display: flex;
97
+ justify-content: space-around;
98
+ .inputsDivItem {
99
+ display: flex;
100
+ align-items: center;
101
+ padding: 0 4px;
102
+ white-space: nowrap;
103
+ .inputsDivItemLabel {
104
+ padding: 0 4px;
105
+ }
106
+ }
107
+ }
108
+
109
+ .reportTable {
110
+ width: 100%;
111
+ border-collapse: collapse;
112
+ table-layout:fixed;
113
+ word-break:break-all;
114
+ }
115
+ }
116
+ .reportMainNoPadding {
117
+ text-align: center;
118
+ margin: 0 auto;
119
+ font-size: 16px;
120
+ color: #000;
121
+ background-color: #fff;
122
+ border-radius: 8px;
123
+
124
+ .reportTitle {
125
+ font-weight: bold;
126
+ }
127
+
128
+ .subTitle {
129
+ display: flex;
130
+ justify-content: space-between;
131
+
132
+ .subTitleItems {
133
+ max-width: 30%;
134
+ }
135
+ }
136
+
137
+ .inputsDiv {
138
+ display: flex;
139
+ justify-content: space-between;
140
+ .inputsDivItem {
141
+ display: flex;
142
+ align-items: center;
143
+ padding: 0 4px;
144
+ white-space: nowrap;
145
+ .inputsDivItemLabel {
146
+ padding: 0 4px;
147
+ }
148
+ }
149
+ }
150
+
151
+ .reportTable {
152
+ width: 100%;
153
+ border-collapse: collapse;
154
+ table-layout:fixed;
155
+ word-break:break-all;
156
+ }
157
+ }
158
+ .tools{
159
+ position: fixed;
160
+ right: 2%;
161
+ text-align: right;
162
+ width: 60%;
163
+ cursor: pointer;
164
+ .toolsItem{
165
+ width: 15%;
166
+ margin-right: 3%;
167
+ display: inline-block;
168
+ }
169
+ }
170
+ </style>
171
+ </head>
172
+ <body>
173
+ <!-- 将需要打印的元素内容复制到新窗口中 -->
174
+ ${elementToPrint.innerHTML}
175
+ </body>
176
+ </html>
177
+ `)
178
+ // 延迟执行打印,以确保新窗口的内容已加载完成
179
+ printWindow.document.close() // 关闭文档流,确保内容完全加载
180
+ setTimeout(() => {
181
+ printWindow.print() // 调用打印方法
182
+ printWindow.close()
183
+ }, 500) // 延迟500毫秒后执行打印
184
+ }
@@ -2,24 +2,23 @@
2
2
  <a-card :bordered="false">
3
3
  <a-tabs :tabBarGutter="10" :activeKey="activeKey" @change="tabPaneChange">
4
4
  <a-tab-pane
5
+ :forceRender="true"
5
6
  v-for="(tab, index) in config.data"
6
7
  :key="index"
7
8
  :tab="tab.title"
8
9
  >
9
- <div>
10
- <component
11
- :is="tab.slotType"
12
- :key="index"
13
- :ref="`tab_com_${tab.slotType}_${index}`"
14
- :serviceName="tab.serviceName"
15
- :serverName="tab.serviceName"
16
- :queryParamsName="tab.slotConfig"
17
- v-on="getEventHandlers(tab,index)"
18
- @hook:mounted="(h)=>onComponentMounted(h,tab,index)"
19
- :config-name="tab.slotConfig"
20
- :env="env"
21
- />
22
- </div>
10
+ <component
11
+ :is="tab.slotType"
12
+ :key="index"
13
+ :ref="`tab_com_${tab.slotType}_${index}`"
14
+ :serviceName="tab.serviceName"
15
+ :serverName="tab.serviceName"
16
+ :queryParamsName="tab.slotConfig"
17
+ v-on="getEventHandlers(tab,index)"
18
+ @hook:mounted="(h)=>onComponentMounted(h,tab,index)"
19
+ :config-name="tab.slotConfig"
20
+ :env="env"
21
+ />
23
22
  </a-tab-pane>
24
23
  </a-tabs>
25
24
  </a-card>
@@ -39,10 +38,11 @@ export default {
39
38
  XAddNativeForm: () => import('@vue2-client/base-client/components/common/XAddNativeForm/XAddNativeForm.vue'),
40
39
  XReportGrid: () => import('@vue2-client/base-client/components/common/XReportGrid/XReport.vue')
41
40
  },
42
- inject: ['isInAModal', 'getSelectedId', 'getSelectedData', 'getOutEnv'],
41
+ inject: ['isInAModal', 'getSelectedId', 'getSelectedData', 'getOutEnv', 'setGlobalData', 'getGlobalData'],
43
42
  provide () {
44
43
  return {
45
- currUser: this.currUser
44
+ currUser: this.currUser,
45
+ getSelectedId: this.getSelectedId
46
46
  }
47
47
  },
48
48
  data () {
@@ -50,6 +50,7 @@ export default {
50
50
  activeKey: 0,
51
51
  // 配置
52
52
  config: undefined,
53
+ attr: {}
53
54
  }
54
55
  },
55
56
  computed: {
@@ -66,6 +67,7 @@ export default {
66
67
  getConfigByName,
67
68
  getConfigByNameAsync,
68
69
  tabPaneChange (newKey) {
70
+ let result = {}
69
71
  if (this.activeKey === newKey) {
70
72
  return
71
73
  }
@@ -76,21 +78,51 @@ export default {
76
78
  newKey,
77
79
  this.config.data[oldKey],
78
80
  this.config.data[newKey],
81
+ `tab_com_${this.config.data[oldKey].slotType}_${oldKey}`,
82
+ `tab_com_${this.config.data[newKey].slotType}_${newKey}`,
79
83
  this.$refs[`tab_com_${this.config.data[oldKey].slotType}_${oldKey}`][0]
80
84
  ]
81
85
  if (!this.$refs[`tab_com_${this.config.data[newKey].slotType}_${newKey}`]) {
86
+ args.push(null)
82
87
  console.warn('新页签示例切换页签时暂未初始化,仅调用该页签初始化方法不调用切换函数')
83
88
  } else {
84
89
  args.push(this.$refs[`tab_com_${this.config.data[newKey].slotType}_${newKey}`][0])
85
- this.$nextTick(() => {
86
- // fromKey,toKey,fromConfig,toConfig,fromRef,toRef
87
- const result = executeStrFunctionByContext(this, this.config.changeFunc, args)
88
- if (result && result.noChange) {
89
- console.info('不切换页签作为按钮使用')
90
- } else {
91
- this.activeKey = newKey
92
- }
93
- })
90
+ }
91
+ result = executeStrFunctionByContext(this, this.config.changeFunc, args)
92
+ if (result && result.noChange) {
93
+ console.info('不切换页签作为按钮使用')
94
+ } else {
95
+ this.activeKey = newKey
96
+ if (result && result.callback && typeof result.callback === 'function') {
97
+ // 使用 $nextTick 等待 DOM 更新完成后再获取组件实例
98
+ this.$nextTick(() => {
99
+ const newComponent = this.$refs[`tab_com_${this.config.data[newKey].slotType}_${newKey}`]
100
+ if (!newComponent || !newComponent[0]) {
101
+ console.warn('组件实例尚未创建,等待组件mounted事件')
102
+ // 使用 MutationObserver 监听DOM变化
103
+ const observer = new MutationObserver((mutations, obs) => {
104
+ const newComp = this.$refs[`tab_com_${this.config.data[newKey].slotType}_${newKey}`]
105
+ if (newComp && newComp[0]) {
106
+ obs.disconnect()
107
+ console.log('组件已创建,执行回调')
108
+ result.callback()
109
+ }
110
+ })
111
+ observer.observe(this.$el, {
112
+ childList: true,
113
+ subtree: true
114
+ })
115
+ // 设置超时,避免无限等待
116
+ setTimeout(() => {
117
+ observer.disconnect()
118
+ console.warn('等待组件创建超时')
119
+ }, 500)
120
+
121
+ return
122
+ }
123
+ result.callback()
124
+ })
125
+ }
94
126
  }
95
127
  } else {
96
128
  this.activeKey = newKey
@@ -31,7 +31,7 @@ function getComponentKey (vnode) {
31
31
  const { componentOptions, key } = vnode
32
32
  return key == null
33
33
  ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
34
- : key + componentOptions.Ctor.cid
34
+ : key + `::${componentOptions.Ctor.cid}`
35
35
  }
36
36
 
37
37
  function getFirstComponentChild (children) {
@@ -95,8 +95,15 @@ export default {
95
95
  clearCaches: function (val) {
96
96
  if (val && val.length > 0) {
97
97
  const { cache, keys } = this
98
- val.forEach(key => {
99
- pruneCacheEntry2(cache, key, keys)
98
+ // 遍历所有缓存的 keys,找到以传入的 key 开头的项进行清除
99
+ keys.forEach(cacheKey => {
100
+ val.forEach(targetKey => {
101
+ // 检查缓存的 key 是否以目标 key 开头
102
+ console.warn('clearCaches:', cacheKey, targetKey, cacheKey.includes(`${targetKey}::`) || cacheKey.startsWith(targetKey))
103
+ if (cacheKey.includes(`${targetKey}::`) || cacheKey.startsWith(targetKey)) {
104
+ pruneCacheEntry2(cache, cacheKey, keys)
105
+ }
106
+ })
100
107
  })
101
108
  this.$emit('clear', [])
102
109
  }
@@ -150,7 +157,7 @@ export default {
150
157
  // same constructor may get registered as different local components
151
158
  // so cid alone is not enough (#3269)
152
159
  ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
153
- : vnode.key + componentOptions.Ctor.cid
160
+ : vnode.key + `::${componentOptions.Ctor.cid}`
154
161
  if (cache[key]) {
155
162
  vnode.componentInstance = cache[key].componentInstance
156
163
  // make current key freshest
@@ -1,18 +1,74 @@
1
1
  <template>
2
2
  <page-toggle-transition :disabled="animate.disabled" :animate="animate.name" :direction="animate.direction">
3
- <router-view />
3
+ <a-keep-alive :exclude-keys="excludeKeys" v-if="cachePage" v-model="clearCaches">
4
+ <router-view v-if="!refreshing" :key="$route.path" />
5
+ </a-keep-alive>
6
+ <router-view v-else-if="!refreshing" />
4
7
  </page-toggle-transition>
5
8
  </template>
6
9
 
7
10
  <script>
8
11
  import PageToggleTransition from '../components/transition/PageToggleTransition'
9
12
  import { mapState } from 'vuex'
13
+ import AKeepAlive from '@vue2-client/components/cache/AKeepAlive'
10
14
 
11
15
  export default {
12
16
  name: 'BlankView',
13
- components: { PageToggleTransition },
17
+ components: { PageToggleTransition, AKeepAlive },
18
+ data () {
19
+ return {
20
+ clearCaches: [],
21
+ excludeKeys: [],
22
+ refreshing: false
23
+ }
24
+ },
14
25
  computed: {
15
- ...mapState('setting', ['multiPage', 'animate'])
26
+ ...mapState('setting', ['cachePage', 'animate'])
27
+ },
28
+ created () {
29
+ this.loadCacheConfig(this.$router?.options?.routes)
30
+ },
31
+ mounted () {
32
+ if (window.__MICRO_APP_ENVIRONMENT__) {
33
+ window.microApp.addDataListener((data) => {
34
+ if (data.type === 'refresh') {
35
+ this.refresh()
36
+ } else if (data.type === 'clearCache' && data.key) {
37
+ this.clearCache(data.key)
38
+ }
39
+ })
40
+ }
41
+ },
42
+ methods: {
43
+ // 加载需要排除缓存的路由配置
44
+ loadCacheConfig (routes, pCache = true) {
45
+ routes.forEach(item => {
46
+ const cacheAble = item.meta?.page?.cacheAble ?? pCache ?? true
47
+ if (!cacheAble) {
48
+ this.excludeKeys.push(new RegExp(`${item.path.replace(/:[^/]*/g, '[^/]*')}(\\?.*)?\\d*$`))
49
+ }
50
+ if (item.children) {
51
+ this.loadCacheConfig(item.children, cacheAble)
52
+ }
53
+ })
54
+ },
55
+ // 刷新页面方法
56
+ refresh () {
57
+ this.refreshing = true
58
+ setTimeout(() => {
59
+ this.refreshing = false
60
+ }, 200)
61
+ },
62
+ // 清除特定页面的缓存
63
+ clearCache (resultKeys) {
64
+ this.clearCaches = resultKeys
65
+ }
66
+ },
67
+ watch: {
68
+ '$router.options.routes': function (val) {
69
+ this.excludeKeys = []
70
+ this.loadCacheConfig(val)
71
+ }
16
72
  }
17
73
  }
18
74
  </script>