amis-editor 4.1.0-beta.4 → 4.2.0-beta.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (216) hide show
  1. package/dist/component/Breadcrumb.d.ts +23 -2
  2. package/dist/component/ClassNameControl.d.ts +1 -1
  3. package/dist/component/Control/APIControl.d.ts +2 -2
  4. package/dist/component/Control/OptionControl.d.ts +3 -3
  5. package/dist/component/Control/PopoverEdit.d.ts +4 -4
  6. package/dist/component/Control/ValidationControl.d.ts +1 -1
  7. package/dist/component/Editor.d.ts +20 -1
  8. package/dist/component/IFramePreview.d.ts +2 -1
  9. package/dist/component/NodeWrapper.d.ts +1 -1
  10. package/dist/component/Panel/RenderersPanel.d.ts +1 -2
  11. package/dist/component/Preview.d.ts +3 -1
  12. package/dist/component/RegionWrapper.d.ts +4 -0
  13. package/dist/component/VRenderer.d.ts +4 -0
  14. package/dist/component/base/InputComponentName.d.ts +1 -1
  15. package/dist/component/base/SearchCustomRendererPanel.d.ts +15 -0
  16. package/dist/component/base/SearchPanel.d.ts +83 -0
  17. package/dist/component/base/SearchRendererPanel.d.ts +2 -42
  18. package/dist/env.d.ts +1 -1
  19. package/dist/exports.min.js +1 -1
  20. package/dist/index.d.ts +4 -1
  21. package/dist/index.min.js +1 -1
  22. package/dist/manager.d.ts +16 -4
  23. package/dist/plugin/Alert.d.ts +1 -1
  24. package/dist/plugin/Button.d.ts +1 -1
  25. package/dist/plugin/Card.d.ts +1 -0
  26. package/dist/plugin/Cards.d.ts +2 -1
  27. package/dist/plugin/Carousel.d.ts +1 -0
  28. package/dist/plugin/Chart.d.ts +1 -0
  29. package/dist/plugin/Collapse.d.ts +1 -0
  30. package/dist/plugin/Custom.d.ts +3 -0
  31. package/dist/plugin/CustomRegion.d.ts +40 -0
  32. package/dist/plugin/Dialog.d.ts +1 -1
  33. package/dist/plugin/Drawer.d.ts +1 -1
  34. package/dist/plugin/DropDownButton.d.ts +1 -1
  35. package/dist/plugin/Each.d.ts +1 -1
  36. package/dist/plugin/Flex.d.ts +1 -0
  37. package/dist/plugin/Form/Control.d.ts +1 -0
  38. package/dist/plugin/Form/Form.d.ts +19 -3
  39. package/dist/plugin/Form/Formula.d.ts +3 -3
  40. package/dist/plugin/Form/InputURL.d.ts +1 -0
  41. package/dist/plugin/Form/Switch.d.ts +2 -0
  42. package/dist/plugin/Grid.d.ts +1 -0
  43. package/dist/plugin/HBox.d.ts +1 -0
  44. package/dist/plugin/IFrame.d.ts +3 -3
  45. package/dist/plugin/Json.d.ts +1 -0
  46. package/dist/plugin/List.d.ts +2 -1
  47. package/dist/plugin/Mapping.d.ts +1 -0
  48. package/dist/plugin/Markdown.d.ts +1 -0
  49. package/dist/plugin/Nav.d.ts +1 -0
  50. package/dist/plugin/Page.d.ts +1 -1
  51. package/dist/plugin/Panel/Outline.d.ts +8 -0
  52. package/dist/plugin/Progress.d.ts +1 -0
  53. package/dist/plugin/QRCode.d.ts +1 -0
  54. package/dist/plugin/Reset.d.ts +0 -1
  55. package/dist/plugin/Service.d.ts +1 -0
  56. package/dist/plugin/Sparkline.d.ts +1 -0
  57. package/dist/plugin/Status.d.ts +1 -0
  58. package/dist/plugin/Steps.d.ts +1 -0
  59. package/dist/plugin/Submit.d.ts +0 -1
  60. package/dist/plugin/Table.d.ts +1 -1
  61. package/dist/plugin/TableView.d.ts +1 -0
  62. package/dist/plugin/Tasks.d.ts +1 -0
  63. package/dist/plugin/TooltipWrapper.d.ts +1 -0
  64. package/dist/plugin/Video.d.ts +1 -0
  65. package/dist/plugin/WebComponent.d.ts +1 -0
  66. package/dist/plugin/Wizard.d.ts +11 -2
  67. package/dist/plugin/Wrapper.d.ts +1 -0
  68. package/dist/plugin.d.ts +8 -7
  69. package/dist/store/editor.d.ts +47 -11
  70. package/dist/store/node.d.ts +6 -0
  71. package/dist/style.css +1 -1
  72. package/dist/util.d.ts +1 -1
  73. package/package.json +10 -3
  74. package/src/component/schemaTpl.tsx +2157 -0
  75. package/src/plugin/Alert.tsx +87 -0
  76. package/src/plugin/AnchorNav.tsx +233 -0
  77. package/src/plugin/Audio.tsx +154 -0
  78. package/src/plugin/Avatar.tsx +77 -0
  79. package/src/plugin/Breadcrumb.tsx +107 -0
  80. package/src/plugin/Button.tsx +281 -0
  81. package/src/plugin/ButtonGroup.tsx +85 -0
  82. package/src/plugin/ButtonToolbar.tsx +87 -0
  83. package/src/plugin/CRUD.tsx +1835 -0
  84. package/src/plugin/Card.tsx +290 -0
  85. package/src/plugin/Cards.tsx +318 -0
  86. package/src/plugin/Carousel.tsx +377 -0
  87. package/src/plugin/Chart.tsx +218 -0
  88. package/src/plugin/CodeView.tsx +60 -0
  89. package/src/plugin/Collapse.tsx +136 -0
  90. package/src/plugin/CollapseGroup.tsx +167 -0
  91. package/src/plugin/Container.tsx +40 -0
  92. package/src/plugin/Custom.tsx +128 -0
  93. package/src/plugin/CustomRegion.tsx +156 -0
  94. package/src/plugin/Date.tsx +74 -0
  95. package/src/plugin/Datetime.tsx +68 -0
  96. package/src/plugin/Dialog.tsx +176 -0
  97. package/src/plugin/Divider.tsx +36 -0
  98. package/src/plugin/Drawer.tsx +214 -0
  99. package/src/plugin/DropDownButton.tsx +235 -0
  100. package/src/plugin/Each.tsx +150 -0
  101. package/src/plugin/ErrorRenderer.tsx +15 -0
  102. package/src/plugin/Flex.tsx +151 -0
  103. package/src/plugin/Form/ButtonGroupSelect.tsx +75 -0
  104. package/src/plugin/Form/ButtonToolbar.tsx +110 -0
  105. package/src/plugin/Form/ChainedSelect.tsx +70 -0
  106. package/src/plugin/Form/Checkbox.tsx +87 -0
  107. package/src/plugin/Form/Checkboxes.tsx +167 -0
  108. package/src/plugin/Form/CodeEditor.tsx +81 -0
  109. package/src/plugin/Form/Combo.tsx +582 -0
  110. package/src/plugin/Form/ConditionBuilder.tsx +315 -0
  111. package/src/plugin/Form/Control.tsx +139 -0
  112. package/src/plugin/Form/DiffEditor.tsx +111 -0
  113. package/src/plugin/Form/FieldSet.tsx +163 -0
  114. package/src/plugin/Form/Form.tsx +687 -0
  115. package/src/plugin/Form/Formula.tsx +79 -0
  116. package/src/plugin/Form/Group.tsx +295 -0
  117. package/src/plugin/Form/Hidden.tsx +44 -0
  118. package/src/plugin/Form/InputArray.tsx +228 -0
  119. package/src/plugin/Form/InputCity.tsx +93 -0
  120. package/src/plugin/Form/InputColor.tsx +123 -0
  121. package/src/plugin/Form/InputDate.tsx +175 -0
  122. package/src/plugin/Form/InputDateRange.tsx +225 -0
  123. package/src/plugin/Form/InputDateTime.tsx +183 -0
  124. package/src/plugin/Form/InputDateTimeRange.tsx +221 -0
  125. package/src/plugin/Form/InputEmail.tsx +33 -0
  126. package/src/plugin/Form/InputExcel.tsx +85 -0
  127. package/src/plugin/Form/InputFile.tsx +221 -0
  128. package/src/plugin/Form/InputGroup.tsx +96 -0
  129. package/src/plugin/Form/InputImage.tsx +266 -0
  130. package/src/plugin/Form/InputKV.tsx +72 -0
  131. package/src/plugin/Form/InputMonth.tsx +35 -0
  132. package/src/plugin/Form/InputMonthRange.tsx +195 -0
  133. package/src/plugin/Form/InputNumber.tsx +89 -0
  134. package/src/plugin/Form/InputPassword.tsx +33 -0
  135. package/src/plugin/Form/InputQuarter.tsx +35 -0
  136. package/src/plugin/Form/InputQuarterRange.tsx +195 -0
  137. package/src/plugin/Form/InputRange.tsx +121 -0
  138. package/src/plugin/Form/InputRating.tsx +78 -0
  139. package/src/plugin/Form/InputRepeat.tsx +57 -0
  140. package/src/plugin/Form/InputRichText.tsx +186 -0
  141. package/src/plugin/Form/InputSubForm.tsx +189 -0
  142. package/src/plugin/Form/InputTable.tsx +434 -0
  143. package/src/plugin/Form/InputTag.tsx +70 -0
  144. package/src/plugin/Form/InputText.tsx +186 -0
  145. package/src/plugin/Form/InputTime.tsx +85 -0
  146. package/src/plugin/Form/InputTree.tsx +229 -0
  147. package/src/plugin/Form/InputURL.tsx +34 -0
  148. package/src/plugin/Form/InputYear.tsx +35 -0
  149. package/src/plugin/Form/Item.tsx +327 -0
  150. package/src/plugin/Form/ListSelect.tsx +73 -0
  151. package/src/plugin/Form/LocationPicker.tsx +62 -0
  152. package/src/plugin/Form/MatrixCheckboxes.tsx +136 -0
  153. package/src/plugin/Form/NestedSelect.tsx +211 -0
  154. package/src/plugin/Form/Picker.tsx +209 -0
  155. package/src/plugin/Form/Radios.tsx +119 -0
  156. package/src/plugin/Form/Select.tsx +233 -0
  157. package/src/plugin/Form/Static.tsx +322 -0
  158. package/src/plugin/Form/Switch.tsx +107 -0
  159. package/src/plugin/Form/TabsTransfer.tsx +259 -0
  160. package/src/plugin/Form/Textarea.tsx +83 -0
  161. package/src/plugin/Form/Transfer.tsx +368 -0
  162. package/src/plugin/Form/TreeSelect.tsx +263 -0
  163. package/src/plugin/Form/UUID.tsx +48 -0
  164. package/src/plugin/Grid.tsx +798 -0
  165. package/src/plugin/HBox.tsx +727 -0
  166. package/src/plugin/IFrame.tsx +70 -0
  167. package/src/plugin/Image.tsx +314 -0
  168. package/src/plugin/Images.tsx +231 -0
  169. package/src/plugin/Json.tsx +69 -0
  170. package/src/plugin/Link.tsx +93 -0
  171. package/src/plugin/List.tsx +278 -0
  172. package/src/plugin/ListItem.tsx +229 -0
  173. package/src/plugin/Log.tsx +52 -0
  174. package/src/plugin/Mapping.tsx +149 -0
  175. package/src/plugin/Markdown.tsx +47 -0
  176. package/src/plugin/Nav.tsx +184 -0
  177. package/src/plugin/Operation.tsx +95 -0
  178. package/src/plugin/Others/Action.tsx +426 -0
  179. package/src/plugin/Others/BasicToolbar.tsx +585 -0
  180. package/src/plugin/Others/DataDebug.tsx +134 -0
  181. package/src/plugin/Others/TableCell.tsx +480 -0
  182. package/src/plugin/Others/Unknown.tsx +37 -0
  183. package/src/plugin/Page.tsx +306 -0
  184. package/src/plugin/Panel/AvailableRenderers.tsx +41 -0
  185. package/src/plugin/Panel/Code.tsx +44 -0
  186. package/src/plugin/Panel/Name.tsx +26 -0
  187. package/src/plugin/Panel/Outline.tsx +40 -0
  188. package/src/plugin/Panel.tsx +243 -0
  189. package/src/plugin/Plain.tsx +84 -0
  190. package/src/plugin/Progress.tsx +125 -0
  191. package/src/plugin/Property.tsx +139 -0
  192. package/src/plugin/QRCode.tsx +96 -0
  193. package/src/plugin/Reset.tsx +23 -0
  194. package/src/plugin/Service.tsx +162 -0
  195. package/src/plugin/Sparkline.tsx +40 -0
  196. package/src/plugin/Status.tsx +76 -0
  197. package/src/plugin/Steps.tsx +128 -0
  198. package/src/plugin/Submit.tsx +23 -0
  199. package/src/plugin/Table.tsx +428 -0
  200. package/src/plugin/TableView.tsx +709 -0
  201. package/src/plugin/Tabs.tsx +362 -0
  202. package/src/plugin/Tasks.tsx +274 -0
  203. package/src/plugin/Time.tsx +68 -0
  204. package/src/plugin/TooltipWrapper.tsx +193 -0
  205. package/src/plugin/Tpl.tsx +158 -0
  206. package/src/plugin/Video.tsx +158 -0
  207. package/src/plugin/WebComponent.tsx +53 -0
  208. package/src/plugin/Wizard.tsx +740 -0
  209. package/src/plugin/Wrapper.tsx +107 -0
  210. package/src/plugin.ts +1050 -0
  211. package/dist/150a58f3318ca7541ed9.png +0 -0
  212. package/dist/471adb97c322b226e589.png +0 -0
  213. package/dist/4de5f42360bc5946c3c2.png +0 -0
  214. package/dist/4e9968bba3855f088fed.png +0 -0
  215. package/dist/7f09c38ebc687fea847a.png +0 -0
  216. package/dist/c94073576487510314ea.png +0 -0
@@ -0,0 +1,1835 @@
1
+ import {toast} from 'amis';
2
+
3
+ import get from 'lodash/get';
4
+ import cloneDeep from 'lodash/cloneDeep';
5
+ import React from 'react';
6
+
7
+ import {registerEditorPlugin} from '../manager';
8
+ import {
9
+ BaseEventContext,
10
+ BasePlugin,
11
+ BasicRendererInfo,
12
+ BasicSubRenderInfo,
13
+ ChangeEventContext,
14
+ PluginEvent,
15
+ PluginInterface,
16
+ RendererEventContext,
17
+ RendererInfoResolveEventContext,
18
+ ScaffoldForm,
19
+ SubRendererInfo
20
+ } from '../plugin';
21
+ import {defaultValue, getSchemaTpl} from '../component/schemaTpl';
22
+ import {isObject, JSONPipeIn} from '../util';
23
+ import {setVariable} from 'amis-core';
24
+ import {ActionSchema} from 'amis/lib/renderers/Action';
25
+ import {getEnv} from 'mobx-state-tree';
26
+ import {normalizeApi} from 'amis-core';
27
+
28
+ interface ColumnItem {
29
+ label: string;
30
+ type: string;
31
+ name: string;
32
+ }
33
+
34
+ // 将展现控件转成编辑控件
35
+ const viewTypeToEditType = (type: string) => {
36
+ return type === 'tpl'
37
+ ? 'input-text'
38
+ : type === 'status' || type === 'mapping'
39
+ ? 'select'
40
+ : `input-${type}`;
41
+ };
42
+
43
+ export class CRUDPlugin extends BasePlugin {
44
+ // 关联渲染器名字
45
+ rendererName = 'crud';
46
+ $schema = '/schemas/CRUDSchema.json';
47
+
48
+ order = -1000;
49
+
50
+ // 组件名称
51
+ name = '增删改查';
52
+ isBaseComponent = true;
53
+ description =
54
+ '用来实现对数据的增删改查,支持三种模式展示:table、cards和list. 负责数据的拉取,分页,单条操作,批量操作,排序,快速编辑等等功能。集成查询条件。';
55
+ docLink = '/amis/zh-CN/components/crud';
56
+ tags = ['功能'];
57
+ icon = 'fa fa-table';
58
+
59
+ scaffold: any = {
60
+ type: 'crud',
61
+ syncLocation: false,
62
+ api: '',
63
+ columns: [
64
+ {
65
+ name: 'id',
66
+ label: 'ID',
67
+ type: 'text'
68
+ },
69
+ {
70
+ name: 'engine',
71
+ label: '渲染引擎',
72
+ type: 'text'
73
+ }
74
+ ],
75
+ bulkActions: [],
76
+ itemActions: []
77
+ };
78
+
79
+ sampleBuilder = (schema: any) => {
80
+ const data: any = {
81
+ items: [],
82
+ total: 0
83
+ };
84
+
85
+ if (Array.isArray(schema.columns)) {
86
+ const item = {};
87
+ schema.columns.forEach((control: any) => {
88
+ if (control.name) {
89
+ setVariable(item, control.name, 'sample');
90
+ }
91
+ });
92
+
93
+ data.items.push(item);
94
+ }
95
+
96
+ return JSON.stringify(
97
+ {
98
+ status: 0,
99
+ msg: '',
100
+ data: data
101
+ },
102
+ null,
103
+ 2
104
+ );
105
+ };
106
+
107
+ btnSchemas = {
108
+ create: {
109
+ label: '新增',
110
+ type: 'button',
111
+ actionType: 'dialog',
112
+ level: 'primary',
113
+ dialog: {
114
+ title: '新增',
115
+ body: {
116
+ type: 'form',
117
+ api: 'xxx/create',
118
+ body: []
119
+ }
120
+ }
121
+ },
122
+ update: {
123
+ label: '编辑',
124
+ type: 'button',
125
+ actionType: 'dialog',
126
+ level: 'link',
127
+ dialog: {
128
+ title: '编辑',
129
+ body: {
130
+ type: 'form',
131
+ api: 'xxx/update',
132
+ body: []
133
+ }
134
+ }
135
+ },
136
+ view: {
137
+ label: '查看',
138
+ type: 'button',
139
+ actionType: 'dialog',
140
+ level: 'link',
141
+ dialog: {
142
+ title: '查看详情',
143
+ body: {
144
+ type: 'form',
145
+ api: 'xxx/update',
146
+ body: []
147
+ }
148
+ }
149
+ },
150
+ delete: {
151
+ type: 'button',
152
+ label: '删除',
153
+ actionType: 'ajax',
154
+ level: 'link',
155
+ className: 'text-danger',
156
+ confirmText: '确定要删除?',
157
+ api: 'delete:/xxx/delete'
158
+ },
159
+ bulkDelete: {
160
+ type: 'button',
161
+ level: 'danger',
162
+ label: '批量删除',
163
+ actionType: 'ajax',
164
+ confirmText: '确定要删除?',
165
+ api: '/xxx/batch-delete'
166
+ },
167
+ bulkUpdate: {
168
+ type: 'button',
169
+ label: '批量编辑',
170
+ actionType: 'dialog',
171
+ dialog: {
172
+ title: '批量编辑',
173
+ size: 'md',
174
+ body: {
175
+ type: 'form',
176
+ api: '/xxx/bacth-edit',
177
+ body: [
178
+ {
179
+ label: '字段1',
180
+ text: '字段1',
181
+ type: 'input-text'
182
+ }
183
+ ]
184
+ }
185
+ }
186
+ },
187
+ // itemDelete: {
188
+ // type: 'button',
189
+ // level: 'danger',
190
+ // label: '删除',
191
+ // api: '/xxx/delete-one',
192
+ // actionType: 'ajax',
193
+ // confirmText: '确定要删除?'
194
+ // },
195
+ filter: {
196
+ title: '查询条件',
197
+ body: [
198
+ {
199
+ type: 'input-text',
200
+ name: 'keywords',
201
+ label: '关键字'
202
+ }
203
+ ]
204
+ }
205
+ };
206
+
207
+ scaffoldForm: ScaffoldForm = {
208
+ title: '增删改查快速开始-CRUD',
209
+ body: [
210
+ getSchemaTpl('api', {
211
+ label: '接口地址',
212
+ sampleBuilder: (schema: any) => {
213
+ const data: any = {
214
+ items: [],
215
+ total: 0
216
+ };
217
+
218
+ if (Array.isArray(schema.columns)) {
219
+ const item = {};
220
+ schema.columns.forEach((control: any) => {
221
+ if (control.name) {
222
+ setVariable(item, control.name, 'sample');
223
+ }
224
+ });
225
+
226
+ data.items.push(item);
227
+ }
228
+
229
+ return JSON.stringify(
230
+ {
231
+ status: 0,
232
+ msg: '',
233
+ data: data
234
+ },
235
+ null,
236
+ 2
237
+ );
238
+ }
239
+ }),
240
+ {
241
+ type: 'button',
242
+ label: '格式校验并自动生成列配置',
243
+ className: 'm-t-xs m-b-xs',
244
+ onClick: async (e: Event, props: any) => {
245
+ const data = props.data;
246
+ const schemaFilter = getEnv((window as any).editorStore).schemaFilter;
247
+ let api: any = data.api;
248
+ // 主要是给爱速搭中替换 url
249
+ if (schemaFilter) {
250
+ api = schemaFilter({
251
+ api: data.api
252
+ }).api;
253
+ }
254
+ const result = await props.env.fetcher(api, data);
255
+
256
+ let autoFillKeyValues: Array<any> = [];
257
+ const items = result.data?.rows || result.data?.items;
258
+ if (items?.length) {
259
+ Object.keys(items[0]).forEach((key: any) => {
260
+ const value = items[0][key];
261
+ autoFillKeyValues.push({
262
+ label: key,
263
+ type: 'text',
264
+ name: key
265
+ });
266
+ });
267
+ props.formStore.setValues({
268
+ columns: autoFillKeyValues
269
+ });
270
+ // 查询条件的字段列表
271
+ props.formStore.setValues({
272
+ filterSettingSource: autoFillKeyValues.map(column => {
273
+ return column.name;
274
+ })
275
+ });
276
+ } else {
277
+ toast.warning(
278
+ `API返回格式不正确,请点击接口地址右侧示例的问号查看示例`
279
+ );
280
+ }
281
+ }
282
+ },
283
+ {
284
+ name: 'features',
285
+ label: '启用功能',
286
+ type: 'checkboxes',
287
+ joinValues: false,
288
+ extractValue: true,
289
+ itemClassName: 'max-w-lg',
290
+ options: [
291
+ {label: '新增', value: 'create'},
292
+ {label: '查询', value: 'filter'},
293
+ {label: '批量删除', value: 'bulkDelete'},
294
+ {label: '批量修改', value: 'bulkUpdate'},
295
+ {label: '操作栏-编辑', value: 'update'},
296
+ {label: '操作栏-查看详情', value: 'view'},
297
+ {label: '操作栏-删除', value: 'delete'}
298
+ ]
299
+ },
300
+ {
301
+ type: 'group',
302
+ body: [
303
+ {
304
+ columnRatio: 10,
305
+ type: 'checkboxes',
306
+ label: '启用的查询字段',
307
+ name: 'filterEnabledList',
308
+ joinValues: false,
309
+ source: '${filterSettingSource}'
310
+ },
311
+ {
312
+ columnRatio: 2,
313
+ type: 'input-number',
314
+ label: '每列显示几个字段',
315
+ value: 3,
316
+ name: 'filterColumnCount'
317
+ }
318
+ ],
319
+ visibleOn: 'data.features && data.features.includes("filter")'
320
+ },
321
+ {
322
+ name: 'columns',
323
+ type: 'input-table',
324
+ label: false,
325
+ addable: true,
326
+ removable: true,
327
+ needConfirm: false,
328
+ columns: [
329
+ {
330
+ type: 'input-text',
331
+ name: 'label',
332
+ label: '标题'
333
+ },
334
+ {
335
+ type: 'input-text',
336
+ name: 'name',
337
+ label: '绑定字段名'
338
+ },
339
+ {
340
+ type: 'select',
341
+ name: 'type',
342
+ label: '类型',
343
+ value: 'text',
344
+ options: [
345
+ {
346
+ value: 'text',
347
+ label: '纯文本'
348
+ },
349
+ {
350
+ value: 'tpl',
351
+ label: '模板'
352
+ },
353
+ {
354
+ value: 'image',
355
+ label: '图片'
356
+ },
357
+ {
358
+ value: 'date',
359
+ label: '日期'
360
+ },
361
+ {
362
+ value: 'progress',
363
+ label: '进度'
364
+ },
365
+ {
366
+ value: 'status',
367
+ label: '状态'
368
+ },
369
+ {
370
+ value: 'mapping',
371
+ label: '映射'
372
+ },
373
+ {
374
+ value: 'operation',
375
+ label: '操作栏'
376
+ }
377
+ ]
378
+ }
379
+ ]
380
+ }
381
+ ],
382
+ pipeOut: (value: any) => {
383
+ let valueSchema = cloneDeep(value);
384
+ // 查看/删除 操作,可选择是否使用接口返回值预填充
385
+ const features: Array<any> = valueSchema.features;
386
+ const oper: {
387
+ type: 'operation';
388
+ label?: string;
389
+ buttons: Array<ActionSchema>;
390
+ } = {
391
+ type: 'operation',
392
+ label: '操作',
393
+ buttons: []
394
+ };
395
+ const itemBtns: Array<string> = ['update', 'view', 'delete'];
396
+ const hasFeatures = get(features, 'length');
397
+
398
+ valueSchema.bulkActions = [];
399
+ /** 统一api格式 */
400
+ valueSchema.api = normalizeApi(valueSchema.api);
401
+ hasFeatures &&
402
+ features.forEach((item: string) => {
403
+ if (itemBtns.includes(item)) {
404
+ let schema;
405
+
406
+ if (item === 'update') {
407
+ schema = cloneDeep(this.btnSchemas.update);
408
+ schema.dialog.body.body = value.columns
409
+ .filter(
410
+ ({type}: any) => type !== 'progress' && type !== 'operation'
411
+ )
412
+ .map(({type, ...rest}: any) => ({
413
+ ...rest,
414
+ type: viewTypeToEditType(type)
415
+ }));
416
+ } else if (item === 'view') {
417
+ schema = cloneDeep(this.btnSchemas.view);
418
+ schema.dialog.body.body = value.columns.map(
419
+ ({type, ...rest}: any) => ({
420
+ ...rest,
421
+ type: 'static'
422
+ })
423
+ );
424
+ } else if (item === 'delete') {
425
+ schema = cloneDeep(this.btnSchemas.delete);
426
+ schema.api = valueSchema.api?.method.match(/^(post|delete)$/i)
427
+ ? valueSchema.api
428
+ : {...valueSchema.api, method: 'post'};
429
+ }
430
+
431
+ // 添加操作按钮
432
+ this.addItem(oper.buttons, schema);
433
+ } else {
434
+ // 批量操作
435
+ if (item === 'bulkUpdate') {
436
+ this.addItem(
437
+ valueSchema.bulkActions,
438
+ cloneDeep(this.btnSchemas.bulkUpdate)
439
+ );
440
+ }
441
+
442
+ if (item === 'bulkDelete') {
443
+ this.addItem(
444
+ valueSchema.bulkActions,
445
+ cloneDeep(this.btnSchemas.bulkDelete)
446
+ );
447
+ }
448
+
449
+ // 创建
450
+ if (item === 'create') {
451
+ const createSchemaBase = this.btnSchemas.create;
452
+ createSchemaBase.dialog.body = {
453
+ type: 'form',
454
+ api: valueSchema.api?.method.match(/^(post|put)$/i)
455
+ ? valueSchema.api
456
+ : {...valueSchema.api, method: 'post'},
457
+ body: valueSchema.columns.map((column: ColumnItem) => {
458
+ const type = column.type;
459
+ return {
460
+ type: viewTypeToEditType(type),
461
+ name: column.name,
462
+ label: column.label
463
+ };
464
+ })
465
+ };
466
+ valueSchema.headerToolbar = [createSchemaBase, 'bulkActions'];
467
+ }
468
+ let keysFilter = Object.keys(valueSchema.filter || {});
469
+ if (item === 'filter' && !keysFilter.length) {
470
+ if (valueSchema.filterEnabledList) {
471
+ valueSchema.filter = {
472
+ title: '查询条件'
473
+ };
474
+ valueSchema.filter.columnCount = value.filterColumnCount;
475
+ valueSchema.filter.mode = 'horizontal';
476
+ valueSchema.filter.body = valueSchema.filterEnabledList.map(
477
+ (item: any) => {
478
+ return {
479
+ type: 'input-text',
480
+ label: item.label,
481
+ name: item.value
482
+ };
483
+ }
484
+ );
485
+ }
486
+ }
487
+ }
488
+ });
489
+ const hasOperate = valueSchema.columns.find(
490
+ (item: any) => item.type === 'operation'
491
+ );
492
+ hasFeatures && !hasOperate && valueSchema.columns.push(oper);
493
+ return valueSchema;
494
+ },
495
+ canRebuild: true
496
+ };
497
+
498
+ addItem(source: any, target: any) {
499
+ const canAdd = source.find((item: any) => item.label === target.label);
500
+ if (!canAdd) {
501
+ source.push(target);
502
+ }
503
+ }
504
+
505
+ multifactor = true;
506
+ previewSchema: any = {
507
+ syncLocation: false,
508
+ type: 'crud',
509
+ className: 'text-left',
510
+ bodyClassName: 'm-b-none',
511
+ affixHeader: false,
512
+ data: {
513
+ items: [
514
+ {a: 1, b: 2},
515
+ {a: 3, b: 4},
516
+ {a: 5, b: 6}
517
+ ]
518
+ },
519
+ source: '${items}',
520
+ columns: [
521
+ {
522
+ label: 'A',
523
+ name: 'a'
524
+ },
525
+ {
526
+ label: 'B',
527
+ name: 'b'
528
+ },
529
+ {
530
+ type: 'operation',
531
+ label: '操作',
532
+ buttons: [
533
+ {
534
+ icon: 'fa fa-eye',
535
+ type: 'button'
536
+ },
537
+
538
+ {
539
+ icon: 'fa fa-edit',
540
+ type: 'button'
541
+ }
542
+ ]
543
+ }
544
+ ]
545
+ };
546
+
547
+ oldFilter?: any;
548
+ panelTitle = '增删改查';
549
+ panelBodyCreator = (context: BaseEventContext) => {
550
+ const store = this.manager.store;
551
+ const id = context.id;
552
+
553
+ return getSchemaTpl('tabs', [
554
+ {
555
+ title: '常规',
556
+ body: [
557
+ {
558
+ name: 'filter',
559
+ type: 'switch',
560
+ mode: 'inline',
561
+ className: 'block',
562
+ label: '启用查询条件',
563
+ pipeIn: (value: any) => !!value,
564
+ pipeOut: (value: any, originValue: any) => {
565
+ if (value) {
566
+ return (
567
+ this.oldFilter ||
568
+ JSONPipeIn({
569
+ title: '查询条件',
570
+ body: [
571
+ {
572
+ type: 'input-text',
573
+ name: 'keywords',
574
+ label: '关键字'
575
+ }
576
+ ]
577
+ })
578
+ );
579
+ } else {
580
+ this.oldFilter = originValue;
581
+ }
582
+
583
+ return null;
584
+ }
585
+ },
586
+
587
+ {
588
+ type: 'divider'
589
+ },
590
+
591
+ {
592
+ label: '批量操作',
593
+ name: 'bulkActions',
594
+ type: 'combo',
595
+ hiddenOn: 'data.pickerMode && data.multiple',
596
+ inputClassName: 'ae-BulkActions-control',
597
+ multiple: true,
598
+ draggable: true,
599
+ draggableTip: '',
600
+ scaffold: {
601
+ label: '按钮',
602
+ type: 'button'
603
+ },
604
+ labelRemark: {
605
+ className: 'm-l-xs',
606
+ trigger: 'click',
607
+ rootClose: true,
608
+ content:
609
+ '通过此可以管理批量操作按钮,只有设置了批量操作按钮才会出现选择框,可在外观中配置批量操作按钮位置。',
610
+ placement: 'left'
611
+ },
612
+ items: [
613
+ {
614
+ type: 'tpl',
615
+ tpl: '<span class="label label-success">${label}</span>',
616
+ columnClassName: 'p-t-xs'
617
+ },
618
+
619
+ {
620
+ columnClassName: 'p-t-xs col-edit',
621
+ children: ({index}: any) => (
622
+ <button
623
+ onClick={this.handleBulkActionEdit.bind(this, id, index)}
624
+ data-tooltip="修改"
625
+ data-position="bottom"
626
+ className="text-muted"
627
+ >
628
+ <i className="fa fa-pencil" />
629
+ </button>
630
+ )
631
+ }
632
+ ]
633
+ },
634
+
635
+ // {
636
+ // name: 'defaultChecked',
637
+ // type: 'switch',
638
+ // mode: 'inline',
639
+ // label: '默认是否全部勾选',
640
+ // visibleOn: 'data.bulkActions && data.bulkActions.length',
641
+ // pipeIn: defaultValue(false)
642
+ // },
643
+
644
+ {
645
+ type: 'divider'
646
+ },
647
+
648
+ {
649
+ label: '单条操作',
650
+ name: 'itemActions',
651
+ type: 'combo',
652
+ labelRemark: {
653
+ className: 'm-l-xs',
654
+ trigger: 'click',
655
+ rootClose: true,
656
+ content:
657
+ '设置后,当鼠标悬停行数据上,会出现该操作按钮,同时顶部操作栏也会显示该按钮,勾选成员时与批量按钮智能切换。',
658
+ placement: 'left'
659
+ },
660
+ hiddenOn: 'this.mode && this.mode !== "table" || this.pickerMode',
661
+ inputClassName: 'ae-BulkActions-control',
662
+ multiple: true,
663
+ draggable: true,
664
+ scaffold: {
665
+ label: '按钮',
666
+ type: 'button'
667
+ },
668
+ items: [
669
+ {
670
+ type: 'tpl',
671
+ tpl: '<span class="label label-success">${label}</span>',
672
+ columnClassName: 'p-t-xs'
673
+ },
674
+
675
+ {
676
+ type: 'checkbox',
677
+ className: 'text-xs',
678
+ option: '悬停隐藏',
679
+ name: 'hiddenOnHover'
680
+ },
681
+
682
+ {
683
+ columnClassName: 'p-t-xs col-edit',
684
+ children: ({index}: any) => (
685
+ <button
686
+ onClick={this.handleItemActionEdit.bind(this, id, index)}
687
+ data-tooltip="修改"
688
+ data-position="bottom"
689
+ className="text-muted"
690
+ >
691
+ <i className="fa fa-pencil" />
692
+ </button>
693
+ )
694
+ }
695
+ ]
696
+ },
697
+
698
+ {
699
+ type: 'divider',
700
+ hiddenOn: 'this.mode && this.mode !== "table" || this.pickerMode'
701
+ },
702
+
703
+ {
704
+ name: 'syncLocation',
705
+ label: '同步地址栏',
706
+ type: 'switch',
707
+ mode: 'inline',
708
+ className: 'block',
709
+ pipeIn: defaultValue(true),
710
+ labelRemark: {
711
+ className: 'm-l-xs',
712
+ trigger: 'click',
713
+ rootClose: true,
714
+ content:
715
+ '开启后会把查询条件数据和分页信息同步到地址栏中,页面中出现多个时,建议只保留一个同步地址栏,否则会相互影响。',
716
+ placement: 'left'
717
+ }
718
+ },
719
+
720
+ {
721
+ label: '默认参数',
722
+ type: 'input-kv',
723
+ name: 'defaultParams',
724
+ labelRemark: {
725
+ className: 'm-l-xs',
726
+ trigger: 'click',
727
+ rootClose: true,
728
+ content: '可以用来设置默认参数,比如 <code>perPage:20</code>',
729
+ placement: 'left'
730
+ }
731
+ },
732
+
733
+ {
734
+ type: 'divider'
735
+ },
736
+
737
+ {
738
+ name: 'keepItemSelectionOnPageChange',
739
+ label: '保留条目选择',
740
+ type: 'switch',
741
+ mode: 'inline',
742
+ className: 'block',
743
+ visbileOn:
744
+ 'this.bulkActions && this.bulkActions.length || this.itemActions && this.itemActions.length',
745
+ labelRemark: {
746
+ className: 'm-l-xs',
747
+ trigger: 'click',
748
+ rootClose: true,
749
+ content:
750
+ '默认分页、搜索后,用户选择条目会被清空,开启此选项后会保留用户选择,可以实现跨页面批量操作。',
751
+ placement: 'left'
752
+ }
753
+ },
754
+
755
+ {
756
+ name: 'labelTpl',
757
+ type: 'input-text',
758
+ label: '单条描述模板',
759
+ visibleOn: 'this.keepItemSelectionOnPageChange',
760
+ labelRemark: {
761
+ className: 'm-l-xs',
762
+ trigger: 'click',
763
+ rootClose: true,
764
+ content:
765
+ '开启【保留条目选择】后会把所有已选择条目列出来,此选项可以用来定制条目展示文案。',
766
+ placement: 'left'
767
+ }
768
+ },
769
+
770
+ {
771
+ name: 'primaryField',
772
+ label: '指定主键',
773
+ type: 'input-text',
774
+ pipeIn: defaultValue('id'),
775
+ description: '默认<code>id</code>,用于批量操作获取行级数据'
776
+ }
777
+ ]
778
+ },
779
+
780
+ {
781
+ title: '接口',
782
+ body: [
783
+ getSchemaTpl('api', {
784
+ label: '数据拉取接口',
785
+ sampleBuilder: (schema: any) => {
786
+ const data: any = {
787
+ items: [],
788
+ total: 0
789
+ };
790
+
791
+ if (Array.isArray(schema.columns)) {
792
+ const item = {};
793
+ schema.columns.forEach((control: any) => {
794
+ if (control.name) {
795
+ setVariable(item, control.name, 'sample');
796
+ }
797
+ });
798
+
799
+ data.items.push(item);
800
+ }
801
+
802
+ return JSON.stringify(
803
+ {
804
+ status: 0,
805
+ msg: '',
806
+ data: data
807
+ },
808
+ null,
809
+ 2
810
+ );
811
+ }
812
+ }),
813
+
814
+ {
815
+ name: 'initFetch',
816
+ type: 'radios',
817
+ label: '是否初始拉取',
818
+ pipeIn: (value: any) =>
819
+ (typeof value == 'boolean' && value) ||
820
+ (typeof value !== 'boolean' && ''),
821
+ inline: true,
822
+ onChange: () => {},
823
+ options: [
824
+ {
825
+ label: '是',
826
+ value: true
827
+ },
828
+
829
+ {
830
+ label: '否',
831
+ value: false
832
+ },
833
+
834
+ {
835
+ label: '表达式',
836
+ value: ''
837
+ }
838
+ ]
839
+ },
840
+
841
+ {
842
+ name: 'initFetch',
843
+ autoComplete: false,
844
+ visibleOn: 'typeof this.initFetch !== "boolean"',
845
+ type: 'input-text',
846
+ placeholder: '用 JS 表达式来决定',
847
+ className: 'm-t-n-sm'
848
+ },
849
+
850
+ {
851
+ name: 'loadDataOnce',
852
+ label: '一次性拉取',
853
+ type: 'switch',
854
+ mode: 'inline',
855
+ className: 'block',
856
+ labelRemark: {
857
+ className: 'm-l-xs',
858
+ trigger: 'click',
859
+ rootClose: true,
860
+ content:
861
+ '开启后,数据只会在初始的时候拉取,后续分页、排序不再请求接口,都由前端直接完成。',
862
+ placement: 'left'
863
+ }
864
+ },
865
+
866
+ {
867
+ label: '开启定时刷新',
868
+ type: 'switch',
869
+ name: 'interval',
870
+ visibleOn: 'data.api',
871
+ pipeIn: (value: any) => !!value,
872
+ pipeOut: (value: any) => (value ? 3000 : undefined),
873
+ mode: 'inline',
874
+ className: 'block'
875
+ },
876
+
877
+ {
878
+ name: 'interval',
879
+ type: 'input-number',
880
+ visibleOn: 'typeof data.interval === "number"',
881
+ step: 500,
882
+ className: 'm-t-n-sm',
883
+ description: '设置后将自动定时刷新,单位 ms'
884
+ },
885
+
886
+ {
887
+ name: 'silentPolling',
888
+ label: '静默刷新',
889
+ type: 'switch',
890
+ mode: 'inline',
891
+ visibleOn: '!!data.interval',
892
+ description: '设置自动定时刷新时是否显示loading'
893
+ },
894
+
895
+ {
896
+ name: 'stopAutoRefreshWhen',
897
+ label: '停止定时刷新检测表达式',
898
+ type: 'input-text',
899
+ visibleOn: '!!data.interval',
900
+ description:
901
+ '定时刷新一旦设置会一直刷新,除非给出表达式,条件满足后则不刷新了。'
902
+ },
903
+
904
+ {
905
+ name: 'stopAutoRefreshWhenModalIsOpen',
906
+ label: '当有弹框时关闭自动刷新',
907
+ type: 'switch',
908
+ visibleOn: '!!data.interval',
909
+ mode: 'inline',
910
+ className: 'block',
911
+ description: '弹框打开关闭自动刷新,关闭弹框又恢复'
912
+ },
913
+
914
+ {
915
+ type: 'divider'
916
+ },
917
+
918
+ {
919
+ name: 'draggable',
920
+ label: '是否可拖拽排序',
921
+ type: 'switch',
922
+ mode: 'inline',
923
+ className: 'block'
924
+ },
925
+
926
+ getSchemaTpl('api', {
927
+ label: '顺序保存接口',
928
+ name: 'saveOrderApi',
929
+ visibleOn: 'data.draggable'
930
+ }),
931
+
932
+ {
933
+ type: 'divider'
934
+ },
935
+
936
+ getSchemaTpl('api', {
937
+ label: '快速保存接口',
938
+ name: 'quickSaveApi',
939
+ description:
940
+ '当 column 中设置了快速编辑后将使用此接口批量保存数据。'
941
+ }),
942
+
943
+ {
944
+ type: 'divider'
945
+ },
946
+
947
+ getSchemaTpl('api', {
948
+ label: '快速保存单条接口',
949
+ name: 'quickSaveItemApi',
950
+ description:
951
+ '当 column 中设置了快速编辑且设置了立即保存,将使用此接口保存数据。'
952
+ }),
953
+
954
+ {
955
+ type: 'divider'
956
+ },
957
+
958
+ {
959
+ label: '默认消息提示',
960
+ type: 'combo',
961
+ name: 'messages',
962
+ multiLine: true,
963
+ description:
964
+ '覆盖默认消息提示,但如果 api 返回 msg 则会优先使用这个 msg',
965
+ items: [
966
+ {
967
+ label: '获取成功提示',
968
+ type: 'input-text',
969
+ name: 'fetchSuccess'
970
+ },
971
+
972
+ {
973
+ label: '获取失败提示',
974
+ type: 'input-text',
975
+ name: 'fetchFailed'
976
+ },
977
+
978
+ {
979
+ label: '保存顺序成功提示',
980
+ type: 'input-text',
981
+ name: 'saveOrderSuccess'
982
+ },
983
+
984
+ {
985
+ label: '保存顺序失败提示',
986
+ type: 'input-text',
987
+ name: 'saveOrderFailed'
988
+ },
989
+
990
+ {
991
+ label: '快速保存成功提示',
992
+ type: 'input-text',
993
+ name: 'quickSaveSuccess'
994
+ },
995
+
996
+ {
997
+ label: '快速保存失败提示',
998
+ type: 'input-text',
999
+ name: 'quickSaveFailed'
1000
+ }
1001
+ ]
1002
+ }
1003
+ ]
1004
+ },
1005
+
1006
+ {
1007
+ title: '外观',
1008
+ body: [
1009
+ {
1010
+ label: '内容展示模式',
1011
+ name: 'mode',
1012
+ type: 'button-group-select',
1013
+ size: 'xs',
1014
+ pipeIn: (value: any, values: any) =>
1015
+ (value === 'grid' ? 'cards' : value) ?? 'table',
1016
+ onChange: (value: any, oldValue: any, model: any, form: any) => {
1017
+ let headerHasColumnsToggle = form?.data?.headerToolbar?.some(
1018
+ (item: any) => item.type === 'columns-toggler'
1019
+ );
1020
+ let headerToolbar = cloneDeep(form?.data?.headerToolbar);
1021
+ let columnsToggler;
1022
+ if (value !== 'table' && oldValue === 'table') {
1023
+ // 存储table模式是否有 columns-toggler
1024
+ columnsToggler = headerToolbar?.find(
1025
+ (item: any) => item.type === 'columns-toggler'
1026
+ ) || {
1027
+ type: 'columns-toggler',
1028
+ align: 'right'
1029
+ };
1030
+ form.setValues({
1031
+ __headerHasColumnsToggler: headerHasColumnsToggle
1032
+ });
1033
+ }
1034
+ headerToolbar =
1035
+ value === 'table'
1036
+ ? headerToolbar
1037
+ : headerToolbar?.filter(
1038
+ (item: any) => item.type !== 'columns-toggler'
1039
+ );
1040
+ if (value === 'table') {
1041
+ if (
1042
+ form?.data?.__headerHasColumnsToggler &&
1043
+ !headerHasColumnsToggle
1044
+ ) {
1045
+ headerToolbar?.push(
1046
+ form?.data?.__cacheColumnsToggler || {
1047
+ type: 'columns-toggler',
1048
+ align: 'right'
1049
+ }
1050
+ );
1051
+ }
1052
+ form.setValues({
1053
+ headerToolbar,
1054
+ columns: form.data.__columns || [
1055
+ {
1056
+ label: 'ID',
1057
+ name: 'id'
1058
+ },
1059
+ {
1060
+ label: '列信息',
1061
+ name: 'name'
1062
+ }
1063
+ ],
1064
+ __headerHasColumnsToggler: headerHasColumnsToggle,
1065
+ __card: form.data.card || form.data.__card,
1066
+ __listItem: form.data.listItem || form.data.__listItem
1067
+ });
1068
+ form.deleteValueByName('card');
1069
+ form.deleteValueByName('listItem');
1070
+ } else if (value === 'cards') {
1071
+ oldValue === 'table' &&
1072
+ form.setValues({
1073
+ __cacheColumnsToggler: columnsToggler
1074
+ });
1075
+ form.setValues({
1076
+ headerToolbar,
1077
+ card: form.data.__card || {
1078
+ type: 'card',
1079
+ header: {
1080
+ title: '标题',
1081
+ subTitle: '副标题'
1082
+ },
1083
+ body: [
1084
+ {
1085
+ name: 'a',
1086
+ label: 'A'
1087
+ },
1088
+ {
1089
+ name: 'b',
1090
+ label: 'B'
1091
+ }
1092
+ ],
1093
+ actions: [
1094
+ {
1095
+ label: '详情',
1096
+ type: 'button'
1097
+ }
1098
+ ]
1099
+ },
1100
+ __columns: form.data.columns || form.data.__columns,
1101
+ __listItem: form.data.listItem || form.data.__listItem
1102
+ });
1103
+ form.deleteValueByName('columns');
1104
+ form.deleteValueByName('listItem');
1105
+ } else {
1106
+ oldValue === 'table' &&
1107
+ form.setValues({
1108
+ __cacheColumnsToggler: columnsToggler
1109
+ });
1110
+ form.setValues({
1111
+ headerToolbar,
1112
+ listItem: form.data.__listItem || {
1113
+ body: [
1114
+ {
1115
+ type: 'tpl',
1116
+ tpl: '简单的展示数据:$a $b'
1117
+ }
1118
+ ],
1119
+ actions: [
1120
+ {
1121
+ icon: 'fa fa-eye',
1122
+ type: 'button'
1123
+ }
1124
+ ]
1125
+ },
1126
+ __columns: form.data.columns || form.data.__columns,
1127
+ __card: form.data.card || form.data.__card
1128
+ });
1129
+ form.deleteValueByName('columns');
1130
+ form.deleteValueByName('card');
1131
+ }
1132
+ },
1133
+ options: [
1134
+ {
1135
+ value: 'table',
1136
+ label: '表格'
1137
+ },
1138
+
1139
+ {
1140
+ value: 'cards',
1141
+ label: '卡片'
1142
+ },
1143
+
1144
+ {
1145
+ value: 'list',
1146
+ label: '列表'
1147
+ }
1148
+ ]
1149
+ },
1150
+
1151
+ {
1152
+ name: 'headerToolbar',
1153
+ type: 'combo',
1154
+ draggable: true,
1155
+ draggableTip: '',
1156
+ descrition: '非内建内容请在预览区选中后编辑',
1157
+ label: '顶部工具栏配置',
1158
+ pipeIn: (value: any) => {
1159
+ if (!Array.isArray(value)) {
1160
+ value = value ? [value] : ['bulkActions'];
1161
+ }
1162
+ return value.map((item: any) => {
1163
+ let type = item.type;
1164
+
1165
+ if (
1166
+ typeof item === 'string' &&
1167
+ ~[
1168
+ 'bulkActions',
1169
+ 'bulk-actions',
1170
+ 'pagination',
1171
+ 'statistics',
1172
+ 'switch-per-page',
1173
+ 'filter-toggler',
1174
+ 'load-more',
1175
+ 'export-csv',
1176
+ 'export-excel'
1177
+ ].indexOf(item)
1178
+ ) {
1179
+ type = item === 'bulkActions' ? 'bulk-actions' : item;
1180
+ item = {type};
1181
+ } else if (typeof item === 'string') {
1182
+ type = 'tpl';
1183
+ item =
1184
+ typeof item === 'string' ? {type: 'tpl', tpl: item} : item;
1185
+ }
1186
+ return {
1187
+ type,
1188
+ ...item
1189
+ };
1190
+ });
1191
+ },
1192
+ pipeOut: (value: any) => {
1193
+ if (Array.isArray(value)) {
1194
+ return value.map((item: any) => {
1195
+ if (item.type === 'button') {
1196
+ return JSONPipeIn({
1197
+ label: '按钮',
1198
+ type: 'button',
1199
+ ...item
1200
+ });
1201
+ } else if (item.type === 'tpl') {
1202
+ return JSONPipeIn({
1203
+ type: 'tpl',
1204
+ tpl: '内容',
1205
+ ...item
1206
+ });
1207
+ }
1208
+
1209
+ return item;
1210
+ });
1211
+ }
1212
+
1213
+ return [];
1214
+ },
1215
+ scaffold: {
1216
+ type: 'tpl',
1217
+ tpl: '内容'
1218
+ },
1219
+ multiple: true,
1220
+ items: [
1221
+ {
1222
+ type: 'select',
1223
+ name: 'type',
1224
+ columnClassName: 'w-ssm',
1225
+ options: [
1226
+ {
1227
+ value: 'bulk-actions',
1228
+ label: '操作栏'
1229
+ },
1230
+
1231
+ {
1232
+ value: 'pagination',
1233
+ label: '分页'
1234
+ },
1235
+
1236
+ {
1237
+ value: 'statistics',
1238
+ label: '统计数据'
1239
+ },
1240
+
1241
+ {
1242
+ value: 'switch-per-page',
1243
+ label: '切换页码'
1244
+ },
1245
+
1246
+ {
1247
+ value: 'load-more',
1248
+ label: '加载更多'
1249
+ },
1250
+
1251
+ {
1252
+ value: 'export-csv',
1253
+ label: '导出 CSV'
1254
+ },
1255
+
1256
+ {
1257
+ value: 'export-excel',
1258
+ label: '导出 Excel'
1259
+ },
1260
+
1261
+ {
1262
+ value: 'columns-toggler',
1263
+ label: '列选择器',
1264
+ visibleOn: '!this.mode || this.mode === "table"'
1265
+ },
1266
+
1267
+ {
1268
+ value: 'filter-toggler',
1269
+ label: '查询条件切换'
1270
+ },
1271
+
1272
+ {
1273
+ value: 'drag-toggler',
1274
+ label: '拖拽切换'
1275
+ },
1276
+
1277
+ {
1278
+ value: 'check-all',
1279
+ label: '全选',
1280
+ hiddenOn: '!this.mode || this.mode === "table"'
1281
+ },
1282
+
1283
+ {
1284
+ value: 'tpl',
1285
+ label: '文本'
1286
+ },
1287
+
1288
+ {
1289
+ value: 'button',
1290
+ label: '按钮'
1291
+ }
1292
+ ]
1293
+ },
1294
+
1295
+ {
1296
+ name: 'align',
1297
+ placeholder: '对齐方式',
1298
+ type: 'select',
1299
+ size: 'xs',
1300
+ options: [
1301
+ {
1302
+ label: '左对齐',
1303
+ value: 'left'
1304
+ },
1305
+
1306
+ {
1307
+ label: '右对齐',
1308
+ value: 'right'
1309
+ }
1310
+ ]
1311
+ }
1312
+
1313
+ // {
1314
+ // type: 'remark',
1315
+ // content: '详情请在预览区域选中后进行编辑。',
1316
+ // trigger: ['click'],
1317
+ // rootClose: true,
1318
+ // placement: 'left',
1319
+ // visibleOn:
1320
+ // '!~["bulkActions", "drag-toggler", "check-all", "bulk-actions", "pagination", "statistics", "switch-per-page", "filter-toggler", "load-more"].indexOf(this.type)',
1321
+ // columnClassName: 'no-grow w-3x p-t-xs',
1322
+ // className: 'm-l-none'
1323
+ // }
1324
+ ]
1325
+ },
1326
+
1327
+ {
1328
+ name: 'footerToolbar',
1329
+ type: 'combo',
1330
+ draggable: true,
1331
+ draggableTip: '',
1332
+ descrition: '非内建内容请在预览区选中后编辑',
1333
+ label: '底部工具栏配置',
1334
+ pipeIn: (value: any) => {
1335
+ if (!Array.isArray(value)) {
1336
+ value = value ? [value] : ['statistics', 'pagination'];
1337
+ }
1338
+
1339
+ return value.map((item: any) => {
1340
+ let type = item.type;
1341
+
1342
+ if (
1343
+ typeof item === 'string' &&
1344
+ ~[
1345
+ 'bulkActions',
1346
+ 'bulk-actions',
1347
+ 'pagination',
1348
+ 'statistics',
1349
+ 'switch-per-page',
1350
+ 'filter-toggler',
1351
+ 'load-more',
1352
+ 'export-csv',
1353
+ 'export-excel'
1354
+ ].indexOf(item)
1355
+ ) {
1356
+ type = item === 'bulkActions' ? 'bulk-actions' : item;
1357
+ item = {type};
1358
+ } else if (typeof item === 'string') {
1359
+ type = 'tpl';
1360
+ item =
1361
+ typeof item === 'string' ? {type: 'tpl', tpl: item} : item;
1362
+ }
1363
+
1364
+ return {
1365
+ type,
1366
+ ...item
1367
+ };
1368
+ });
1369
+ },
1370
+ pipeOut: (value: any) => {
1371
+ if (Array.isArray(value)) {
1372
+ return value.map((item: any) => {
1373
+ if (item.type === 'button') {
1374
+ return JSONPipeIn({
1375
+ label: '按钮',
1376
+ type: 'button',
1377
+ ...item
1378
+ });
1379
+ } else if (item.type === 'tpl') {
1380
+ return JSONPipeIn({
1381
+ type: 'tpl',
1382
+ tpl: '内容',
1383
+ ...item
1384
+ });
1385
+ }
1386
+
1387
+ return item;
1388
+ });
1389
+ }
1390
+
1391
+ return [];
1392
+ },
1393
+ scaffold: {
1394
+ type: 'tpl',
1395
+ tpl: '内容'
1396
+ },
1397
+ multiple: true,
1398
+ items: [
1399
+ {
1400
+ type: 'select',
1401
+ name: 'type',
1402
+ columnClassName: 'w-ssm',
1403
+ options: [
1404
+ {
1405
+ value: 'bulk-actions',
1406
+ label: '操作栏'
1407
+ },
1408
+
1409
+ {
1410
+ value: 'pagination',
1411
+ label: '分页'
1412
+ },
1413
+
1414
+ {
1415
+ value: 'statistics',
1416
+ label: '统计数据'
1417
+ },
1418
+
1419
+ {
1420
+ value: 'switch-per-page',
1421
+ label: '切换页码'
1422
+ },
1423
+
1424
+ {
1425
+ value: 'load-more',
1426
+ label: '加载更多'
1427
+ },
1428
+
1429
+ {
1430
+ value: 'export-csv',
1431
+ label: '导出 CSV'
1432
+ },
1433
+
1434
+ {
1435
+ value: 'export-excel',
1436
+ label: '导出 Excel'
1437
+ },
1438
+
1439
+ {
1440
+ value: 'columns-toggler',
1441
+ label: '列选择器',
1442
+ hiddenOn: '["grid", "cards", "list"].indexOf(this.mode)'
1443
+ },
1444
+
1445
+ {
1446
+ value: 'filter-toggler',
1447
+ label: '查询条件切换'
1448
+ },
1449
+
1450
+ {
1451
+ value: 'drag-toggler',
1452
+ label: '拖拽切换'
1453
+ },
1454
+
1455
+ {
1456
+ value: 'check-all',
1457
+ label: '全选',
1458
+ hiddenOn: '!this.mode || this.mode === "table"'
1459
+ },
1460
+
1461
+ {
1462
+ value: 'tpl',
1463
+ label: '文本'
1464
+ },
1465
+
1466
+ {
1467
+ value: 'button',
1468
+ label: '按钮'
1469
+ }
1470
+ ]
1471
+ },
1472
+
1473
+ {
1474
+ name: 'align',
1475
+ placeholder: '对齐方式',
1476
+ size: 'xs',
1477
+ type: 'select',
1478
+ options: [
1479
+ {
1480
+ label: '左对齐',
1481
+ value: 'left'
1482
+ },
1483
+
1484
+ {
1485
+ label: '右对齐',
1486
+ value: 'right'
1487
+ }
1488
+ ]
1489
+ },
1490
+
1491
+ {
1492
+ type: 'remark',
1493
+ content: '详情请在预览区域选中后进行编辑。',
1494
+ trigger: ['click'],
1495
+ rootClose: true,
1496
+ placement: 'left',
1497
+ visibleOn:
1498
+ '!~["bulkActions", "drag-toggler", "check-all", "bulk-actions", "pagination", "statistics", "switch-per-page", "filter-toggler", "load-more", "export-csv", "export-excel"].indexOf(this.type)',
1499
+ columnClassName: 'no-grow w-3x p-t-xs',
1500
+ className: 'm-l-none'
1501
+ }
1502
+ ]
1503
+ },
1504
+
1505
+ {
1506
+ name: 'filterTogglable',
1507
+ type: 'switch',
1508
+ label: '是否可显隐查询条件',
1509
+ mode: 'inline',
1510
+ className: 'block',
1511
+ visibleOn: 'data.filter'
1512
+ },
1513
+
1514
+ {
1515
+ name: 'filterDefaultVisible',
1516
+ type: 'switch',
1517
+ label: '查询条件默认是否可见',
1518
+ pipeIn: defaultValue(true),
1519
+ mode: 'inline',
1520
+ className: 'block',
1521
+ visibleOn: 'data.filter && data.filterTogglable'
1522
+ },
1523
+
1524
+ {
1525
+ name: 'hideQuickSaveBtn',
1526
+ label: '隐藏顶部快速保存提示',
1527
+ type: 'switch',
1528
+ mode: 'inline',
1529
+ className: 'block'
1530
+ },
1531
+
1532
+ {
1533
+ name: 'alwaysShowPagination',
1534
+ label: '是否总是显示分页',
1535
+ type: 'switch',
1536
+ mode: 'inline',
1537
+ className: 'block'
1538
+ },
1539
+
1540
+ {
1541
+ name: 'hideCheckToggler',
1542
+ type: 'switch',
1543
+ label: '隐藏选择按钮',
1544
+ mode: 'inline',
1545
+ className: 'block',
1546
+ visibleOn: 'data.checkOnItemClick'
1547
+ },
1548
+
1549
+ getSchemaTpl('className'),
1550
+
1551
+ getSchemaTpl('className', {
1552
+ name: 'bodyClassName',
1553
+ label: '内容 CSS 类名'
1554
+ })
1555
+ ]
1556
+ },
1557
+
1558
+ {
1559
+ title: '其他',
1560
+ body: [
1561
+ getSchemaTpl('ref'),
1562
+ {
1563
+ name: 'source',
1564
+ label: '数据源',
1565
+ type: 'input-text',
1566
+ description:
1567
+ '不填写,默认读取接口返回的 items 或者 rows 属性,如果是别的,请在此设置,如: <code>\\${xxxx}</code>'
1568
+ },
1569
+
1570
+ {
1571
+ name: 'perPage',
1572
+ label: '每页数量',
1573
+ type: 'input-number'
1574
+ },
1575
+
1576
+ {
1577
+ name: 'keepItemSelectionOnPageChange',
1578
+ label: '翻页时保留选择',
1579
+ type: 'switch',
1580
+ mode: 'inline',
1581
+ className: 'block'
1582
+ },
1583
+
1584
+ {
1585
+ name: 'maxKeepItemSelectionLength',
1586
+ label: '最大选择数量',
1587
+ type: 'input-number',
1588
+ mode: 'inline',
1589
+ className: 'block'
1590
+ },
1591
+
1592
+ {
1593
+ name: 'pageField',
1594
+ label: '页码字段名',
1595
+ type: 'input-text',
1596
+ pipeIn: defaultValue('page')
1597
+ },
1598
+
1599
+ {
1600
+ name: 'perPageField',
1601
+ label: '分页步长字段名',
1602
+ type: 'input-text',
1603
+ pipeIn: defaultValue('perPage')
1604
+ },
1605
+
1606
+ {
1607
+ name: 'orderField',
1608
+ label: '排序权重字段',
1609
+ type: 'input-text',
1610
+ labelRemark: {
1611
+ className: 'm-l-xs',
1612
+ trigger: 'click',
1613
+ rootClose: true,
1614
+ content:
1615
+ '设置用来确定位置的字段名,设置后新的顺序将被赋值到该字段中。',
1616
+ placement: 'left'
1617
+ }
1618
+ },
1619
+
1620
+ {
1621
+ name: 'perPageAvailable',
1622
+ label: '切换每页数',
1623
+ type: 'input-array',
1624
+ hiddenOn: 'data.loadDataOnce',
1625
+ items: {
1626
+ type: 'input-number',
1627
+ required: true
1628
+ },
1629
+ value: [10]
1630
+ },
1631
+
1632
+ getSchemaTpl('name'),
1633
+
1634
+ {
1635
+ name: 'itemCheckableOn',
1636
+ type: 'input-text',
1637
+ label: '配置单条可选中的表达式',
1638
+ description: '请使用 js 表达式,不设置的话每条都可选中。',
1639
+ visibleOn:
1640
+ 'data.bulkActions && data.bulkActions.length || data.pickerMode'
1641
+ },
1642
+
1643
+ {
1644
+ name: 'checkOnItemClick',
1645
+ type: 'switch',
1646
+ label: '开启单条点击整个区域选中',
1647
+ mode: 'inline',
1648
+ className: 'block',
1649
+ visibleOn:
1650
+ 'data.bulkActions && data.bulkActions.length || data.pickerMode'
1651
+ },
1652
+
1653
+ {
1654
+ name: 'autoJumpToTopOnPagerChange',
1655
+ type: 'switch',
1656
+ label: '自动跳顶部',
1657
+ mode: 'inline',
1658
+ className: 'block',
1659
+ description: '当切分页的时候,是否自动跳顶部'
1660
+ },
1661
+
1662
+ {
1663
+ name: 'syncResponse2Query',
1664
+ type: 'switch',
1665
+ label: '同步查询条件',
1666
+ mode: 'inline',
1667
+ className: 'block',
1668
+ description: '查询后将返回的数据同步到查询条件上'
1669
+ }
1670
+ ]
1671
+ }
1672
+ ]);
1673
+ };
1674
+
1675
+ handleBulkActionEdit(id: string, index: number) {
1676
+ const store = this.manager.store;
1677
+ const schema = store.getSchema(id);
1678
+ const action = schema?.bulkActions[index];
1679
+
1680
+ if (action && action.$$id) {
1681
+ store.setActiveId(action.$$id);
1682
+ }
1683
+ }
1684
+ handleItemActionEdit(id: string, index: number) {
1685
+ const store = this.manager.store;
1686
+ const schema = store.getSchema(id);
1687
+ const action = schema?.itemActions[index];
1688
+
1689
+ if (action && action.$$id) {
1690
+ store.setActiveId(action.$$id);
1691
+ }
1692
+ }
1693
+
1694
+ wrapperProps = {
1695
+ affixHeader: false
1696
+ };
1697
+
1698
+ /**
1699
+ * 默认什么组件都加入的子组件里面,子类里面可以复写这个改变行为。
1700
+ * @param context
1701
+ * @param renderers
1702
+ */
1703
+ buildSubRenderers(
1704
+ context: RendererEventContext,
1705
+ renderers: Array<SubRendererInfo>
1706
+ ): BasicSubRenderInfo | Array<BasicSubRenderInfo> | void {
1707
+ const plugin: PluginInterface = this;
1708
+ if (plugin.name && plugin.description) {
1709
+ return {
1710
+ name: plugin.name,
1711
+ icon: plugin.icon,
1712
+ description: plugin.description,
1713
+ previewSchema: plugin.previewSchema,
1714
+ tags: plugin.tags,
1715
+ docLink: plugin.docLink,
1716
+ type: plugin.type,
1717
+ scaffold: plugin.scaffold,
1718
+ disabledRendererPlugin: plugin.disabledRendererPlugin,
1719
+ isBaseComponent: plugin.isBaseComponent,
1720
+ scaffoldForm: this.scaffoldForm,
1721
+ rendererName: plugin.rendererName
1722
+ };
1723
+ }
1724
+ }
1725
+
1726
+ getRendererInfo(
1727
+ context: RendererInfoResolveEventContext
1728
+ ): BasicRendererInfo | void {
1729
+ const info = super.getRendererInfo(context);
1730
+ if (info) {
1731
+ info.scaffoldForm = this.scaffoldForm;
1732
+ }
1733
+ return info;
1734
+ }
1735
+
1736
+ renderEditableComponents(props: any) {
1737
+ const render = props.render;
1738
+ const bulkActions = props.bulkActions;
1739
+ const itemActions = props.itemActions;
1740
+ const doms: Array<JSX.Element> = [];
1741
+
1742
+ if (Array.isArray(bulkActions) && bulkActions.length) {
1743
+ doms.push(
1744
+ <div key="bulkActions" className="ae-EditableRender">
1745
+ <div className="ae-EditableRender-title">批量操作</div>
1746
+ <div className="ae-EditableRender-body">
1747
+ {bulkActions.map(action =>
1748
+ render(
1749
+ 'bulk-action',
1750
+ {
1751
+ type: 'button',
1752
+ size: 'sm',
1753
+ ...action
1754
+ },
1755
+ {
1756
+ key: action.$$id
1757
+ }
1758
+ )
1759
+ )}
1760
+ </div>
1761
+ </div>
1762
+ );
1763
+ }
1764
+
1765
+ if (Array.isArray(itemActions) && itemActions.length) {
1766
+ doms.push(
1767
+ <div key="itemActions" className="ae-EditableRender">
1768
+ <div className="ae-EditableRender-title">单条操作</div>
1769
+ <div className="ae-EditableRender-body">
1770
+ {itemActions.map(action =>
1771
+ render(
1772
+ 'bulk-action',
1773
+ {
1774
+ type: 'button',
1775
+ size: 'sm',
1776
+ ...action
1777
+ },
1778
+ {
1779
+ key: action.$$id
1780
+ }
1781
+ )
1782
+ )}
1783
+ </div>
1784
+ </div>
1785
+ );
1786
+ }
1787
+
1788
+ if (!doms.length) {
1789
+ return null;
1790
+ }
1791
+
1792
+ return (
1793
+ <div className="ae-EditableRenderers">
1794
+ <div className="ae-EditableRenderers-tip">「增删改查」编辑辅助区</div>
1795
+ {doms}
1796
+ </div>
1797
+ );
1798
+ }
1799
+
1800
+ renderRenderer(props: any) {
1801
+ const $$editor = props.$$editor;
1802
+ const renderer = $$editor.renderer;
1803
+ return (
1804
+ <div className="ae-CRUDEditor">
1805
+ {this.renderEditableComponents(props)}
1806
+ <renderer.component {...props} />
1807
+ </div>
1808
+ );
1809
+ }
1810
+
1811
+ filterProps(props: any) {
1812
+ if (props.pickerMode) {
1813
+ props.options = props.data.options;
1814
+ }
1815
+
1816
+ return props;
1817
+ }
1818
+
1819
+ afterUpdate(event: PluginEvent<ChangeEventContext>) {
1820
+ const context = event.context;
1821
+
1822
+ // mode 内容形式变化,需要重新构建面板。
1823
+ if (
1824
+ context.info.plugin === this &&
1825
+ context.diff?.some(change => change.path?.join('.') === 'mode')
1826
+ ) {
1827
+ setTimeout(() => {
1828
+ this.manager.buildPanels();
1829
+ this.manager.buildToolbars();
1830
+ }, 20);
1831
+ }
1832
+ }
1833
+ }
1834
+
1835
+ registerEditorPlugin(CRUDPlugin);