amis-editor 4.1.0-beta.1 → 4.1.0-beta.20

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