vue2-client 1.8.239 → 1.8.241

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 +192 -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 +98 -98
  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 +408 -408
  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 +346 -346
  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 +355 -386
  44. package/src/base-client/components/common/LowCodePageRender/LowCodePageRender.vue +29 -29
  45. package/src/base-client/components/common/LowCodePageRender/editorPageRender.vue +467 -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 +92 -92
  54. package/src/base-client/components/common/XAddNativeForm/XAddNativeForm.vue +729 -729
  55. package/src/base-client/components/common/XAddNativeForm/index.md +146 -146
  56. package/src/base-client/components/common/XAddNativeForm/lowcodeEditorRegister.js +12 -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 +1 -3
  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 +256 -256
  74. package/src/base-client/components/common/XForm/XFormItem.vue +766 -761
  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 +242 -242
  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 +12 -12
  87. package/src/base-client/components/common/XImportExcel/XImportExcel.vue +147 -147
  88. package/src/base-client/components/common/XReport/XReport.vue +837 -837
  89. package/src/base-client/components/common/XReport/XReportDemo.vue +2225 -2225
  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 +742 -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 +320 -320
  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 +9 -9
  107. package/src/base-client/components/index.js +47 -47
  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 +1285 -1288
  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 +78 -78
  195. package/src/utils/lowcode/lowcodeLog.js +29 -29
  196. package/src/utils/lowcode/lowcodeUtils.js +129 -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 +231 -231
  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,1288 +1,1285 @@
1
- <template>
2
- <div>
3
- <!-- 标题 -->
4
- <a-card>
5
- <a-page-header
6
- title="奥枫低代码前端编辑器"
7
- sub-title="af-lowcode"
8
- :backIcon="false"
9
- @back="() => null"
10
- >
11
- <template slot="extra">
12
- <a-button @click="test">测试</a-button>
13
- <a-button @click="editModeActive">编辑</a-button>
14
- <a-button @click="previewModeActive">预览</a-button>
15
- <a-button type="primary" @click="exportConfig">导出</a-button>
16
- </template>
17
- </a-page-header>
18
- </a-card>
19
- <!-- 预览模式 -->
20
- <a-card v-if="preview">
21
- <editor-page-render :page-config="config" :edit-mode="false"/>
22
- </a-card>
23
- <!-- 编辑模式 -->
24
- <div v-show="!preview">
25
- <a-row :gutter="2">
26
- <!-- 左侧 -->
27
- <a-col :span="4">
28
- <a-card>
29
- <a-tabs>
30
- <a-tab-pane key="1" tab="UI库">
31
- <!-- UI库 -->
32
- <a-card style="margin-bottom: 5%">
33
- <!-- 所有组件 -->
34
- <a-card-grid class="ui-item" @click="addContainer">
35
- 组件容器
36
- </a-card-grid>
37
- <template v-for="(item, index) in getRegisteredComponents()">
38
- <a-card-grid :key="index" class="ui-item" @click="addComponentToContainer(item)">
39
- {{ item }}
40
- </a-card-grid>
41
- </template>
42
- </a-card>
43
- </a-tab-pane>
44
- <a-tab-pane key="2" tab="架构">
45
- <!-- 页面架构 -->
46
- <a-card style="margin-bottom: 3%">
47
- <LowCodePageOrganization
48
- :config="config"
49
- v-if="showPageOrganization"
50
- @renamePage="renamePage"
51
- @pasteItem="handlePasteItem"
52
- @componentMove="handleTreeDrag"
53
- @deleteComponent="deleteComponentInTree"
54
- @treeOrganizationClick="treeOrganizationClick"
55
- @addComponent="handleAddComponent"/>
56
- </a-card>
57
- </a-tab-pane>
58
- </a-tabs>
59
- </a-card>
60
- </a-col>
61
- <!-- 中间主体编辑器 -->
62
- <a-col :span="15">
63
- <a-card>
64
- <!-- 切换显示的组件 -->
65
- <div style="margin-bottom: 3%">
66
- <a-menu v-model="mainPageMenu" mode="horizontal" @click="handleMainPageMenuChange">
67
- <template v-for="(page) in config.page">
68
- <a-menu-item :key="page.id">{{ page.title + '(' + determinePageType(page.type) + ')' }}</a-menu-item>
69
- </template>
70
- </a-menu>
71
- </div>
72
- <!-- 渲染器 -->
73
- <div v-if="activeMainPageType === 'page'">
74
- <editor-page-render
75
- v-if="renderPreview"
76
- @spanDrag="handleDrag"
77
- @containerDelete="handleContainerDelete"
78
- @clickComponentInEditor="clickComponentInEditor"
79
- :page-config="{ data: config.data, page: config.page.filter(page => page.id === activeMainPage)}"/>
80
- <a-skeleton v-else/>
81
- </div>
82
- <div v-if="activeMainPageType === 'modal'">
83
- <editor-page-render
84
- v-if="renderModalPreview"
85
- @spanDrag="handleDrag"
86
- @containerDelete="handleContainerDelete"
87
- @clickComponentInEditor="clickComponentInEditor"
88
- :page-config="{ data: config.data, page: config.page.filter(page => page.id === activeMainPage)}"/>
89
- <a-skeleton v-else/>
90
- </div>
91
- <div v-if="activeMainPageType === 'draw'">
92
- <editor-page-render
93
- v-if="renderDrawPreview"
94
- @spanDrag="handleDrag"
95
- @containerDelete="handleContainerDelete"
96
- @clickComponentInEditor="clickComponentInEditor"
97
- :page-config="{ data: config.data, page: config.page.filter(page => page.id === activeMainPage)}"/>
98
- <a-skeleton v-else/>
99
- </div>
100
- </a-card>
101
- </a-col>
102
- <!-- 右侧 -->
103
- <a-col :span="5">
104
- <!-- 属性编辑 -->
105
- <a-card>
106
- <template v-if="editorPropertiesConfig === 'unregistered'">
107
- <p>所选组件并未注册</p>
108
- </template>
109
- <template v-else>
110
- <!-- 组件ID -->
111
- <div v-if="editorPropertiesConfig.id">
112
- <a-statistic title="组件ID" :value="editorPropertiesConfig.id" valueStyle="font-size: 1.2em"/>
113
- </div>
114
- <!-- 切换 -->
115
- <a-menu v-model="editorPanelCurrent" mode="horizontal" @click="() => null">
116
- <a-menu-item key="properties">属性</a-menu-item>
117
- <a-menu-item key="events">事件</a-menu-item>
118
- </a-menu>
119
- <!-- 属性编辑 -->
120
- <div v-if="editorPanelCurrent[0] === 'properties'">
121
- <div v-if="editorPropertiesConfig.props !== undefined">
122
- <div>
123
- 栅格数:<a-input :default-value="editorPropertiesConfig.span" @change="changeSpan"/>
124
- </div>
125
- <template v-for="(value,key) in editorPropertiesConfig.props">
126
- <div :key="editorPropertiesConfig.id + '_' + key">
127
- {{ key }}:<a-input :default-value="value" @change="editorPropertiesInputChange($event, key)"/>
128
- </div>
129
- </template>
130
- </div>
131
- <p v-else>您未选择任何组件</p>
132
- </div>
133
- <!-- 事件编辑 -->
134
- <div v-else-if="editorPanelCurrent[0] === 'events'">
135
- <template v-if="editorPropertiesConfig.onEvent !== undefined">
136
- <a-collapse v-model="eventCollapseActive">
137
- <a-collapse-panel
138
- v-for="(eventConfig,eventType) in editorPropertiesConfig.onEvent"
139
- :key="eventType"
140
- :header="eventType">
141
- <div v-for="(singleEvent,singleEventIndex) in eventConfig" :key="singleEventIndex" class="singleEvent">
142
- <p>
143
- <span style="color:rgb( 24,144,255)">{{ singleEvent.eventType }}</span>
144
- 事件
145
- </p>
146
- <!-- 事件 编辑/删除 按钮 -->
147
- <div style="display: flex; justify-content: space-evenly">
148
- <a-icon type="edit" theme="twoTone" class="edit_icon" @click="editEventIconClick(eventType,singleEventIndex)"/>
149
- <a-popconfirm title="确认删除" ok-text="确认删除" cancel-text="取消" @confirm="removeEventClick(eventType,singleEventIndex)" @cancel="() => null">
150
- <a-icon type="delete" theme="twoTone" class="edit_icon"/>
151
- </a-popconfirm>
152
- </div>
153
- </div>
154
- </a-collapse-panel>
155
- </a-collapse>
156
- </template>
157
- <a-button v-if="editorPropertiesConfig.id !== undefined" @click="addEvent">添加事件</a-button>
158
- <p v-else>您未选择任何组件</p>
159
- </div>
160
- </template>
161
- </a-card>
162
- </a-col>
163
- </a-row>
164
- </div>
165
- <!-- 自定义事件弹框 -->
166
- <a-modal
167
- title="事件编辑器"
168
- width="60%"
169
- :z-index="1001"
170
- :destroyOnClose="true"
171
- @ok="handleEventEditorOk"
172
- @cancel="handleEventEditorCancel"
173
- v-if="showEventEditor"
174
- :visible="showEventEditor">
175
- <a-form :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
176
- <!-- 事件触发类型 -->
177
- <a-form-item label="事件触发类型">
178
- <a-select @change="handleEventEditorTypeChange" :default-value="eventEditorContent.emitType">
179
- <a-select-option
180
- v-for="(eventType, eventTypeIndex) in editorPropertiesConfig.selfEvent"
181
- :key="eventTypeIndex"
182
- :value="eventType">
183
- {{ eventType }}
184
- </a-select-option>
185
- <a-select-option value="customEmitType">
186
- 自定义触发类型
187
- </a-select-option>
188
- </a-select>
189
- </a-form-item>
190
- <!-- 自定义事件触发类型 -->
191
- <a-form-item label="自定义事件触发名" v-if="eventEditorContent.emitType === 'customEmitType'">
192
- <a-input v-model="eventEditorContent.customEmitType"/>
193
- </a-form-item>
194
- <!-- 事件类型 -->
195
- <a-form-item label="事件类型">
196
- <a-select @change="handleEventEditorEventTypeChange" :default-value="eventEditorContent.eventType">
197
- <a-select-option value="changeValue">
198
- 修改组件的值
199
- </a-select-option>
200
- <a-select-option value="changeProps">
201
- 修改组件的Props
202
- </a-select-option>
203
- <a-select-option value="runLogic">
204
- 执行Logic
205
- </a-select-option>
206
- <a-select-option value="log">
207
- 打印日志
208
- </a-select-option>
209
- <a-select-option value="showModal" v-if="this.config.page.filter(page => page.type === 'modal').length > 0">
210
- 修改弹框可见
211
- </a-select-option>
212
- <a-select-option value="showDraw" v-if="this.config.page.filter(page => page.type === 'draw').length > 0">
213
- 修改抽屉可见
214
- </a-select-option>
215
- </a-select>
216
- </a-form-item>
217
- <!-- 修改弹框可见 or 修改抽屉可见 -->
218
- <a-form-item label="修改可见" v-if="eventEditorContent.eventType === 'showModal' || eventEditorContent.eventType === 'showDraw'">
219
- <a-radio-group v-model="eventEditorContent.visible" button-style="solid">
220
- <a-radio-button value="open">
221
- 显示
222
- </a-radio-button>
223
- <a-radio-button value="close">
224
- 隐藏
225
- </a-radio-button>
226
- </a-radio-group>
227
- </a-form-item>
228
- <!-- 弹框容器ID -->
229
- <a-form-item label="弹框容器ID" v-if="eventEditorContent.eventType === 'showModal'">
230
- <a-select v-model="eventEditorContent.containerId">
231
- <a-select-option
232
- v-for="(modal) in config.page.filter(page => page.type === 'modal')"
233
- :key="modal.id"
234
- :value="modal.id">
235
- 弹框_{{ modal.id }}
236
- </a-select-option>
237
- </a-select>
238
- </a-form-item>
239
- <!-- 抽屉容器ID -->
240
- <a-form-item label="弹框容器ID" v-if="eventEditorContent.eventType === 'showDraw'">
241
- <a-select v-model="eventEditorContent.containerId">
242
- <a-select-option
243
- v-for="(draw) in config.page.filter(page => page.type === 'draw')"
244
- :key="draw.id"
245
- :value="draw.id">
246
- 抽屉_{{ draw.id }}
247
- </a-select-option>
248
- </a-select>
249
- </a-form-item>
250
- <!-- Logic名 -->
251
- <a-form-item label="Logic名" v-if="eventEditorContent.eventType === 'runLogic'">
252
- <a-input v-model="eventEditorContent.logicName"/>
253
- </a-form-item>
254
- <!-- 服务名 -->
255
- <a-form-item label="服务名" v-if="eventEditorContent.eventType === 'runLogic'">
256
- <a-input v-model="eventEditorContent.serviceName"/>
257
- </a-form-item>
258
- <!-- 自定义Logic参数,由哪些组件传递 -->
259
- <a-form-item label="Logic参数取值组件" v-if="eventEditorContent.eventType === 'runLogic'">
260
- <a-transfer
261
- :data-source="logicParamTransferDataSource"
262
- :render="item => item.title"
263
- :target-keys="eventEditorContent.logicParamTransfer"
264
- @change="handleLogicParamTransferChange"/>
265
- </a-form-item>
266
- <!-- 自定义Logic参数 -->
267
- <a-form-item label="自定义Logic参数" v-if="eventEditorContent.eventType === 'runLogic'">
268
- <a-button type="primary" @click="openLogicParamJSEditor">
269
- 打开编辑器
270
- </a-button>
271
- </a-form-item>
272
- <!-- 自定义Logic回调 -->
273
- <a-form-item label="自定义Logic回调" v-if="eventEditorContent.eventType === 'runLogic'" >
274
- <a-button type="primary" @click="openLogicCallbackEditor">
275
- 打开编辑器
276
- </a-button>
277
- </a-form-item>
278
- <!-- 修改组件的值 才会显示的其余参数 -->
279
- <template v-if="eventEditorContent.eventType === 'changeValue' || eventEditorContent.eventType === 'changeProps'">
280
- <!-- 目标组件 -->
281
- <a-form-item label="目标组件">
282
- <a-select @change="handleEventEditorTargetChange" :default-value="eventEditorContent.target">
283
- <a-select-option
284
- v-for="(targetId, targetIndex) in getAllRenderedComponents()"
285
- :key="targetIndex"
286
- :value="targetId">
287
- {{ targetId }}
288
- </a-select-option>
289
- </a-select>
290
- </a-form-item>
291
- <!-- 目标组件执行事件名 -->
292
- <a-form-item label="目标组件执行事件名" v-if="eventEditorContent.eventName === 'changeValue'">
293
- <a-select @change="handleEventEditorTargetEventTypeChange" :default-value="eventEditorContent.eventName">
294
- <a-select-option :value="eventType" v-for="(eventType,eventTypeIndex) in supportedEventType" :key="'eventType_' + eventTypeIndex">
295
- {{ eventType }}
296
- </a-select-option>
297
- </a-select>
298
- </a-form-item>
299
- <!-- 目标组件修改值对应的key -->
300
- <a-form-item label="目标组件修改值对应的key" v-if="eventEditorContent.target !== undefined">
301
- <a-input v-model="eventEditorContent.targetKey"/>
302
- </a-form-item>
303
- </template>
304
- <!-- 自定义JS方法 -->
305
- <a-form-item label="自定义JS方法">
306
- <a-button type="primary" @click="openEventJSEditor">打开编辑器</a-button>
307
- </a-form-item>
308
- </a-form>
309
- </a-modal>
310
- <!-- 自定义JS事件弹框 -->
311
- <a-modal
312
- title="事件编辑器"
313
- width="60%"
314
- :destroyOnClose="true"
315
- :z-index="1002"
316
- @ok="handleJSEventEditorOk"
317
- @cancel="handleJSEventEditorCancel"
318
- :visible="showJSEventEditor">
319
- <a-popover title="参数说明" style="margin-right: 5%">
320
- <template slot="content">
321
- <p>该方法有以下几个参数:</p>
322
- <p>eventType:事件类型,比如:changeValue代表修改目标组件的值</p>
323
- <p>data:由事件源发出的参数列表</p>
324
- <p>targetKey:修改目标组件值所对应的key</p>
325
- <p>sourceVM:事件源的vue对象</p>
326
- <p>targetVM:目标的vue对象</p>
327
- </template>
328
- <a-button type="primary">
329
- 参数说明
330
- </a-button>
331
- </a-popover>
332
- <a-popover title="返回值说明" style="margin-bottom: 5%">
333
- <template slot="content">
334
- <p>该方法需要的返回值:</p>
335
- <p>eventType:事件类型</p>
336
- <p>data:传递给目标组件的数据</p>
337
- <p>targetKey:修改目标组件值所对应的key</p>
338
- </template>
339
- <a-button type="primary">
340
- 返回值说明
341
- </a-button>
342
- </a-popover>
343
- <code-mirror
344
- :style-obj="{height:'80%',fontSize:'18px',marginBottom:'15px'}"
345
- :mode="'javascript'"
346
- :theme="'monokai'"
347
- v-model="eventEditorContent.JSFunction"
348
- :value="eventEditorContent.JSFunction"/>
349
- </a-modal>
350
- <!-- 自定义Logic参数JS弹框 -->
351
- <a-modal
352
- title="自定义Logic参数JS编辑器"
353
- width="60%"
354
- :destroyOnClose="true"
355
- :z-index="1002"
356
- @ok="() => { showLogicParamJSEditor = false}"
357
- @cancel="() => { showLogicParamJSEditor = false}"
358
- :visible="showLogicParamJSEditor">
359
- <a-popover title="参数说明" style="margin-right: 5%">
360
- <template slot="content">
361
- <p>该方法有以下几个参数:</p>
362
- <p>componentData:Logic参数取值组件中选中的组件,将会把数据打包存在此对象中,key则为组件的id</p>
363
- <p>data:由事件源emit发出的参数</p>
364
- </template>
365
- <a-button type="primary">
366
- 参数说明
367
- </a-button>
368
- </a-popover>
369
- <a-popover title="返回值说明" style="margin-bottom: 5%">
370
- <template slot="content">
371
- <p>该方法需要一个JSON类型的返回值</p>
372
- <p>该返回值就是传递给Logic执行的参数</p>
373
- </template>
374
- <a-button type="primary">
375
- 返回值说明
376
- </a-button>
377
- </a-popover>
378
- <code-mirror
379
- :style-obj="{height:'80%',fontSize:'18px',marginBottom:'15px'}"
380
- :mode="'javascript'"
381
- :theme="'monokai'"
382
- v-model="eventEditorContent.logicParamJSFunction"
383
- :value="eventEditorContent.logicParamJSFunction"/>
384
- </a-modal>
385
- <!-- 自定义Logic回调弹框 -->
386
- <a-modal
387
- title="事件编辑器"
388
- width="60%"
389
- :destroyOnClose="true"
390
- :z-index="1002"
391
- @ok="() => { showLogicCallBackEditor = false}"
392
- @cancel="() => { showLogicCallBackEditor = false}"
393
- :visible="showLogicCallBackEditor">
394
- <a-popover title="参数说明" style="margin-bottom: 5%">
395
- <template slot="content">
396
- <p>该方法有以下几个参数:</p>
397
- <p>componentsMap:所有组件注册的Map</p>
398
- <p>responseData:后端的返回值</p>
399
- </template>
400
- <a-button type="primary">
401
- 参数说明
402
- </a-button>
403
- </a-popover>
404
- <code-mirror
405
- :style-obj="{height:'80%',fontSize:'18px',marginBottom:'15px'}"
406
- :mode="'javascript'"
407
- :theme="'monokai'"
408
- v-model="eventEditorContent.logicCallBackFunction"
409
- :value="eventEditorContent.logicCallBackFunction"/>
410
- </a-modal>
411
- </div>
412
- </template>
413
-
414
- <script>
415
- import editorPageRender from '@vue2-client/base-client/components/common/LowCodePageRender/editorPageRender.vue'
416
- import * as registeredRender from '@vue2-client/utils/lowcode/registerComponentForRender'
417
- import * as lowcodeUtils from '@vue2-client/utils/lowcode/lowcodeUtils'
418
- import codeMirror from '@vue2-client/components/CodeMirror/inedx.vue'
419
- import { nanoid } from 'nanoid'
420
- import lowcodeComponentMixin from '@vue2-client/utils/lowcode/lowcodeComponentMixin'
421
- // eslint-disable-next-line no-unused-vars
422
- import lowcodeLog from '@vue2-client/utils/lowcode/lowcodeLog'
423
- import LowCodePageOrganization from '@vue2-client/base-client/components/common/LowCodeComponent/LowCodePageOrganization.vue'
424
-
425
- // 函数编辑器显示的模板
426
- const JSEventFunctionTemplate = 'function(eventType, data, targetKey, sourceVM, targetVM) {\n \n return {\n "eventType": eventType,\n "data": data,\n "targetKey": targetKey\n }\n}'
427
- const LogicParamFunctionTemplate = 'function(componentData, data) {\n \n return {\n \n }\n}'
428
- const LogicCallBackFunctionTemplate = 'function(componentsMap, responseData) {\n \n}'
429
-
430
- export default {
431
- components: {
432
- LowCodePageOrganization,
433
- editorPageRender,
434
- codeMirror
435
- },
436
- props: {
437
- // 页面原始的配置,用于从琉璃中读取
438
- originalConfig: {
439
- type: Object,
440
- default: () => {
441
- return {
442
- page: []
443
- }
444
- }
445
- }
446
- },
447
- data () {
448
- return {
449
- // 主体窗口选择的标签
450
- mainPageMenu: ['none'],
451
- // 默认的配置
452
- config: { page: [] },
453
- // 选中的容器
454
- targetContainer: undefined,
455
- // 控制是否渲染页面
456
- preview: false,
457
- // 控制架构树显隐,用于刷新组件
458
- showPageOrganization: true,
459
- // 用于保存右侧编辑组件的属性
460
- editorPropertiesConfig: {},
461
- // 编辑属性时用到的定时器
462
- inputTimeout: undefined,
463
- // 当前激活的是组件事件中哪一类触发属性,对应事件编辑中的手风琴面板
464
- eventCollapseActive: undefined,
465
- // 控制事件编辑器弹框显隐
466
- showEventEditor: false,
467
- // 控制自定义JS函数弹框显隐
468
- showJSEventEditor: false,
469
- // 控制页面显隐,用于属性面板编辑后,触发页面更新
470
- renderPreview: true,
471
- // 控制弹框显隐,用于属性面板编辑后,触发页面更新
472
- renderModalPreview: true,
473
- // 控制抽屉显隐,用于属性面板编辑后,触发页面更新
474
- renderDrawPreview: true,
475
- // 控制右侧编辑器切换标签页
476
- editorPanelCurrent: ['properties'],
477
- // 事件编辑内容的缓存
478
- eventEditorContent: {},
479
- // 用于事件编辑的回显,在点击事件编辑按钮后,会将此变量赋值
480
- eventEditorCurrent: undefined,
481
- // 保存目标组件可以触发哪些事件
482
- supportedEventType: undefined,
483
- // 控制自定义Logic参数自定义JS函数弹框显隐
484
- showLogicParamJSEditor: false,
485
- // 控制自定义Logic回调弹框显隐
486
- showLogicCallBackEditor: false,
487
- // 保存主体中,当前激活的标签栏ID
488
- activeMainPage: undefined,
489
- // 保存主体中,当前激活的标签栏类型
490
- activeMainPageType: undefined,
491
- // 定义Logic参数从哪些组件获取
492
- logicParamTransferDataSource: []
493
- }
494
- },
495
- provide () {
496
- return {
497
- // 将注册的组件传递给子组件
498
- componentsMap: {}
499
- }
500
- },
501
- methods: {
502
- // 页面容器重命名
503
- renamePage (pageId, newName) {
504
- const page = lowcodeUtils.getConfig(pageId, this.config)
505
- page.title = newName
506
- this.refreshOrganization()
507
- },
508
- // 复制粘贴组件
509
- handlePasteItem (id, copyCache, type) {
510
- const target = lowcodeUtils.getConfig(id, this.config)
511
- // 页面中插入行
512
- if (type === 'page-row') {
513
- const content = copyCache.content
514
- const contentKeys = Object.keys(content)
515
- const result = []
516
- contentKeys.forEach(key => {
517
- result.push(content[key])
518
- })
519
- target.body.push(result)
520
- } else if (type === 'row-item') {
521
- // 行中插入组件
522
- target.push(copyCache.content)
523
- } else if (type === 'page') {
524
- // 复制页面
525
- this.config.page.push(copyCache)
526
- this.$message.success('复制成功!')
527
- }
528
- this.refreshOrganization()
529
- },
530
- // span属性通过input框修改
531
- changeSpan (event) {
532
- this.editorPropertiesConfig.span = event.target.value
533
- },
534
- // logic从组件中取值穿梭框改变事件
535
- handleLogicParamTransferChange (targetKeys, direction, moveKeys) {
536
- this.eventEditorContent.logicParamTransfer = targetKeys
537
- this.$forceUpdate()
538
- },
539
- // 点击架构树
540
- treeOrganizationClick (id, type) {
541
- // 如果类型是page证明,选中的是最外层容器
542
- if (type === 'page') {
543
- this.mainPageMenu[0] = id
544
- this.activeMainPage = id
545
- for (let i = 0; i < this.config.page.length; i++) {
546
- if (this.config.page[i].id === this.activeMainPage) {
547
- this.activeMainPageType = this.config.page[i].type
548
- break
549
- }
550
- }
551
- this.$forceUpdate()
552
- } else if (type === 'component') {
553
- this.config.page.forEach(page => {
554
- page.body.forEach(row => {
555
- row.forEach(item => {
556
- if (item.id === id) {
557
- this.mainPageMenu[0] = page.id
558
- this.activeMainPage = page.id
559
- this.activeMainPageType = page.type
560
- this.$forceUpdate()
561
- }
562
- })
563
- })
564
- })
565
- // 将组件选中
566
- const target = lowcodeUtils.getComponentConfig(id, this.config)
567
- this.clickComponentInEditor(target)
568
- }
569
- },
570
- // 架构树拖拽事件
571
- handleTreeDrag (dragKey, dropKey, dropLevel, dropPosition) {
572
- let dragElement
573
- // 如果被拖拽的id小于等于5位则为行
574
- if (dragKey.length <= 5) {
575
- const targetPageId = dragKey.split('_')[0]
576
- const targetRowId = dragKey.split('_')[1] - 1
577
- for (let i = 0; i < this.config.page.length; i++) {
578
- const page = this.config.page[i]
579
- if (page.id === targetPageId) {
580
- dragElement = page.body[targetRowId]
581
- }
582
- }
583
- this.deleteRow(dragKey)
584
- } else {
585
- // 组件的拖拽
586
- dragElement = JSON.parse(JSON.stringify(lowcodeUtils.getComponentConfig(dragKey, this.config)))
587
- this.deleteComponent(dragKey, false)
588
- }
589
-
590
- // position有三种状态,-1表示在目标前,0表示插入,1表示在目标之后
591
- if (dropPosition === 0) {
592
- const target = lowcodeUtils.getComponentConfig(dropKey, this.config)
593
- target.unshift(dragElement)
594
- this.refreshOrganization()
595
- this.$forceUpdate()
596
- } else {
597
- // 如果目标是一行
598
- if (dropLevel === 'row') {
599
- const targetPageId = dropKey.split('_')[0]
600
- const targetRowId = dropKey.split('_')[1] - 1
601
- for (let i = 0; i < this.config.page.length; i++) {
602
- const page = this.config.page[i]
603
- if (page.id === targetPageId) {
604
- if (dropPosition > 0) {
605
- page.body.splice(targetRowId + 1, 0, dragElement)
606
- } else {
607
- page.body.splice(targetRowId, 0, dragElement)
608
- }
609
- this.refreshOrganization()
610
- this.$forceUpdate()
611
- return
612
- }
613
- }
614
- // 如果目标是组件
615
- } else if (dropLevel === 'item') {
616
- for (let i = 0; i < this.config.page.length; i++) {
617
- const page = this.config.page[i]
618
- for (let j = 0; j < page.body.length; j++) {
619
- const row = page.body[j]
620
- for (let k = 0; k < row.length; k++) {
621
- const item = row[k]
622
- if (item.id === dropKey) {
623
- if (dropPosition > 0) {
624
- row.splice(k + 1, 0, dragElement)
625
- } else {
626
- row.splice(k, 0, dragElement)
627
- }
628
- this.refreshOrganization()
629
- this.$forceUpdate()
630
- return
631
- }
632
- }
633
- }
634
- }
635
- }
636
- }
637
- },
638
- // 主页面标签切换
639
- handleMainPageMenuChange (value) {
640
- this.activeMainPage = value.key
641
- for (let i = 0; i < this.config.page.length; i++) {
642
- if (this.config.page[i].id === this.activeMainPage) {
643
- this.activeMainPageType = this.config.page[i].type
644
- return
645
- }
646
- }
647
- },
648
- // 将页面标签类型渲染为对应的文字
649
- determinePageType (type) {
650
- return lowcodeUtils.resolvePageType(type)
651
- },
652
- // 架构添加组件后,将配置添加到config中
653
- handleAddComponent (config) {
654
- this.config.page.push(config)
655
- this.refreshOrganization()
656
- },
657
- // 打开logic回调编辑弹框
658
- openLogicCallbackEditor () {
659
- if (!this.eventEditorContent.logicCallBackFunction) {
660
- this.eventEditorContent.logicCallBackFunction = LogicCallBackFunctionTemplate
661
- }
662
- this.showLogicCallBackEditor = true
663
- },
664
- // 打开logic参数JS编辑器弹框
665
- openLogicParamJSEditor () {
666
- if (!this.eventEditorContent.logicParamJSFunction) {
667
- this.eventEditorContent.logicParamJSFunction = LogicParamFunctionTemplate
668
- }
669
- this.showLogicParamJSEditor = true
670
- },
671
- // 刷新架构
672
- refreshOrganization () {
673
- this.showPageOrganization = false
674
- this.$nextTick(() => {
675
- this.showPageOrganization = true
676
- })
677
- },
678
- // 拖拽完成后,将新的span赋值
679
- handleDrag (targetEle, nextEle) {
680
- const target = lowcodeUtils.getComponentConfig(targetEle.id, this.config.page)
681
- const targetNext = lowcodeUtils.getComponentConfig(nextEle.id, this.config.page)
682
- target.span = targetEle.span
683
- targetNext.span = nextEle.span
684
- },
685
- // 删除组件
686
- deleteComponentInTree (id, type) {
687
- if (type === 'page') {
688
- this.deletePage(id)
689
- } else if (type === 'component') {
690
- this.deleteComponent(id)
691
- } else if (type === 'row') {
692
- this.deleteRow(id)
693
- }
694
- },
695
- // 删除行
696
- deleteRow (id) {
697
- const arr = id.split('_')
698
- for (let i = 0; i < this.config.page.length; i++) {
699
- const page = this.config.page[i]
700
- if (page.id === arr[0]) {
701
- page.body.splice(arr[1] - 1, 1)
702
- this.targetContainer = undefined
703
- this.editorPropertiesConfig = {}
704
- this.refreshOrganization()
705
- }
706
- }
707
- },
708
- // 删除页面容器
709
- deletePage (id) {
710
- for (let i = 0; i < this.config.page.length; i++) {
711
- const page = this.config.page[i]
712
- if (page.id === id) {
713
- // 将该容器中所有已注册的组件全部删除
714
- page.body.forEach(item => {
715
- delete this.$children[0]._provided.componentsMap[item.id]
716
- })
717
- this.targetContainer = undefined
718
- this.editorPropertiesConfig = {}
719
- this.refreshOrganization()
720
- this.config.page.splice(i, 1)
721
- return
722
- }
723
- }
724
- },
725
- // 删除组件
726
- deleteComponent (id, addOnSpan = true) {
727
- this.config.page.forEach(page => {
728
- for (let i = 0; i < page.body.length; i++) {
729
- const row = page.body[i]
730
- for (let j = 0; j < row.length; j++) {
731
- const item = row[j]
732
- if (item.id === id) {
733
- // 记录被删除的组件span
734
- const deletedSpan = item.span
735
- // 删除
736
- row.splice(j, 1)
737
- if (addOnSpan) {
738
- // 如果该组件之前还有组件,将该组件的span加给之前的组件
739
- if (j !== 0) {
740
- row[j - 1].span += deletedSpan
741
- } else if (row.length > 0) {
742
- row[0].span += deletedSpan
743
- }
744
- }
745
- // 从注册的全局Map中删除
746
- delete this.$children[0]._provided.componentsMap[this.editorPropertiesConfig.id]
747
- this.targetContainer = undefined
748
- this.editorPropertiesConfig = {}
749
- this.refreshOrganization()
750
- return
751
- }
752
- }
753
- }
754
- })
755
- },
756
- // 打开JS函数编辑器
757
- openEventJSEditor () {
758
- if (!this.eventEditorContent.JSFunction) {
759
- this.eventEditorContent.JSFunction = JSEventFunctionTemplate
760
- }
761
- this.showJSEventEditor = true
762
- },
763
- // 事件编辑器中,点击编辑按钮
764
- editEventIconClick (eventType, eventIndex) {
765
- // 找到目标配置
766
- const targetConfig = lowcodeUtils.getComponentConfig(this.editorPropertiesConfig.id, this.config.page)
767
- // 将目标对应的配置赋值到事件编辑器缓存
768
- this.eventEditorContent = { ...targetConfig.onEvent[eventType][eventIndex] }
769
- this.eventEditorContent.emitType = eventType
770
- this.eventEditorCurrent = {
771
- type: eventType,
772
- index: eventIndex
773
- }
774
- this.showEventEditor = true
775
- },
776
- // 删除事件
777
- removeEventClick (eventType, eventIndex) {
778
- const targetConfig = lowcodeUtils.getComponentConfig(this.editorPropertiesConfig.id, this.config.page)
779
- targetConfig.onEvent[eventType].splice(eventIndex, 1)
780
- if (targetConfig.onEvent[eventType].length === 0) {
781
- delete targetConfig.onEvent[eventType]
782
- }
783
- this.$forceUpdate()
784
- },
785
- // 添加事件
786
- addEvent () {
787
- this.showEventEditor = true
788
- },
789
- // 获取所有注册组件
790
- getAllRenderedComponents () {
791
- return Object.keys(this.$children[0]._provided.componentsMap)
792
- },
793
- // 容器删除
794
- handleContainerDelete (id) {
795
- let target
796
- let pageIndex
797
- // 找到目标page
798
- for (let i = 0; i < this.config.page.length; i++) {
799
- const tempPage = this.config.page[i].body
800
- for (let j = 0; j < tempPage.length; j++) {
801
- const row = tempPage[j]
802
- for (let k = 0; k < row.length; k++) {
803
- const item = row[k]
804
- if (item.id === id) {
805
- target = this.config.page[i]
806
- // eslint-disable-next-line no-unused-vars
807
- pageIndex = i
808
- }
809
- }
810
- }
811
- }
812
- // 找到该page下对应的item
813
- let targetIndex
814
- let rowIndex
815
- for (let i = 0; i < target.body.length; i++) {
816
- const row = target.body[i]
817
- for (let j = 0; j < row.length; j++) {
818
- const item = row[j]
819
- if (item.id === id) {
820
- targetIndex = j
821
- rowIndex = i
822
- break
823
- }
824
- }
825
- }
826
- target.body[rowIndex].splice(targetIndex, 1)
827
- this.targetContainer = undefined
828
- // 如果删除后只剩一个容器,将该容器span设置为24
829
- if (target.body[rowIndex].length === 1) {
830
- target.body[rowIndex][0].span = 24
831
- }
832
- this.refreshOrganization()
833
- },
834
- // 事件编辑器点击完成
835
- handleEventEditorOk () {
836
- let emitTypeKey = this.eventEditorContent.emitType
837
- // 是否是自定义事件触发
838
- if (this.eventEditorContent.customEmitType) {
839
- emitTypeKey = this.eventEditorContent.customEmitType
840
- }
841
- // 如果当前是回显事件
842
- if (this.eventEditorCurrent) {
843
- const targetConfig = lowcodeUtils.getComponentConfig(this.editorPropertiesConfig.id, this.config.page)
844
- targetConfig.onEvent[this.eventEditorCurrent.type][this.eventEditorCurrent.index] = { ...this.eventEditorContent }
845
- } else {
846
- // 当前是新增事件
847
- const target = lowcodeUtils.getComponentConfig(this.editorPropertiesConfig.id, this.config.page)
848
- // 如果没有onEvent属性则初始化
849
- if (!target.onEvent) {
850
- target.onEvent = {}
851
- }
852
- // 如果当前触发类型没有初始化,则初始化
853
- if (!target.onEvent[emitTypeKey]) {
854
- target.onEvent[emitTypeKey] = []
855
- }
856
- // 将缓存的事件属性赋值
857
- target.onEvent[emitTypeKey].push({
858
- ...this.eventEditorContent
859
- })
860
- }
861
- this.showEventEditor = false
862
- this.eventEditorContent = {}
863
- this.eventEditorCurrent = undefined
864
- },
865
- // 关闭事件编辑器弹框
866
- handleEventEditorCancel () {
867
- this.showEventEditor = false
868
- this.eventEditorContent = {}
869
- this.eventEditorCurrent = undefined
870
- },
871
- // 事件编辑器中,触发类型改变
872
- handleEventEditorTypeChange (type) {
873
- this.eventEditorContent.emitType = type
874
- this.$forceUpdate()
875
- },
876
- // 事件编辑器中,目标组件改变
877
- handleEventEditorTargetChange (target) {
878
- this.eventEditorContent.target = target
879
- this.$forceUpdate()
880
- },
881
- // 事件编辑器中,事件类型改变
882
- handleEventEditorEventTypeChange (type) {
883
- this.eventEditorContent.eventType = type
884
- this.logicParamTransferDataSource = []
885
- // 如果事件为运行Logic将组件加入穿梭框
886
- if (type === 'runLogic') {
887
- this.config.page.forEach(page => {
888
- page.body.forEach(row => {
889
- row.forEach(item => {
890
- if (!item.id.startsWith('container')) {
891
- this.logicParamTransferDataSource.push({
892
- key: item.id,
893
- title: item.id
894
- })
895
- }
896
- })
897
- })
898
- })
899
- this.eventEditorContent.logicParamTransfer = []
900
- }
901
- this.$forceUpdate()
902
- },
903
- // 事件编辑器中,目标组件执行事件类型改变
904
- handleEventEditorTargetEventTypeChange (type) {
905
- this.eventEditorContent.eventName = type
906
- this.$forceUpdate()
907
- },
908
- // 自定义JS方法弹框确认
909
- handleJSEventEditorOk () {
910
- this.showJSEventEditor = false
911
- },
912
- // 自定义JS方法弹框关闭
913
- handleJSEventEditorCancel () {
914
- this.showJSEventEditor = false
915
- },
916
- // 添加组件到容器中
917
- addComponentToContainer (type) {
918
- // 如果没有选中容器
919
- if (!this.targetContainer) {
920
- // 并且配置中没有任何其他组件,则认为是单组件页面,直接将组件添加到页面
921
- if (this.config.page.length === 0) {
922
- this.config.page.push({
923
- id: nanoid(2),
924
- type: 'page',
925
- body: [
926
- {
927
- span: 24,
928
- type: type,
929
- id: type + '_' + nanoid(6),
930
- }
931
- ]
932
- })
933
- this.refreshOrganization()
934
- } else {
935
- this.$message.error('如需多个组件请先添加组件容器!')
936
- }
937
- this.targetContainer = undefined
938
- return
939
- }
940
- // 获取选中的容器
941
- const target = lowcodeUtils.getComponentConfig(this.targetContainer.id, this.config.page)
942
- // 将容器的类型和id改变
943
- target.type = type
944
- target.id = target.type + '_' + nanoid(6)
945
- this.targetContainer = undefined
946
- this.refreshOrganization()
947
- },
948
- // 添加容器
949
- addContainer () {
950
- // 如果目标不是一个容器
951
- if (!this.targetContainer) {
952
- // 如果没有指定页面容器,则直接报错
953
- if (this.activeMainPage === undefined) {
954
- this.$message.error('未选中任何工作空间!')
955
- return
956
- }
957
- // 获取当前选中的页面容器
958
- let targetIndex = this.activeMainPage
959
- for (let i = 0; i < this.config.page.length; i++) {
960
- if (this.config.page[i].id === this.activeMainPage) {
961
- targetIndex = i
962
- break
963
- }
964
- }
965
- // 如果是page类型,添加两个容器。其他类型添加一个容器
966
- if (this.config.page[targetIndex].type === 'page') {
967
- this.config.page[targetIndex].body.push([
968
- {
969
- type: 'container',
970
- span: 12,
971
- id: 'container_' + nanoid(6)
972
- },
973
- {
974
- type: 'container',
975
- span: 12,
976
- id: 'container_' + nanoid(6)
977
- }
978
- ])
979
- } else {
980
- this.config.page[targetIndex].body.push([{
981
- type: 'container',
982
- span: 24,
983
- id: 'container_' + nanoid(6)
984
- }])
985
- }
986
- } else {
987
- // 如果目标是容器
988
- let targetIndex = -1
989
- let maxWidth = -1
990
- let targetPageIndex = -1
991
- let targetRowIndex = -1
992
- // 获取目标的配置
993
- for (let i = 0; i < this.config.page.length; i++) {
994
- const page = this.config.page[i]
995
- for (let j = 0; j < page.body.length; j++) {
996
- const row = page.body[j]
997
- for (let k = 0; k < row.length; k++) {
998
- const item = row[k]
999
- if (item.id === this.targetContainer.id) {
1000
- targetIndex = k
1001
- maxWidth = item.span
1002
- targetPageIndex = i
1003
- targetRowIndex = j
1004
- }
1005
- }
1006
- }
1007
- }
1008
- // 将目标容器一分为二
1009
- this.config.page[targetPageIndex].body[targetRowIndex].splice(targetIndex, 1, {
1010
- type: 'container',
1011
- span: Math.floor(maxWidth / 2),
1012
- id: 'container_' + nanoid(6)
1013
- }, {
1014
- type: 'container',
1015
- span: Math.ceil(maxWidth / 2),
1016
- id: 'container_' + nanoid(6)
1017
- })
1018
- this.targetContainer = undefined
1019
- }
1020
- this.refreshOrganization()
1021
- },
1022
- // 获取所有已注册组件,用于添加至UI库
1023
- getRegisteredComponents () {
1024
- return Object.keys(registeredRender)
1025
- },
1026
- // 组件属性编辑
1027
- editorPropertiesInputChange (event, key) {
1028
- this.renderPreview = false
1029
- this.renderModalPreview = false
1030
- this.renderDrawPreview = false
1031
- // 如果当前有定时器,清除该定时器,并设置新的定时器
1032
- // 也就是说:每次操作间隔指定时间后才会触发更新
1033
- // 如果在此期间又进行了操作,则重新开始计时
1034
- if (this.inputTimeout) {
1035
- clearTimeout(this.inputTimeout)
1036
- }
1037
- this.inputTimeout = setTimeout(() => {
1038
- const target = lowcodeUtils.getComponentConfig(this.editorPropertiesConfig.id, this.config.page)
1039
- lowcodeLog('组件属性修改', '触发更新', target.id, true, false)
1040
- // 拿到组件注册的配置
1041
- const editorConfig = lowcodeUtils.getEditorConfigById(this.editorPropertiesConfig.id, this.config.page)
1042
- // 根据类型,将input框中的内容赋值
1043
- if (editorConfig.properties[key].type === 'object') {
1044
- target.props[key] = JSON.parse(event.target.value)
1045
- } else if (editorConfig.properties[key].type === 'string') {
1046
- target.props[key] = event.target.value
1047
- } else if (editorConfig.properties[key].type === 'boolean') {
1048
- const input = event.target.value.toLowerCase()
1049
- if (input === 'true' || input !== '0') {
1050
- target.props[key] = true
1051
- } else {
1052
- target.props[key] = false
1053
- }
1054
- }
1055
- this.renderPreview = true
1056
- this.renderModalPreview = true
1057
- this.renderDrawPreview = true
1058
- }, 1500)
1059
- },
1060
- // 切换预览模式
1061
- previewModeActive () {
1062
- this.preview = true
1063
- },
1064
- // 切换编辑模式
1065
- editModeActive () {
1066
- this.preview = false
1067
- },
1068
- // 选中某个组件
1069
- clickComponentInEditor (configItem) {
1070
- this.editorPropertiesConfig = {}
1071
- // 如果选中的是容器
1072
- if (configItem.type === 'container') {
1073
- // 如果已经选中,则反选,selected属性用于改变容器样式
1074
- if (configItem.selected) {
1075
- configItem.selected = false
1076
- this.targetContainer = undefined
1077
- } else {
1078
- // 将所有已选中组件取消选择
1079
- this.config.page.forEach(page => {
1080
- page.body.forEach(row => {
1081
- row.forEach(item => {
1082
- item.selected = false
1083
- })
1084
- })
1085
- })
1086
- // 将目标设置为选定
1087
- configItem.selected = true
1088
- this.targetContainer = configItem
1089
- }
1090
- return
1091
- }
1092
- // 如果是组件对象
1093
- // 拿注册的配置
1094
- const configInJson = lowcodeUtils.getEditorConfigByType(configItem.type)
1095
- if (configInJson) {
1096
- this.editorPropertiesConfig = configItem
1097
- // 为编辑器变量初始化
1098
- if (configInJson.properties) {
1099
- if (!this.editorPropertiesConfig.props) {
1100
- this.editorPropertiesConfig.props = {}
1101
- }
1102
- const editableKeys = Object.keys(configInJson.properties)
1103
- editableKeys.forEach(editableKey => {
1104
- // 如果该值并不存在,则初始化
1105
- if (!this.editorPropertiesConfig.props[editableKey]) {
1106
- this.editorPropertiesConfig.props[editableKey] = ''
1107
- } else {
1108
- if (typeof this.editorPropertiesConfig.props[editableKey] === 'object') {
1109
- this.editorPropertiesConfig.props[editableKey] = JSON.stringify(this.editorPropertiesConfig.props[editableKey])
1110
- }
1111
- }
1112
- })
1113
- }
1114
- // 为编辑器事件初始化
1115
- if (configInJson.selfEvent) {
1116
- if (!this.editorPropertiesConfig.selfEvent) {
1117
- this.editorPropertiesConfig.selfEvent = []
1118
- configInJson.selfEvent.forEach(everyEvent => {
1119
- this.editorPropertiesConfig.selfEvent.push(everyEvent)
1120
- })
1121
- }
1122
- }
1123
- } else {
1124
- this.editorPropertiesConfig = 'unregistered'
1125
- }
1126
- },
1127
- // 点击测试按钮
1128
- test () {
1129
- // 输出当前配置,和组件注册Map
1130
- console.warn('config', this.config)
1131
- console.warn('map', this.$children[0]._provided.componentsMap)
1132
- },
1133
- // 点击导出按钮
1134
- exportConfig () {
1135
- console.warn('导出', this.config)
1136
- this.$emit('exportConfig', this.config)
1137
- }
1138
- },
1139
- mounted () {
1140
- // 将mixin中已经实现的通用响应方法添加
1141
- this.supportedEventType = [...lowcodeComponentMixin.supportedEventType]
1142
- // 深拷贝外侧传来的配置
1143
- this.config = JSON.parse(JSON.stringify(this.originalConfig))
1144
- this.config = {
1145
- page: [
1146
- {
1147
- id: 'KB',
1148
- type: 'page',
1149
- title: '111',
1150
- body: [
1151
- [
1152
- {
1153
- type: 'XFormTable',
1154
- span: 12,
1155
- id: 'XFormTable_BV6Nwk',
1156
- selected: false,
1157
- props: {
1158
- queryParamsName: '',
1159
- serviceName: ''
1160
- },
1161
- selfEvent: [
1162
- 'action'
1163
- ]
1164
- },
1165
- {
1166
- type: 'XAddNativeForm',
1167
- span: 12,
1168
- id: 'XAddNativeForm_ekihTp',
1169
- selected: false,
1170
- props: {
1171
- configNameForLowCode: '',
1172
- systemNameForLowCode: ''
1173
- },
1174
- selfEvent: [
1175
- 'onSubmit'
1176
- ]
1177
- }
1178
- ],
1179
- [
1180
- {
1181
- type: 'XTreeOne',
1182
- span: 12,
1183
- id: 'XTreeOne_szu7Al',
1184
- selected: false
1185
- },
1186
- {
1187
- type: 'XDescriptions',
1188
- span: 12,
1189
- id: 'XDescriptions_DTkbEg',
1190
- selected: false,
1191
- props: {
1192
- title: '111',
1193
- content: {
1194
- c_f_user_phone: '2323',
1195
- c_f_total_fee: 33356,
1196
- c_f_address: '22',
1197
- c_f_meterlen: 2,
1198
- c_f_bank_card_number: '23',
1199
- c_f_create_user: '超级管理员',
1200
- c_f_customer: '23',
1201
- c_f_balance: 33356,
1202
- c_f_create_date: '2024-06-23 21:31:24',
1203
- c_f_operator_date: '2024-06-23 21:31:24',
1204
- c_f_total_times: 2,
1205
- c_f_user_name: '23',
1206
- c_f_comments: '323',
1207
- c_id: 39,
1208
- c_f_operatorid: '15',
1209
- c_f_operator: '超级管理员',
1210
- c_f_orgid: '9'
1211
- },
1212
- configName: 'Unit_Desc_Config',
1213
- serviceName: 'af-revenue',
1214
- getRealData: true
1215
- },
1216
- selfEvent: []
1217
- }
1218
- ]
1219
- ]
1220
- },
1221
- {
1222
- id: 'Fg',
1223
- type: 'page',
1224
- title: '22',
1225
- body: [
1226
- [
1227
- {
1228
- type: 'container',
1229
- span: 4,
1230
- id: 'container_ir2gR2',
1231
- selected: false
1232
- },
1233
- {
1234
- type: 'container',
1235
- span: 10,
1236
- id: 'container_xIRHGg'
1237
- },
1238
- {
1239
- type: 'container',
1240
- span: 10,
1241
- id: 'container_PT9n3Q'
1242
- }
1243
- ],
1244
- [
1245
- {
1246
- type: 'container',
1247
- span: 18,
1248
- id: 'container_q04vQr',
1249
- selected: false
1250
- },
1251
- {
1252
- type: 'container',
1253
- span: 6,
1254
- id: 'container_MKwNvz',
1255
- selected: false
1256
- }
1257
- ]
1258
- ]
1259
- }
1260
- ]
1261
- }
1262
- this.refreshOrganization()
1263
- }
1264
- }
1265
- </script>
1266
-
1267
- <style scoped lang="less">
1268
- .ui-item:hover {
1269
- cursor: pointer;
1270
- }
1271
-
1272
- .ui-item{
1273
- width: 100%;
1274
- height:10%;
1275
- text-align: center;
1276
- overflow-wrap: break-word;
1277
- padding: 7%
1278
- }
1279
-
1280
- .singleEvent {
1281
- border: black dashed 1px;
1282
- padding: 10%;
1283
- }
1284
-
1285
- .edit_icon:hover {
1286
- cursor: pointer;
1287
- }
1288
- </style>
1
+ <template>
2
+ <div>
3
+ <!-- 标题 -->
4
+ <a-card>
5
+ <a-page-header
6
+ title="奥枫低代码前端编辑器"
7
+ sub-title="af-lowcode"
8
+ :backIcon="false"
9
+ @back="() => null"
10
+ >
11
+ <template slot="extra">
12
+ <a-button @click="test">测试</a-button>
13
+ <a-button @click="editModeActive">编辑</a-button>
14
+ <a-button @click="previewModeActive">预览</a-button>
15
+ <a-button type="primary" @click="exportConfig">导出</a-button>
16
+ </template>
17
+ </a-page-header>
18
+ </a-card>
19
+ <!-- 预览模式 -->
20
+ <a-card v-if="preview">
21
+ <editor-page-render :page-config="config" :edit-mode="false"/>
22
+ </a-card>
23
+ <!-- 编辑模式 -->
24
+ <div v-show="!preview">
25
+ <a-row :gutter="2">
26
+ <!-- 左侧 -->
27
+ <a-col :span="4">
28
+ <!-- UI库 -->
29
+ <a-card style="margin-bottom: 5%">
30
+ <a-page-header
31
+ title="UI库"
32
+ sub-title="在此选择基础组件"
33
+ :backIcon="false"
34
+ @back="() => null"
35
+ />
36
+ <!-- 所有组件 -->
37
+ <a-card-grid class="ui-item" @click="addContainer">
38
+ 组件容器
39
+ </a-card-grid>
40
+ <template v-for="(item, index) in getRegisteredComponents()">
41
+ <a-card-grid :key="index" class="ui-item" @click="addComponentToContainer(item)">
42
+ {{ item }}
43
+ </a-card-grid>
44
+ </template>
45
+ </a-card>
46
+ </a-col>
47
+ <!-- 中间主体编辑器 -->
48
+ <a-col :span="15">
49
+ <a-card>
50
+ <!-- 切换显示的组件 -->
51
+ <div style="margin-bottom: 3%">
52
+ <a-menu v-model="mainPageMenu" mode="horizontal" @click="handleMainPageMenuChange">
53
+ <template v-for="(page) in config.page">
54
+ <a-menu-item :key="page.id">{{ page.title + '(' + determinePageType(page.type) + ')' }}</a-menu-item>
55
+ </template>
56
+ </a-menu>
57
+ </div>
58
+ <!-- 渲染器 -->
59
+ <div v-if="activeMainPageType === 'page'">
60
+ <editor-page-render
61
+ v-if="renderPreview"
62
+ @spanDrag="handleDrag"
63
+ @containerDelete="handleContainerDelete"
64
+ @clickComponentInEditor="clickComponentInEditor"
65
+ :page-config="{ data: config.data, page: config.page.filter(page => page.id === activeMainPage)}"/>
66
+ <a-skeleton v-else/>
67
+ </div>
68
+ <div v-if="activeMainPageType === 'modal'">
69
+ <editor-page-render
70
+ v-if="renderModalPreview"
71
+ @spanDrag="handleDrag"
72
+ @containerDelete="handleContainerDelete"
73
+ @clickComponentInEditor="clickComponentInEditor"
74
+ :page-config="{ data: config.data, page: config.page.filter(page => page.id === activeMainPage)}"/>
75
+ <a-skeleton v-else/>
76
+ </div>
77
+ <div v-if="activeMainPageType === 'draw'">
78
+ <editor-page-render
79
+ v-if="renderDrawPreview"
80
+ @spanDrag="handleDrag"
81
+ @containerDelete="handleContainerDelete"
82
+ @clickComponentInEditor="clickComponentInEditor"
83
+ :page-config="{ data: config.data, page: config.page.filter(page => page.id === activeMainPage)}"/>
84
+ <a-skeleton v-else/>
85
+ </div>
86
+ </a-card>
87
+ </a-col>
88
+ <!-- 右侧 -->
89
+ <a-col :span="5">
90
+ <!-- 页面架构 -->
91
+ <a-card style="margin-bottom: 3%">
92
+ <a-page-header
93
+ title="架构"
94
+ sub-title="页面的组织架构"
95
+ :backIcon="false"
96
+ @back="() => null"
97
+ />
98
+ <LowCodePageOrganization
99
+ :config="config"
100
+ v-if="showPageOrganization"
101
+ @pasteItem="handlePasteItem"
102
+ @componentMove="handleTreeDrag"
103
+ @deleteComponent="deleteComponentInTree"
104
+ @treeOrganizationClick="treeOrganizationClick"
105
+ @addComponent="handleAddComponent"/>
106
+ </a-card>
107
+ <!-- 属性编辑 -->
108
+ <a-card>
109
+ <template v-if="editorPropertiesConfig === 'unregistered'">
110
+ <p>所选组件并未注册</p>
111
+ </template>
112
+ <template v-else>
113
+ <!-- 组件ID -->
114
+ <div v-if="editorPropertiesConfig.id">
115
+ <a-statistic title="组件ID" :value="editorPropertiesConfig.id" valueStyle="font-size: 1.2em"/>
116
+ </div>
117
+ <!-- 切换 -->
118
+ <a-menu v-model="editorPanelCurrent" mode="horizontal" @click="() => null">
119
+ <a-menu-item key="properties">属性</a-menu-item>
120
+ <a-menu-item key="events">事件</a-menu-item>
121
+ </a-menu>
122
+ <!-- 属性编辑 -->
123
+ <div v-if="editorPanelCurrent[0] === 'properties'">
124
+ <div v-if="editorPropertiesConfig.props !== undefined">
125
+ <div>
126
+ 栅格数:<a-input :default-value="editorPropertiesConfig.span" @change="changeSpan"/>
127
+ </div>
128
+ <template v-for="(value,key) in editorPropertiesConfig.props">
129
+ <div :key="editorPropertiesConfig.id + '_' + key">
130
+ {{ key }}:<a-input :default-value="value" @change="editorPropertiesInputChange($event, key)"/>
131
+ </div>
132
+ </template>
133
+ </div>
134
+ <p v-else>您未选择任何组件</p>
135
+ </div>
136
+ <!-- 事件编辑 -->
137
+ <div v-else-if="editorPanelCurrent[0] === 'events'">
138
+ <template v-if="editorPropertiesConfig.onEvent !== undefined">
139
+ <a-collapse v-model="eventCollapseActive">
140
+ <a-collapse-panel
141
+ v-for="(eventConfig,eventType) in editorPropertiesConfig.onEvent"
142
+ :key="eventType"
143
+ :header="eventType">
144
+ <div v-for="(singleEvent,singleEventIndex) in eventConfig" :key="singleEventIndex" class="singleEvent">
145
+ <p>
146
+ <span style="color:rgb( 24,144,255)">{{ singleEvent.eventType }}</span>
147
+ 事件
148
+ </p>
149
+ <!-- 事件 编辑/删除 按钮 -->
150
+ <div style="display: flex; justify-content: space-evenly">
151
+ <a-icon type="edit" theme="twoTone" class="edit_icon" @click="editEventIconClick(eventType,singleEventIndex)"/>
152
+ <a-popconfirm title="确认删除" ok-text="确认删除" cancel-text="取消" @confirm="removeEventClick(eventType,singleEventIndex)" @cancel="() => null">
153
+ <a-icon type="delete" theme="twoTone" class="edit_icon"/>
154
+ </a-popconfirm>
155
+ </div>
156
+ </div>
157
+ </a-collapse-panel>
158
+ </a-collapse>
159
+ </template>
160
+ <a-button v-if="editorPropertiesConfig.id !== undefined" @click="addEvent">添加事件</a-button>
161
+ <p v-else>您未选择任何组件</p>
162
+ </div>
163
+ </template>
164
+ </a-card>
165
+ </a-col>
166
+ </a-row>
167
+ </div>
168
+ <!-- 自定义事件弹框 -->
169
+ <a-modal
170
+ title="事件编辑器"
171
+ width="60%"
172
+ :z-index="1001"
173
+ :destroyOnClose="true"
174
+ @ok="handleEventEditorOk"
175
+ @cancel="handleEventEditorCancel"
176
+ v-if="showEventEditor"
177
+ :visible="showEventEditor">
178
+ <a-form :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
179
+ <!-- 事件触发类型 -->
180
+ <a-form-item label="事件触发类型">
181
+ <a-select @change="handleEventEditorTypeChange" :default-value="eventEditorContent.emitType">
182
+ <a-select-option
183
+ v-for="(eventType, eventTypeIndex) in editorPropertiesConfig.selfEvent"
184
+ :key="eventTypeIndex"
185
+ :value="eventType">
186
+ {{ eventType }}
187
+ </a-select-option>
188
+ <a-select-option value="customEmitType">
189
+ 自定义触发类型
190
+ </a-select-option>
191
+ </a-select>
192
+ </a-form-item>
193
+ <!-- 自定义事件触发类型 -->
194
+ <a-form-item label="自定义事件触发名" v-if="eventEditorContent.emitType === 'customEmitType'">
195
+ <a-input v-model="eventEditorContent.customEmitType"/>
196
+ </a-form-item>
197
+ <!-- 事件类型 -->
198
+ <a-form-item label="事件类型">
199
+ <a-select @change="handleEventEditorEventTypeChange" :default-value="eventEditorContent.eventType">
200
+ <a-select-option value="changeValue">
201
+ 修改组件的值
202
+ </a-select-option>
203
+ <a-select-option value="changeProps">
204
+ 修改组件的Props
205
+ </a-select-option>
206
+ <a-select-option value="runLogic">
207
+ 执行Logic
208
+ </a-select-option>
209
+ <a-select-option value="log">
210
+ 打印日志
211
+ </a-select-option>
212
+ <a-select-option value="showModal" v-if="this.config.page.filter(page => page.type === 'modal').length > 0">
213
+ 修改弹框可见
214
+ </a-select-option>
215
+ <a-select-option value="showDraw" v-if="this.config.page.filter(page => page.type === 'draw').length > 0">
216
+ 修改抽屉可见
217
+ </a-select-option>
218
+ </a-select>
219
+ </a-form-item>
220
+ <!-- 修改弹框可见 or 修改抽屉可见 -->
221
+ <a-form-item label="修改可见" v-if="eventEditorContent.eventType === 'showModal' || eventEditorContent.eventType === 'showDraw'">
222
+ <a-radio-group v-model="eventEditorContent.visible" button-style="solid">
223
+ <a-radio-button value="open">
224
+ 显示
225
+ </a-radio-button>
226
+ <a-radio-button value="close">
227
+ 隐藏
228
+ </a-radio-button>
229
+ </a-radio-group>
230
+ </a-form-item>
231
+ <!-- 弹框容器ID -->
232
+ <a-form-item label="弹框容器ID" v-if="eventEditorContent.eventType === 'showModal'">
233
+ <a-select v-model="eventEditorContent.containerId">
234
+ <a-select-option
235
+ v-for="(modal) in config.page.filter(page => page.type === 'modal')"
236
+ :key="modal.id"
237
+ :value="modal.id">
238
+ 弹框_{{ modal.id }}
239
+ </a-select-option>
240
+ </a-select>
241
+ </a-form-item>
242
+ <!-- 抽屉容器ID -->
243
+ <a-form-item label="弹框容器ID" v-if="eventEditorContent.eventType === 'showDraw'">
244
+ <a-select v-model="eventEditorContent.containerId">
245
+ <a-select-option
246
+ v-for="(draw) in config.page.filter(page => page.type === 'draw')"
247
+ :key="draw.id"
248
+ :value="draw.id">
249
+ 抽屉_{{ draw.id }}
250
+ </a-select-option>
251
+ </a-select>
252
+ </a-form-item>
253
+ <!-- Logic名 -->
254
+ <a-form-item label="Logic名" v-if="eventEditorContent.eventType === 'runLogic'">
255
+ <a-input v-model="eventEditorContent.logicName"/>
256
+ </a-form-item>
257
+ <!-- 服务名 -->
258
+ <a-form-item label="服务名" v-if="eventEditorContent.eventType === 'runLogic'">
259
+ <a-input v-model="eventEditorContent.serviceName"/>
260
+ </a-form-item>
261
+ <!-- 自定义Logic参数,由哪些组件传递 -->
262
+ <a-form-item label="Logic参数取值组件" v-if="eventEditorContent.eventType === 'runLogic'">
263
+ <a-transfer
264
+ :data-source="logicParamTransferDataSource"
265
+ :render="item => item.title"
266
+ :target-keys="eventEditorContent.logicParamTransfer"
267
+ @change="handleLogicParamTransferChange"/>
268
+ </a-form-item>
269
+ <!-- 自定义Logic参数 -->
270
+ <a-form-item label="自定义Logic参数" v-if="eventEditorContent.eventType === 'runLogic'">
271
+ <a-button type="primary" @click="openLogicParamJSEditor">
272
+ 打开编辑器
273
+ </a-button>
274
+ </a-form-item>
275
+ <!-- 自定义Logic回调 -->
276
+ <a-form-item label="自定义Logic回调" v-if="eventEditorContent.eventType === 'runLogic'" >
277
+ <a-button type="primary" @click="openLogicCallbackEditor">
278
+ 打开编辑器
279
+ </a-button>
280
+ </a-form-item>
281
+ <!-- 修改组件的值 才会显示的其余参数 -->
282
+ <template v-if="eventEditorContent.eventType === 'changeValue' || eventEditorContent.eventType === 'changeProps'">
283
+ <!-- 目标组件 -->
284
+ <a-form-item label="目标组件">
285
+ <a-select @change="handleEventEditorTargetChange" :default-value="eventEditorContent.target">
286
+ <a-select-option
287
+ v-for="(targetId, targetIndex) in getAllRenderedComponents()"
288
+ :key="targetIndex"
289
+ :value="targetId">
290
+ {{ targetId }}
291
+ </a-select-option>
292
+ </a-select>
293
+ </a-form-item>
294
+ <!-- 目标组件执行事件名 -->
295
+ <a-form-item label="目标组件执行事件名" v-if="eventEditorContent.eventName === 'changeValue'">
296
+ <a-select @change="handleEventEditorTargetEventTypeChange" :default-value="eventEditorContent.eventName">
297
+ <a-select-option :value="eventType" v-for="(eventType,eventTypeIndex) in supportedEventType" :key="'eventType_' + eventTypeIndex">
298
+ {{ eventType }}
299
+ </a-select-option>
300
+ </a-select>
301
+ </a-form-item>
302
+ <!-- 目标组件修改值对应的key -->
303
+ <a-form-item label="目标组件修改值对应的key" v-if="eventEditorContent.target !== undefined">
304
+ <a-input v-model="eventEditorContent.targetKey"/>
305
+ </a-form-item>
306
+ </template>
307
+ <!-- 自定义JS方法 -->
308
+ <a-form-item label="自定义JS方法">
309
+ <a-button type="primary" @click="openEventJSEditor">打开编辑器</a-button>
310
+ </a-form-item>
311
+ </a-form>
312
+ </a-modal>
313
+ <!-- 自定义JS事件弹框 -->
314
+ <a-modal
315
+ title="事件编辑器"
316
+ width="60%"
317
+ :destroyOnClose="true"
318
+ :z-index="1002"
319
+ @ok="handleJSEventEditorOk"
320
+ @cancel="handleJSEventEditorCancel"
321
+ :visible="showJSEventEditor">
322
+ <a-popover title="参数说明" style="margin-right: 5%">
323
+ <template slot="content">
324
+ <p>该方法有以下几个参数:</p>
325
+ <p>eventType:事件类型,比如:changeValue代表修改目标组件的值</p>
326
+ <p>data:由事件源发出的参数列表</p>
327
+ <p>targetKey:修改目标组件值所对应的key</p>
328
+ <p>sourceVM:事件源的vue对象</p>
329
+ <p>targetVM:目标的vue对象</p>
330
+ </template>
331
+ <a-button type="primary">
332
+ 参数说明
333
+ </a-button>
334
+ </a-popover>
335
+ <a-popover title="返回值说明" style="margin-bottom: 5%">
336
+ <template slot="content">
337
+ <p>该方法需要的返回值:</p>
338
+ <p>eventType:事件类型</p>
339
+ <p>data:传递给目标组件的数据</p>
340
+ <p>targetKey:修改目标组件值所对应的key</p>
341
+ </template>
342
+ <a-button type="primary">
343
+ 返回值说明
344
+ </a-button>
345
+ </a-popover>
346
+ <code-mirror
347
+ :style-obj="{height:'80%',fontSize:'18px',marginBottom:'15px'}"
348
+ :mode="'javascript'"
349
+ :theme="'monokai'"
350
+ v-model="eventEditorContent.JSFunction"
351
+ :value="eventEditorContent.JSFunction"/>
352
+ </a-modal>
353
+ <!-- 自定义Logic参数JS弹框 -->
354
+ <a-modal
355
+ title="自定义Logic参数JS编辑器"
356
+ width="60%"
357
+ :destroyOnClose="true"
358
+ :z-index="1002"
359
+ @ok="() => { showLogicParamJSEditor = false}"
360
+ @cancel="() => { showLogicParamJSEditor = false}"
361
+ :visible="showLogicParamJSEditor">
362
+ <a-popover title="参数说明" style="margin-right: 5%">
363
+ <template slot="content">
364
+ <p>该方法有以下几个参数:</p>
365
+ <p>componentData:Logic参数取值组件中选中的组件,将会把数据打包存在此对象中,key则为组件的id</p>
366
+ <p>data:由事件源emit发出的参数</p>
367
+ </template>
368
+ <a-button type="primary">
369
+ 参数说明
370
+ </a-button>
371
+ </a-popover>
372
+ <a-popover title="返回值说明" style="margin-bottom: 5%">
373
+ <template slot="content">
374
+ <p>该方法需要一个JSON类型的返回值</p>
375
+ <p>该返回值就是传递给Logic执行的参数</p>
376
+ </template>
377
+ <a-button type="primary">
378
+ 返回值说明
379
+ </a-button>
380
+ </a-popover>
381
+ <code-mirror
382
+ :style-obj="{height:'80%',fontSize:'18px',marginBottom:'15px'}"
383
+ :mode="'javascript'"
384
+ :theme="'monokai'"
385
+ v-model="eventEditorContent.logicParamJSFunction"
386
+ :value="eventEditorContent.logicParamJSFunction"/>
387
+ </a-modal>
388
+ <!-- 自定义Logic回调弹框 -->
389
+ <a-modal
390
+ title="事件编辑器"
391
+ width="60%"
392
+ :destroyOnClose="true"
393
+ :z-index="1002"
394
+ @ok="() => { showLogicCallBackEditor = false}"
395
+ @cancel="() => { showLogicCallBackEditor = false}"
396
+ :visible="showLogicCallBackEditor">
397
+ <a-popover title="参数说明" style="margin-bottom: 5%">
398
+ <template slot="content">
399
+ <p>该方法有以下几个参数:</p>
400
+ <p>componentsMap:所有组件注册的Map</p>
401
+ <p>responseData:后端的返回值</p>
402
+ </template>
403
+ <a-button type="primary">
404
+ 参数说明
405
+ </a-button>
406
+ </a-popover>
407
+ <code-mirror
408
+ :style-obj="{height:'80%',fontSize:'18px',marginBottom:'15px'}"
409
+ :mode="'javascript'"
410
+ :theme="'monokai'"
411
+ v-model="eventEditorContent.logicCallBackFunction"
412
+ :value="eventEditorContent.logicCallBackFunction"/>
413
+ </a-modal>
414
+ </div>
415
+ </template>
416
+
417
+ <script>
418
+ import editorPageRender from '@vue2-client/base-client/components/common/LowCodePageRender/editorPageRender.vue'
419
+ import * as registeredRender from '@vue2-client/utils/lowcode/registerComponentForRender'
420
+ import * as lowcodeUtils from '@vue2-client/utils/lowcode/lowcodeUtils'
421
+ import codeMirror from '@vue2-client/components/CodeMirror/inedx.vue'
422
+ import { nanoid } from 'nanoid'
423
+ import lowcodeComponentMixin from '@vue2-client/utils/lowcode/lowcodeComponentMixin'
424
+ // eslint-disable-next-line no-unused-vars
425
+ import lowcodeLog from '@vue2-client/utils/lowcode/lowcodeLog'
426
+ import LowCodePageOrganization from '@vue2-client/base-client/components/common/LowCodeComponent/LowCodePageOrganization.vue'
427
+
428
+ // 函数编辑器显示的模板
429
+ const JSEventFunctionTemplate = 'function(eventType, data, targetKey, sourceVM, targetVM) {\n \n return {\n "eventType": eventType,\n "data": data,\n "targetKey": targetKey\n }\n}'
430
+ const LogicParamFunctionTemplate = 'function(componentData, data) {\n \n return {\n \n }\n}'
431
+ const LogicCallBackFunctionTemplate = 'function(componentsMap, responseData) {\n \n}'
432
+
433
+ export default {
434
+ components: {
435
+ LowCodePageOrganization,
436
+ editorPageRender,
437
+ codeMirror
438
+ },
439
+ props: {
440
+ // 页面原始的配置,用于从琉璃中读取
441
+ originalConfig: {
442
+ type: Object,
443
+ default: () => {
444
+ return {
445
+ page: []
446
+ }
447
+ }
448
+ }
449
+ },
450
+ data () {
451
+ return {
452
+ // 主体窗口选择的标签
453
+ mainPageMenu: ['none'],
454
+ // 默认的配置
455
+ config: { page: [] },
456
+ // 选中的容器
457
+ targetContainer: undefined,
458
+ // 控制是否渲染页面
459
+ preview: false,
460
+ // 控制架构树显隐,用于刷新组件
461
+ showPageOrganization: true,
462
+ // 用于保存右侧编辑组件的属性
463
+ editorPropertiesConfig: {},
464
+ // 编辑属性时用到的定时器
465
+ inputTimeout: undefined,
466
+ // 当前激活的是组件事件中哪一类触发属性,对应事件编辑中的手风琴面板
467
+ eventCollapseActive: undefined,
468
+ // 控制事件编辑器弹框显隐
469
+ showEventEditor: false,
470
+ // 控制自定义JS函数弹框显隐
471
+ showJSEventEditor: false,
472
+ // 控制页面显隐,用于属性面板编辑后,触发页面更新
473
+ renderPreview: true,
474
+ // 控制弹框显隐,用于属性面板编辑后,触发页面更新
475
+ renderModalPreview: true,
476
+ // 控制抽屉显隐,用于属性面板编辑后,触发页面更新
477
+ renderDrawPreview: true,
478
+ // 控制右侧编辑器切换标签页
479
+ editorPanelCurrent: ['properties'],
480
+ // 事件编辑内容的缓存
481
+ eventEditorContent: {},
482
+ // 用于事件编辑的回显,在点击事件编辑按钮后,会将此变量赋值
483
+ eventEditorCurrent: undefined,
484
+ // 保存目标组件可以触发哪些事件
485
+ supportedEventType: undefined,
486
+ // 控制自定义Logic参数自定义JS函数弹框显隐
487
+ showLogicParamJSEditor: false,
488
+ // 控制自定义Logic回调弹框显隐
489
+ showLogicCallBackEditor: false,
490
+ // 保存主体中,当前激活的标签栏ID
491
+ activeMainPage: undefined,
492
+ // 保存主体中,当前激活的标签栏类型
493
+ activeMainPageType: undefined,
494
+ // 定义Logic参数从哪些组件获取
495
+ logicParamTransferDataSource: []
496
+ }
497
+ },
498
+ provide () {
499
+ return {
500
+ // 将注册的组件传递给子组件
501
+ componentsMap: {}
502
+ }
503
+ },
504
+ methods: {
505
+ // 复制粘贴组件
506
+ handlePasteItem (id, copyCache, type) {
507
+ const target = lowcodeUtils.getConfig(id, this.config)
508
+ // 页面中插入行
509
+ if (type === 'page-row') {
510
+ const content = copyCache.content
511
+ const contentKeys = Object.keys(content)
512
+ const result = []
513
+ contentKeys.forEach(key => {
514
+ result.push(content[key])
515
+ })
516
+ target.body.push(result)
517
+ } else if (type === 'row-item') {
518
+ // 行中插入组件
519
+ target.push(copyCache.content)
520
+ } else if (type === 'page') {
521
+ // 复制页面
522
+ this.config.page.push(copyCache)
523
+ this.$message.success('复制成功!')
524
+ }
525
+ this.refreshOrganization()
526
+ },
527
+ // span属性通过input框修改
528
+ changeSpan (event) {
529
+ this.editorPropertiesConfig.span = event.target.value
530
+ },
531
+ // logic从组件中取值穿梭框改变事件
532
+ handleLogicParamTransferChange (targetKeys, direction, moveKeys) {
533
+ this.eventEditorContent.logicParamTransfer = targetKeys
534
+ this.$forceUpdate()
535
+ },
536
+ // 点击架构树
537
+ treeOrganizationClick (id, type) {
538
+ // 如果类型是page证明,选中的是最外层容器
539
+ if (type === 'page') {
540
+ this.mainPageMenu[0] = id
541
+ this.activeMainPage = id
542
+ for (let i = 0; i < this.config.page.length; i++) {
543
+ if (this.config.page[i].id === this.activeMainPage) {
544
+ this.activeMainPageType = this.config.page[i].type
545
+ break
546
+ }
547
+ }
548
+ this.$forceUpdate()
549
+ } else if (type === 'component') {
550
+ this.config.page.forEach(page => {
551
+ page.body.forEach(row => {
552
+ row.forEach(item => {
553
+ if (item.id === id) {
554
+ this.mainPageMenu[0] = page.id
555
+ this.activeMainPage = page.id
556
+ this.activeMainPageType = page.type
557
+ this.$forceUpdate()
558
+ }
559
+ })
560
+ })
561
+ })
562
+ // 将组件选中
563
+ const target = lowcodeUtils.getComponentConfig(id, this.config)
564
+ this.clickComponentInEditor(target)
565
+ }
566
+ },
567
+ // 架构树拖拽事件
568
+ handleTreeDrag (dragKey, dropKey, dropLevel, dropPosition) {
569
+ let dragElement
570
+ // 如果被拖拽的id小于等于5位则为行
571
+ if (dragKey.length <= 5) {
572
+ const targetPageId = dragKey.split('_')[0]
573
+ const targetRowId = dragKey.split('_')[1] - 1
574
+ for (let i = 0; i < this.config.page.length; i++) {
575
+ const page = this.config.page[i]
576
+ if (page.id === targetPageId) {
577
+ dragElement = page.body[targetRowId]
578
+ }
579
+ }
580
+ this.deleteRow(dragKey)
581
+ } else {
582
+ // 组件的拖拽
583
+ dragElement = JSON.parse(JSON.stringify(lowcodeUtils.getComponentConfig(dragKey, this.config)))
584
+ this.deleteComponent(dragKey, false)
585
+ }
586
+
587
+ // position有三种状态,-1表示在目标前,0表示插入,1表示在目标之后
588
+ if (dropPosition === 0) {
589
+ const target = lowcodeUtils.getComponentConfig(dropKey, this.config)
590
+ target.unshift(dragElement)
591
+ this.refreshOrganization()
592
+ this.$forceUpdate()
593
+ } else {
594
+ // 如果目标是一行
595
+ if (dropLevel === 'row') {
596
+ const targetPageId = dropKey.split('_')[0]
597
+ const targetRowId = dropKey.split('_')[1] - 1
598
+ for (let i = 0; i < this.config.page.length; i++) {
599
+ const page = this.config.page[i]
600
+ if (page.id === targetPageId) {
601
+ if (dropPosition > 0) {
602
+ page.body.splice(targetRowId + 1, 0, dragElement)
603
+ } else {
604
+ page.body.splice(targetRowId, 0, dragElement)
605
+ }
606
+ this.refreshOrganization()
607
+ this.$forceUpdate()
608
+ return
609
+ }
610
+ }
611
+ // 如果目标是组件
612
+ } else if (dropLevel === 'item') {
613
+ for (let i = 0; i < this.config.page.length; i++) {
614
+ const page = this.config.page[i]
615
+ for (let j = 0; j < page.body.length; j++) {
616
+ const row = page.body[j]
617
+ for (let k = 0; k < row.length; k++) {
618
+ const item = row[k]
619
+ if (item.id === dropKey) {
620
+ if (dropPosition > 0) {
621
+ row.splice(k + 1, 0, dragElement)
622
+ } else {
623
+ row.splice(k, 0, dragElement)
624
+ }
625
+ this.refreshOrganization()
626
+ this.$forceUpdate()
627
+ return
628
+ }
629
+ }
630
+ }
631
+ }
632
+ }
633
+ }
634
+ },
635
+ // 主页面标签切换
636
+ handleMainPageMenuChange (value) {
637
+ this.activeMainPage = value.key
638
+ for (let i = 0; i < this.config.page.length; i++) {
639
+ if (this.config.page[i].id === this.activeMainPage) {
640
+ this.activeMainPageType = this.config.page[i].type
641
+ return
642
+ }
643
+ }
644
+ },
645
+ // 将页面标签类型渲染为对应的文字
646
+ determinePageType (type) {
647
+ return lowcodeUtils.resolvePageType(type)
648
+ },
649
+ // 架构添加组件后,将配置添加到config中
650
+ handleAddComponent (config) {
651
+ this.config.page.push(config)
652
+ this.refreshOrganization()
653
+ },
654
+ // 打开logic回调编辑弹框
655
+ openLogicCallbackEditor () {
656
+ if (!this.eventEditorContent.logicCallBackFunction) {
657
+ this.eventEditorContent.logicCallBackFunction = LogicCallBackFunctionTemplate
658
+ }
659
+ this.showLogicCallBackEditor = true
660
+ },
661
+ // 打开logic参数JS编辑器弹框
662
+ openLogicParamJSEditor () {
663
+ if (!this.eventEditorContent.logicParamJSFunction) {
664
+ this.eventEditorContent.logicParamJSFunction = LogicParamFunctionTemplate
665
+ }
666
+ this.showLogicParamJSEditor = true
667
+ },
668
+ // 刷新架构
669
+ refreshOrganization () {
670
+ this.showPageOrganization = false
671
+ this.$nextTick(() => {
672
+ this.showPageOrganization = true
673
+ })
674
+ },
675
+ // 拖拽完成后,将新的span赋值
676
+ handleDrag (targetEle, nextEle) {
677
+ const target = lowcodeUtils.getComponentConfig(targetEle.id, this.config.page)
678
+ const targetNext = lowcodeUtils.getComponentConfig(nextEle.id, this.config.page)
679
+ target.span = targetEle.span
680
+ targetNext.span = nextEle.span
681
+ },
682
+ // 删除组件
683
+ deleteComponentInTree (id, type) {
684
+ if (type === 'page') {
685
+ this.deletePage(id)
686
+ } else if (type === 'component') {
687
+ this.deleteComponent(id)
688
+ } else if (type === 'row') {
689
+ this.deleteRow(id)
690
+ }
691
+ },
692
+ // 删除行
693
+ deleteRow (id) {
694
+ const arr = id.split('_')
695
+ for (let i = 0; i < this.config.page.length; i++) {
696
+ const page = this.config.page[i]
697
+ if (page.id === arr[0]) {
698
+ page.body.splice(arr[1] - 1, 1)
699
+ this.targetContainer = undefined
700
+ this.editorPropertiesConfig = {}
701
+ this.refreshOrganization()
702
+ }
703
+ }
704
+ },
705
+ // 删除页面容器
706
+ deletePage (id) {
707
+ for (let i = 0; i < this.config.page.length; i++) {
708
+ const page = this.config.page[i]
709
+ if (page.id === id) {
710
+ // 将该容器中所有已注册的组件全部删除
711
+ page.body.forEach(item => {
712
+ delete this.$children[0]._provided.componentsMap[item.id]
713
+ })
714
+ this.targetContainer = undefined
715
+ this.editorPropertiesConfig = {}
716
+ this.refreshOrganization()
717
+ this.config.page.splice(i, 1)
718
+ return
719
+ }
720
+ }
721
+ },
722
+ // 删除组件
723
+ deleteComponent (id, addOnSpan = true) {
724
+ this.config.page.forEach(page => {
725
+ for (let i = 0; i < page.body.length; i++) {
726
+ const row = page.body[i]
727
+ for (let j = 0; j < row.length; j++) {
728
+ const item = row[j]
729
+ if (item.id === id) {
730
+ // 记录被删除的组件span
731
+ const deletedSpan = item.span
732
+ // 删除
733
+ row.splice(j, 1)
734
+ if (addOnSpan) {
735
+ // 如果该组件之前还有组件,将该组件的span加给之前的组件
736
+ if (j !== 0) {
737
+ row[j - 1].span += deletedSpan
738
+ } else if (row.length > 0) {
739
+ row[0].span += deletedSpan
740
+ }
741
+ }
742
+ // 从注册的全局Map中删除
743
+ delete this.$children[0]._provided.componentsMap[this.editorPropertiesConfig.id]
744
+ this.targetContainer = undefined
745
+ this.editorPropertiesConfig = {}
746
+ this.refreshOrganization()
747
+ return
748
+ }
749
+ }
750
+ }
751
+ })
752
+ },
753
+ // 打开JS函数编辑器
754
+ openEventJSEditor () {
755
+ if (!this.eventEditorContent.JSFunction) {
756
+ this.eventEditorContent.JSFunction = JSEventFunctionTemplate
757
+ }
758
+ this.showJSEventEditor = true
759
+ },
760
+ // 事件编辑器中,点击编辑按钮
761
+ editEventIconClick (eventType, eventIndex) {
762
+ // 找到目标配置
763
+ const targetConfig = lowcodeUtils.getComponentConfig(this.editorPropertiesConfig.id, this.config.page)
764
+ // 将目标对应的配置赋值到事件编辑器缓存
765
+ this.eventEditorContent = { ...targetConfig.onEvent[eventType][eventIndex] }
766
+ this.eventEditorContent.emitType = eventType
767
+ this.eventEditorCurrent = {
768
+ type: eventType,
769
+ index: eventIndex
770
+ }
771
+ this.showEventEditor = true
772
+ },
773
+ // 删除事件
774
+ removeEventClick (eventType, eventIndex) {
775
+ const targetConfig = lowcodeUtils.getComponentConfig(this.editorPropertiesConfig.id, this.config.page)
776
+ targetConfig.onEvent[eventType].splice(eventIndex, 1)
777
+ if (targetConfig.onEvent[eventType].length === 0) {
778
+ delete targetConfig.onEvent[eventType]
779
+ }
780
+ this.$forceUpdate()
781
+ },
782
+ // 添加事件
783
+ addEvent () {
784
+ this.showEventEditor = true
785
+ },
786
+ // 获取所有注册组件
787
+ getAllRenderedComponents () {
788
+ return Object.keys(this.$children[0]._provided.componentsMap)
789
+ },
790
+ // 容器删除
791
+ handleContainerDelete (id) {
792
+ let target
793
+ let pageIndex
794
+ // 找到目标page
795
+ for (let i = 0; i < this.config.page.length; i++) {
796
+ const tempPage = this.config.page[i].body
797
+ for (let j = 0; j < tempPage.length; j++) {
798
+ const row = tempPage[j]
799
+ for (let k = 0; k < row.length; k++) {
800
+ const item = row[k]
801
+ if (item.id === id) {
802
+ target = this.config.page[i]
803
+ // eslint-disable-next-line no-unused-vars
804
+ pageIndex = i
805
+ }
806
+ }
807
+ }
808
+ }
809
+ // 找到该page下对应的item
810
+ let targetIndex
811
+ let rowIndex
812
+ for (let i = 0; i < target.body.length; i++) {
813
+ const row = target.body[i]
814
+ for (let j = 0; j < row.length; j++) {
815
+ const item = row[j]
816
+ if (item.id === id) {
817
+ targetIndex = j
818
+ rowIndex = i
819
+ break
820
+ }
821
+ }
822
+ }
823
+ target.body[rowIndex].splice(targetIndex, 1)
824
+ this.targetContainer = undefined
825
+ // 如果删除后只剩一个容器,将该容器span设置为24
826
+ if (target.body[rowIndex].length === 1) {
827
+ target.body[rowIndex][0].span = 24
828
+ }
829
+ this.refreshOrganization()
830
+ },
831
+ // 事件编辑器点击完成
832
+ handleEventEditorOk () {
833
+ let emitTypeKey = this.eventEditorContent.emitType
834
+ // 是否是自定义事件触发
835
+ if (this.eventEditorContent.customEmitType) {
836
+ emitTypeKey = this.eventEditorContent.customEmitType
837
+ }
838
+ // 如果当前是回显事件
839
+ if (this.eventEditorCurrent) {
840
+ const targetConfig = lowcodeUtils.getComponentConfig(this.editorPropertiesConfig.id, this.config.page)
841
+ targetConfig.onEvent[this.eventEditorCurrent.type][this.eventEditorCurrent.index] = { ...this.eventEditorContent }
842
+ } else {
843
+ // 当前是新增事件
844
+ const target = lowcodeUtils.getComponentConfig(this.editorPropertiesConfig.id, this.config.page)
845
+ // 如果没有onEvent属性则初始化
846
+ if (!target.onEvent) {
847
+ target.onEvent = {}
848
+ }
849
+ // 如果当前触发类型没有初始化,则初始化
850
+ if (!target.onEvent[emitTypeKey]) {
851
+ target.onEvent[emitTypeKey] = []
852
+ }
853
+ // 将缓存的事件属性赋值
854
+ target.onEvent[emitTypeKey].push({
855
+ ...this.eventEditorContent
856
+ })
857
+ }
858
+ this.showEventEditor = false
859
+ this.eventEditorContent = {}
860
+ this.eventEditorCurrent = undefined
861
+ },
862
+ // 关闭事件编辑器弹框
863
+ handleEventEditorCancel () {
864
+ this.showEventEditor = false
865
+ this.eventEditorContent = {}
866
+ this.eventEditorCurrent = undefined
867
+ },
868
+ // 事件编辑器中,触发类型改变
869
+ handleEventEditorTypeChange (type) {
870
+ this.eventEditorContent.emitType = type
871
+ this.$forceUpdate()
872
+ },
873
+ // 事件编辑器中,目标组件改变
874
+ handleEventEditorTargetChange (target) {
875
+ this.eventEditorContent.target = target
876
+ this.$forceUpdate()
877
+ },
878
+ // 事件编辑器中,事件类型改变
879
+ handleEventEditorEventTypeChange (type) {
880
+ this.eventEditorContent.eventType = type
881
+ this.logicParamTransferDataSource = []
882
+ // 如果事件为运行Logic将组件加入穿梭框
883
+ if (type === 'runLogic') {
884
+ this.config.page.forEach(page => {
885
+ page.body.forEach(row => {
886
+ row.forEach(item => {
887
+ if (!item.id.startsWith('container')) {
888
+ this.logicParamTransferDataSource.push({
889
+ key: item.id,
890
+ title: item.id
891
+ })
892
+ }
893
+ })
894
+ })
895
+ })
896
+ this.eventEditorContent.logicParamTransfer = []
897
+ }
898
+ this.$forceUpdate()
899
+ },
900
+ // 事件编辑器中,目标组件执行事件类型改变
901
+ handleEventEditorTargetEventTypeChange (type) {
902
+ this.eventEditorContent.eventName = type
903
+ this.$forceUpdate()
904
+ },
905
+ // 自定义JS方法弹框确认
906
+ handleJSEventEditorOk () {
907
+ this.showJSEventEditor = false
908
+ },
909
+ // 自定义JS方法弹框关闭
910
+ handleJSEventEditorCancel () {
911
+ this.showJSEventEditor = false
912
+ },
913
+ // 添加组件到容器中
914
+ addComponentToContainer (type) {
915
+ // 如果没有选中容器
916
+ if (!this.targetContainer) {
917
+ // 并且配置中没有任何其他组件,则认为是单组件页面,直接将组件添加到页面
918
+ if (this.config.page.length === 0) {
919
+ this.config.page.push({
920
+ id: nanoid(2),
921
+ type: 'page',
922
+ body: [
923
+ {
924
+ span: 24,
925
+ type: type,
926
+ id: type + '_' + nanoid(6),
927
+ }
928
+ ]
929
+ })
930
+ this.refreshOrganization()
931
+ } else {
932
+ this.$message.error('如需多个组件请先添加组件容器!')
933
+ }
934
+ this.targetContainer = undefined
935
+ return
936
+ }
937
+ // 获取选中的容器
938
+ const target = lowcodeUtils.getComponentConfig(this.targetContainer.id, this.config.page)
939
+ // 将容器的类型和id改变
940
+ target.type = type
941
+ target.id = target.type + '_' + nanoid(6)
942
+ this.targetContainer = undefined
943
+ this.refreshOrganization()
944
+ },
945
+ // 添加容器
946
+ addContainer () {
947
+ // 如果目标不是一个容器
948
+ if (!this.targetContainer) {
949
+ // 如果没有指定页面容器,则直接报错
950
+ if (this.activeMainPage === undefined) {
951
+ this.$message.error('未选中任何工作空间!')
952
+ return
953
+ }
954
+ // 获取当前选中的页面容器
955
+ let targetIndex = this.activeMainPage
956
+ for (let i = 0; i < this.config.page.length; i++) {
957
+ if (this.config.page[i].id === this.activeMainPage) {
958
+ targetIndex = i
959
+ break
960
+ }
961
+ }
962
+ // 如果是page类型,添加两个容器。其他类型添加一个容器
963
+ if (this.config.page[targetIndex].type === 'page') {
964
+ this.config.page[targetIndex].body.push([
965
+ {
966
+ type: 'container',
967
+ span: 12,
968
+ id: 'container_' + nanoid(6)
969
+ },
970
+ {
971
+ type: 'container',
972
+ span: 12,
973
+ id: 'container_' + nanoid(6)
974
+ }
975
+ ])
976
+ } else {
977
+ this.config.page[targetIndex].body.push([{
978
+ type: 'container',
979
+ span: 24,
980
+ id: 'container_' + nanoid(6)
981
+ }])
982
+ }
983
+ } else {
984
+ // 如果目标是容器
985
+ let targetIndex = -1
986
+ let maxWidth = -1
987
+ let targetPageIndex = -1
988
+ let targetRowIndex = -1
989
+ // 获取目标的配置
990
+ for (let i = 0; i < this.config.page.length; i++) {
991
+ const page = this.config.page[i]
992
+ for (let j = 0; j < page.body.length; j++) {
993
+ const row = page.body[j]
994
+ for (let k = 0; k < row.length; k++) {
995
+ const item = row[k]
996
+ if (item.id === this.targetContainer.id) {
997
+ targetIndex = k
998
+ maxWidth = item.span
999
+ targetPageIndex = i
1000
+ targetRowIndex = j
1001
+ }
1002
+ }
1003
+ }
1004
+ }
1005
+ // 将目标容器一分为二
1006
+ this.config.page[targetPageIndex].body[targetRowIndex].splice(targetIndex, 1, {
1007
+ type: 'container',
1008
+ span: Math.floor(maxWidth / 2),
1009
+ id: 'container_' + nanoid(6)
1010
+ }, {
1011
+ type: 'container',
1012
+ span: Math.ceil(maxWidth / 2),
1013
+ id: 'container_' + nanoid(6)
1014
+ })
1015
+ this.targetContainer = undefined
1016
+ }
1017
+ this.refreshOrganization()
1018
+ },
1019
+ // 获取所有已注册组件,用于添加至UI库
1020
+ getRegisteredComponents () {
1021
+ return Object.keys(registeredRender)
1022
+ },
1023
+ // 组件属性编辑
1024
+ editorPropertiesInputChange (event, key) {
1025
+ this.renderPreview = false
1026
+ this.renderModalPreview = false
1027
+ this.renderDrawPreview = false
1028
+ // 如果当前有定时器,清除该定时器,并设置新的定时器
1029
+ // 也就是说:每次操作间隔指定时间后才会触发更新
1030
+ // 如果在此期间又进行了操作,则重新开始计时
1031
+ if (this.inputTimeout) {
1032
+ clearTimeout(this.inputTimeout)
1033
+ }
1034
+ this.inputTimeout = setTimeout(() => {
1035
+ const target = lowcodeUtils.getComponentConfig(this.editorPropertiesConfig.id, this.config.page)
1036
+ lowcodeLog('组件属性修改', '触发更新', target.id, true, false)
1037
+ // 拿到组件注册的配置
1038
+ const editorConfig = lowcodeUtils.getEditorConfigById(this.editorPropertiesConfig.id, this.config.page)
1039
+ // 根据类型,将input框中的内容赋值
1040
+ if (editorConfig.properties[key].type === 'object') {
1041
+ target.props[key] = JSON.parse(event.target.value)
1042
+ } else if (editorConfig.properties[key].type === 'string') {
1043
+ target.props[key] = event.target.value
1044
+ } else if (editorConfig.properties[key].type === 'boolean') {
1045
+ const input = event.target.value.toLowerCase()
1046
+ if (input === 'true' || input !== '0') {
1047
+ target.props[key] = true
1048
+ } else {
1049
+ target.props[key] = false
1050
+ }
1051
+ }
1052
+ this.renderPreview = true
1053
+ this.renderModalPreview = true
1054
+ this.renderDrawPreview = true
1055
+ }, 1500)
1056
+ },
1057
+ // 切换预览模式
1058
+ previewModeActive () {
1059
+ this.preview = true
1060
+ },
1061
+ // 切换编辑模式
1062
+ editModeActive () {
1063
+ this.preview = false
1064
+ },
1065
+ // 选中某个组件
1066
+ clickComponentInEditor (configItem) {
1067
+ this.editorPropertiesConfig = {}
1068
+ // 如果选中的是容器
1069
+ if (configItem.type === 'container') {
1070
+ // 如果已经选中,则反选,selected属性用于改变容器样式
1071
+ if (configItem.selected) {
1072
+ configItem.selected = false
1073
+ this.targetContainer = undefined
1074
+ } else {
1075
+ // 将所有已选中组件取消选择
1076
+ this.config.page.forEach(page => {
1077
+ page.body.forEach(row => {
1078
+ row.forEach(item => {
1079
+ item.selected = false
1080
+ })
1081
+ })
1082
+ })
1083
+ // 将目标设置为选定
1084
+ configItem.selected = true
1085
+ this.targetContainer = configItem
1086
+ }
1087
+ return
1088
+ }
1089
+ // 如果是组件对象
1090
+ // 拿注册的配置
1091
+ const configInJson = lowcodeUtils.getEditorConfigByType(configItem.type)
1092
+ if (configInJson) {
1093
+ this.editorPropertiesConfig = configItem
1094
+ // 为编辑器变量初始化
1095
+ if (configInJson.properties) {
1096
+ if (!this.editorPropertiesConfig.props) {
1097
+ this.editorPropertiesConfig.props = {}
1098
+ }
1099
+ const editableKeys = Object.keys(configInJson.properties)
1100
+ editableKeys.forEach(editableKey => {
1101
+ // 如果该值并不存在,则初始化
1102
+ if (!this.editorPropertiesConfig.props[editableKey]) {
1103
+ this.editorPropertiesConfig.props[editableKey] = ''
1104
+ } else {
1105
+ if (typeof this.editorPropertiesConfig.props[editableKey] === 'object') {
1106
+ this.editorPropertiesConfig.props[editableKey] = JSON.stringify(this.editorPropertiesConfig.props[editableKey])
1107
+ }
1108
+ }
1109
+ })
1110
+ }
1111
+ // 为编辑器事件初始化
1112
+ if (configInJson.selfEvent) {
1113
+ if (!this.editorPropertiesConfig.selfEvent) {
1114
+ this.editorPropertiesConfig.selfEvent = []
1115
+ configInJson.selfEvent.forEach(everyEvent => {
1116
+ this.editorPropertiesConfig.selfEvent.push(everyEvent)
1117
+ })
1118
+ }
1119
+ }
1120
+ } else {
1121
+ this.editorPropertiesConfig = 'unregistered'
1122
+ }
1123
+ },
1124
+ // 点击测试按钮
1125
+ test () {
1126
+ // 输出当前配置,和组件注册Map
1127
+ console.warn('config', this.config)
1128
+ console.warn('map', this.$children[0]._provided.componentsMap)
1129
+ },
1130
+ // 点击导出按钮
1131
+ exportConfig () {
1132
+ console.warn('导出', this.config)
1133
+ this.$emit('exportConfig', this.config)
1134
+ }
1135
+ },
1136
+ mounted () {
1137
+ // 将mixin中已经实现的通用响应方法添加
1138
+ this.supportedEventType = [...lowcodeComponentMixin.supportedEventType]
1139
+ // 深拷贝外侧传来的配置
1140
+ this.config = JSON.parse(JSON.stringify(this.originalConfig))
1141
+ // this.config = {
1142
+ // page: [
1143
+ // {
1144
+ // id: 'KB',
1145
+ // type: 'page',
1146
+ // title: '111',
1147
+ // body: [
1148
+ // [
1149
+ // {
1150
+ // type: 'XFormTable',
1151
+ // span: 12,
1152
+ // id: 'XFormTable_BV6Nwk',
1153
+ // selected: false,
1154
+ // props: {
1155
+ // queryParamsName: '',
1156
+ // serviceName: ''
1157
+ // },
1158
+ // selfEvent: [
1159
+ // 'action'
1160
+ // ]
1161
+ // },
1162
+ // {
1163
+ // type: 'XAddNativeForm',
1164
+ // span: 12,
1165
+ // id: 'XAddNativeForm_ekihTp',
1166
+ // selected: false,
1167
+ // props: {
1168
+ // configNameForLowCode: '',
1169
+ // systemNameForLowCode: ''
1170
+ // },
1171
+ // selfEvent: [
1172
+ // 'onSubmit'
1173
+ // ]
1174
+ // }
1175
+ // ],
1176
+ // [
1177
+ // {
1178
+ // type: 'XTreeOne',
1179
+ // span: 12,
1180
+ // id: 'XTreeOne_szu7Al',
1181
+ // selected: false
1182
+ // },
1183
+ // {
1184
+ // type: 'XDescriptions',
1185
+ // span: 12,
1186
+ // id: 'XDescriptions_DTkbEg',
1187
+ // selected: false,
1188
+ // props: {
1189
+ // title: '111',
1190
+ // content: {
1191
+ // c_f_user_phone: '2323',
1192
+ // c_f_total_fee: 33356,
1193
+ // c_f_address: '22',
1194
+ // c_f_meterlen: 2,
1195
+ // c_f_bank_card_number: '23',
1196
+ // c_f_create_user: '超级管理员',
1197
+ // c_f_customer: '23',
1198
+ // c_f_balance: 33356,
1199
+ // c_f_create_date: '2024-06-23 21:31:24',
1200
+ // c_f_operator_date: '2024-06-23 21:31:24',
1201
+ // c_f_total_times: 2,
1202
+ // c_f_user_name: '23',
1203
+ // c_f_comments: '323',
1204
+ // c_id: 39,
1205
+ // c_f_operatorid: '15',
1206
+ // c_f_operator: '超级管理员',
1207
+ // c_f_orgid: '9'
1208
+ // },
1209
+ // configName: 'Unit_Desc_Config',
1210
+ // serviceName: 'af-revenue',
1211
+ // getRealData: true
1212
+ // },
1213
+ // selfEvent: []
1214
+ // }
1215
+ // ]
1216
+ // ]
1217
+ // },
1218
+ // {
1219
+ // id: 'Fg',
1220
+ // type: 'page',
1221
+ // title: '22',
1222
+ // body: [
1223
+ // [
1224
+ // {
1225
+ // type: 'container',
1226
+ // span: 4,
1227
+ // id: 'container_ir2gR2',
1228
+ // selected: false
1229
+ // },
1230
+ // {
1231
+ // type: 'container',
1232
+ // span: 10,
1233
+ // id: 'container_xIRHGg'
1234
+ // },
1235
+ // {
1236
+ // type: 'container',
1237
+ // span: 10,
1238
+ // id: 'container_PT9n3Q'
1239
+ // }
1240
+ // ],
1241
+ // [
1242
+ // {
1243
+ // type: 'container',
1244
+ // span: 18,
1245
+ // id: 'container_q04vQr',
1246
+ // selected: false
1247
+ // },
1248
+ // {
1249
+ // type: 'container',
1250
+ // span: 6,
1251
+ // id: 'container_MKwNvz',
1252
+ // selected: false
1253
+ // }
1254
+ // ]
1255
+ // ]
1256
+ // }
1257
+ // ]
1258
+ // }
1259
+ this.refreshOrganization()
1260
+ }
1261
+ }
1262
+ </script>
1263
+
1264
+ <style scoped lang="less">
1265
+ .ui-item:hover {
1266
+ cursor: pointer;
1267
+ }
1268
+
1269
+ .ui-item{
1270
+ width: 100%;
1271
+ height:10%;
1272
+ text-align: center;
1273
+ overflow-wrap: break-word;
1274
+ padding: 7%
1275
+ }
1276
+
1277
+ .singleEvent {
1278
+ border: black dashed 1px;
1279
+ padding: 10%;
1280
+ }
1281
+
1282
+ .edit_icon:hover {
1283
+ cursor: pointer;
1284
+ }
1285
+ </style>