vue2-client 1.8.310 → 1.8.311

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 (215) 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/LowCode/lowcode.md +155 -155
  7. package/docs/LowCode/lowcodeForDeveloper.md +230 -230
  8. package/docs/index.md +30 -30
  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 +97 -97
  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 +438 -416
  23. package/src/base-client/components/common/AddressSearchCombobox/demo.vue +36 -36
  24. package/src/base-client/components/common/AddressSearchCombobox/ic_map.svg +6 -6
  25. package/src/base-client/components/common/AmapMarker/AmapPointRendering.vue +120 -120
  26. package/src/base-client/components/common/CitySelect/CitySelect.vue +342 -342
  27. package/src/base-client/components/common/CitySelect/index.js +3 -3
  28. package/src/base-client/components/common/CitySelect/index.md +109 -109
  29. package/src/base-client/components/common/CreateQuery/CreateQuery.vue +669 -669
  30. package/src/base-client/components/common/CreateQuery/CreateQueryItem.vue +1014 -1014
  31. package/src/base-client/components/common/CreateQuery/index.js +3 -3
  32. package/src/base-client/components/common/CreateQuery/index.md +42 -42
  33. package/src/base-client/components/common/CreateSimpleFormQuery/CreateSimpleFormQuery.vue +452 -452
  34. package/src/base-client/components/common/CreateSimpleFormQuery/CreateSimpleFormQueryItem.vue +511 -511
  35. package/src/base-client/components/common/CreateSimpleFormQuery/index.js +3 -3
  36. package/src/base-client/components/common/CreateSimpleFormQuery/index.md +42 -42
  37. package/src/base-client/components/common/FormGroupEdit/FormGroupEdit.vue +149 -149
  38. package/src/base-client/components/common/FormGroupEdit/index.js +3 -3
  39. package/src/base-client/components/common/FormGroupEdit/index.md +43 -43
  40. package/src/base-client/components/common/FormGroupQuery/FormGroupQuery.vue +166 -166
  41. package/src/base-client/components/common/FormGroupQuery/index.js +3 -3
  42. package/src/base-client/components/common/FormGroupQuery/index.md +43 -43
  43. package/src/base-client/components/common/JSONToTree/jsontotree.vue +271 -271
  44. package/src/base-client/components/common/LowCodeComponent/LowCodeEditorModal.vue +108 -108
  45. package/src/base-client/components/common/LowCodeComponent/LowCodeEditorPanel.vue +350 -350
  46. package/src/base-client/components/common/LowCodeComponent/LowCodePageOrganization.vue +502 -502
  47. package/src/base-client/components/common/LowCodeComponent/LowCodeRender.vue +699 -699
  48. package/src/base-client/components/common/LowCodeComponent/LowCodeRenderEnter.vue +29 -29
  49. package/src/base-client/components/common/LowCodeComponent/LowCodeUIStore.vue +162 -162
  50. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeAddPageModal.vue +117 -117
  51. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeCustomJSModal.vue +80 -80
  52. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeEventEditorModal.vue +398 -398
  53. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeLifeCycleModal.vue +65 -65
  54. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeLogicCallbackModal.vue +64 -64
  55. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeLogicParamModal.vue +73 -73
  56. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeRunFunctionParamModal.vue +76 -76
  57. package/src/base-client/components/common/PersonSetting/PersonSetting.vue +208 -208
  58. package/src/base-client/components/common/PersonSetting/index.js +3 -3
  59. package/src/base-client/components/common/Tree/Tree.vue +149 -149
  60. package/src/base-client/components/common/Tree/index.js +2 -2
  61. package/src/base-client/components/common/Upload/Upload.vue +239 -239
  62. package/src/base-client/components/common/Upload/index.js +3 -3
  63. package/src/base-client/components/common/XAddForm/XAddForm.vue +105 -105
  64. package/src/base-client/components/common/XAddNativeForm/XAddNativeForm.vue +807 -807
  65. package/src/base-client/components/common/XAddNativeForm/index.md +146 -146
  66. package/src/base-client/components/common/XAddNativeForm/lowcodeEditorRegister.js +16 -16
  67. package/src/base-client/components/common/XAddNativeFormOA/XAddNativeFormOA.vue +303 -303
  68. package/src/base-client/components/common/XAddNativeFormOA/index.js +3 -3
  69. package/src/base-client/components/common/XAddNativeFormOA/index.md +146 -146
  70. package/src/base-client/components/common/XBadge/XBadge.vue +78 -78
  71. package/src/base-client/components/common/XCard/XCard.vue +64 -64
  72. package/src/base-client/components/common/XDataDrawer/XDataDrawer.vue +180 -180
  73. package/src/base-client/components/common/XDataDrawer/index.js +3 -3
  74. package/src/base-client/components/common/XDataDrawer/index.md +41 -41
  75. package/src/base-client/components/common/XDescriptions/XDescriptions.vue +187 -187
  76. package/src/base-client/components/common/XDescriptions/XDescriptionsGroup.vue +306 -306
  77. package/src/base-client/components/common/XDescriptions/demo.vue +50 -50
  78. package/src/base-client/components/common/XDescriptions/index.js +3 -3
  79. package/src/base-client/components/common/XDescriptions/index.md +83 -83
  80. package/src/base-client/components/common/XDescriptions/lowcodeEditorRegister.js +31 -31
  81. package/src/base-client/components/common/XDetailsView/XDetailsView.vue +214 -214
  82. package/src/base-client/components/common/XDetailsView/index.js +3 -3
  83. package/src/base-client/components/common/XForm/XForm.vue +294 -294
  84. package/src/base-client/components/common/XForm/XFormItem.vue +911 -911
  85. package/src/base-client/components/common/XForm/XTreeSelect.vue +207 -207
  86. package/src/base-client/components/common/XForm/index.md +178 -178
  87. package/src/base-client/components/common/XFormCol/XFormCol.vue +36 -36
  88. package/src/base-client/components/common/XFormGroup/XFormGroup.vue +241 -241
  89. package/src/base-client/components/common/XFormGroup/demo.vue +40 -40
  90. package/src/base-client/components/common/XFormGroup/index.js +3 -3
  91. package/src/base-client/components/common/XFormGroup/index.md +38 -38
  92. package/src/base-client/components/common/XFormGroupDetails/XFormGroupDetails.vue +72 -72
  93. package/src/base-client/components/common/XFormGroupDetails/index.js +3 -3
  94. package/src/base-client/components/common/XFormTable/XFormTable.vue +539 -539
  95. package/src/base-client/components/common/XFormTable/demo.vue +72 -72
  96. package/src/base-client/components/common/XFormTable/index.md +98 -98
  97. package/src/base-client/components/common/XFormTable/lowcodeEditorRegister.js +30 -30
  98. package/src/base-client/components/common/XImportExcel/XImportExcel.vue +147 -147
  99. package/src/base-client/components/common/XReport/XReport.vue +858 -858
  100. package/src/base-client/components/common/XReport/XReportDemo.vue +266 -266
  101. package/src/base-client/components/common/XReport/XReportDesign.vue +509 -509
  102. package/src/base-client/components/common/XReport/XReportJsonRender.vue +295 -295
  103. package/src/base-client/components/common/XReport/XReportTrGroup.vue +801 -801
  104. package/src/base-client/components/common/XReport/index.js +3 -3
  105. package/src/base-client/components/common/XReport/index.md +44 -44
  106. package/src/base-client/components/common/XReportSlot/XReportSlot.vue +110 -110
  107. package/src/base-client/components/common/XReportSlot/index.js +3 -3
  108. package/src/base-client/components/common/XReportSlot/index.md +48 -48
  109. package/src/base-client/components/common/XStepView/XStepView.vue +252 -252
  110. package/src/base-client/components/common/XStepView/index.js +3 -3
  111. package/src/base-client/components/common/XStepView/index.md +31 -31
  112. package/src/base-client/components/common/XTable/XTable.vue +676 -676
  113. package/src/base-client/components/common/XTable/index.md +255 -255
  114. package/src/base-client/components/common/XTree/XTree.vue +423 -423
  115. package/src/base-client/components/common/XTree/index.js +3 -3
  116. package/src/base-client/components/common/XTree/index.md +36 -36
  117. package/src/base-client/components/common/XTreeOne/XTreeOne.vue +114 -114
  118. package/src/base-client/components/common/XTreeOne/lowcodeEditorRegister.js +11 -11
  119. package/src/base-client/components/index.js +51 -51
  120. package/src/base-client/components/system/DictionaryDetailsView/DictionaryDetailsView.vue +232 -232
  121. package/src/base-client/components/system/QueryParamsDetailsView/QueryParamsDetailsView.vue +281 -281
  122. package/src/base-client/plugins/AppData.js +121 -121
  123. package/src/base-client/plugins/Config.js +19 -19
  124. package/src/base-client/plugins/GetLoginInfoService.js +183 -183
  125. package/src/base-client/plugins/tabs-page-plugin.js +39 -39
  126. package/src/bootstrap.js +39 -39
  127. package/src/components/FilePreview/FilePreview.vue +166 -166
  128. package/src/components/NumberInfo/NumberInfo.vue +54 -54
  129. package/src/components/STable/index.js +361 -361
  130. package/src/components/checkbox/ColorCheckbox.vue +157 -157
  131. package/src/components/checkbox/ImgCheckbox.vue +163 -163
  132. package/src/components/menu/SideMenu.vue +75 -75
  133. package/src/components/menu/menu.js +273 -273
  134. package/src/components/tool/AStepItem.vue +60 -60
  135. package/src/config/default/antd.config.js +89 -89
  136. package/src/config/default/setting.config.js +55 -55
  137. package/src/font-style/font.css +4 -4
  138. package/src/layouts/CommonLayout.vue +56 -56
  139. package/src/layouts/PageLayout.vue +151 -151
  140. package/src/layouts/SinglePageView.vue +138 -138
  141. package/src/layouts/header/AdminHeader.vue +132 -132
  142. package/src/layouts/header/HeaderNotice.vue +177 -177
  143. package/src/layouts/tabs/TabsHead.vue +189 -189
  144. package/src/layouts/tabs/TabsView.vue +387 -387
  145. package/src/lib.js +1 -1
  146. package/src/main.js +26 -26
  147. package/src/mock/extend/index.js +84 -84
  148. package/src/mock/goods/index.js +108 -108
  149. package/src/pages/AMisDemo/AMisDemo.vue +325 -325
  150. package/src/pages/AMisDemo/AMisDemo2.vue +74 -74
  151. package/src/pages/DynamicStatistics/ChartSelector.vue +331 -331
  152. package/src/pages/DynamicStatistics/DataTabs.vue +83 -83
  153. package/src/pages/DynamicStatistics/DynamicTable.vue +128 -128
  154. package/src/pages/DynamicStatistics/EvaluationArea.vue +69 -69
  155. package/src/pages/DynamicStatistics/FavoriteList.vue +51 -51
  156. package/src/pages/DynamicStatistics/QuestionHistoryAndFavorites.vue +591 -591
  157. package/src/pages/DynamicStatistics/SearchBar.vue +192 -192
  158. package/src/pages/DynamicStatistics/index.vue +282 -282
  159. package/src/pages/Example/index.vue +33 -33
  160. package/src/pages/ServiceReview/index.vue +284 -284
  161. package/src/pages/XReportView/index.vue +62 -62
  162. package/src/pages/login/Login.vue +378 -378
  163. package/src/pages/login/LoginV3.vue +389 -389
  164. package/src/pages/lowCode/lowCodeEditor.vue +1030 -1030
  165. package/src/pages/lowCode/lowCodeRenderPage.vue +43 -43
  166. package/src/pages/resourceManage/orgListManage.vue +98 -98
  167. package/src/pages/system/dictionary/index.vue +44 -44
  168. package/src/pages/system/monitor/loginInfor/index.vue +37 -37
  169. package/src/pages/system/monitor/operLog/index.vue +37 -37
  170. package/src/pages/system/settings/modifyPassword.vue +117 -117
  171. package/src/pages/system/ticket/index.vue +480 -480
  172. package/src/pages/system/ticket/submitTicketSuccess.vue +484 -484
  173. package/src/router/async/config.async.js +34 -34
  174. package/src/router/async/router.map.js +104 -104
  175. package/src/router/guards.js +223 -223
  176. package/src/router/index.js +27 -27
  177. package/src/router.js +19 -19
  178. package/src/services/api/TicketDetailsViewApi.js +46 -46
  179. package/src/services/api/cas.js +79 -79
  180. package/src/services/api/common.js +307 -307
  181. package/src/services/api/entity.js +18 -18
  182. package/src/services/api/index.js +17 -17
  183. package/src/services/api/restTools.js +46 -46
  184. package/src/services/apiService.js +14 -14
  185. package/src/services/user.js +71 -71
  186. package/src/services/v3Api.js +81 -81
  187. package/src/store/modules/index.js +5 -5
  188. package/src/store/modules/lowCode.js +33 -33
  189. package/src/store/modules/setting.js +119 -119
  190. package/src/theme/default/style.less +58 -58
  191. package/src/theme/global.less +139 -139
  192. package/src/utils/authority-utils.js +85 -85
  193. package/src/utils/errorCode.js +6 -6
  194. package/src/utils/formatter.js +80 -80
  195. package/src/utils/htmlToPDF.js +108 -108
  196. package/src/utils/htmlToPDFApi.js +5 -5
  197. package/src/utils/indexedDB.js +258 -258
  198. package/src/utils/login.js +188 -188
  199. package/src/utils/lowcode/lowcodeComponentMixin.js +120 -120
  200. package/src/utils/lowcode/lowcodeLog.js +29 -29
  201. package/src/utils/lowcode/lowcodeUtils.js +373 -373
  202. package/src/utils/lowcode/registerComponentForEditor.js +11 -11
  203. package/src/utils/lowcode/registerComponentForRender.js +11 -11
  204. package/src/utils/map-utils.js +47 -47
  205. package/src/utils/reg.js +95 -95
  206. package/src/utils/request.js +347 -347
  207. package/src/utils/routerUtil.js +435 -435
  208. package/src/utils/runEvalFunction.js +6 -6
  209. package/src/utils/util.js +241 -241
  210. package/src/utils/waterMark.js +31 -31
  211. package/test/Amis.spec.js +163 -163
  212. package/test/Tree.spec.js +167 -167
  213. package/test/myDialog.spec.js +46 -46
  214. package/vue.config.js +181 -181
  215. package//350/277/201/347/247/273/346/227/245/345/277/227.md +15 -15
@@ -1,699 +1,699 @@
1
- <template>
2
- <div style="width: 100%">
3
- <template v-for="(page,pageIndex) in pageConfig.page">
4
- <!-- 拖拽时显示的临时容器 -->
5
- <template v-if="showDragSpan">
6
- <div style="display: flex" :key="pageIndex">
7
- <template v-for="item in dragConfig">
8
- <div class="container" style="font-size: 1.5em" :key="item.id" :style="'width:' + item.width + 'px'">
9
- 宽度:{{ item.span }}
10
- </div>
11
- </template>
12
- </div>
13
- </template>
14
- <!-- 渲染器主体 -->
15
- <template v-for="(row,rowIndex) in page.body">
16
- <a-row
17
- :key="pageIndex + '_' + rowIndex"
18
- type="flex"
19
- :justify="row.config.justify"
20
- :gutter="row.config.gutter"
21
- :align="row.config.align">
22
- <template v-if="!showDragSpan">
23
- <template v-for="(item, itemIndex) in row.body">
24
- <a-col :span="item.span" :key="item.id">
25
- <!-- 显示容器 -->
26
- <div
27
- v-if="item.type === 'container' && editMode"
28
- style="display: flex;align-items: center"
29
- @click="clickComponentInEditor(item)">
30
- <div :class="item.selected ? 'selected_container' : 'container'">
31
- <div>
32
- <p style="font-size: 1.5em">宽度:{{ item.span }}</p>
33
- </div>
34
- <div>
35
- <a-button @click.stop="handelContainerDelete(item.id, pageIndex)">删除</a-button>
36
- </div>
37
- </div>
38
- <div
39
- v-if="itemIndex !== row.body.length - 1"
40
- style="width: 6px;font-size: 1em;color: rgb( 24,144,255)"
41
- class="dragDiv"
42
- @mousedown="dragStart($event, item.id, row)">
43
- || <br> ||
44
- </div>
45
- </div>
46
- <!-- 递归显示页面容器 -->
47
- <div
48
- v-else-if="item.type === 'container_page'"
49
- style="display: flex;align-items: center">
50
- <LowCodeRender
51
- ref="sub"
52
- :is-root="false"
53
- @showDraw="handelSubShowDraw"
54
- @showModal="handelSubShowModal"
55
- v-if="renderSub"
56
- @spanDrag="handleDrag"
57
- @containerDelete="handleContainerDelete"
58
- @clickComponentInEditor="clickComponentInner"
59
- :page-config="item"
60
- :edit-mode="editMode"/>
61
- <div
62
- v-if="itemIndex !== row.body.length - 1"
63
- style="width: 6px;font-size: 1em;color: rgb( 24,144,255);"
64
- class="dragDiv"
65
- @mousedown="dragStart($event, item.id, row)">
66
- || <br> ||
67
- </div>
68
- </div>
69
- <!-- 页面渲染 / 编辑模式中,将弹框或抽屉中的内容渲染为页面 -->
70
- <div :ref="item.id" :id="item.id" v-else-if="editMode || (page.type !== 'modal' && page.type !== 'draw')">
71
- <div
72
- @click="clickComponentInEditor(item)"
73
- :class=" editMode ? 'componentInEditor' : '' ">
74
- <component
75
- v-if="checkComponentRequiredProps(item.type, item.props)"
76
- :lifeCycleFunction="resolveLifeCycleEvent(item)"
77
- :is="resolveComponentType(item.type, item.id)"
78
- :propsData="{...item.props}"
79
- @componentDidMounted="componentDidMounted"
80
- @onEvent="handleEvent"
81
- :mixinComponentId="item.id"/>
82
- <div v-else class="propsNotFixedComponent">
83
- <p style="line-height: 200px; text-align: center; font-size: 2em; margin: 0">{{ item.type }}</p>
84
- <p style="text-align: center; font-size: 1.2em">必填参数未设置完全!暂停渲染</p>
85
- </div>
86
- </div>
87
- </div>
88
- </a-col>
89
- </template>
90
- </template>
91
- </a-row>
92
- </template>
93
- </template>
94
- <!-- 弹框渲染 -->
95
- <template v-for="(modal, modalIndex) in pageConfig.page.filter(page => page.type === 'modal')">
96
- <a-modal
97
- :key="'modalIndex_' + modalIndex"
98
- :title="modal.title"
99
- :width="modal.width"
100
- :dialog-style="{ top: '5rem' }"
101
- :visible="modalVisible[modal.id]"
102
- :z-index="1003"
103
- :maskClosable="false"
104
- @cancel="closeModalOrDraw(modal.id, 'modal')"
105
- :destroyOnClose="true">
106
- <template v-for="(row, rowIndex) in modal.body">
107
- <template v-for="(item, itemIndex) in row.body">
108
- <component
109
- v-if="checkComponentRequiredProps(item.type, item.props)"
110
- :lifeCycleFunction="resolveLifeCycleEvent(item)"
111
- :key="'modalItem_' + rowIndex + '_' + itemIndex"
112
- :is="resolveComponentType(item.type)"
113
- :propsData="{...item.props, showModalOrDraw: false}"
114
- @componentDidMounted="componentDidMounted"
115
- @onEvent="handleEvent"
116
- :mixinComponentId="item.id"/>
117
- <div v-else :key="'modalItem_' + rowIndex + '_' + itemIndex" class="propsNotFixedComponent">
118
- <p style="line-height: 200px; text-align: center; font-size: 2em; margin: 0">{{ item.type }}</p>
119
- <p style="text-align: center; font-size: 1.2em">必填参数未设置完全!暂停渲染</p>
120
- </div>
121
- </template>
122
- </template>
123
- </a-modal>
124
- </template>
125
- <!-- 抽屉渲染 -->
126
- <template v-for="(draw, drawIndex) in pageConfig.page.filter(page => page.type === 'draw')">
127
- <a-drawer
128
- :key="'drawIndex_' + drawIndex"
129
- :title="draw.title"
130
- :width="draw.width"
131
- :visible="drawVisible[draw.id]"
132
- :z-index="1003"
133
- @close="closeModalOrDraw(draw.id, 'draw')"
134
- :destroyOnClose="true">
135
- <template v-for="(row, rowIndex) in draw.body">
136
- <template v-for="(item, itemIndex) in row.body">
137
- <component
138
- v-if="checkComponentRequiredProps(item.type, item.props)"
139
- :lifeCycleFunction="resolveLifeCycleEvent(item)"
140
- :key="'drawItem_' + rowIndex + '_' + itemIndex"
141
- :is="resolveComponentType(item.type)"
142
- :propsData="{...item.props, showModalOrDraw: false}"
143
- @componentDidMounted="componentDidMounted"
144
- @onEvent="handleEvent"
145
- :mixinComponentId="item.id"/>
146
- <div v-else :key="'drawItem_' + rowIndex + '_' + itemIndex" class="propsNotFixedComponent">
147
- <p style="line-height: 200px; text-align: center; font-size: 2em; margin: 0">{{ item.type }}</p>
148
- <p style="text-align: center; font-size: 1.2em">必填参数未设置完全!暂停渲染</p>
149
- </div>
150
- </template>
151
- </template>
152
- </a-drawer>
153
- </template>
154
- </div>
155
- </template>
156
-
157
- <script>
158
- // eslint-disable-next-line no-unused-vars
159
- import Vue from 'vue'
160
- import * as allComponents from '@vue2-client/utils/lowcode/registerComponentForRender'
161
- import lowcodeLog from '@vue2-client/utils/lowcode/lowcodeLog'
162
- import * as lowcodeUtils from '@vue2-client/utils/lowcode/lowcodeUtils'
163
- import { runLogic } from '@vue2-client/services/api/common'
164
-
165
- export default {
166
- name: 'LowCodeRender',
167
- props: {
168
- // 页面配置
169
- pageConfig: {
170
- type: Object,
171
- required: true
172
- },
173
- // 是否为编辑模式
174
- editMode: {
175
- type: Boolean,
176
- default: true
177
- },
178
- // 用于标识渲染器是否为顶级渲染器
179
- // 非顶级渲染器在控制弹框、抽屉显隐的时候需要emit而不是修改值
180
- isRoot: {
181
- type: Boolean,
182
- default: true
183
- }
184
- },
185
- data () {
186
- return {
187
- // 传递给组件的Props合集
188
- propsData: {},
189
- // 是否为拖拽模式
190
- showDragSpan: false,
191
- // 拖拽的缓存
192
- dragConfig: [],
193
- // 记录拖拽位移单位量
194
- beforeSpanThrough: -1,
195
- // 记录拖拽之前的span
196
- originalSpan: -1,
197
- // 记录拖拽目标下一个元素的原始span
198
- nextOriginalSpan: -1,
199
- // 弹框显示集合
200
- modalVisible: {},
201
- // 抽屉显示集合
202
- drawVisible: {},
203
- // 控制递归渲染
204
- renderSub: true,
205
- // 用于控制组件外框闪烁
206
- colClassName: '',
207
- // 控制容器渲染,用于递归时,刷新递归中容器的状态
208
- showContainer: true,
209
- // 控制闪烁的定时器
210
- twinkTimer: undefined,
211
- // 缓存正在闪烁的组件,用于还原状态
212
- twinkBefore: undefined
213
- }
214
- },
215
- inject: [
216
- 'componentsMap'
217
- ],
218
- mounted () {
219
- // 初始化控制弹框和抽屉的变量合集
220
- this.pageConfig.page.forEach(page => {
221
- if (page.type === 'modal') {
222
- this.modalVisible[page.id] = false
223
- } else if (page.type === 'draw') {
224
- this.drawVisible[page.id] = false
225
- }
226
- })
227
- },
228
- methods: {
229
- // 检查组件必要的props是否全部满足
230
- checkComponentRequiredProps (type, props) {
231
- if (type === 'container') {
232
- return true
233
- }
234
- const propertiesDef = lowcodeUtils.getEditorConfigByType(type).properties
235
- const defKeys = Object.keys(propertiesDef)
236
- const requiredProps = []
237
- defKeys.forEach(key => {
238
- if (propertiesDef[key].required) {
239
- requiredProps.push(key)
240
- }
241
- })
242
- for (let i = 0; i < requiredProps.length; i++) {
243
- const eachRequired = requiredProps[i]
244
- if (props[eachRequired] === undefined || props[eachRequired] === '' || props[eachRequired] === null) {
245
- return false
246
- }
247
- }
248
- return true
249
- },
250
- // 用于控制递归渲染器中的修改抽屉显隐
251
- handelSubShowDraw (id, visible) {
252
- this.drawVisible[id] = visible === 'open'
253
- this.$forceUpdate()
254
- lowcodeLog(
255
- id,
256
- '修改抽屉可见性',
257
- visible === 'open' ? '可见' : '隐藏',
258
- false,
259
- true
260
- )
261
- },
262
- // 用于控制递归渲染器中的修改弹框显隐
263
- handelSubShowModal (id, visible) {
264
- this.modalVisible[id] = visible === 'open'
265
- this.$forceUpdate()
266
- lowcodeLog(
267
- id,
268
- '修改弹窗可见性',
269
- visible === 'open' ? '可见' : '隐藏',
270
- false,
271
- true
272
- )
273
- },
274
- // 将钩子函数格式化成mixin的格式并传入
275
- resolveLifeCycleEvent (config) {
276
- if (!config.onEvent || !config.onEvent.lifeCycle) {
277
- return undefined
278
- } else {
279
- const result = []
280
- const lifeCycle = config.onEvent.lifeCycle
281
- lifeCycle.forEach(item => {
282
- result.push({
283
- lifeCycleName: item.lifeCycle,
284
- functionStr: item.LifeCycleFunction
285
- })
286
- })
287
- return result
288
- }
289
- },
290
- // 关闭弹窗或抽屉
291
- closeModalOrDraw (id, type) {
292
- if (type === 'modal') {
293
- this.modalVisible[id] = false
294
- } else if (type === 'draw') {
295
- this.drawVisible[id] = false
296
- }
297
- this.$forceUpdate()
298
- },
299
- // 递归拖拽完成后的回调
300
- handleDrag (targetEle, nextEle) {
301
- this.$emit('spanDrag', targetEle, nextEle)
302
- },
303
- // 递归容器删除后的回调
304
- handleContainerDelete (id) {
305
- this.$emit('containerDelete', id)
306
- },
307
- // 刷新递归的渲染器
308
- refreshSubRender () {
309
- this.renderSub = false
310
- this.$nextTick(() => {
311
- this.renderSub = true
312
- })
313
- },
314
- // 刷新递归容器
315
- refreshSubContainer () {
316
- this.showContainer = false
317
- this.$nextTick(() => {
318
- this.showContainer = true
319
- })
320
- },
321
- // 递归点击组件后的回调
322
- clickComponentInner (configItem) {
323
- this.$emit('clickComponentInEditor', configItem, this)
324
- },
325
- // 拖拽改变Span
326
- dragStart (event, id, row) {
327
- // 获取目标html元素
328
- const targetElement = event.srcElement
329
- // 获取外层元素用于计算总宽度
330
- const outerElement = targetElement.parentNode.parentNode.parentNode
331
- const outerWidth = outerElement.offsetWidth
332
- // 计算每一个span对应的像素
333
- const outerSpanWidth = outerWidth / 24
334
-
335
- // 记录初始X
336
- const startX = event.clientX
337
-
338
- // 记录兄弟元素
339
- const targetElementBros = outerElement.childNodes
340
-
341
- let targetComponent
342
- let targetNextComponent
343
-
344
- // 缓存拖拽组件,用于显示拖拽时的实时Span,拖拽完成后再统一赋值
345
- this.dragConfig = []
346
- for (let i = 0; i < row.body.length; i++) {
347
- this.dragConfig.push({
348
- id: row.body[i].id,
349
- span: row.body[i].span,
350
- width: targetElementBros[i].offsetWidth
351
- })
352
- }
353
-
354
- this.showDragSpan = true
355
-
356
- // 保存目标容器,和目标的下一个容器,用于改变宽度
357
- for (let i = 0; i < this.dragConfig.length; i++) {
358
- const item = this.dragConfig[i]
359
- if (item.id === id) {
360
- targetComponent = this.dragConfig[i]
361
- targetNextComponent = this.dragConfig[i + 1]
362
- }
363
- }
364
-
365
- // 如果鼠标之后没有组件,禁止移动
366
- if (!targetComponent || !targetNextComponent) {
367
- this.$message.error('单个组件无法移动!')
368
- this.showDragSpan = false
369
- return
370
- }
371
-
372
- // 保存原始的像素宽度
373
- const orignalTargetWidth = targetComponent.width
374
- const orignalTargetNextWidth = targetNextComponent.width
375
-
376
- // 保存原始的span
377
- this.originalSpan = targetComponent.span
378
- this.nextOriginalSpan = targetNextComponent.span
379
-
380
- // 拖拽事件
381
- const onDrag = (e) => {
382
- // 计算出移动的像素数
383
- let deltaX = e.clientX - startX
384
- // 判断移动方向
385
- let direction = 1
386
- if (deltaX < 0) {
387
- direction = -1
388
- deltaX = 0 - deltaX
389
- }
390
-
391
- // 根据移动像素数计算出移动了多少个span
392
- const throughSpanNum = Math.floor(deltaX / outerSpanWidth)
393
- if (this.beforeSpanThrough === -1) {
394
- this.beforeSpanThrough = throughSpanNum
395
- }
396
-
397
- // 将移动的距离更新到临时显示的span中
398
- if (direction > 0) {
399
- targetComponent.width = orignalTargetWidth + deltaX
400
- targetNextComponent.width = orignalTargetNextWidth - deltaX
401
- if (this.beforeSpanThrough !== throughSpanNum) {
402
- this.beforeSpanThrough = throughSpanNum
403
- targetComponent.span = this.originalSpan + throughSpanNum
404
- targetNextComponent.span = this.nextOriginalSpan - throughSpanNum
405
- }
406
- } else {
407
- targetComponent.width = orignalTargetWidth - deltaX
408
- targetNextComponent.width = orignalTargetNextWidth + deltaX
409
- if (this.beforeSpanThrough !== throughSpanNum) {
410
- this.beforeSpanThrough = throughSpanNum
411
- targetComponent.span = this.originalSpan - throughSpanNum
412
- targetNextComponent.span = this.nextOriginalSpan + throughSpanNum
413
- }
414
- }
415
- }
416
-
417
- // 拖拽结束
418
- const dragEnd = (e) => {
419
- // 解绑事件,更新数据
420
- this.showDragSpan = false
421
- document.removeEventListener('mouseup', dragEnd)
422
- document.removeEventListener('mousemove', onDrag)
423
- this.$emit('spanDrag', targetComponent, targetNextComponent)
424
- }
425
-
426
- // 绑定拖拽事件和结束事件
427
- document.addEventListener('mouseup', dragEnd)
428
- document.addEventListener('mousemove', onDrag)
429
- },
430
- // 解析配置中的type,找出对应的渲染器
431
- resolveComponentType (type, componentId) {
432
- // 从组件注册中拿到所有注册的组件
433
- const allComponentKeys = Object.keys(allComponents)
434
- for (let i = 0; i < allComponentKeys.length; i++) {
435
- const keyStr = allComponentKeys[i].toString()
436
- if (type === keyStr) {
437
- return allComponents[keyStr]
438
- }
439
- }
440
- },
441
- // mixin中组件mounted后的回调
442
- componentDidMounted (vm, id) {
443
- // 将组件注册到全局的Map中
444
- if (vm && id) {
445
- this.componentsMap[id] = vm
446
- }
447
- // 如果组件中有props,将其挨个set到vm中
448
- const config = lowcodeUtils.getComponentConfig(id, this.pageConfig)
449
- const keys = Object.keys(config.props)
450
- keys.forEach(key => {
451
- if (config.props[key] !== undefined && config.props[key] !== '') {
452
- Vue.set(vm, key, config.props[key])
453
- }
454
- })
455
- },
456
- // 点击组件
457
- clickComponentInEditor (configItem) {
458
- this.$emit('clickComponentInEditor', configItem, this)
459
- },
460
- // 删除容器
461
- handelContainerDelete (id, pageIndex) {
462
- this.$emit('containerDelete', id, pageIndex)
463
- },
464
- // 处理组件的事件
465
- handleEvent (data, eventTiggerType, id) {
466
- // 找到目标对象的配置
467
- const targetConfig = lowcodeUtils.getComponentConfig(id, this.pageConfig.page)
468
- // 找到目标对象对应触发事件的配置
469
- const eventConfigs = targetConfig.onEvent[eventTiggerType]
470
-
471
- if (!eventConfigs) {
472
- return
473
- }
474
-
475
- const vm = this.componentsMap[id]
476
- lowcodeLog(
477
- ` 事件数据:${data} \n 源组件: ${id}`,
478
- '触发事件',
479
- eventTiggerType,
480
- true
481
- )
482
-
483
- let targetComponentId = ''
484
-
485
- // 遍历该类型触发事件,挨个执行
486
- eventConfigs.forEach(eachEvent => {
487
- lowcodeLog(
488
- ` 事件数据:${data} \n 目标组件: ${targetComponentId}`,
489
- '开始遍历执行事件',
490
- eachEvent.eventType,
491
- false
492
- )
493
- // 修改弹窗显隐
494
- if (eachEvent.eventType === 'showDraw') {
495
- // 如果不是顶级渲染器,则向外抛出事件
496
- if (!this.isRoot) {
497
- this.$emit('showDraw', eachEvent.containerId, eachEvent.visible)
498
- } else {
499
- this.drawVisible[eachEvent.containerId] = eachEvent.visible === 'open'
500
- this.$forceUpdate()
501
- lowcodeLog(
502
- eachEvent.containerId,
503
- '修改抽屉可见性',
504
- eachEvent.visible === 'open' ? '可见' : '隐藏',
505
- false,
506
- true
507
- )
508
- }
509
- } else if (eachEvent.eventType === 'showModal') {
510
- // 修改抽屉显隐
511
- // 如果不是顶级渲染器,则向外抛出事件
512
- if (!this.isRoot) {
513
- this.$emit('showModal', eachEvent.containerId, eachEvent.visible)
514
- } else {
515
- this.modalVisible[eachEvent.containerId] = eachEvent.visible === 'open'
516
- this.$forceUpdate()
517
- lowcodeLog(
518
- eachEvent.containerId,
519
- '修改弹窗可见性',
520
- eachEvent.visible === 'open' ? '可见' : '隐藏',
521
- false,
522
- true
523
- )
524
- }
525
- } else if (eachEvent.eventType === 'customJSFunction') {
526
- const targetVM = this.componentsMap[eachEvent.target]
527
- // eslint-disable-next-line no-eval
528
- const customFunction = eval('(' + eachEvent.JSFunction + ')')
529
- customFunction(eachEvent.eventType, data, targetVM, vm)
530
- lowcodeLog(
531
- undefined,
532
- '执行自定义函数完成',
533
- undefined,
534
- false,
535
- true
536
- )
537
- } else if (eachEvent.eventType === 'runLogic') {
538
- // 运行Logic
539
- // eslint-disable-next-line no-eval
540
- const logicCallBackFunction = eval('(' + eachEvent.logicCallBackFunction + ')')
541
- // eslint-disable-next-line no-eval
542
- const logicParamFunction = eval('(' + eachEvent.logicParamFunction + ')')
543
- // 将需要的组件变量组织好,并传递给函数
544
- const componentData = {}
545
- const allComponents = Object.keys(this.componentsMap)
546
- allComponents.forEach(component => {
547
- componentData[component] = this.componentsMap[component].dataForLowCode
548
- })
549
- const param = logicParamFunction(componentData, data)
550
- lowcodeLog(
551
- JSON.stringify(param),
552
- '执行Logic',
553
- eachEvent.logicName,
554
- false,
555
- true
556
- )
557
- runLogic(eachEvent.logicName, param, eachEvent.serviceName)
558
- .then(res => { logicCallBackFunction(this.componentsMap, res) })
559
- } else if (eachEvent.eventType === 'changeProps') {
560
- // 修改组件props
561
- const targetConfig = lowcodeUtils.getComponentConfig(eachEvent.target, this.pageConfig.page)
562
- targetConfig.props[eachEvent.targetKey] = data
563
- lowcodeLog(
564
- `目标key:${eachEvent.targetKey},新的值:${JSON.stringify(data)}`,
565
- '修改Props',
566
- targetConfig.id,
567
- false,
568
- true
569
- )
570
- } else if (eachEvent.eventType === 'log') {
571
- // 打印日志
572
- lowcodeLog(
573
- JSON.stringify(data),
574
- '打印日志',
575
- targetConfig.id,
576
- false,
577
- true
578
- )
579
- } else if (eachEvent.eventType === 'runFunction') {
580
- // 修改组件的值
581
- // 寻找target
582
- targetComponentId = eachEvent.target
583
- const targetVM = this.componentsMap[targetComponentId]
584
- // 调用函数获取参数
585
- // eslint-disable-next-line no-eval
586
- const paramFunction = eval('(' + eachEvent.runFunctionParam + ')')
587
- const params = paramFunction(vm, data)
588
- // 执行
589
- targetVM[eachEvent.eventType](...params)
590
- lowcodeLog(
591
- JSON.stringify(data),
592
- '执行目标方法完成',
593
- eachEvent.eventType,
594
- false,
595
- true
596
- )
597
- }
598
- })
599
- },
600
- // 组件闪烁
601
- twink (id) {
602
- // 如果组件不在本层渲染器,则向下递归
603
- if (this.$refs[id] === undefined || this.$refs[id].length === 0) {
604
- if (this.$refs.sub) {
605
- this.$refs.sub[0].twink(id)
606
- }
607
- } else {
608
- const _this = this
609
- // 将之前闪烁的组件还原,避免在classname赋值以后打断动画,样式被保留
610
- if (this.twinkBefore) {
611
- this.twinkBefore.className = ''
612
- }
613
- this.twinkBefore = this.$refs[id][0]
614
- // 如果存在定时器则将之前的动画打断
615
- if (!this.twinkTimer) {
616
- this.twinkTimer = []
617
- } else {
618
- this.twinkTimer.forEach(timer => {
619
- clearTimeout(timer)
620
- })
621
- }
622
- // 定义关键帧间隔
623
- const frame = 400
624
- this.$refs[id][0].className = 'colWithBorder'
625
- for (let i = 1; i <= 3; i++) {
626
- const timer = setTimeout(() => {
627
- if (i % 2 !== 0) {
628
- _this.$refs[id][0].className = ''
629
- } else {
630
- _this.$refs[id][0].className = 'colWithBorder'
631
- }
632
- }, frame * i)
633
- this.twinkTimer.push(timer)
634
- }
635
- }
636
- }
637
- },
638
- watch: {
639
- pageConfig: {
640
- handler (newVal) {
641
- },
642
- deep: true
643
- }
644
- }
645
- }
646
- </script>
647
-
648
- <style scoped>
649
- .componentInEditor{
650
- border: none;
651
- }
652
- .componentInEditor:hover{
653
- border: 2px rgb( 24,144,255) solid;
654
- box-shadow: 3px 3px 5px 1px rgba(0,0,0,0.2);
655
- }
656
- .colWithBorder{
657
- border: 2px rgb( 24,144,255) solid;
658
- box-shadow: 3px 3px 5px 1px rgba(0,0,0,0.2);
659
- }
660
- .container{
661
- display: flex;
662
- flex-direction: column;
663
- align-items: center;
664
- justify-content: space-evenly;
665
- width: calc(100% - 6px);
666
- height: 50vh;
667
- border: rgba( 24,144,255, 0.2) 2px solid;
668
- background-color: rgba(24, 144, 255, 0.05);
669
- }
670
- .selected_container{
671
- display: flex;
672
- flex-direction: column;
673
- align-items: center;
674
- justify-content: space-evenly;
675
- width: calc(100% - 6px);
676
- height: 50vh;
677
- border: rgba( 24,144,255, 0.2) 2px solid;
678
- background-color: rgba( 24,144,255, 0.2);
679
- }
680
- .colSpanSuit{
681
- color: green;
682
- font-size: 1.5em;
683
- }
684
- .colSpanNotSuit{
685
- color: red;
686
- font-size: 1.5em;
687
- }
688
- .dragDiv:hover{
689
- cursor: w-resize;
690
- z-index: 99999;
691
- }
692
-
693
- .propsNotFixedComponent {
694
- background-color: rgba(24, 144, 255, 0.05);
695
- border: rgba( 24,144,255, 0.2) 2px dashed;
696
- width: 100%;
697
- height: 300px;
698
- }
699
- </style>
1
+ <template>
2
+ <div style="width: 100%">
3
+ <template v-for="(page,pageIndex) in pageConfig.page">
4
+ <!-- 拖拽时显示的临时容器 -->
5
+ <template v-if="showDragSpan">
6
+ <div style="display: flex" :key="pageIndex">
7
+ <template v-for="item in dragConfig">
8
+ <div class="container" style="font-size: 1.5em" :key="item.id" :style="'width:' + item.width + 'px'">
9
+ 宽度:{{ item.span }}
10
+ </div>
11
+ </template>
12
+ </div>
13
+ </template>
14
+ <!-- 渲染器主体 -->
15
+ <template v-for="(row,rowIndex) in page.body">
16
+ <a-row
17
+ :key="pageIndex + '_' + rowIndex"
18
+ type="flex"
19
+ :justify="row.config.justify"
20
+ :gutter="row.config.gutter"
21
+ :align="row.config.align">
22
+ <template v-if="!showDragSpan">
23
+ <template v-for="(item, itemIndex) in row.body">
24
+ <a-col :span="item.span" :key="item.id">
25
+ <!-- 显示容器 -->
26
+ <div
27
+ v-if="item.type === 'container' && editMode"
28
+ style="display: flex;align-items: center"
29
+ @click="clickComponentInEditor(item)">
30
+ <div :class="item.selected ? 'selected_container' : 'container'">
31
+ <div>
32
+ <p style="font-size: 1.5em">宽度:{{ item.span }}</p>
33
+ </div>
34
+ <div>
35
+ <a-button @click.stop="handelContainerDelete(item.id, pageIndex)">删除</a-button>
36
+ </div>
37
+ </div>
38
+ <div
39
+ v-if="itemIndex !== row.body.length - 1"
40
+ style="width: 6px;font-size: 1em;color: rgb( 24,144,255)"
41
+ class="dragDiv"
42
+ @mousedown="dragStart($event, item.id, row)">
43
+ || <br> ||
44
+ </div>
45
+ </div>
46
+ <!-- 递归显示页面容器 -->
47
+ <div
48
+ v-else-if="item.type === 'container_page'"
49
+ style="display: flex;align-items: center">
50
+ <LowCodeRender
51
+ ref="sub"
52
+ :is-root="false"
53
+ @showDraw="handelSubShowDraw"
54
+ @showModal="handelSubShowModal"
55
+ v-if="renderSub"
56
+ @spanDrag="handleDrag"
57
+ @containerDelete="handleContainerDelete"
58
+ @clickComponentInEditor="clickComponentInner"
59
+ :page-config="item"
60
+ :edit-mode="editMode"/>
61
+ <div
62
+ v-if="itemIndex !== row.body.length - 1"
63
+ style="width: 6px;font-size: 1em;color: rgb( 24,144,255);"
64
+ class="dragDiv"
65
+ @mousedown="dragStart($event, item.id, row)">
66
+ || <br> ||
67
+ </div>
68
+ </div>
69
+ <!-- 页面渲染 / 编辑模式中,将弹框或抽屉中的内容渲染为页面 -->
70
+ <div :ref="item.id" :id="item.id" v-else-if="editMode || (page.type !== 'modal' && page.type !== 'draw')">
71
+ <div
72
+ @click="clickComponentInEditor(item)"
73
+ :class=" editMode ? 'componentInEditor' : '' ">
74
+ <component
75
+ v-if="checkComponentRequiredProps(item.type, item.props)"
76
+ :lifeCycleFunction="resolveLifeCycleEvent(item)"
77
+ :is="resolveComponentType(item.type, item.id)"
78
+ :propsData="{...item.props}"
79
+ @componentDidMounted="componentDidMounted"
80
+ @onEvent="handleEvent"
81
+ :mixinComponentId="item.id"/>
82
+ <div v-else class="propsNotFixedComponent">
83
+ <p style="line-height: 200px; text-align: center; font-size: 2em; margin: 0">{{ item.type }}</p>
84
+ <p style="text-align: center; font-size: 1.2em">必填参数未设置完全!暂停渲染</p>
85
+ </div>
86
+ </div>
87
+ </div>
88
+ </a-col>
89
+ </template>
90
+ </template>
91
+ </a-row>
92
+ </template>
93
+ </template>
94
+ <!-- 弹框渲染 -->
95
+ <template v-for="(modal, modalIndex) in pageConfig.page.filter(page => page.type === 'modal')">
96
+ <a-modal
97
+ :key="'modalIndex_' + modalIndex"
98
+ :title="modal.title"
99
+ :width="modal.width"
100
+ :dialog-style="{ top: '5rem' }"
101
+ :visible="modalVisible[modal.id]"
102
+ :z-index="1003"
103
+ :maskClosable="false"
104
+ @cancel="closeModalOrDraw(modal.id, 'modal')"
105
+ :destroyOnClose="true">
106
+ <template v-for="(row, rowIndex) in modal.body">
107
+ <template v-for="(item, itemIndex) in row.body">
108
+ <component
109
+ v-if="checkComponentRequiredProps(item.type, item.props)"
110
+ :lifeCycleFunction="resolveLifeCycleEvent(item)"
111
+ :key="'modalItem_' + rowIndex + '_' + itemIndex"
112
+ :is="resolveComponentType(item.type)"
113
+ :propsData="{...item.props, showModalOrDraw: false}"
114
+ @componentDidMounted="componentDidMounted"
115
+ @onEvent="handleEvent"
116
+ :mixinComponentId="item.id"/>
117
+ <div v-else :key="'modalItem_' + rowIndex + '_' + itemIndex" class="propsNotFixedComponent">
118
+ <p style="line-height: 200px; text-align: center; font-size: 2em; margin: 0">{{ item.type }}</p>
119
+ <p style="text-align: center; font-size: 1.2em">必填参数未设置完全!暂停渲染</p>
120
+ </div>
121
+ </template>
122
+ </template>
123
+ </a-modal>
124
+ </template>
125
+ <!-- 抽屉渲染 -->
126
+ <template v-for="(draw, drawIndex) in pageConfig.page.filter(page => page.type === 'draw')">
127
+ <a-drawer
128
+ :key="'drawIndex_' + drawIndex"
129
+ :title="draw.title"
130
+ :width="draw.width"
131
+ :visible="drawVisible[draw.id]"
132
+ :z-index="1003"
133
+ @close="closeModalOrDraw(draw.id, 'draw')"
134
+ :destroyOnClose="true">
135
+ <template v-for="(row, rowIndex) in draw.body">
136
+ <template v-for="(item, itemIndex) in row.body">
137
+ <component
138
+ v-if="checkComponentRequiredProps(item.type, item.props)"
139
+ :lifeCycleFunction="resolveLifeCycleEvent(item)"
140
+ :key="'drawItem_' + rowIndex + '_' + itemIndex"
141
+ :is="resolveComponentType(item.type)"
142
+ :propsData="{...item.props, showModalOrDraw: false}"
143
+ @componentDidMounted="componentDidMounted"
144
+ @onEvent="handleEvent"
145
+ :mixinComponentId="item.id"/>
146
+ <div v-else :key="'drawItem_' + rowIndex + '_' + itemIndex" class="propsNotFixedComponent">
147
+ <p style="line-height: 200px; text-align: center; font-size: 2em; margin: 0">{{ item.type }}</p>
148
+ <p style="text-align: center; font-size: 1.2em">必填参数未设置完全!暂停渲染</p>
149
+ </div>
150
+ </template>
151
+ </template>
152
+ </a-drawer>
153
+ </template>
154
+ </div>
155
+ </template>
156
+
157
+ <script>
158
+ // eslint-disable-next-line no-unused-vars
159
+ import Vue from 'vue'
160
+ import * as allComponents from '@vue2-client/utils/lowcode/registerComponentForRender'
161
+ import lowcodeLog from '@vue2-client/utils/lowcode/lowcodeLog'
162
+ import * as lowcodeUtils from '@vue2-client/utils/lowcode/lowcodeUtils'
163
+ import { runLogic } from '@vue2-client/services/api/common'
164
+
165
+ export default {
166
+ name: 'LowCodeRender',
167
+ props: {
168
+ // 页面配置
169
+ pageConfig: {
170
+ type: Object,
171
+ required: true
172
+ },
173
+ // 是否为编辑模式
174
+ editMode: {
175
+ type: Boolean,
176
+ default: true
177
+ },
178
+ // 用于标识渲染器是否为顶级渲染器
179
+ // 非顶级渲染器在控制弹框、抽屉显隐的时候需要emit而不是修改值
180
+ isRoot: {
181
+ type: Boolean,
182
+ default: true
183
+ }
184
+ },
185
+ data () {
186
+ return {
187
+ // 传递给组件的Props合集
188
+ propsData: {},
189
+ // 是否为拖拽模式
190
+ showDragSpan: false,
191
+ // 拖拽的缓存
192
+ dragConfig: [],
193
+ // 记录拖拽位移单位量
194
+ beforeSpanThrough: -1,
195
+ // 记录拖拽之前的span
196
+ originalSpan: -1,
197
+ // 记录拖拽目标下一个元素的原始span
198
+ nextOriginalSpan: -1,
199
+ // 弹框显示集合
200
+ modalVisible: {},
201
+ // 抽屉显示集合
202
+ drawVisible: {},
203
+ // 控制递归渲染
204
+ renderSub: true,
205
+ // 用于控制组件外框闪烁
206
+ colClassName: '',
207
+ // 控制容器渲染,用于递归时,刷新递归中容器的状态
208
+ showContainer: true,
209
+ // 控制闪烁的定时器
210
+ twinkTimer: undefined,
211
+ // 缓存正在闪烁的组件,用于还原状态
212
+ twinkBefore: undefined
213
+ }
214
+ },
215
+ inject: [
216
+ 'componentsMap'
217
+ ],
218
+ mounted () {
219
+ // 初始化控制弹框和抽屉的变量合集
220
+ this.pageConfig.page.forEach(page => {
221
+ if (page.type === 'modal') {
222
+ this.modalVisible[page.id] = false
223
+ } else if (page.type === 'draw') {
224
+ this.drawVisible[page.id] = false
225
+ }
226
+ })
227
+ },
228
+ methods: {
229
+ // 检查组件必要的props是否全部满足
230
+ checkComponentRequiredProps (type, props) {
231
+ if (type === 'container') {
232
+ return true
233
+ }
234
+ const propertiesDef = lowcodeUtils.getEditorConfigByType(type).properties
235
+ const defKeys = Object.keys(propertiesDef)
236
+ const requiredProps = []
237
+ defKeys.forEach(key => {
238
+ if (propertiesDef[key].required) {
239
+ requiredProps.push(key)
240
+ }
241
+ })
242
+ for (let i = 0; i < requiredProps.length; i++) {
243
+ const eachRequired = requiredProps[i]
244
+ if (props[eachRequired] === undefined || props[eachRequired] === '' || props[eachRequired] === null) {
245
+ return false
246
+ }
247
+ }
248
+ return true
249
+ },
250
+ // 用于控制递归渲染器中的修改抽屉显隐
251
+ handelSubShowDraw (id, visible) {
252
+ this.drawVisible[id] = visible === 'open'
253
+ this.$forceUpdate()
254
+ lowcodeLog(
255
+ id,
256
+ '修改抽屉可见性',
257
+ visible === 'open' ? '可见' : '隐藏',
258
+ false,
259
+ true
260
+ )
261
+ },
262
+ // 用于控制递归渲染器中的修改弹框显隐
263
+ handelSubShowModal (id, visible) {
264
+ this.modalVisible[id] = visible === 'open'
265
+ this.$forceUpdate()
266
+ lowcodeLog(
267
+ id,
268
+ '修改弹窗可见性',
269
+ visible === 'open' ? '可见' : '隐藏',
270
+ false,
271
+ true
272
+ )
273
+ },
274
+ // 将钩子函数格式化成mixin的格式并传入
275
+ resolveLifeCycleEvent (config) {
276
+ if (!config.onEvent || !config.onEvent.lifeCycle) {
277
+ return undefined
278
+ } else {
279
+ const result = []
280
+ const lifeCycle = config.onEvent.lifeCycle
281
+ lifeCycle.forEach(item => {
282
+ result.push({
283
+ lifeCycleName: item.lifeCycle,
284
+ functionStr: item.LifeCycleFunction
285
+ })
286
+ })
287
+ return result
288
+ }
289
+ },
290
+ // 关闭弹窗或抽屉
291
+ closeModalOrDraw (id, type) {
292
+ if (type === 'modal') {
293
+ this.modalVisible[id] = false
294
+ } else if (type === 'draw') {
295
+ this.drawVisible[id] = false
296
+ }
297
+ this.$forceUpdate()
298
+ },
299
+ // 递归拖拽完成后的回调
300
+ handleDrag (targetEle, nextEle) {
301
+ this.$emit('spanDrag', targetEle, nextEle)
302
+ },
303
+ // 递归容器删除后的回调
304
+ handleContainerDelete (id) {
305
+ this.$emit('containerDelete', id)
306
+ },
307
+ // 刷新递归的渲染器
308
+ refreshSubRender () {
309
+ this.renderSub = false
310
+ this.$nextTick(() => {
311
+ this.renderSub = true
312
+ })
313
+ },
314
+ // 刷新递归容器
315
+ refreshSubContainer () {
316
+ this.showContainer = false
317
+ this.$nextTick(() => {
318
+ this.showContainer = true
319
+ })
320
+ },
321
+ // 递归点击组件后的回调
322
+ clickComponentInner (configItem) {
323
+ this.$emit('clickComponentInEditor', configItem, this)
324
+ },
325
+ // 拖拽改变Span
326
+ dragStart (event, id, row) {
327
+ // 获取目标html元素
328
+ const targetElement = event.srcElement
329
+ // 获取外层元素用于计算总宽度
330
+ const outerElement = targetElement.parentNode.parentNode.parentNode
331
+ const outerWidth = outerElement.offsetWidth
332
+ // 计算每一个span对应的像素
333
+ const outerSpanWidth = outerWidth / 24
334
+
335
+ // 记录初始X
336
+ const startX = event.clientX
337
+
338
+ // 记录兄弟元素
339
+ const targetElementBros = outerElement.childNodes
340
+
341
+ let targetComponent
342
+ let targetNextComponent
343
+
344
+ // 缓存拖拽组件,用于显示拖拽时的实时Span,拖拽完成后再统一赋值
345
+ this.dragConfig = []
346
+ for (let i = 0; i < row.body.length; i++) {
347
+ this.dragConfig.push({
348
+ id: row.body[i].id,
349
+ span: row.body[i].span,
350
+ width: targetElementBros[i].offsetWidth
351
+ })
352
+ }
353
+
354
+ this.showDragSpan = true
355
+
356
+ // 保存目标容器,和目标的下一个容器,用于改变宽度
357
+ for (let i = 0; i < this.dragConfig.length; i++) {
358
+ const item = this.dragConfig[i]
359
+ if (item.id === id) {
360
+ targetComponent = this.dragConfig[i]
361
+ targetNextComponent = this.dragConfig[i + 1]
362
+ }
363
+ }
364
+
365
+ // 如果鼠标之后没有组件,禁止移动
366
+ if (!targetComponent || !targetNextComponent) {
367
+ this.$message.error('单个组件无法移动!')
368
+ this.showDragSpan = false
369
+ return
370
+ }
371
+
372
+ // 保存原始的像素宽度
373
+ const orignalTargetWidth = targetComponent.width
374
+ const orignalTargetNextWidth = targetNextComponent.width
375
+
376
+ // 保存原始的span
377
+ this.originalSpan = targetComponent.span
378
+ this.nextOriginalSpan = targetNextComponent.span
379
+
380
+ // 拖拽事件
381
+ const onDrag = (e) => {
382
+ // 计算出移动的像素数
383
+ let deltaX = e.clientX - startX
384
+ // 判断移动方向
385
+ let direction = 1
386
+ if (deltaX < 0) {
387
+ direction = -1
388
+ deltaX = 0 - deltaX
389
+ }
390
+
391
+ // 根据移动像素数计算出移动了多少个span
392
+ const throughSpanNum = Math.floor(deltaX / outerSpanWidth)
393
+ if (this.beforeSpanThrough === -1) {
394
+ this.beforeSpanThrough = throughSpanNum
395
+ }
396
+
397
+ // 将移动的距离更新到临时显示的span中
398
+ if (direction > 0) {
399
+ targetComponent.width = orignalTargetWidth + deltaX
400
+ targetNextComponent.width = orignalTargetNextWidth - deltaX
401
+ if (this.beforeSpanThrough !== throughSpanNum) {
402
+ this.beforeSpanThrough = throughSpanNum
403
+ targetComponent.span = this.originalSpan + throughSpanNum
404
+ targetNextComponent.span = this.nextOriginalSpan - throughSpanNum
405
+ }
406
+ } else {
407
+ targetComponent.width = orignalTargetWidth - deltaX
408
+ targetNextComponent.width = orignalTargetNextWidth + deltaX
409
+ if (this.beforeSpanThrough !== throughSpanNum) {
410
+ this.beforeSpanThrough = throughSpanNum
411
+ targetComponent.span = this.originalSpan - throughSpanNum
412
+ targetNextComponent.span = this.nextOriginalSpan + throughSpanNum
413
+ }
414
+ }
415
+ }
416
+
417
+ // 拖拽结束
418
+ const dragEnd = (e) => {
419
+ // 解绑事件,更新数据
420
+ this.showDragSpan = false
421
+ document.removeEventListener('mouseup', dragEnd)
422
+ document.removeEventListener('mousemove', onDrag)
423
+ this.$emit('spanDrag', targetComponent, targetNextComponent)
424
+ }
425
+
426
+ // 绑定拖拽事件和结束事件
427
+ document.addEventListener('mouseup', dragEnd)
428
+ document.addEventListener('mousemove', onDrag)
429
+ },
430
+ // 解析配置中的type,找出对应的渲染器
431
+ resolveComponentType (type, componentId) {
432
+ // 从组件注册中拿到所有注册的组件
433
+ const allComponentKeys = Object.keys(allComponents)
434
+ for (let i = 0; i < allComponentKeys.length; i++) {
435
+ const keyStr = allComponentKeys[i].toString()
436
+ if (type === keyStr) {
437
+ return allComponents[keyStr]
438
+ }
439
+ }
440
+ },
441
+ // mixin中组件mounted后的回调
442
+ componentDidMounted (vm, id) {
443
+ // 将组件注册到全局的Map中
444
+ if (vm && id) {
445
+ this.componentsMap[id] = vm
446
+ }
447
+ // 如果组件中有props,将其挨个set到vm中
448
+ const config = lowcodeUtils.getComponentConfig(id, this.pageConfig)
449
+ const keys = Object.keys(config.props)
450
+ keys.forEach(key => {
451
+ if (config.props[key] !== undefined && config.props[key] !== '') {
452
+ Vue.set(vm, key, config.props[key])
453
+ }
454
+ })
455
+ },
456
+ // 点击组件
457
+ clickComponentInEditor (configItem) {
458
+ this.$emit('clickComponentInEditor', configItem, this)
459
+ },
460
+ // 删除容器
461
+ handelContainerDelete (id, pageIndex) {
462
+ this.$emit('containerDelete', id, pageIndex)
463
+ },
464
+ // 处理组件的事件
465
+ handleEvent (data, eventTiggerType, id) {
466
+ // 找到目标对象的配置
467
+ const targetConfig = lowcodeUtils.getComponentConfig(id, this.pageConfig.page)
468
+ // 找到目标对象对应触发事件的配置
469
+ const eventConfigs = targetConfig.onEvent[eventTiggerType]
470
+
471
+ if (!eventConfigs) {
472
+ return
473
+ }
474
+
475
+ const vm = this.componentsMap[id]
476
+ lowcodeLog(
477
+ ` 事件数据:${data} \n 源组件: ${id}`,
478
+ '触发事件',
479
+ eventTiggerType,
480
+ true
481
+ )
482
+
483
+ let targetComponentId = ''
484
+
485
+ // 遍历该类型触发事件,挨个执行
486
+ eventConfigs.forEach(eachEvent => {
487
+ lowcodeLog(
488
+ ` 事件数据:${data} \n 目标组件: ${targetComponentId}`,
489
+ '开始遍历执行事件',
490
+ eachEvent.eventType,
491
+ false
492
+ )
493
+ // 修改弹窗显隐
494
+ if (eachEvent.eventType === 'showDraw') {
495
+ // 如果不是顶级渲染器,则向外抛出事件
496
+ if (!this.isRoot) {
497
+ this.$emit('showDraw', eachEvent.containerId, eachEvent.visible)
498
+ } else {
499
+ this.drawVisible[eachEvent.containerId] = eachEvent.visible === 'open'
500
+ this.$forceUpdate()
501
+ lowcodeLog(
502
+ eachEvent.containerId,
503
+ '修改抽屉可见性',
504
+ eachEvent.visible === 'open' ? '可见' : '隐藏',
505
+ false,
506
+ true
507
+ )
508
+ }
509
+ } else if (eachEvent.eventType === 'showModal') {
510
+ // 修改抽屉显隐
511
+ // 如果不是顶级渲染器,则向外抛出事件
512
+ if (!this.isRoot) {
513
+ this.$emit('showModal', eachEvent.containerId, eachEvent.visible)
514
+ } else {
515
+ this.modalVisible[eachEvent.containerId] = eachEvent.visible === 'open'
516
+ this.$forceUpdate()
517
+ lowcodeLog(
518
+ eachEvent.containerId,
519
+ '修改弹窗可见性',
520
+ eachEvent.visible === 'open' ? '可见' : '隐藏',
521
+ false,
522
+ true
523
+ )
524
+ }
525
+ } else if (eachEvent.eventType === 'customJSFunction') {
526
+ const targetVM = this.componentsMap[eachEvent.target]
527
+ // eslint-disable-next-line no-eval
528
+ const customFunction = eval('(' + eachEvent.JSFunction + ')')
529
+ customFunction(eachEvent.eventType, data, targetVM, vm)
530
+ lowcodeLog(
531
+ undefined,
532
+ '执行自定义函数完成',
533
+ undefined,
534
+ false,
535
+ true
536
+ )
537
+ } else if (eachEvent.eventType === 'runLogic') {
538
+ // 运行Logic
539
+ // eslint-disable-next-line no-eval
540
+ const logicCallBackFunction = eval('(' + eachEvent.logicCallBackFunction + ')')
541
+ // eslint-disable-next-line no-eval
542
+ const logicParamFunction = eval('(' + eachEvent.logicParamFunction + ')')
543
+ // 将需要的组件变量组织好,并传递给函数
544
+ const componentData = {}
545
+ const allComponents = Object.keys(this.componentsMap)
546
+ allComponents.forEach(component => {
547
+ componentData[component] = this.componentsMap[component].dataForLowCode
548
+ })
549
+ const param = logicParamFunction(componentData, data)
550
+ lowcodeLog(
551
+ JSON.stringify(param),
552
+ '执行Logic',
553
+ eachEvent.logicName,
554
+ false,
555
+ true
556
+ )
557
+ runLogic(eachEvent.logicName, param, eachEvent.serviceName)
558
+ .then(res => { logicCallBackFunction(this.componentsMap, res) })
559
+ } else if (eachEvent.eventType === 'changeProps') {
560
+ // 修改组件props
561
+ const targetConfig = lowcodeUtils.getComponentConfig(eachEvent.target, this.pageConfig.page)
562
+ targetConfig.props[eachEvent.targetKey] = data
563
+ lowcodeLog(
564
+ `目标key:${eachEvent.targetKey},新的值:${JSON.stringify(data)}`,
565
+ '修改Props',
566
+ targetConfig.id,
567
+ false,
568
+ true
569
+ )
570
+ } else if (eachEvent.eventType === 'log') {
571
+ // 打印日志
572
+ lowcodeLog(
573
+ JSON.stringify(data),
574
+ '打印日志',
575
+ targetConfig.id,
576
+ false,
577
+ true
578
+ )
579
+ } else if (eachEvent.eventType === 'runFunction') {
580
+ // 修改组件的值
581
+ // 寻找target
582
+ targetComponentId = eachEvent.target
583
+ const targetVM = this.componentsMap[targetComponentId]
584
+ // 调用函数获取参数
585
+ // eslint-disable-next-line no-eval
586
+ const paramFunction = eval('(' + eachEvent.runFunctionParam + ')')
587
+ const params = paramFunction(vm, data)
588
+ // 执行
589
+ targetVM[eachEvent.eventType](...params)
590
+ lowcodeLog(
591
+ JSON.stringify(data),
592
+ '执行目标方法完成',
593
+ eachEvent.eventType,
594
+ false,
595
+ true
596
+ )
597
+ }
598
+ })
599
+ },
600
+ // 组件闪烁
601
+ twink (id) {
602
+ // 如果组件不在本层渲染器,则向下递归
603
+ if (this.$refs[id] === undefined || this.$refs[id].length === 0) {
604
+ if (this.$refs.sub) {
605
+ this.$refs.sub[0].twink(id)
606
+ }
607
+ } else {
608
+ const _this = this
609
+ // 将之前闪烁的组件还原,避免在classname赋值以后打断动画,样式被保留
610
+ if (this.twinkBefore) {
611
+ this.twinkBefore.className = ''
612
+ }
613
+ this.twinkBefore = this.$refs[id][0]
614
+ // 如果存在定时器则将之前的动画打断
615
+ if (!this.twinkTimer) {
616
+ this.twinkTimer = []
617
+ } else {
618
+ this.twinkTimer.forEach(timer => {
619
+ clearTimeout(timer)
620
+ })
621
+ }
622
+ // 定义关键帧间隔
623
+ const frame = 400
624
+ this.$refs[id][0].className = 'colWithBorder'
625
+ for (let i = 1; i <= 3; i++) {
626
+ const timer = setTimeout(() => {
627
+ if (i % 2 !== 0) {
628
+ _this.$refs[id][0].className = ''
629
+ } else {
630
+ _this.$refs[id][0].className = 'colWithBorder'
631
+ }
632
+ }, frame * i)
633
+ this.twinkTimer.push(timer)
634
+ }
635
+ }
636
+ }
637
+ },
638
+ watch: {
639
+ pageConfig: {
640
+ handler (newVal) {
641
+ },
642
+ deep: true
643
+ }
644
+ }
645
+ }
646
+ </script>
647
+
648
+ <style scoped>
649
+ .componentInEditor{
650
+ border: none;
651
+ }
652
+ .componentInEditor:hover{
653
+ border: 2px rgb( 24,144,255) solid;
654
+ box-shadow: 3px 3px 5px 1px rgba(0,0,0,0.2);
655
+ }
656
+ .colWithBorder{
657
+ border: 2px rgb( 24,144,255) solid;
658
+ box-shadow: 3px 3px 5px 1px rgba(0,0,0,0.2);
659
+ }
660
+ .container{
661
+ display: flex;
662
+ flex-direction: column;
663
+ align-items: center;
664
+ justify-content: space-evenly;
665
+ width: calc(100% - 6px);
666
+ height: 50vh;
667
+ border: rgba( 24,144,255, 0.2) 2px solid;
668
+ background-color: rgba(24, 144, 255, 0.05);
669
+ }
670
+ .selected_container{
671
+ display: flex;
672
+ flex-direction: column;
673
+ align-items: center;
674
+ justify-content: space-evenly;
675
+ width: calc(100% - 6px);
676
+ height: 50vh;
677
+ border: rgba( 24,144,255, 0.2) 2px solid;
678
+ background-color: rgba( 24,144,255, 0.2);
679
+ }
680
+ .colSpanSuit{
681
+ color: green;
682
+ font-size: 1.5em;
683
+ }
684
+ .colSpanNotSuit{
685
+ color: red;
686
+ font-size: 1.5em;
687
+ }
688
+ .dragDiv:hover{
689
+ cursor: w-resize;
690
+ z-index: 99999;
691
+ }
692
+
693
+ .propsNotFixedComponent {
694
+ background-color: rgba(24, 144, 255, 0.05);
695
+ border: rgba( 24,144,255, 0.2) 2px dashed;
696
+ width: 100%;
697
+ height: 300px;
698
+ }
699
+ </style>