vue2-client 1.8.259 → 1.8.261

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 (210) hide show
  1. package/.env +19 -19
  2. package/.eslintrc.js +90 -90
  3. package/CHANGELOG.md +824 -824
  4. package/Components.md +60 -60
  5. package/babel.config.js +21 -21
  6. package/docs/index.md +30 -30
  7. package/docs/lowcode.md +188 -188
  8. package/docs/lowcodeForDeveloper.md +200 -192
  9. package/index.js +31 -31
  10. package/jest-transform-stub.js +8 -8
  11. package/jest.config.js +21 -21
  12. package/jest.setup.js +7 -7
  13. package/package.json +95 -95
  14. package/public/index.html +27 -27
  15. package/src/App.vue +188 -188
  16. package/src/ReportView.js +19 -19
  17. package/src/assets/img/querySlotDemo.svg +15 -15
  18. package/src/assets/svg/badtwo.svg +1 -1
  19. package/src/assets/svg/goodtwo.svg +1 -1
  20. package/src/base-client/components/common/AMisRender/index.js +3 -3
  21. package/src/base-client/components/common/AMisRender/index.vue +263 -263
  22. package/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox.vue +413 -413
  23. package/src/base-client/components/common/AddressSearchCombobox/demo.vue +36 -36
  24. package/src/base-client/components/common/AmapMarker/AmapPointRendering.vue +120 -120
  25. package/src/base-client/components/common/CitySelect/CitySelect.vue +348 -348
  26. package/src/base-client/components/common/CitySelect/index.js +3 -3
  27. package/src/base-client/components/common/CitySelect/index.md +109 -109
  28. package/src/base-client/components/common/CreateQuery/CreateQuery.vue +669 -669
  29. package/src/base-client/components/common/CreateQuery/CreateQueryItem.vue +1014 -1014
  30. package/src/base-client/components/common/CreateQuery/index.js +3 -3
  31. package/src/base-client/components/common/CreateQuery/index.md +42 -42
  32. package/src/base-client/components/common/CreateSimpleFormQuery/CreateSimpleFormQuery.vue +452 -452
  33. package/src/base-client/components/common/CreateSimpleFormQuery/CreateSimpleFormQueryItem.vue +511 -511
  34. package/src/base-client/components/common/CreateSimpleFormQuery/index.js +3 -3
  35. package/src/base-client/components/common/CreateSimpleFormQuery/index.md +42 -42
  36. package/src/base-client/components/common/FormGroupEdit/FormGroupEdit.vue +149 -149
  37. package/src/base-client/components/common/FormGroupEdit/index.js +3 -3
  38. package/src/base-client/components/common/FormGroupEdit/index.md +43 -43
  39. package/src/base-client/components/common/FormGroupQuery/FormGroupQuery.vue +166 -166
  40. package/src/base-client/components/common/FormGroupQuery/index.js +3 -3
  41. package/src/base-client/components/common/FormGroupQuery/index.md +43 -43
  42. package/src/base-client/components/common/JSONToTree/jsontotree.vue +271 -271
  43. package/src/base-client/components/common/LowCodeComponent/LowCodePageOrganization.vue +394 -355
  44. package/src/base-client/components/common/LowCodePageRender/LowCodePageRender.vue +29 -29
  45. package/src/base-client/components/common/LowCodePageRender/editorPageRender.vue +533 -467
  46. package/src/base-client/components/common/LowCodePageRender/index.js +3 -3
  47. package/src/base-client/components/common/PersonSetting/PersonSetting.vue +208 -208
  48. package/src/base-client/components/common/PersonSetting/index.js +3 -3
  49. package/src/base-client/components/common/Tree/Tree.vue +149 -149
  50. package/src/base-client/components/common/Tree/index.js +2 -2
  51. package/src/base-client/components/common/Upload/Upload.vue +197 -197
  52. package/src/base-client/components/common/Upload/index.js +3 -3
  53. package/src/base-client/components/common/XAddForm/XAddForm.vue +98 -98
  54. package/src/base-client/components/common/XAddNativeForm/XAddNativeForm.vue +732 -732
  55. package/src/base-client/components/common/XAddNativeForm/index.md +146 -146
  56. package/src/base-client/components/common/XAddNativeForm/lowcodeEditorRegister.js +16 -12
  57. package/src/base-client/components/common/XAddNativeFormOA/XAddNativeFormOA.vue +303 -303
  58. package/src/base-client/components/common/XAddNativeFormOA/index.js +3 -3
  59. package/src/base-client/components/common/XAddNativeFormOA/index.md +146 -146
  60. package/src/base-client/components/common/XBadge/XBadge.vue +78 -78
  61. package/src/base-client/components/common/XCard/XCard.vue +64 -64
  62. package/src/base-client/components/common/XDataDrawer/XDataDrawer.vue +180 -180
  63. package/src/base-client/components/common/XDataDrawer/index.js +3 -3
  64. package/src/base-client/components/common/XDataDrawer/index.md +41 -41
  65. package/src/base-client/components/common/XDescriptions/XDescriptions.vue +167 -167
  66. package/src/base-client/components/common/XDescriptions/XDescriptionsGroup.vue +299 -299
  67. package/src/base-client/components/common/XDescriptions/demo.vue +50 -50
  68. package/src/base-client/components/common/XDescriptions/index.js +3 -3
  69. package/src/base-client/components/common/XDescriptions/index.md +83 -83
  70. package/src/base-client/components/common/XDescriptions/lowcodeEditorRegister.js +15 -5
  71. package/src/base-client/components/common/XDetailsView/XDetailsView.vue +214 -214
  72. package/src/base-client/components/common/XDetailsView/index.js +3 -3
  73. package/src/base-client/components/common/XForm/XForm.vue +281 -281
  74. package/src/base-client/components/common/XForm/XFormItem.vue +807 -807
  75. package/src/base-client/components/common/XForm/XTreeSelect.vue +206 -206
  76. package/src/base-client/components/common/XForm/index.md +178 -178
  77. package/src/base-client/components/common/XFormCol/XFormCol.vue +36 -36
  78. package/src/base-client/components/common/XFormGroup/XFormGroup.vue +241 -241
  79. package/src/base-client/components/common/XFormGroup/demo.vue +40 -40
  80. package/src/base-client/components/common/XFormGroup/index.js +3 -3
  81. package/src/base-client/components/common/XFormGroup/index.md +38 -38
  82. package/src/base-client/components/common/XFormGroupDetails/XFormGroupDetails.vue +72 -72
  83. package/src/base-client/components/common/XFormGroupDetails/index.js +3 -3
  84. package/src/base-client/components/common/XFormTable/XFormTable.vue +519 -519
  85. package/src/base-client/components/common/XFormTable/index.md +98 -98
  86. package/src/base-client/components/common/XFormTable/lowcodeEditorRegister.js +16 -12
  87. package/src/base-client/components/common/XImportExcel/XImportExcel.vue +147 -147
  88. package/src/base-client/components/common/XReport/XReport.vue +843 -843
  89. package/src/base-client/components/common/XReport/XReportDemo.vue +2233 -2233
  90. package/src/base-client/components/common/XReport/XReportDesign.vue +470 -470
  91. package/src/base-client/components/common/XReport/XReportJsonRender.vue +267 -267
  92. package/src/base-client/components/common/XReport/XReportTrGroup.vue +745 -742
  93. package/src/base-client/components/common/XReport/index.js +3 -3
  94. package/src/base-client/components/common/XReport/index.md +44 -44
  95. package/src/base-client/components/common/XReportSlot/XReportSlot.vue +110 -110
  96. package/src/base-client/components/common/XReportSlot/index.js +3 -3
  97. package/src/base-client/components/common/XStepView/XStepView.vue +252 -252
  98. package/src/base-client/components/common/XStepView/index.js +3 -3
  99. package/src/base-client/components/common/XStepView/index.md +31 -31
  100. package/src/base-client/components/common/XTable/XTable.vue +636 -636
  101. package/src/base-client/components/common/XTable/index.md +255 -255
  102. package/src/base-client/components/common/XTree/XTree.vue +318 -318
  103. package/src/base-client/components/common/XTree/index.js +3 -3
  104. package/src/base-client/components/common/XTree/index.md +36 -36
  105. package/src/base-client/components/common/XTreeOne/XTreeOne.vue +114 -114
  106. package/src/base-client/components/common/XTreeOne/lowcodeEditorRegister.js +11 -9
  107. package/src/base-client/components/index.js +51 -51
  108. package/src/base-client/components/system/DictionaryDetailsView/DictionaryDetailsView.vue +232 -232
  109. package/src/base-client/components/system/QueryParamsDetailsView/QueryParamsDetailsView.vue +281 -281
  110. package/src/base-client/plugins/AppData.js +115 -115
  111. package/src/base-client/plugins/Config.js +19 -19
  112. package/src/base-client/plugins/GetLoginInfoService.js +183 -183
  113. package/src/base-client/plugins/tabs-page-plugin.js +39 -39
  114. package/src/bootstrap.js +39 -39
  115. package/src/components/CodeMirror/inedx.vue +118 -118
  116. package/src/components/CodeMirror/setting.js +40 -40
  117. package/src/components/FilePreview/FilePreview.vue +166 -166
  118. package/src/components/NumberInfo/NumberInfo.vue +54 -54
  119. package/src/components/STable/index.js +323 -323
  120. package/src/components/checkbox/ColorCheckbox.vue +157 -157
  121. package/src/components/checkbox/ImgCheckbox.vue +163 -163
  122. package/src/components/menu/SideMenu.vue +75 -75
  123. package/src/components/menu/menu.js +273 -273
  124. package/src/components/tool/AStepItem.vue +60 -60
  125. package/src/config/CreateQueryConfig.js +322 -322
  126. package/src/config/default/antd.config.js +89 -89
  127. package/src/config/default/setting.config.js +55 -55
  128. package/src/font-style/font.css +4 -4
  129. package/src/layouts/CommonLayout.vue +56 -56
  130. package/src/layouts/PageLayout.vue +151 -151
  131. package/src/layouts/SinglePageView.vue +138 -138
  132. package/src/layouts/header/AdminHeader.vue +132 -132
  133. package/src/layouts/header/HeaderNotice.vue +177 -177
  134. package/src/layouts/tabs/TabsHead.vue +189 -189
  135. package/src/layouts/tabs/TabsView.vue +387 -387
  136. package/src/lib.js +1 -1
  137. package/src/main.js +26 -26
  138. package/src/mock/extend/index.js +84 -84
  139. package/src/mock/goods/index.js +108 -108
  140. package/src/pages/AMisDemo/AMisDemo.vue +325 -325
  141. package/src/pages/AMisDemo/AMisDemo2.vue +74 -74
  142. package/src/pages/DynamicStatistics/ChartSelector.vue +331 -331
  143. package/src/pages/DynamicStatistics/DataTabs.vue +83 -83
  144. package/src/pages/DynamicStatistics/DynamicTable.vue +128 -128
  145. package/src/pages/DynamicStatistics/EvaluationArea.vue +69 -69
  146. package/src/pages/DynamicStatistics/FavoriteList.vue +51 -51
  147. package/src/pages/DynamicStatistics/QuestionHistoryAndFavorites.vue +591 -591
  148. package/src/pages/DynamicStatistics/SearchBar.vue +192 -192
  149. package/src/pages/DynamicStatistics/index.vue +282 -282
  150. package/src/pages/Example/index.vue +32 -32
  151. package/src/pages/NewDynamicStatistics/ChartSelector.vue +331 -331
  152. package/src/pages/NewDynamicStatistics/DataTabs.vue +122 -122
  153. package/src/pages/NewDynamicStatistics/DynamicTable.vue +128 -128
  154. package/src/pages/NewDynamicStatistics/EvaluationArea.vue +69 -69
  155. package/src/pages/NewDynamicStatistics/FavoriteList.vue +51 -51
  156. package/src/pages/NewDynamicStatistics/QuestionHistoryAndFavorites.vue +289 -289
  157. package/src/pages/NewDynamicStatistics/SearchBar.vue +193 -193
  158. package/src/pages/NewDynamicStatistics/index.vue +258 -258
  159. package/src/pages/ServiceReview/index.vue +284 -284
  160. package/src/pages/XReportView/index.vue +62 -62
  161. package/src/pages/login/Login.vue +378 -378
  162. package/src/pages/login/LoginV3.vue +389 -389
  163. package/src/pages/lowCode/lowCodeEditor.vue +1501 -1285
  164. package/src/pages/lowCode/lowCodeRender.vue +39 -39
  165. package/src/pages/resourceManage/orgListManage.vue +98 -98
  166. package/src/pages/system/dictionary/index.vue +44 -44
  167. package/src/pages/system/monitor/loginInfor/index.vue +37 -37
  168. package/src/pages/system/monitor/operLog/index.vue +37 -37
  169. package/src/pages/system/settings/modifyPassword.vue +117 -117
  170. package/src/pages/system/ticket/index.vue +480 -480
  171. package/src/pages/system/ticket/submitTicketSuccess.vue +484 -484
  172. package/src/router/async/config.async.js +33 -33
  173. package/src/router/async/router.map.js +107 -107
  174. package/src/router/guards.js +220 -220
  175. package/src/router/index.js +27 -27
  176. package/src/router.js +19 -19
  177. package/src/services/api/TicketDetailsViewApi.js +46 -46
  178. package/src/services/api/cas.js +79 -79
  179. package/src/services/api/common.js +284 -284
  180. package/src/services/api/entity.js +18 -18
  181. package/src/services/api/index.js +17 -17
  182. package/src/services/api/restTools.js +46 -46
  183. package/src/services/apiService.js +14 -14
  184. package/src/services/user.js +71 -71
  185. package/src/store/modules/setting.js +119 -119
  186. package/src/theme/default/style.less +57 -57
  187. package/src/theme/global.less +130 -130
  188. package/src/utils/authority-utils.js +85 -85
  189. package/src/utils/errorCode.js +6 -6
  190. package/src/utils/htmlToPDF.js +108 -108
  191. package/src/utils/htmlToPDFApi.js +5 -5
  192. package/src/utils/indexedDB.js +201 -201
  193. package/src/utils/login.js +144 -144
  194. package/src/utils/lowcode/lowcodeComponentMixin.js +112 -78
  195. package/src/utils/lowcode/lowcodeLog.js +29 -29
  196. package/src/utils/lowcode/lowcodeUtils.js +276 -129
  197. package/src/utils/lowcode/registerComponentForEditor.js +11 -11
  198. package/src/utils/lowcode/registerComponentForRender.js +11 -11
  199. package/src/utils/map-utils.js +47 -47
  200. package/src/utils/reg.js +19 -19
  201. package/src/utils/request.js +343 -343
  202. package/src/utils/routerUtil.js +435 -435
  203. package/src/utils/runEvalFunction.js +6 -6
  204. package/src/utils/util.js +241 -241
  205. package/src/utils/waterMark.js +31 -31
  206. package/test/Amis.spec.js +163 -163
  207. package/test/Tree.spec.js +167 -167
  208. package/test/myDialog.spec.js +46 -46
  209. package/vue.config.js +177 -177
  210. package//350/277/201/347/247/273/346/227/245/345/277/227.md +15 -15
@@ -1,387 +1,387 @@
1
- <template>
2
- <div id="TabsView">
3
- <admin-layout>
4
- <contextmenu :itemList="menuItemList" :visible.sync="menuVisible" @select="onMenuSelect" />
5
- <tabs-head
6
- v-if="multiPage"
7
- :active="activePage"
8
- :page-list="pageList"
9
- @change="changePage"
10
- @close="remove"
11
- @refresh="refresh"
12
- @contextmenu="onContextmenu"
13
- />
14
- <div :class="['tabs-view-content', layout, pageWidth]" :style="`margin-top: ${multiPage ? -24 : 0}px`">
15
- <page-toggle-transition v-show="!$route.meta.singlePage" :disabled="animate.disabled" :animate="animate.name" :direction="animate.direction">
16
- <a-keep-alive :exclude-keys="excludeKeys" v-if="multiPage && cachePage" v-model="clearCaches">
17
- <router-view v-if="!refreshing" ref="tabContent" :key="$route.fullPath" />
18
- </a-keep-alive>
19
- <router-view ref="tabContent" v-else-if="!refreshing" />
20
- </page-toggle-transition>
21
- <template v-for="page in single">
22
- <single-page-view
23
- v-show="page.meta.singlePage === $route.meta.singlePage"
24
- :single-page-url="page.meta.singlePage"
25
- :full-path="page.fullPath"
26
- :key="page.meta.singlePage"
27
- @load="onSinglePageLoad" />
28
- </template>
29
- </div>
30
- </admin-layout>
31
- </div>
32
- </template>
33
-
34
- <script>
35
- import AdminLayout from '@vue2-client/layouts/AdminLayout'
36
- import Contextmenu from '@vue2-client/components/menu/Contextmenu'
37
- import PageToggleTransition from '@vue2-client/components/transition/PageToggleTransition'
38
- import { mapState, mapMutations } from 'vuex'
39
- import { getI18nKey } from '@vue2-client/utils/routerUtil'
40
- import AKeepAlive from '@vue2-client/components/cache/AKeepAlive'
41
- import TabsHead from '@vue2-client/layouts/tabs/TabsHead'
42
- import SinglePageView from '../SinglePageView'
43
-
44
- export default {
45
- name: 'TabsView',
46
- i18n: require('./i18n'),
47
- components: { SinglePageView, TabsHead, PageToggleTransition, Contextmenu, AdminLayout, AKeepAlive },
48
- data () {
49
- return {
50
- clearCaches: [],
51
- pageList: [],
52
- activePage: '',
53
- menuVisible: false,
54
- refreshing: false,
55
- allSinglePages: [],
56
- excludeKeys: []
57
- }
58
- },
59
- computed: {
60
- ...mapState('setting', ['multiPage', 'cachePage', 'animate', 'layout', 'pageWidth']),
61
- ...mapState('account', ['single']),
62
- menuItemList () {
63
- return [
64
- { key: '1', icon: 'vertical-right', text: this.$t('closeLeft') },
65
- { key: '2', icon: 'vertical-left', text: this.$t('closeRight') },
66
- { key: '3', icon: 'close', text: this.$t('closeOthers') },
67
- { key: '4', icon: 'sync', text: this.$t('refresh') }
68
- ]
69
- },
70
- tabsOffset () {
71
- return this.multiPage ? 24 : 0
72
- }
73
- },
74
- created () {
75
- this.loadCacheConfig(this.$router?.options?.routes)
76
- this.loadCachedTabs()
77
- // 解决单页面为首页时首次登录不加载问题
78
- if (this.$route.meta.singlePage && this.single.length === 0) {
79
- this.allSinglePages.forEach(item => {
80
- if (this.$route.fullPath.includes(item.fullPath)) {
81
- this.setSingle(item)
82
- }
83
- })
84
- }
85
- const route = this.$route
86
- if (this.pageList.findIndex(item => item.path === route.fullPath) === -1) {
87
- this.pageList.push(this.createPage(route))
88
- }
89
- this.activePage = route.fullPath
90
- if (this.multiPage) {
91
- this.$nextTick(() => {
92
- this.setCachedKey(route)
93
- })
94
- this.addListener()
95
- }
96
- },
97
- mounted () {
98
- this.correctPageMinHeight(-this.tabsOffset)
99
- },
100
- beforeDestroy () {
101
- this.removeListener()
102
- this.correctPageMinHeight(this.tabsOffset)
103
- },
104
- watch: {
105
- '$router.options.routes': function (val) {
106
- this.excludeKeys = []
107
- this.loadCacheConfig(val)
108
- },
109
- $route: function (newRoute) {
110
- this.activePage = newRoute.fullPath
111
- const page = this.pageList.find(item => item.path === newRoute.fullPath)
112
- if (!this.multiPage) {
113
- this.pageList = [this.createPage(newRoute)]
114
- } else if (page) {
115
- page.fullPath = newRoute.fullPath
116
- } else if (!page) {
117
- this.pageList.push(this.createPage(newRoute))
118
- }
119
- if (this.multiPage) {
120
- this.$nextTick(() => {
121
- this.setCachedKey(newRoute)
122
- })
123
- }
124
- },
125
- multiPage: function (newVal) {
126
- if (!newVal) {
127
- this.pageList = [this.createPage(this.$route)]
128
- this.removeListener()
129
- } else {
130
- this.addListener()
131
- }
132
- },
133
- tabsOffset (newVal, oldVal) {
134
- this.correctPageMinHeight(oldVal - newVal)
135
- }
136
- },
137
- methods: {
138
- changePage (key) {
139
- this.activePage = key
140
- const page = this.pageList.find(item => item.path === key)
141
- this.$router.push(page.fullPath)
142
- },
143
- remove (key, next) {
144
- if (this.pageList.length === 1) {
145
- return this.$message.warning(this.$t('warn'))
146
- }
147
- this.setSingle({ path: key, delete: true })
148
- // 清除缓存
149
- let index = this.pageList.findIndex(item => item.path === key)
150
- this.clearCaches = this.pageList.splice(index, 1).map(page => page.cachedKey)
151
- if (next) {
152
- this.$router.push(next)
153
- } else if (key === this.activePage) {
154
- index = index >= this.pageList.length ? this.pageList.length - 1 : index
155
- this.activePage = this.pageList[index].path
156
- this.$router.push(this.activePage)
157
- }
158
- },
159
- refresh (key, page) {
160
- page = page || this.pageList.find(item => item.path === key)
161
- page.loading = true
162
- // 单页面刷新
163
- const singlePage = this.allSinglePages.find(item => item.fullPath === key)
164
- if (singlePage) {
165
- window.frames[singlePage.fullPath].location.reload()
166
- return
167
- }
168
- this.clearCache(page)
169
- if (key === this.activePage) {
170
- // eslint-disable-next-line no-return-assign
171
- this.reloadContent(() => page.loading = false)
172
- } else {
173
- // 其实刷新很快,加这个延迟纯粹为了 loading 状态多展示一会儿,让用户感知刷新这一过程
174
- // eslint-disable-next-line no-return-assign
175
- setTimeout(() => page.loading = false, 500)
176
- }
177
- },
178
- onSinglePageLoad (fullPath) {
179
- const page = this.pageList.find(item => item.fullPath === fullPath)
180
- page.loading = false
181
- },
182
- onContextmenu (pageKey, e) {
183
- if (pageKey) {
184
- e.preventDefault()
185
- e.meta = pageKey
186
- this.menuVisible = true
187
- }
188
- },
189
- onMenuSelect (key, target, pageKey) {
190
- switch (key) {
191
- case '1': this.closeLeft(pageKey); break
192
- case '2': this.closeRight(pageKey); break
193
- case '3': this.closeOthers(pageKey); break
194
- case '4': this.refresh(pageKey); break
195
- default: break
196
- }
197
- },
198
- closeOthers (pageKey) {
199
- // 清除缓存
200
- const clearPages = this.pageList.filter(item => item.path !== pageKey && !item.unclose)
201
- this.clearCaches = clearPages.map(item => item.cachedKey)
202
- this.pageList = this.pageList.filter(item => !clearPages.includes(item))
203
- // 判断跳转
204
- if (this.activePage !== pageKey) {
205
- this.activePage = pageKey
206
- this.$router.push(this.activePage)
207
- }
208
- },
209
- closeLeft (pageKey) {
210
- const index = this.pageList.findIndex(item => item.path === pageKey)
211
- // 清除缓存
212
- const clearPages = this.pageList.filter((item, i) => i < index && !item.unclose)
213
- this.clearCaches = clearPages.map(item => item.cachedKey)
214
- this.pageList = this.pageList.filter(item => !clearPages.includes(item))
215
- // 判断跳转
216
- if (!this.pageList.find(item => item.path === this.activePage)) {
217
- this.activePage = pageKey
218
- this.$router.push(this.activePage)
219
- }
220
- },
221
- closeRight (pageKey) {
222
- // 清除缓存
223
- const index = this.pageList.findIndex(item => item.path === pageKey)
224
- const clearPages = this.pageList.filter((item, i) => i > index && !item.unclose)
225
- this.clearCaches = clearPages.map(item => item.cachedKey)
226
- this.pageList = this.pageList.filter(item => !clearPages.includes(item))
227
- // 判断跳转
228
- if (!this.pageList.find(item => item.path === this.activePage)) {
229
- this.activePage = pageKey
230
- this.$router.push(this.activePage)
231
- }
232
- },
233
- clearCache (page) {
234
- page._init_ = false
235
- this.clearCaches = [page.cachedKey]
236
- },
237
- reloadContent (onLoaded) {
238
- this.refreshing = true
239
- setTimeout(() => {
240
- this.refreshing = false
241
- this.$nextTick(() => {
242
- this.setCachedKey(this.$route)
243
- if (typeof onLoaded === 'function') {
244
- onLoaded.apply(this, [])
245
- }
246
- })
247
- }, 200)
248
- },
249
- pageName (page) {
250
- return this.$t(getI18nKey(page.keyPath))
251
- },
252
- /**
253
- * 添加监听器
254
- */
255
- addListener () {
256
- window.addEventListener('page:close', this.closePageListener)
257
- window.addEventListener('page:refresh', this.refreshPageListener)
258
- window.addEventListener('unload', this.unloadListener)
259
- },
260
- /**
261
- * 移出监听器
262
- */
263
- removeListener () {
264
- window.removeEventListener('page:close', this.closePageListener)
265
- window.removeEventListener('page:refresh', this.refreshPageListener)
266
- window.removeEventListener('unload', this.unloadListener)
267
- },
268
- /**
269
- * 页签关闭事件监听
270
- * @param event 页签关闭事件
271
- */
272
- closePageListener (event) {
273
- const { closeRoute, nextRoute } = event.detail
274
- const closePath = typeof closeRoute === 'string' ? closeRoute : closeRoute.path
275
- const path = closePath && closePath.split('?')[0]
276
- this.remove(path, nextRoute)
277
- },
278
- /**
279
- * 页面刷新事件监听
280
- * @param event 页签关闭事件
281
- */
282
- refreshPageListener (event) {
283
- const { pageKey } = event.detail
284
- const path = pageKey && pageKey.split('?')[0]
285
- this.refresh(path)
286
- },
287
- /**
288
- * 页面 unload 事件监听器,添加页签到 session 缓存,用于刷新时保留页签
289
- */
290
- unloadListener () {
291
- const tabs = this.pageList.map(item => ({ ...item, _init_: false }))
292
- sessionStorage.setItem(process.env.VUE_APP_TBAS_KEY, JSON.stringify(tabs))
293
- },
294
- createPage (route) {
295
- return {
296
- keyPath: route.matched[route.matched.length - 1].path,
297
- fullPath: route.fullPath,
298
- loading: false,
299
- path: route.fullPath,
300
- title: route.meta && route.meta.page && route.meta.page.title,
301
- unclose: route.meta && route.meta.page && (route.meta.page.closable === false)
302
- }
303
- },
304
- /**
305
- * 设置页面缓存的key
306
- * @param route 页面对应的路由
307
- */
308
- setCachedKey (route) {
309
- const page = this.pageList.find(item => item.path === route.path)
310
- page.unclose = route.meta && route.meta.page && (route.meta.page.closable === false)
311
- if (!page._init_) {
312
- const vnode = this.$refs.tabContent.$vnode
313
- page.cachedKey = vnode.key + vnode.componentOptions.Ctor.cid
314
- page._init_ = true
315
- }
316
- },
317
- /**
318
- * 加载缓存的 tabs
319
- */
320
- loadCachedTabs () {
321
- const cachedTabsStr = sessionStorage.getItem(process.env.VUE_APP_TBAS_KEY)
322
- if (cachedTabsStr) {
323
- try {
324
- // 加载缓存的单页面
325
- const allCachedPath = JSON.parse(cachedTabsStr).map(str => { return str.fullPath })
326
- this.allSinglePages.forEach(item => {
327
- if (allCachedPath.includes(item.fullPath)) {
328
- // 如果缓存中有单页面 加载到 state.single
329
- this.setSingle(item)
330
- }
331
- })
332
- const cachedTabs = JSON.parse(cachedTabsStr)
333
- if (cachedTabs.length > 0) {
334
- this.pageList = cachedTabs
335
- }
336
- } catch (e) {
337
- console.warn('failed to load cached tabs, got exception:', e)
338
- } finally {
339
- sessionStorage.removeItem(process.env.VUE_APP_TBAS_KEY)
340
- }
341
- }
342
- },
343
- loadCacheConfig (routes, pCache = true) {
344
- routes.forEach(item => {
345
- const cacheAble = item.meta?.page?.cacheAble ?? pCache ?? true
346
- if (item.meta && item.meta.singlePage) {
347
- // 找到所有单页面添加到 allSinglePages 中
348
- this.allSinglePages.push(item)
349
- }
350
- if (!cacheAble) {
351
- this.excludeKeys.push(new RegExp(`${item.path.replace(/:[^/]*/g, '[^/]*')}(\\?.*)?\\d*$`))
352
- }
353
- if (item.children) {
354
- this.loadCacheConfig(item.children, cacheAble)
355
- }
356
- })
357
- },
358
- ...mapMutations('setting', ['correctPageMinHeight']),
359
- ...mapMutations('account', ['setSingle'])
360
- }
361
- }
362
- </script>
363
-
364
- <style lang="less">
365
- #TabsView {
366
- .tabs-view {
367
- margin: -16px auto 8px;
368
- &.head.fixed {
369
- max-width: 100%;
370
- }
371
- }
372
- .tabs-view-content {
373
- position: relative;
374
- &.head.fixed {
375
- width: 100%;
376
- margin: 0 auto;
377
- }
378
- > div > div > .ant-card:first-of-type > .ant-card-body {
379
- max-height: calc(100vh - 64px - 48px - 24px);
380
- overflow-y: auto;
381
- &::-webkit-scrollbar {
382
- display: none;
383
- }
384
- }
385
- }
386
- }
387
- </style>
1
+ <template>
2
+ <div id="TabsView">
3
+ <admin-layout>
4
+ <contextmenu :itemList="menuItemList" :visible.sync="menuVisible" @select="onMenuSelect" />
5
+ <tabs-head
6
+ v-if="multiPage"
7
+ :active="activePage"
8
+ :page-list="pageList"
9
+ @change="changePage"
10
+ @close="remove"
11
+ @refresh="refresh"
12
+ @contextmenu="onContextmenu"
13
+ />
14
+ <div :class="['tabs-view-content', layout, pageWidth]" :style="`margin-top: ${multiPage ? -24 : 0}px`">
15
+ <page-toggle-transition v-show="!$route.meta.singlePage" :disabled="animate.disabled" :animate="animate.name" :direction="animate.direction">
16
+ <a-keep-alive :exclude-keys="excludeKeys" v-if="multiPage && cachePage" v-model="clearCaches">
17
+ <router-view v-if="!refreshing" ref="tabContent" :key="$route.fullPath" />
18
+ </a-keep-alive>
19
+ <router-view ref="tabContent" v-else-if="!refreshing" />
20
+ </page-toggle-transition>
21
+ <template v-for="page in single">
22
+ <single-page-view
23
+ v-show="page.meta.singlePage === $route.meta.singlePage"
24
+ :single-page-url="page.meta.singlePage"
25
+ :full-path="page.fullPath"
26
+ :key="page.meta.singlePage"
27
+ @load="onSinglePageLoad" />
28
+ </template>
29
+ </div>
30
+ </admin-layout>
31
+ </div>
32
+ </template>
33
+
34
+ <script>
35
+ import AdminLayout from '@vue2-client/layouts/AdminLayout'
36
+ import Contextmenu from '@vue2-client/components/menu/Contextmenu'
37
+ import PageToggleTransition from '@vue2-client/components/transition/PageToggleTransition'
38
+ import { mapState, mapMutations } from 'vuex'
39
+ import { getI18nKey } from '@vue2-client/utils/routerUtil'
40
+ import AKeepAlive from '@vue2-client/components/cache/AKeepAlive'
41
+ import TabsHead from '@vue2-client/layouts/tabs/TabsHead'
42
+ import SinglePageView from '../SinglePageView'
43
+
44
+ export default {
45
+ name: 'TabsView',
46
+ i18n: require('./i18n'),
47
+ components: { SinglePageView, TabsHead, PageToggleTransition, Contextmenu, AdminLayout, AKeepAlive },
48
+ data () {
49
+ return {
50
+ clearCaches: [],
51
+ pageList: [],
52
+ activePage: '',
53
+ menuVisible: false,
54
+ refreshing: false,
55
+ allSinglePages: [],
56
+ excludeKeys: []
57
+ }
58
+ },
59
+ computed: {
60
+ ...mapState('setting', ['multiPage', 'cachePage', 'animate', 'layout', 'pageWidth']),
61
+ ...mapState('account', ['single']),
62
+ menuItemList () {
63
+ return [
64
+ { key: '1', icon: 'vertical-right', text: this.$t('closeLeft') },
65
+ { key: '2', icon: 'vertical-left', text: this.$t('closeRight') },
66
+ { key: '3', icon: 'close', text: this.$t('closeOthers') },
67
+ { key: '4', icon: 'sync', text: this.$t('refresh') }
68
+ ]
69
+ },
70
+ tabsOffset () {
71
+ return this.multiPage ? 24 : 0
72
+ }
73
+ },
74
+ created () {
75
+ this.loadCacheConfig(this.$router?.options?.routes)
76
+ this.loadCachedTabs()
77
+ // 解决单页面为首页时首次登录不加载问题
78
+ if (this.$route.meta.singlePage && this.single.length === 0) {
79
+ this.allSinglePages.forEach(item => {
80
+ if (this.$route.fullPath.includes(item.fullPath)) {
81
+ this.setSingle(item)
82
+ }
83
+ })
84
+ }
85
+ const route = this.$route
86
+ if (this.pageList.findIndex(item => item.path === route.fullPath) === -1) {
87
+ this.pageList.push(this.createPage(route))
88
+ }
89
+ this.activePage = route.fullPath
90
+ if (this.multiPage) {
91
+ this.$nextTick(() => {
92
+ this.setCachedKey(route)
93
+ })
94
+ this.addListener()
95
+ }
96
+ },
97
+ mounted () {
98
+ this.correctPageMinHeight(-this.tabsOffset)
99
+ },
100
+ beforeDestroy () {
101
+ this.removeListener()
102
+ this.correctPageMinHeight(this.tabsOffset)
103
+ },
104
+ watch: {
105
+ '$router.options.routes': function (val) {
106
+ this.excludeKeys = []
107
+ this.loadCacheConfig(val)
108
+ },
109
+ $route: function (newRoute) {
110
+ this.activePage = newRoute.fullPath
111
+ const page = this.pageList.find(item => item.path === newRoute.fullPath)
112
+ if (!this.multiPage) {
113
+ this.pageList = [this.createPage(newRoute)]
114
+ } else if (page) {
115
+ page.fullPath = newRoute.fullPath
116
+ } else if (!page) {
117
+ this.pageList.push(this.createPage(newRoute))
118
+ }
119
+ if (this.multiPage) {
120
+ this.$nextTick(() => {
121
+ this.setCachedKey(newRoute)
122
+ })
123
+ }
124
+ },
125
+ multiPage: function (newVal) {
126
+ if (!newVal) {
127
+ this.pageList = [this.createPage(this.$route)]
128
+ this.removeListener()
129
+ } else {
130
+ this.addListener()
131
+ }
132
+ },
133
+ tabsOffset (newVal, oldVal) {
134
+ this.correctPageMinHeight(oldVal - newVal)
135
+ }
136
+ },
137
+ methods: {
138
+ changePage (key) {
139
+ this.activePage = key
140
+ const page = this.pageList.find(item => item.path === key)
141
+ this.$router.push(page.fullPath)
142
+ },
143
+ remove (key, next) {
144
+ if (this.pageList.length === 1) {
145
+ return this.$message.warning(this.$t('warn'))
146
+ }
147
+ this.setSingle({ path: key, delete: true })
148
+ // 清除缓存
149
+ let index = this.pageList.findIndex(item => item.path === key)
150
+ this.clearCaches = this.pageList.splice(index, 1).map(page => page.cachedKey)
151
+ if (next) {
152
+ this.$router.push(next)
153
+ } else if (key === this.activePage) {
154
+ index = index >= this.pageList.length ? this.pageList.length - 1 : index
155
+ this.activePage = this.pageList[index].path
156
+ this.$router.push(this.activePage)
157
+ }
158
+ },
159
+ refresh (key, page) {
160
+ page = page || this.pageList.find(item => item.path === key)
161
+ page.loading = true
162
+ // 单页面刷新
163
+ const singlePage = this.allSinglePages.find(item => item.fullPath === key)
164
+ if (singlePage) {
165
+ window.frames[singlePage.fullPath].location.reload()
166
+ return
167
+ }
168
+ this.clearCache(page)
169
+ if (key === this.activePage) {
170
+ // eslint-disable-next-line no-return-assign
171
+ this.reloadContent(() => page.loading = false)
172
+ } else {
173
+ // 其实刷新很快,加这个延迟纯粹为了 loading 状态多展示一会儿,让用户感知刷新这一过程
174
+ // eslint-disable-next-line no-return-assign
175
+ setTimeout(() => page.loading = false, 500)
176
+ }
177
+ },
178
+ onSinglePageLoad (fullPath) {
179
+ const page = this.pageList.find(item => item.fullPath === fullPath)
180
+ page.loading = false
181
+ },
182
+ onContextmenu (pageKey, e) {
183
+ if (pageKey) {
184
+ e.preventDefault()
185
+ e.meta = pageKey
186
+ this.menuVisible = true
187
+ }
188
+ },
189
+ onMenuSelect (key, target, pageKey) {
190
+ switch (key) {
191
+ case '1': this.closeLeft(pageKey); break
192
+ case '2': this.closeRight(pageKey); break
193
+ case '3': this.closeOthers(pageKey); break
194
+ case '4': this.refresh(pageKey); break
195
+ default: break
196
+ }
197
+ },
198
+ closeOthers (pageKey) {
199
+ // 清除缓存
200
+ const clearPages = this.pageList.filter(item => item.path !== pageKey && !item.unclose)
201
+ this.clearCaches = clearPages.map(item => item.cachedKey)
202
+ this.pageList = this.pageList.filter(item => !clearPages.includes(item))
203
+ // 判断跳转
204
+ if (this.activePage !== pageKey) {
205
+ this.activePage = pageKey
206
+ this.$router.push(this.activePage)
207
+ }
208
+ },
209
+ closeLeft (pageKey) {
210
+ const index = this.pageList.findIndex(item => item.path === pageKey)
211
+ // 清除缓存
212
+ const clearPages = this.pageList.filter((item, i) => i < index && !item.unclose)
213
+ this.clearCaches = clearPages.map(item => item.cachedKey)
214
+ this.pageList = this.pageList.filter(item => !clearPages.includes(item))
215
+ // 判断跳转
216
+ if (!this.pageList.find(item => item.path === this.activePage)) {
217
+ this.activePage = pageKey
218
+ this.$router.push(this.activePage)
219
+ }
220
+ },
221
+ closeRight (pageKey) {
222
+ // 清除缓存
223
+ const index = this.pageList.findIndex(item => item.path === pageKey)
224
+ const clearPages = this.pageList.filter((item, i) => i > index && !item.unclose)
225
+ this.clearCaches = clearPages.map(item => item.cachedKey)
226
+ this.pageList = this.pageList.filter(item => !clearPages.includes(item))
227
+ // 判断跳转
228
+ if (!this.pageList.find(item => item.path === this.activePage)) {
229
+ this.activePage = pageKey
230
+ this.$router.push(this.activePage)
231
+ }
232
+ },
233
+ clearCache (page) {
234
+ page._init_ = false
235
+ this.clearCaches = [page.cachedKey]
236
+ },
237
+ reloadContent (onLoaded) {
238
+ this.refreshing = true
239
+ setTimeout(() => {
240
+ this.refreshing = false
241
+ this.$nextTick(() => {
242
+ this.setCachedKey(this.$route)
243
+ if (typeof onLoaded === 'function') {
244
+ onLoaded.apply(this, [])
245
+ }
246
+ })
247
+ }, 200)
248
+ },
249
+ pageName (page) {
250
+ return this.$t(getI18nKey(page.keyPath))
251
+ },
252
+ /**
253
+ * 添加监听器
254
+ */
255
+ addListener () {
256
+ window.addEventListener('page:close', this.closePageListener)
257
+ window.addEventListener('page:refresh', this.refreshPageListener)
258
+ window.addEventListener('unload', this.unloadListener)
259
+ },
260
+ /**
261
+ * 移出监听器
262
+ */
263
+ removeListener () {
264
+ window.removeEventListener('page:close', this.closePageListener)
265
+ window.removeEventListener('page:refresh', this.refreshPageListener)
266
+ window.removeEventListener('unload', this.unloadListener)
267
+ },
268
+ /**
269
+ * 页签关闭事件监听
270
+ * @param event 页签关闭事件
271
+ */
272
+ closePageListener (event) {
273
+ const { closeRoute, nextRoute } = event.detail
274
+ const closePath = typeof closeRoute === 'string' ? closeRoute : closeRoute.path
275
+ const path = closePath && closePath.split('?')[0]
276
+ this.remove(path, nextRoute)
277
+ },
278
+ /**
279
+ * 页面刷新事件监听
280
+ * @param event 页签关闭事件
281
+ */
282
+ refreshPageListener (event) {
283
+ const { pageKey } = event.detail
284
+ const path = pageKey && pageKey.split('?')[0]
285
+ this.refresh(path)
286
+ },
287
+ /**
288
+ * 页面 unload 事件监听器,添加页签到 session 缓存,用于刷新时保留页签
289
+ */
290
+ unloadListener () {
291
+ const tabs = this.pageList.map(item => ({ ...item, _init_: false }))
292
+ sessionStorage.setItem(process.env.VUE_APP_TBAS_KEY, JSON.stringify(tabs))
293
+ },
294
+ createPage (route) {
295
+ return {
296
+ keyPath: route.matched[route.matched.length - 1].path,
297
+ fullPath: route.fullPath,
298
+ loading: false,
299
+ path: route.fullPath,
300
+ title: route.meta && route.meta.page && route.meta.page.title,
301
+ unclose: route.meta && route.meta.page && (route.meta.page.closable === false)
302
+ }
303
+ },
304
+ /**
305
+ * 设置页面缓存的key
306
+ * @param route 页面对应的路由
307
+ */
308
+ setCachedKey (route) {
309
+ const page = this.pageList.find(item => item.path === route.path)
310
+ page.unclose = route.meta && route.meta.page && (route.meta.page.closable === false)
311
+ if (!page._init_) {
312
+ const vnode = this.$refs.tabContent.$vnode
313
+ page.cachedKey = vnode.key + vnode.componentOptions.Ctor.cid
314
+ page._init_ = true
315
+ }
316
+ },
317
+ /**
318
+ * 加载缓存的 tabs
319
+ */
320
+ loadCachedTabs () {
321
+ const cachedTabsStr = sessionStorage.getItem(process.env.VUE_APP_TBAS_KEY)
322
+ if (cachedTabsStr) {
323
+ try {
324
+ // 加载缓存的单页面
325
+ const allCachedPath = JSON.parse(cachedTabsStr).map(str => { return str.fullPath })
326
+ this.allSinglePages.forEach(item => {
327
+ if (allCachedPath.includes(item.fullPath)) {
328
+ // 如果缓存中有单页面 加载到 state.single
329
+ this.setSingle(item)
330
+ }
331
+ })
332
+ const cachedTabs = JSON.parse(cachedTabsStr)
333
+ if (cachedTabs.length > 0) {
334
+ this.pageList = cachedTabs
335
+ }
336
+ } catch (e) {
337
+ console.warn('failed to load cached tabs, got exception:', e)
338
+ } finally {
339
+ sessionStorage.removeItem(process.env.VUE_APP_TBAS_KEY)
340
+ }
341
+ }
342
+ },
343
+ loadCacheConfig (routes, pCache = true) {
344
+ routes.forEach(item => {
345
+ const cacheAble = item.meta?.page?.cacheAble ?? pCache ?? true
346
+ if (item.meta && item.meta.singlePage) {
347
+ // 找到所有单页面添加到 allSinglePages 中
348
+ this.allSinglePages.push(item)
349
+ }
350
+ if (!cacheAble) {
351
+ this.excludeKeys.push(new RegExp(`${item.path.replace(/:[^/]*/g, '[^/]*')}(\\?.*)?\\d*$`))
352
+ }
353
+ if (item.children) {
354
+ this.loadCacheConfig(item.children, cacheAble)
355
+ }
356
+ })
357
+ },
358
+ ...mapMutations('setting', ['correctPageMinHeight']),
359
+ ...mapMutations('account', ['setSingle'])
360
+ }
361
+ }
362
+ </script>
363
+
364
+ <style lang="less">
365
+ #TabsView {
366
+ .tabs-view {
367
+ margin: -16px auto 8px;
368
+ &.head.fixed {
369
+ max-width: 100%;
370
+ }
371
+ }
372
+ .tabs-view-content {
373
+ position: relative;
374
+ &.head.fixed {
375
+ width: 100%;
376
+ margin: 0 auto;
377
+ }
378
+ > div > div > .ant-card:first-of-type > .ant-card-body {
379
+ max-height: calc(100vh - 64px - 48px - 24px);
380
+ overflow-y: auto;
381
+ &::-webkit-scrollbar {
382
+ display: none;
383
+ }
384
+ }
385
+ }
386
+ }
387
+ </style>