@dckj-npm/dc-material 0.1.375 → 0.1.377

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/build/docs/colorful-button.html +3 -3
  2. package/build/docs/colorful-input.html +3 -3
  3. package/build/docs/index.html +3 -3
  4. package/build/docs/teletext-list.html +3 -3
  5. package/build/docs/umi.6f6bf535.js +1 -0
  6. package/build/docs/{umi.6743fcd4.css → umi.9770df27.css} +1 -1
  7. package/build/docs/~demos/colorful-button-demo.html +3 -3
  8. package/build/docs/~demos/colorful-input-demo.html +3 -3
  9. package/build/docs/~demos/teletext-list-demo-1.html +3 -3
  10. package/build/docs/~demos/teletext-list-demo.html +3 -3
  11. package/build/lowcode/assets-daily.json +13 -13
  12. package/build/lowcode/assets-dev.json +2 -2
  13. package/build/lowcode/assets-prod.json +13 -13
  14. package/build/lowcode/meta.design.js +1 -1
  15. package/build/lowcode/meta.js +1 -1
  16. package/build/lowcode/render/default/view.css +1 -1
  17. package/build/lowcode/render/default/view.js +1 -1
  18. package/build/lowcode/view.css +1 -1
  19. package/build/lowcode/view.js +1 -1
  20. package/dist/BizComps.css +1 -1
  21. package/dist/BizComps.js +2 -2
  22. package/dist/BizComps.js.map +1 -1
  23. package/es/components/teletext-list/teletext-list-item.d.ts +14 -77
  24. package/es/components/teletext-list/teletext-list-item.js +153 -157
  25. package/es/components/teletext-list/teletext-list-item.scss +53 -4
  26. package/es/components/teletext-list/teletext-list.d.ts +60 -4
  27. package/es/components/teletext-list/teletext-list.js +55 -37
  28. package/lib/components/teletext-list/teletext-list-item.d.ts +14 -77
  29. package/lib/components/teletext-list/teletext-list-item.js +153 -156
  30. package/lib/components/teletext-list/teletext-list-item.scss +53 -4
  31. package/lib/components/teletext-list/teletext-list.d.ts +60 -4
  32. package/lib/components/teletext-list/teletext-list.js +55 -37
  33. package/lowcode/teletext-list/meta.ts +460 -760
  34. package/lowcode/teletext-list/meta.ts.bak +821 -0
  35. package/lowcode_es/meta.js +1 -1
  36. package/lowcode_es/teletext-list/meta.js +686 -646
  37. package/lowcode_es/teletext-list/meta.ts.bak +821 -0
  38. package/lowcode_lib/meta.js +1 -1
  39. package/lowcode_lib/teletext-list/meta.js +688 -648
  40. package/lowcode_lib/teletext-list/meta.ts.bak +821 -0
  41. package/package.json +3 -3
  42. package/build/docs/umi.04debc3c.js +0 -1
@@ -3,13 +3,6 @@ import {
3
3
  IPublicTypeSnippet,
4
4
  } from '@alilc/lowcode-types'
5
5
 
6
- const IMAGE_KEY = 'image'
7
-
8
- const normalizeNodeKey = (rawKey: any): string => {
9
- if (rawKey === undefined || rawKey === null) return ''
10
- return String(rawKey).replace(/^\.?\$?/, '')
11
- }
12
-
13
6
  const parsePxNumber = (value: any): number | undefined => {
14
7
  if (typeof value === 'number' && Number.isFinite(value)) {
15
8
  return value
@@ -27,46 +20,6 @@ const parsePxNumber = (value: any): number | undefined => {
27
20
  return undefined
28
21
  }
29
22
 
30
- const findImageChildNode = (target: any): any | undefined => {
31
- const children = target?.node?.children
32
- if (!children) return undefined
33
- if (typeof children.find === 'function') {
34
- return children.find((child: any) => {
35
- return normalizeNodeKey(child?.getPropValue?.('key')) === IMAGE_KEY
36
- })
37
- }
38
- return undefined
39
- }
40
-
41
- const getImageStyleNumber = (target: any, styleKey: 'width' | 'height'): number | undefined => {
42
- const imageChildNode = findImageChildNode(target)
43
- if (imageChildNode) {
44
- return parsePxNumber(imageChildNode.getPropValue?.('style')?.[styleKey])
45
- }
46
- return undefined
47
- }
48
-
49
- /**
50
- * 同步 Image 子节点的 style.width / style.height。
51
- * 使用 Promise.resolve().then() 异步执行,避免在父节点 setPropValue
52
- * 的 MobX 同步响应链中触发子节点变更(可能导致 SettingField 重建)。
53
- */
54
- const syncImageStyleValue = (target: any, styleKey: 'width' | 'height', value: number): void => {
55
- Promise.resolve().then(() => {
56
- const imageChildNode = findImageChildNode(target)
57
- if (!imageChildNode) return
58
- const currentStyle = imageChildNode.getPropValue?.('style') || {}
59
- const updatedStyle: Record<string, any> = { ...currentStyle, [styleKey]: `${value}px` }
60
- const otherKey = styleKey === 'width' ? 'height' : 'width'
61
- if (!updatedStyle[otherKey]) {
62
- const otherPropKey = otherKey === 'width' ? 'imgWidth' : 'imgHeight'
63
- const otherPropValue = parsePxNumber(target?.getProps?.()?.getPropValue?.(otherPropKey))
64
- updatedStyle[otherKey] = `${otherPropValue ?? 100}px`
65
- }
66
- imageChildNode.setPropValue?.('style', updatedStyle)
67
- })
68
- }
69
-
70
23
  const TeletextListMeta: IPublicTypeComponentMetadata = {
71
24
  group: '低代码组件',
72
25
  componentName: 'TeletextList',
@@ -85,434 +38,484 @@ const TeletextListMeta: IPublicTypeComponentMetadata = {
85
38
  },
86
39
  configure: {
87
40
  props: [
41
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
42
+ // 分组一:数据与内容
43
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
88
44
  {
89
- title: {
90
- label: {
91
- type: 'i18n',
92
- 'en-US': 'type',
93
- 'zh-CN': '类型',
94
- },
95
- },
96
- name: 'type',
97
- description: '类型',
98
- setter: {
99
- componentName: 'RadioGroupSetter',
100
- props: {
101
- dataSource: [
102
- {
103
- label: '图文',
104
- value: 'textAndImg',
45
+ type: 'group',
46
+ title: '数据与内容',
47
+ display: 'accordion',
48
+ items: [
49
+ {
50
+ title: '标题',
51
+ name: 'title',
52
+ description: '列表头部标题文本',
53
+ setter: { componentName: 'StringSetter', isRequired: false, initialValue: '' },
54
+ },
55
+ {
56
+ title: '更多文字',
57
+ name: 'moreText',
58
+ description: '更多按钮文字,为空时不显示',
59
+ setter: { componentName: 'StringSetter', isRequired: false, initialValue: '' },
60
+ },
61
+ {
62
+ title: '文本槽位数',
63
+ name: 'textLines',
64
+ description: '每项渲染几个文本字段:2=标题+说明,3=加text3,4=加text3+text4。这是"显示几格",不是"每格显示几行"——行数截断请到"标题/说明文字样式"分组修改"最大行数"。',
65
+ setter: {
66
+ componentName: 'NumberSetter',
67
+ isRequired: false,
68
+ initialValue: 2,
69
+ defaultValue: 2,
70
+ props: { min: 2, max: 4 },
71
+ },
72
+ extraProps: {
73
+ setValue(target, value) {
74
+ target.getProps().setPropValue('textLines', value)
75
+ const dataListBindProp = (target?.parent as any)?.items?.find(
76
+ (item: any) => item.name === 'dataListBind',
77
+ )
78
+ if (dataListBindProp?.setter) {
79
+ const baseChildren = [
80
+ { label: '图片链接', value: 'image' },
81
+ { label: '类型', value: 'itemType' },
82
+ { label: '标题', value: 'title' },
83
+ { label: '说明', value: 'description' },
84
+ ]
85
+ const textChildren = value > 2
86
+ ? Array.from({ length: value - 2 }).map((_, i) => ({
87
+ label: `文本${i + 3}`,
88
+ value: `text${i + 3}`,
89
+ }))
90
+ : []
91
+ dataListBindProp.setter.props.attributes[0].children = [
92
+ ...baseChildren,
93
+ ...textChildren,
94
+ ]
95
+ }
105
96
  },
106
- {
107
- label: '仅有图片',
108
- value: 'imgOnly',
97
+ },
98
+ },
99
+ {
100
+ title: '数据源绑定',
101
+ name: 'dataListBind',
102
+ setter: {
103
+ componentName: 'SetterFormVariable',
104
+ props: {
105
+ attributes: [
106
+ {
107
+ label: '图文数据',
108
+ value: 'dataList',
109
+ children: [
110
+ { label: '图片链接', value: 'image' },
111
+ { label: '行类型(值为"开关"时该行显示开关控件)', value: 'itemType' },
112
+ { label: '标题', value: 'title' },
113
+ { label: '说明', value: 'description' },
114
+ ],
115
+ },
116
+ ],
109
117
  },
110
- {
111
- label: '仅有文字',
112
- value: 'textOnly',
118
+ },
119
+ extraProps: {},
120
+ },
121
+ {
122
+ title: { label: { type: 'i18n', 'en-US': 'dataList', 'zh-CN': '静态数据' }, tip: 'dataList | 静态数据' },
123
+ name: 'dataList',
124
+ description: '列表静态数据,绑定数据源后此项被覆盖',
125
+ setter: {
126
+ componentName: 'ArraySetter',
127
+ props: {
128
+ itemSetter: {
129
+ componentName: 'ObjectSetter',
130
+ props: {
131
+ config: {
132
+ items: [
133
+ {
134
+ title: { label: { type: 'i18n', 'en-US': 'title', 'zh-CN': '标题' } },
135
+ name: 'title',
136
+ setter: { componentName: 'StringSetter', isRequired: false, initialValue: '' },
137
+ },
138
+ {
139
+ title: { label: { type: 'i18n', 'en-US': 'image', 'zh-CN': '图片地址' } },
140
+ name: 'image',
141
+ setter: { componentName: 'CustomImageSetter', isRequired: false, initialValue: '' },
142
+ },
143
+ {
144
+ title: { label: { type: 'i18n', 'en-US': 'description', 'zh-CN': '描述' } },
145
+ name: 'description',
146
+ setter: { componentName: 'StringSetter', isRequired: false, initialValue: '' },
147
+ },
148
+ {
149
+ title: { label: { type: 'i18n', 'en-US': 'text3', 'zh-CN': '文本3' } },
150
+ name: 'text3',
151
+ description: '文本槽位数 ≥ 3 时显示',
152
+ setter: { componentName: 'StringSetter', isRequired: false, initialValue: '' },
153
+ },
154
+ {
155
+ title: { label: { type: 'i18n', 'en-US': 'text4', 'zh-CN': '文本4' } },
156
+ name: 'text4',
157
+ description: '文本槽位数 = 4 时显示',
158
+ setter: { componentName: 'StringSetter', isRequired: false, initialValue: '' },
159
+ },
160
+ {
161
+ title: { label: { type: 'i18n', 'en-US': 'itemType', 'zh-CN': '行类型' } },
162
+ name: 'itemType',
163
+ description: '值为"开关"时该行显示开关控件,留空为默认文字行',
164
+ setter: {
165
+ componentName: 'SelectSetter',
166
+ props: {
167
+ options: [
168
+ { label: '默认(文字行)', value: '' },
169
+ { label: '开关', value: '开关' },
170
+ ],
171
+ },
172
+ initialValue: '',
173
+ },
174
+ },
175
+ ],
176
+ extraSetter: { componentName: 'MixedSetter', isRequired: false, props: {} },
177
+ },
178
+ },
179
+ },
113
180
  },
114
- ],
115
- options: [
116
- {
117
- label: '图文',
118
- value: 'textAndImg',
181
+ initialValue: (target) => {
182
+ const existing = target?.node?.schema?.props?.dataList
183
+ ?? target?.getProps?.()?.getPropValue?.('dataList')
184
+ if (existing !== undefined) return existing
185
+ return DEFAULT_DATA_LIST
119
186
  },
120
- {
121
- label: '仅有图片',
122
- value: 'imgOnly',
187
+ },
188
+ extraProps: {
189
+ ignoreDefaultValue: () => true,
190
+ getValue: (target: any, currentValue: any) => {
191
+ if (currentValue !== undefined) return currentValue
192
+ const fromSchema = target?.node?.schema?.props?.dataList
193
+ if (fromSchema !== undefined) return fromSchema
194
+ return undefined
123
195
  },
124
- {
125
- label: '仅有文字',
126
- value: 'textOnly',
196
+ },
197
+ },
198
+ {
199
+ title: '类型',
200
+ name: 'type',
201
+ description: '列表类型',
202
+ setter: {
203
+ componentName: 'RadioGroupSetter',
204
+ props: {
205
+ options: [
206
+ { label: '图文', value: 'textAndImg' },
207
+ { label: '仅图片', value: 'imgOnly' },
208
+ { label: '仅文字', value: 'textOnly' },
209
+ ],
127
210
  },
128
- ],
211
+ initialValue: 'textAndImg',
212
+ },
129
213
  },
130
- initialValue: 'textAndImg',
131
- },
214
+ {
215
+ title: '是否购物车列表',
216
+ name: 'isShoppingCart',
217
+ setter: { componentName: 'BoolSetter', isRequired: true, initialValue: false },
218
+ },
219
+ {
220
+ title: '是否愿望单列表',
221
+ name: 'isWishList',
222
+ setter: { componentName: 'BoolSetter', isRequired: true, initialValue: false },
223
+ },
224
+ {
225
+ title: '是否用户菜单列表',
226
+ name: 'isUserMenu',
227
+ setter: { componentName: 'BoolSetter', isRequired: true, initialValue: false },
228
+ },
229
+ ],
132
230
  },
231
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
232
+ // 分组二:列表布局
233
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
133
234
  {
134
- title: {
135
- label: {
136
- type: 'i18n',
137
- 'en-US': 'imagePlacement',
138
- 'zh-CN': '图片位置',
139
- },
140
- },
141
- name: 'imagePlacement',
142
- description: '图片位置',
143
- setter: {
144
- componentName: 'RadioGroupSetter',
145
- props: {
146
- dataSource: [
147
- {
148
- label: '左',
149
- value: 'left',
150
- },
151
- {
152
- label: '右',
153
- value: 'right',
154
- },
155
- {
156
- label: '上',
157
- value: 'top',
158
- },
159
- {
160
- label: '下',
161
- value: 'bottom',
162
- },
163
- {
164
- label: '无',
165
- value: 'none',
166
- },
167
- ],
168
- options: [
169
- {
170
- label: '左',
171
- value: 'left',
172
- },
173
- {
174
- label: '右',
175
- value: 'right',
176
- },
177
- {
178
- label: '上',
179
- value: 'top',
235
+ type: 'group',
236
+ title: '列表布局',
237
+ display: 'accordion',
238
+ items: [
239
+ {
240
+ title: '子项分布',
241
+ name: 'itemRowAlign',
242
+ description: '列方向或横向一行滚动',
243
+ setter: {
244
+ componentName: 'RadioGroupSetter',
245
+ props: {
246
+ options: [
247
+ { label: '纵向列表', value: 'column' },
248
+ { label: '横向滚动', value: 'row' },
249
+ ],
180
250
  },
181
- {
182
- label: '下',
183
- value: 'bottom',
251
+ initialValue: 'column',
252
+ },
253
+ },
254
+ {
255
+ title: '子项列数',
256
+ name: 'itemColumns',
257
+ description: '纵向模式时的列数(1-4)',
258
+ setter: {
259
+ componentName: 'NumberSetter',
260
+ isRequired: false,
261
+ initialValue: (target) => {
262
+ const p = target.getProps().getPropValue('imagePlacement')
263
+ return p === 'top' || p === 'bottom' ? 2 : 1
184
264
  },
185
- {
186
- label: '',
187
- value: 'none',
265
+ defaultValue: (target) => {
266
+ const p = target.getProps().getPropValue('imagePlacement')
267
+ return p === 'top' || p === 'bottom' ? 2 : 1
188
268
  },
189
- ],
269
+ props: { min: 1, max: 4 },
270
+ },
190
271
  },
191
- initialValue: 'left',
192
- },
193
- extraProps: {
194
- // 引擎已自动 setPropValue('imagePlacement', value),无需再做任何额外写入
195
- // 之前的快照-还原逻辑反而触发多余的 MobX 响应链,导致 dataList 被覆盖
196
- },
197
- },
198
- {
199
- title: '图片宽度',
200
- name: 'imgWidth',
201
- description: '图片宽度',
202
- setter: {
203
- componentName: 'NumberSetter',
204
- isRequired: false,
205
- initialValue: 100,
206
- },
207
- extraProps: {
208
- getValue: (target, value) => {
209
- if (value !== undefined) return parsePxNumber(value) ?? 100
210
- const styleWidth = getImageStyleNumber(target, 'width')
211
- if (styleWidth !== undefined) return styleWidth
212
- return 100
213
- },
214
- setValue: (target, value) => {
215
- // 引擎已自动 setPropValue('imgWidth', value)
216
- // 只需同步到 Image 子节点的 style
217
- const parsedValue = parsePxNumber(value)
218
- if (parsedValue !== undefined) {
219
- syncImageStyleValue(target, 'width', parsedValue)
220
- }
272
+ {
273
+ title: '子项间距',
274
+ name: 'itemGap',
275
+ description: '子项之间的间距(px)',
276
+ setter: { componentName: 'NumberSetter', isRequired: false, initialValue: 10, defaultValue: 10, props: { min: 0 } },
221
277
  },
222
- },
278
+ ],
223
279
  },
280
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
281
+ // 分组三:列表项样式
282
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
224
283
  {
225
- title: '图片高度',
226
- name: 'imgHeight',
227
- description: '图片高度',
228
- setter: {
229
- componentName: 'NumberSetter',
230
- isRequired: false,
231
- initialValue: 100,
232
- },
233
- extraProps: {
234
- getValue: (target, value) => {
235
- if (value !== undefined) return parsePxNumber(value) ?? 100
236
- const styleHeight = getImageStyleNumber(target, 'height')
237
- if (styleHeight !== undefined) return styleHeight
238
- return 100
239
- },
240
- setValue: (target, value) => {
241
- // 引擎已自动 setPropValue('imgHeight', value)
242
- // 只需同步到 Image 子节点的 style
243
- const parsedValue = parsePxNumber(value)
244
- if (parsedValue !== undefined) {
245
- syncImageStyleValue(target, 'height', parsedValue)
246
- }
247
- },
248
- },
284
+ type: 'group',
285
+ title: '子项样式',
286
+ display: 'accordion',
287
+ items: [
288
+ {
289
+ title: '内边距',
290
+ name: 'itemPadding',
291
+ description: '列表项内边距(px)',
292
+ setter: { componentName: 'NumberSetter', isRequired: false, initialValue: 0, defaultValue: 0, props: { min: 0 } },
293
+ },
294
+ {
295
+ title: '背景颜色',
296
+ name: 'itemBgColor',
297
+ description: '列表项背景颜色',
298
+ setter: { componentName: 'ColorSetter', isRequired: false, initialValue: '#ffffff' },
299
+ },
300
+ {
301
+ title: '圆角',
302
+ name: 'itemBorderRadius',
303
+ description: '列表项圆角(px)',
304
+ setter: { componentName: 'NumberSetter', isRequired: false, initialValue: 0, defaultValue: 0, props: { min: 0 } },
305
+ },
306
+ {
307
+ title: '边框颜色',
308
+ name: 'itemBorderColor',
309
+ description: '列表项边框颜色',
310
+ setter: { componentName: 'ColorSetter', isRequired: false, initialValue: '' },
311
+ },
312
+ {
313
+ title: '边框宽度',
314
+ name: 'itemBorderWidth',
315
+ description: '列表项边框宽度(px),设置边框颜色后生效',
316
+ setter: { componentName: 'NumberSetter', isRequired: false, initialValue: 0, defaultValue: 0, props: { min: 0, max: 10 } },
317
+ },
318
+ ],
249
319
  },
320
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
321
+ // 分组四:图片样式
322
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
250
323
  {
251
- title: '数据源绑定',
252
- name: 'dataListBind',
253
- setter: {
254
- componentName: 'SetterFormVariable',
255
- props: {
256
- attributes: [
257
- {
258
- label: '图文数据',
259
- value: 'dataList',
260
- children: [
261
- { label: '图片链接', value: 'image' },
262
- { label: '类型', value: 'itemType' },
263
- { label: '标题', value: 'title' },
264
- { label: '说明', value: 'description' },
324
+ type: 'group',
325
+ title: '图片样式',
326
+ display: 'accordion',
327
+ items: [
328
+ {
329
+ title: '图片位置',
330
+ name: 'imagePlacement',
331
+ setter: {
332
+ componentName: 'RadioGroupSetter',
333
+ props: {
334
+ options: [
335
+ { label: '', value: 'left' },
336
+ { label: '', value: 'right' },
337
+ { label: '', value: 'top' },
338
+ { label: '下', value: 'bottom' },
339
+ { label: '无', value: 'none' },
265
340
  ],
266
341
  },
267
- ],
268
- },
269
- },
270
- extraProps: {
271
- setValue: (target, value) => {
272
- target.getProps().setPropValue('dataListBind', value)
342
+ initialValue: 'left',
343
+ },
344
+ extraProps: {},
345
+ },
346
+ {
347
+ title: '图文对齐',
348
+ name: 'textAlign',
349
+ description: '图片与文字的交叉轴对齐方式',
350
+ setter: {
351
+ componentName: 'RadioGroupSetter',
352
+ props: {
353
+ options: [
354
+ { label: '顶对齐', value: 'flex-start' },
355
+ { label: '居中', value: 'center' },
356
+ { label: '底对齐', value: 'flex-end' },
357
+ ],
358
+ },
359
+ initialValue: 'flex-start',
360
+ },
273
361
  },
274
- },
275
- },
276
- {
277
- title: '标题',
278
- name: 'title',
279
- description: '标题',
280
- setter: {
281
- componentName: 'StringSetter',
282
- isRequired: false,
283
- initialValue: '',
284
- },
285
- },
286
- {
287
- title: {
288
- label: {
289
- type: 'i18n',
290
- 'en-US': 'moreText',
291
- 'zh-CN': '更多文字',
362
+ {
363
+ title: '图文间距',
364
+ name: 'textImgGap',
365
+ description: '图片与文字区域之间的间距(px)',
366
+ setter: { componentName: 'NumberSetter', isRequired: false, initialValue: 16, defaultValue: 16, props: { min: 0 } },
367
+ },
368
+ {
369
+ title: '宽度',
370
+ name: 'imgWidth',
371
+ description: '图片宽度(px)',
372
+ setter: { componentName: 'NumberSetter', isRequired: false, initialValue: 100, props: { min: 10 } },
373
+ extraProps: {
374
+ ignoreDefaultValue: () => true,
375
+ getValue: (target: any, value: any) => {
376
+ const parsed = parsePxNumber(value)
377
+ if (parsed !== undefined) return parsed
378
+ const fromSchema = parsePxNumber(target?.node?.schema?.props?.imgWidth)
379
+ if (fromSchema !== undefined) return fromSchema
380
+ return 100
381
+ },
382
+ },
292
383
  },
293
- tip: 'moreText | 更多文字',
294
- },
295
- name: 'moreText',
296
- description: '更多文字',
297
- setter: {
298
- componentName: 'StringSetter',
299
- isRequired: false,
300
- initialValue: '',
301
- },
302
- },
303
- {
304
- title: '文字行数',
305
- name: 'textLines',
306
- description: '文字行数',
307
- setter: {
308
- componentName: 'NumberSetter',
309
- isRequired: false,
310
- initialValue: 2,
311
- defaultValue: 2,
312
- props: {
313
- min: 2,
314
- max: 4,
384
+ {
385
+ title: '高度',
386
+ name: 'imgHeight',
387
+ description: '图片高度(px)',
388
+ setter: { componentName: 'NumberSetter', isRequired: false, initialValue: 100, props: { min: 10 } },
389
+ extraProps: {
390
+ ignoreDefaultValue: () => true,
391
+ getValue: (target: any, value: any) => {
392
+ const parsed = parsePxNumber(value)
393
+ if (parsed !== undefined) return parsed
394
+ const fromSchema = parsePxNumber(target?.node?.schema?.props?.imgHeight)
395
+ if (fromSchema !== undefined) return fromSchema
396
+ return 100
397
+ },
398
+ },
315
399
  },
316
- },
317
- extraProps: {
318
- setValue(target, value) {
319
- target.getProps().setPropValue('textLines', value)
320
- const schema: any = target?.node?.schema
321
- const node: any = target?.node
322
- const schemaChildren: any[] = Array.isArray(schema?.children) ? schema.children : []
323
-
324
- // 获取当前文本组件数量
325
- const currentLength =
326
- schemaChildren.filter(
327
- (child) =>
328
- child.componentName === 'NextText' && child?.props?.key?.startsWith('text-'),
329
- )?.length || 0
330
-
331
- if (value > currentLength) {
332
- // 需要添加新的文本组件
333
- for (let i = currentLength + 1; i <= value; i++) {
334
- const newChild = {
335
- componentName: 'NextText',
336
- props: {
337
- type: 'inherit',
338
- children: '基于 Ali-Lowcode-Engine 快速打造高生产力的低代码研发平台',
339
- key: `text-${i}`,
340
- },
341
- }
342
- node?.children?.push(newChild)
343
- }
344
- } else if (value < currentLength) {
345
- // 收集需要移除的节点,再调用 child.remove() 通过引擎 API 逐个删除
346
- // 避免 node.children = [...] 直接赋值(IPublicModelNodeChildren 不支持重新赋值)
347
- const nodesToRemove: any[] = []
348
- node?.children?.forEach?.((child: any) => {
349
- const key = child?.schema?.props?.key
350
- if (
351
- child?.componentName === 'NextText' &&
352
- typeof key === 'string' &&
353
- key.startsWith('text-')
354
- ) {
355
- const order = Number(key.split('-')[1])
356
- if (!Number.isNaN(order) && order > value) {
357
- nodesToRemove.push(child)
358
- }
359
- }
360
- })
361
- nodesToRemove.forEach((child) => child?.remove?.())
362
- }
363
-
364
- // 更新数据源绑定的配置
365
- const dataListBindProp = (target?.parent as any)?.items?.find(
366
- (item) => item.name === 'dataListBind',
367
- )
368
- if (dataListBindProp && dataListBindProp.setter) {
369
- const baseChildren = [
370
- { label: '图片链接', value: 'image' },
371
- { label: '类型', value: 'itemType' },
372
- { label: '标题', value: 'title' },
373
- { label: '说明', value: 'description' },
374
- ]
375
-
376
- // 只有当value大于2时才添加额外的文本字段
377
- const textChildren =
378
- value > 2
379
- ? Array.from({ length: value - 2 }).map((_, index) => ({
380
- label: `文本${index + 3}`,
381
- value: `text${index + 3}`,
382
- }))
383
- : []
384
-
385
- // 更新setter的attributes
386
- dataListBindProp.setter.props.attributes[0].children = [
387
- ...baseChildren,
388
- ...textChildren,
389
- ]
390
- }
400
+ {
401
+ title: '圆角',
402
+ name: 'imgBorderRadius',
403
+ description: '图片圆角(px),设为 999 可得到圆形',
404
+ setter: { componentName: 'NumberSetter', isRequired: false, initialValue: 0, defaultValue: 0, props: { min: 0 } },
405
+ },
406
+ {
407
+ title: '填充方式',
408
+ name: 'imgObjectFit',
409
+ description: '图片在容器内的填充方式',
410
+ setter: {
411
+ componentName: 'RadioGroupSetter',
412
+ props: {
413
+ options: [
414
+ { label: '覆盖', value: 'cover' },
415
+ { label: '适应', value: 'contain' },
416
+ { label: '拉伸', value: 'fill' },
417
+ { label: '原始', value: 'none' },
418
+ ],
419
+ },
420
+ initialValue: 'cover',
421
+ },
391
422
  },
392
- },
423
+ ],
393
424
  },
425
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
426
+ // 分组五:标题文字样式
427
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
394
428
  {
395
- title: '子项列数',
396
- name: 'itemColumns',
397
- description: '子项列数',
398
- setter: {
399
- componentName: 'NumberSetter',
400
- isRequired: false,
401
- initialValue: (target) => {
402
- const isTwoColumns =
403
- target.getProps().getPropValue('imagePlacement') === 'top' ||
404
- target.getProps().getPropValue('imagePlacement') === 'bottom'
405
- return isTwoColumns ? 2 : 1
406
- },
407
- defaultValue: (target) => {
408
- const isTwoColumns =
409
- target.getProps().getPropValue('imagePlacement') === 'top' ||
410
- target.getProps().getPropValue('imagePlacement') === 'bottom'
411
- return isTwoColumns ? 2 : 1
429
+ type: 'group',
430
+ title: '标题文字样式',
431
+ display: 'accordion',
432
+ items: [
433
+ {
434
+ title: '颜色',
435
+ name: 'titleColor',
436
+ setter: { componentName: 'ColorSetter', isRequired: false, initialValue: '' },
437
+ },
438
+ {
439
+ title: '字体大小',
440
+ name: 'titleFontSize',
441
+ description: '标题字体大小(px)',
442
+ setter: { componentName: 'NumberSetter', isRequired: false, initialValue: 14, defaultValue: 14, props: { min: 10, max: 60 } },
443
+ },
444
+ {
445
+ title: '字重',
446
+ name: 'titleFontWeight',
447
+ setter: {
448
+ componentName: 'RadioGroupSetter',
449
+ props: {
450
+ options: [
451
+ { label: '常规', value: 'normal' },
452
+ { label: '中等', value: '500' },
453
+ { label: '半粗', value: '600' },
454
+ { label: '粗体', value: 'bold' },
455
+ ],
456
+ },
457
+ initialValue: '600',
458
+ },
412
459
  },
413
- props: {
414
- min: 1,
415
- max: 2,
460
+ {
461
+ title: '最大行数',
462
+ name: 'titleLineClamp',
463
+ description: '超出后显示省略号,0 表示不限制',
464
+ setter: { componentName: 'NumberSetter', isRequired: false, initialValue: 1, defaultValue: 1, props: { min: 0, max: 10 } },
416
465
  },
417
- },
418
- },
419
- {
420
- title: '子项间距',
421
- name: 'itemGap',
422
- description: '子项间距',
423
- setter: {
424
- componentName: 'NumberSetter',
425
- isRequired: false,
426
- initialValue: 10,
427
- defaultValue: 10,
428
- },
429
- },
430
- {
431
- title: '子项内边距',
432
- name: 'itemPadding',
433
- description: '子项内边距',
434
- setter: {
435
- componentName: 'NumberSetter',
436
- isRequired: false,
437
- initialValue: 0,
438
- defaultValue: 0,
439
- },
440
- },
441
- {
442
- title: '子项背景颜色',
443
- name: 'itemBgColor',
444
- description: '子项背景颜色',
445
- setter: {
446
- componentName: 'ColorSetter',
447
- isRequired: false,
448
- initialValue: '#fff',
449
- defaultValue: '#fff',
450
- },
466
+ ],
451
467
  },
468
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
469
+ // 分组六:说明文字样式
470
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
452
471
  {
453
- title: '子项分布',
454
- name: 'itemRowAlign',
455
- description: '子项分布',
456
- setter: {
457
- componentName: 'SelectSetter',
458
- props: {
459
- options: [
460
- {
461
- label: '列分布',
462
- value: 'column',
463
- },
464
- {
465
- label: '一行显示',
466
- value: 'row',
472
+ type: 'group',
473
+ title: '说明文字样式',
474
+ display: 'accordion',
475
+ items: [
476
+ {
477
+ title: '颜色',
478
+ name: 'descriptionColor',
479
+ setter: { componentName: 'ColorSetter', isRequired: false, initialValue: '' },
480
+ },
481
+ {
482
+ title: '字体大小',
483
+ name: 'descriptionFontSize',
484
+ description: '说明字体大小(px)',
485
+ setter: { componentName: 'NumberSetter', isRequired: false, initialValue: 13, defaultValue: 13, props: { min: 10, max: 60 } },
486
+ },
487
+ {
488
+ title: '字重',
489
+ name: 'descriptionFontWeight',
490
+ setter: {
491
+ componentName: 'RadioGroupSetter',
492
+ props: {
493
+ options: [
494
+ { label: '常规', value: 'normal' },
495
+ { label: '中等', value: '500' },
496
+ { label: '半粗', value: '600' },
497
+ { label: '粗体', value: 'bold' },
498
+ ],
467
499
  },
468
- ],
500
+ initialValue: 'normal',
501
+ },
469
502
  },
470
- initialValue: 'column',
471
- },
472
- },
473
- {
474
- title: '图文对齐方式',
475
- name: 'textAlign',
476
- description: '图文对齐方式',
477
- setter: {
478
- componentName: 'SelectSetter',
479
- props: {
480
- options: [
481
- {
482
- label: '左对齐',
483
- value: 'flex-start',
484
- },
485
- {
486
- label: '右对齐',
487
- value: 'flex-end',
488
- },
489
- {
490
- label: '居中对齐',
491
- value: 'center',
492
- },
493
- ],
503
+ {
504
+ title: '最大行数',
505
+ name: 'descriptionLineClamp',
506
+ description: '超出后显示省略号,0 表示不限制',
507
+ setter: { componentName: 'NumberSetter', isRequired: false, initialValue: 1, defaultValue: 1, props: { min: 0, max: 10 } },
494
508
  },
495
- initialValue: 'flex-start',
496
- },
497
- },
498
- {
499
- title: '图文间距',
500
- name: 'textImgGap',
501
- description: '图文间距',
502
- setter: {
503
- componentName: 'NumberSetter',
504
- isRequired: false,
505
- initialValue: 0,
506
- defaultValue: 0,
507
- },
509
+ ],
508
510
  },
511
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
512
+ // 浮层图标
513
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
509
514
  {
510
- title: '图标配置',
515
+ title: '浮层图标',
511
516
  name: 'iconList',
512
- extraProps: {
513
- display: 'accordion',
514
- defaultCollapsed: false,
515
- },
517
+ description: '在每个列表项上叠加绝对定位图标(如角标、标签等)',
518
+ extraProps: { display: 'accordion', defaultCollapsed: true },
516
519
  setter: {
517
520
  componentName: 'ArraySetter',
518
521
  props: {
@@ -526,9 +529,7 @@ const TeletextListMeta: IPublicTypeComponentMetadata = {
526
529
  title: '图标',
527
530
  setter: 'IconSetter',
528
531
  isRequired: true,
529
- props: {
530
- hasClear: false,
531
- },
532
+ props: { hasClear: false },
532
533
  },
533
534
  {
534
535
  name: 'size',
@@ -537,42 +538,15 @@ const TeletextListMeta: IPublicTypeComponentMetadata = {
537
538
  componentName: 'SelectSetter',
538
539
  props: {
539
540
  options: [
540
- {
541
- label: 'xxs',
542
- value: 'xxs',
543
- },
544
- {
545
- label: 'xs',
546
- value: 'xs',
547
- },
548
- {
549
- label: 'small',
550
- value: 'small',
551
- },
552
- {
553
- label: 'medium',
554
- value: 'medium',
555
- },
556
- {
557
- label: 'large',
558
- value: 'large',
559
- },
560
- {
561
- label: 'xl',
562
- value: 'xl',
563
- },
564
- {
565
- label: 'xxl',
566
- value: 'xxl',
567
- },
568
- {
569
- label: 'xxxl',
570
- value: 'xxxl',
571
- },
572
- {
573
- label: 'inherit',
574
- value: 'inherit',
575
- },
541
+ { label: 'xxs', value: 'xxs' },
542
+ { label: 'xs', value: 'xs' },
543
+ { label: 'small', value: 'small' },
544
+ { label: 'medium', value: 'medium' },
545
+ { label: 'large', value: 'large' },
546
+ { label: 'xl', value: 'xl' },
547
+ { label: 'xxl', value: 'xxl' },
548
+ { label: 'xxxl', value: 'xxxl' },
549
+ { label: 'inherit', value: 'inherit' },
576
550
  ],
577
551
  },
578
552
  },
@@ -587,26 +561,11 @@ const TeletextListMeta: IPublicTypeComponentMetadata = {
587
561
  componentName: 'SelectSetter',
588
562
  props: {
589
563
  options: [
590
- {
591
- label: '左上角',
592
- value: 'leftTop',
593
- },
594
- {
595
- label: '左下角',
596
- value: 'leftBottom',
597
- },
598
- {
599
- label: '右上角',
600
- value: 'rightTop',
601
- },
602
- {
603
- label: '右下角',
604
- value: 'rightBottom',
605
- },
606
- {
607
- label: '自定义',
608
- value: 'customize',
609
- },
564
+ { label: '左上角', value: 'leftTop' },
565
+ { label: '左下角', value: 'leftBottom' },
566
+ { label: '右上角', value: 'rightTop' },
567
+ { label: '右下角', value: 'rightBottom' },
568
+ { label: '自定义', value: 'customize' },
610
569
  ],
611
570
  },
612
571
  },
@@ -621,167 +580,21 @@ const TeletextListMeta: IPublicTypeComponentMetadata = {
621
580
  title: '右偏移',
622
581
  setter: 'NumberSetter',
623
582
  defaultValue: 0,
624
- condition: (target) => {
625
- return target.getProps().getPropValue('position') === 'customize'
626
- },
583
+ condition: (target) => target.getProps().getPropValue('position') === 'customize',
627
584
  },
628
585
  {
629
586
  name: 'topOffset',
630
587
  title: '上偏移',
631
588
  setter: 'NumberSetter',
632
589
  defaultValue: 0,
633
- condition: (target) => {
634
- return target.getProps().getPropValue('position') === 'customize'
635
- },
636
- },
637
- ],
638
- },
639
- },
640
- initialValue: {
641
- size: 'medium',
642
- position: 'rightTop',
643
- rightOffset: 0,
644
- topOffset: 0,
645
- },
646
- },
647
- },
648
- },
649
- },
650
- {
651
- title: '是否为购物车列表',
652
- name: 'isShoppingCart',
653
- description: '是否为购物车列表',
654
- setter: {
655
- componentName: 'BoolSetter',
656
- isRequired: true,
657
- initialValue: false,
658
- },
659
- },
660
- {
661
- title: '是否为愿望单列表',
662
- name: 'isWishList',
663
- description: '是否为愿望单列表',
664
- setter: {
665
- componentName: 'BoolSetter',
666
- isRequired: true,
667
- initialValue: false,
668
- },
669
- },
670
- {
671
- title: '是否为用户菜单列表',
672
- name: 'isUserMenu',
673
- description: '是否为用户菜单列表',
674
- setter: {
675
- componentName: 'BoolSetter',
676
- isRequired: true,
677
- initialValue: false,
678
- },
679
- },
680
- {
681
- title: {
682
- label: {
683
- type: 'i18n',
684
- 'en-US': 'dataList',
685
- 'zh-CN': '数据',
686
- },
687
- tip: 'dataList | 数据',
688
- },
689
- name: 'dataList',
690
- description: '数据',
691
- setter: {
692
- componentName: 'ArraySetter',
693
- props: {
694
- itemSetter: {
695
- componentName: 'ObjectSetter',
696
- props: {
697
- config: {
698
- items: [
699
- {
700
- title: {
701
- label: {
702
- type: 'i18n',
703
- 'en-US': 'title',
704
- 'zh-CN': '标题',
705
- },
706
- },
707
- name: 'title',
708
- description: '标题',
709
- setter: {
710
- componentName: 'StringSetter',
711
- isRequired: false,
712
- initialValue: '',
713
- },
714
- },
715
- {
716
- title: {
717
- label: {
718
- type: 'i18n',
719
- 'en-US': 'image',
720
- 'zh-CN': '图片地址',
721
- },
722
- },
723
- name: 'image',
724
- description: '图片地址',
725
- setter: {
726
- componentName: 'CustomImageSetter',
727
- isRequired: false,
728
- initialValue: '',
729
- },
730
- },
731
- {
732
- title: {
733
- label: {
734
- type: 'i18n',
735
- 'en-US': 'description',
736
- 'zh-CN': '描述',
737
- },
738
- },
739
- name: 'description',
740
- description: '描述',
741
- setter: {
742
- componentName: 'StringSetter',
743
- isRequired: false,
744
- initialValue: '',
745
- },
590
+ condition: (target) => target.getProps().getPropValue('position') === 'customize',
746
591
  },
747
592
  ],
748
- extraSetter: {
749
- componentName: 'MixedSetter',
750
- isRequired: false,
751
- props: {},
752
- },
753
593
  },
754
594
  },
595
+ initialValue: { size: 'medium', position: 'rightTop', rightOffset: 0, topOffset: 0 },
755
596
  },
756
597
  },
757
- initialValue: (target) => {
758
- // ignoreDefaultValue: () => true 保证此函数在 SettingFieldView remount 时
759
- // 永远不会被 initDefaultValue 调用,仅作为安全兜底保留。
760
- // 正常的首次创建数据由 snippet.props.dataList 提供。
761
- const existing = target?.node?.schema?.props?.dataList
762
- ?? target?.getProps?.()?.getPropValue?.('dataList')
763
- if (existing !== undefined) return existing
764
- return DEFAULT_DATA_LIST
765
- },
766
- },
767
- extraProps: {
768
- /**
769
- * ignoreDefaultValue: 彻底阻止引擎在 SettingFieldView remount 时
770
- * 调用 initDefaultValue → 把 initialValue(默认数据数组)通过 field.setValue
771
- * 写入 dataList prop,覆盖已绑定的 JSExpression。
772
- *
773
- * 这是根本性解决方案:在引擎层面阻断 initDefaultValue 的执行,
774
- * 而不是试图在 initialValue/getValue/setValue 中做缓存和还原来补救。
775
- */
776
- ignoreDefaultValue: () => true,
777
- getValue: (target: any, currentValue: any) => {
778
- // currentValue 已有值时直接返回
779
- if (currentValue !== undefined) return currentValue
780
- // 从 schema 快照兜底读取(最可靠的源头数据,始终反映持久化状态)
781
- const fromSchema = target?.node?.schema?.props?.dataList
782
- if (fromSchema !== undefined) return fromSchema
783
- return undefined
784
- },
785
598
  },
786
599
  },
787
600
  ],
@@ -831,121 +644,8 @@ const getSnippets = (textLines = 2): IPublicTypeSnippet[] => [
831
644
  // SettingFieldView remount 时覆盖已绑定的 JSExpression,
832
645
  // 所以 initDefaultValue 永远不会运行,首次拖入的初始数据必须由 snippet 提供。
833
646
  dataList: DEFAULT_DATA_LIST,
647
+ title: '列表标题',
834
648
  },
835
- children: [
836
- {
837
- componentName: 'NextText',
838
- props: {
839
- type: 'h5',
840
- children: '列表标题',
841
- key: 'box-title',
842
- style: {
843
- fontSize: '16px',
844
- fontWeight: 'bold',
845
- },
846
- },
847
- },
848
- {
849
- componentName: 'Image',
850
- props: {
851
- imgSrc: 'https://img.alicdn.com/tps/TB16TQvOXXXXXbiaFXXXXXXXXXX-120-120.svg',
852
- key: 'image',
853
- },
854
- },
855
- // 动态生成文本组件
856
- // ...Array.from({ length: textLines }).map((_, index) => ({
857
- // componentName: 'NextText',
858
- // props: {
859
- // type: index === 0 ? 'h5' : 'inherit',
860
- // children:
861
- // index === 0
862
- // ? '标题标题'
863
- // : '基于1 Ali-Lowcode-Engine 快速打造高生产力的低代码研发平台, 基于自然布局体系快速搭建页面',
864
- // key: `text-${index + 1}`,
865
- // },
866
- // })),
867
- {
868
- componentName: 'NextText',
869
- props: {
870
- type: 'h5',
871
- children: '标题标题',
872
- key: `text-1`,
873
- },
874
- },
875
- {
876
- componentName: 'NextText',
877
- props: {
878
- type: 'inherit',
879
- children:
880
- '基于1 Ali-Lowcode-Engine 快速打造高生产力的低代码研发平台, 基于自然布局体系快速搭建页面',
881
- key: `text-2`,
882
- },
883
- },
884
- {
885
- componentName: 'NextText',
886
- props: {
887
- type: 'inherit',
888
- children:
889
- '基于1 Ali-Lowcode-Engine 快速打造高生产力的低代码研发平台, 基于自然布局体系快速搭建页面',
890
- key: `text-3`,
891
- },
892
- },
893
- {
894
- componentName: 'NextText',
895
- props: {
896
- type: 'inherit',
897
- children:
898
- '基于1 Ali-Lowcode-Engine 快速打造高生产力的低代码研发平台, 基于自然布局体系快速搭建页面',
899
- key: `text-4`,
900
- },
901
- },
902
- {
903
- componentName: 'Select',
904
- props: {
905
- popType: 'dialog',
906
- selectType: 'number',
907
- value: 1,
908
- prefix: '数量: ',
909
- dialogTitle: '选择数量',
910
- btnText: '确定',
911
- key: 'select-box-1',
912
- },
913
- },
914
- {
915
- componentName: 'Select',
916
- props: {
917
- popType: 'dialog',
918
- selectType: 'string',
919
- dataList: [
920
- {
921
- label: 'M',
922
- value: 'M',
923
- },
924
- {
925
- label: 'X',
926
- value: 'X',
927
- },
928
- {
929
- label: 'XL',
930
- value: 'XL',
931
- },
932
- ],
933
- value: 'X',
934
- prefix: '尺码: ',
935
- dialogTitle: '选择尺码',
936
- btnText: '确定',
937
- key: 'select-box-2',
938
- },
939
- },
940
- {
941
- componentName: 'Switch',
942
- props: {
943
- size: 'small',
944
- disabled: false,
945
- key: 'switch-1',
946
- },
947
- },
948
- ],
949
649
  },
950
650
  },
951
651
  ]