@dckj-npm/dc-material 0.1.371 → 0.1.373

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.
@@ -68,41 +68,49 @@ const getImageStyleNumber = (target: any, styleKey: 'width' | 'height'): number
68
68
  return parsePxNumber(imageChildSchema?.props?.style?.[styleKey])
69
69
  }
70
70
 
71
- const syncImageStyleValue = (target: any, styleKey: 'width' | 'height', value: number) => {
72
- // 优先通过引擎节点 API 更新子节点 style,确保引擎感知变化(布局面板读取时可见)
73
- const imageChildNode = findImageChildNode(target)
74
- if (imageChildNode) {
75
- const currentStyle = imageChildNode.getPropValue?.('style') || {}
76
- // 同时确保 width/height 都存在于子节点 style 中,防止布局面板 replace 时丢失其中一个
77
- const updatedStyle: Record<string, any> = { ...currentStyle, [styleKey]: `${value}px` }
78
- // 如果另一轴尺寸在子节点 style 中不存在,则从父级 prop 补充,保证两轴都写入
79
- const otherKey = styleKey === 'width' ? 'height' : 'width'
80
- if (!updatedStyle[otherKey]) {
81
- const otherPropKey = otherKey === 'width' ? 'imgWidth' : 'imgHeight'
82
- const otherPropValue = parsePxNumber(target?.getProps?.()?.getPropValue?.(otherPropKey))
83
- if (otherPropValue !== undefined) {
84
- updatedStyle[otherKey] = `${otherPropValue}px`
85
- } else {
86
- // 子节点 style 也没有,使用默认值 100
87
- updatedStyle[otherKey] = '100px'
71
+ /**
72
+ * 异步写入 Image 子节点的 style,避免在 imgWidth/imgHeight.setValue 的同步执行栈内
73
+ * 触发引擎重评估 dataList.initialValue(会先清空 dataList prop,导致默认图覆盖绑定数据)。
74
+ * 通过 Promise.resolve().then() 将写入推迟到当前 settings 重评估完成后执行,
75
+ * 此时 dataList 已稳定为正确的 JSExpression,重评估无副作用。
76
+ */
77
+ const syncImageStyleValue = (target: any, styleKey: 'width' | 'height', value: number): void => {
78
+ Promise.resolve().then(() => {
79
+ // 优先通过引擎节点 API 更新子节点 style,确保引擎感知变化(布局面板读取时可见)
80
+ const imageChildNode = findImageChildNode(target)
81
+ if (imageChildNode) {
82
+ const currentStyle = imageChildNode.getPropValue?.('style') || {}
83
+ // 同时确保 width/height 都存在于子节点 style 中,防止布局面板 replace 时丢失其中一个
84
+ const updatedStyle: Record<string, any> = { ...currentStyle, [styleKey]: `${value}px` }
85
+ // 如果另一轴尺寸在子节点 style 中不存在,则从父级 prop 补充,保证两轴都写入
86
+ const otherKey = styleKey === 'width' ? 'height' : 'width'
87
+ if (!updatedStyle[otherKey]) {
88
+ const otherPropKey = otherKey === 'width' ? 'imgWidth' : 'imgHeight'
89
+ const otherPropValue = parsePxNumber(target?.getProps?.()?.getPropValue?.(otherPropKey))
90
+ if (otherPropValue !== undefined) {
91
+ updatedStyle[otherKey] = `${otherPropValue}px`
92
+ } else {
93
+ // 子节点 style 也没有,使用默认值 100
94
+ updatedStyle[otherKey] = '100px'
95
+ }
88
96
  }
97
+ imageChildNode.setPropValue?.('style', updatedStyle)
98
+ return
89
99
  }
90
- imageChildNode.setPropValue?.('style', updatedStyle)
91
- return
92
- }
93
- // 降级:直接写 schema(引擎无法感知,但保留作为兜底)
94
- const imageChildSchema = findImageChildSchema(target)
95
- if (!imageChildSchema) {
96
- return
97
- }
98
- if (!imageChildSchema.props) {
99
- imageChildSchema.props = {}
100
- }
101
- const currentStyle = imageChildSchema.props.style || {}
102
- imageChildSchema.props.style = {
103
- ...currentStyle,
104
- [styleKey]: `${value}px`,
105
- }
100
+ // 降级:直接写 schema(引擎无法感知,但保留作为兜底)
101
+ const imageChildSchema = findImageChildSchema(target)
102
+ if (!imageChildSchema) {
103
+ return
104
+ }
105
+ if (!imageChildSchema.props) {
106
+ imageChildSchema.props = {}
107
+ }
108
+ const currentStyle = imageChildSchema.props.style || {}
109
+ imageChildSchema.props.style = {
110
+ ...currentStyle,
111
+ [styleKey]: `${value}px`,
112
+ }
113
+ })
106
114
  }
107
115
 
108
116
  const syncImageDimensionPropsFromChild = (target: any) => {
@@ -135,30 +143,30 @@ const isDataListBoundExpression = (target: any): boolean => {
135
143
  }
136
144
 
137
145
  /**
138
- * 模块级 WeakMap 缓存:以 IPublicModelNode 对象引用为 key,存储每个 TeletextList 节点
139
- * 最后一次已知的「非默认」dataList 值。
140
- *
141
- * 作用:在 setPropValue 触发的 settings 重评估中,引擎可能先将 node prop 清空再调用
142
- * dataList.initialValue;此时 node.getPropValue 与 getProps().getPropValue 均返回
143
- * undefined,导致 initialValue 回退默认数组、覆盖已绑定的 JSExpression 或用户数据。
144
- * 通过在每次 imgWidth/imgHeight/imagePlacement.setValue 执行任何 setPropValue 之前
145
- * 将当前 dataList 写入此缓存,initialValue 可从缓存安全恢复,彻底切断引擎中间态影响。
146
+ * 模块级缓存:使用 node.id(稳定的字符串 ID)作为 key
147
+ * 替代 WeakMap 方案:WeakMap 以 target.node 对象引用为 key,
148
+ * 但引擎可能通过 Proxy/getter 每次返回不同的包装对象,导致缓存命中失败。
149
+ * 使用 node.id 字符串做 key 彻底消除引用不一致问题。
146
150
  */
147
- const _nodeDataListCache = new WeakMap<object, any>()
151
+ const _dataListCacheById: Record<string, any> = {}
148
152
 
149
153
  const _cacheDataList = (target: any): void => {
150
- const node = target?.node
151
- if (!node) return
152
- // 优先从 node 级 API 读取(schema 层,不受 settings 重评估中间态影响)
153
- const fromNode = node?.getPropValue?.('dataList')
154
+ const nodeId = target?.node?.id
155
+ if (!nodeId) return
156
+ const fromNode = target?.node?.getPropValue?.('dataList')
154
157
  if (fromNode !== undefined) {
155
- _nodeDataListCache.set(node, fromNode)
158
+ _dataListCacheById[nodeId] = fromNode
159
+ return
160
+ }
161
+ // schema 序列化快照:源头数据,不受 settings 中间态影响
162
+ const fromSchema = target?.node?.schema?.props?.dataList
163
+ if (fromSchema !== undefined) {
164
+ _dataListCacheById[nodeId] = fromSchema
156
165
  return
157
166
  }
158
- // 降级:从 settings API 读取
159
167
  const fromProps = target?.getProps?.()?.getPropValue?.('dataList')
160
168
  if (fromProps !== undefined) {
161
- _nodeDataListCache.set(node, fromProps)
169
+ _dataListCacheById[nodeId] = fromProps
162
170
  }
163
171
  }
164
172
 
@@ -365,17 +373,15 @@ const TeletextListMeta: IPublicTypeComponentMetadata = {
365
373
  return
366
374
  }
367
375
  const props = target.getProps()
368
- // 在任何 setPropValue 之前先写入模块级缓存(与 imagePlacement.setValue 同策略)
369
376
  _cacheDataList(target)
370
- // 快照需要保护的数据,防止 syncImageStyleValue imageChildNode.setPropValue
371
- // 触发引擎重评估 dataList.initialValue,导致 dataList 被重置为默认图
377
+ // 快照 dataList:在 setPropValue 前捕获,防止引擎重评估时被默认值覆盖
372
378
  const prevDataList = props.getPropValue('dataList')
373
- const prevDataListBind = props.getPropValue('dataListBind')
374
379
  props.setPropValue('imgWidth', parsedValue)
380
+ // 还原 dataList(幂等操作,若引擎未覆盖则无副作用)
381
+ if (prevDataList !== undefined) {
382
+ props.setPropValue('dataList', prevDataList)
383
+ }
375
384
  syncImageStyleValue(target, 'width', parsedValue)
376
- // 还原被保护的数据(幂等操作,若引擎未重置则无副作用)
377
- if (prevDataList !== undefined) props.setPropValue('dataList', prevDataList)
378
- if (prevDataListBind !== undefined) props.setPropValue('dataListBind', prevDataListBind)
379
385
  },
380
386
  },
381
387
  },
@@ -434,17 +440,15 @@ const TeletextListMeta: IPublicTypeComponentMetadata = {
434
440
  return
435
441
  }
436
442
  const props = target.getProps()
437
- // 在任何 setPropValue 之前先写入模块级缓存(与 imagePlacement.setValue 同策略)
438
443
  _cacheDataList(target)
439
- // 快照需要保护的数据,防止 syncImageStyleValue imageChildNode.setPropValue
440
- // 触发引擎重评估 dataList.initialValue,导致 dataList 被重置为默认图
444
+ // 快照 dataList:在 setPropValue 前捕获,防止引擎重评估时被默认值覆盖
441
445
  const prevDataList = props.getPropValue('dataList')
442
- const prevDataListBind = props.getPropValue('dataListBind')
443
446
  props.setPropValue('imgHeight', parsedValue)
447
+ // 还原 dataList(幂等操作,若引擎未覆盖则无副作用)
448
+ if (prevDataList !== undefined) {
449
+ props.setPropValue('dataList', prevDataList)
450
+ }
444
451
  syncImageStyleValue(target, 'height', parsedValue)
445
- // 还原被保护的数据(幂等操作,若引擎未重置则无副作用)
446
- if (prevDataList !== undefined) props.setPropValue('dataList', prevDataList)
447
- if (prevDataListBind !== undefined) props.setPropValue('dataListBind', prevDataListBind)
448
452
  },
449
453
  },
450
454
  },
@@ -956,29 +960,30 @@ const TeletextListMeta: IPublicTypeComponentMetadata = {
956
960
  },
957
961
  },
958
962
  initialValue: (target) => {
959
- // 读取顺序(由最可靠到最不可靠):
960
- // 1. node API(schema 层,引擎重评估前通常仍有值)
961
- // 2. 模块级 WeakMap 缓存(在任何 setPropValue 之前写入,完全不受引擎清空影响)
962
- // 3. settings API(重评估中间态下可能已清空,作为最后手段)
963
- // 4. 默认占位数据(仅首次创建组件时触达)
964
- const node = target?.node
965
- const fromNode = node?.getPropValue?.('dataList')
963
+ const nodeId = target?.node?.id
964
+ // 1. node API
965
+ const fromNode = target?.node?.getPropValue?.('dataList')
966
966
  if (fromNode !== undefined) {
967
- // 同步更新缓存,为后续可能的重评估提供后备
968
- if (node) _nodeDataListCache.set(node, fromNode)
967
+ if (nodeId) _dataListCacheById[nodeId] = fromNode
969
968
  return fromNode
970
969
  }
971
- // node.getPropValue 返回 undefined:引擎已在调用 initialValue 前清空 node prop
972
- // 读取模块级缓存(在 setValue 中任何 setPropValue 之前写入,最可靠的后备)
973
- const cached = node ? _nodeDataListCache.get(node) : undefined
974
- if (cached !== undefined) {
975
- return cached
970
+ // 2. 模块级缓存(node.id 索引,不受 Proxy 引用问题影响)
971
+ if (nodeId && _dataListCacheById[nodeId] !== undefined) {
972
+ return _dataListCacheById[nodeId]
976
973
  }
974
+ // 3. settings API
977
975
  const current = target?.getProps?.()?.getPropValue?.('dataList')
978
976
  if (current !== undefined) {
979
- if (node) _nodeDataListCache.set(node, current)
977
+ if (nodeId) _dataListCacheById[nodeId] = current
980
978
  return current
981
979
  }
980
+ // 4. schema 序列化快照(源头数据,不受 settings 中间态影响)
981
+ const fromSchema = target?.node?.schema?.props?.dataList
982
+ if (fromSchema !== undefined) {
983
+ if (nodeId) _dataListCacheById[nodeId] = fromSchema
984
+ return fromSchema
985
+ }
986
+ // 5. 默认数据(仅首次创建组件时触达)
982
987
  return [
983
988
  {
984
989
  image: 'https://img.alicdn.com/tps/TB16TQvOXXXXXbiaFXXXXXXXXXX-120-120.svg',
@@ -1007,53 +1012,45 @@ const TeletextListMeta: IPublicTypeComponentMetadata = {
1007
1012
  },
1008
1013
  extraProps: {
1009
1014
  /**
1010
- * 自定义 getValue:保证引擎重评估期间 field.getValue() 始终返回有效值(非 undefined),
1011
- * 从而阻止 initDefaultValue 在不应该的时机调用 initialValue 并覆盖为默认图数组。
1012
- *
1013
- * 触发场景:修改 imgWidth/imgHeight 或通过布局面板修改图片 margin 时,
1014
- * imageChildNode.setPropValue('style', ...) 会触发引擎对父节点 settings 的重评估;
1015
- * 若此时 dataList Prop 处于 "unset" 中间态,parent.getPropValue 会返回 undefined,
1016
- * 导致不带 getValue 时 field.getValue() = undefined → initDefaultValue 触发 → 默认图。
1017
- * 有了此 getValue 后,即使 schema 层暂时返回 undefined,从缓存取值仍可返回用户数据,
1018
- * field.getValue() 非 undefined → initDefaultValue 永远跳过 → 默认图问题彻底消失。
1015
+ * 保证引擎重评估期间 field.getValue() 始终返回有效值(非 undefined),
1016
+ * 阻止 initDefaultValue 覆盖已绑定的 JSExpression。
1017
+ * 回退链:currentValue → 缓存(node.id) → schema 快照 → node API。
1019
1018
  */
1020
1019
  getValue: (target: any, currentValue: any) => {
1021
- const node = target?.node
1020
+ const nodeId = target?.node?.id
1022
1021
  if (currentValue !== undefined) {
1023
- // schema 层有值:同步更新缓存,确保用户最新编辑的数据被记录
1024
- if (node) _nodeDataListCache.set(node, currentValue)
1022
+ if (nodeId) _dataListCacheById[nodeId] = currentValue
1025
1023
  return currentValue
1026
1024
  }
1027
- // schema 层暂时无值(引擎重评估中间态):从缓存恢复,避免 initDefaultValue 触发
1028
- const cached = node ? _nodeDataListCache.get(node) : undefined
1029
- return cached // undefined 仅在缓存为空(全新组件首次初始化)时出现,属正常情况
1025
+ // 引擎 currentValue undefined(重评估中间态),逐级回退:
1026
+ if (nodeId && _dataListCacheById[nodeId] !== undefined) {
1027
+ return _dataListCacheById[nodeId]
1028
+ }
1029
+ // node.schema 序列化快照:不受 settings 中间态影响,是最可靠的源头数据
1030
+ const fromSchema = target?.node?.schema?.props?.dataList
1031
+ if (fromSchema !== undefined) {
1032
+ if (nodeId) _dataListCacheById[nodeId] = fromSchema
1033
+ return fromSchema
1034
+ }
1035
+ const fromNode = target?.node?.getPropValue?.('dataList')
1036
+ if (fromNode !== undefined) {
1037
+ if (nodeId) _dataListCacheById[nodeId] = fromNode
1038
+ return fromNode
1039
+ }
1040
+ return undefined
1030
1041
  },
1031
1042
  /**
1032
- * 自定义 setValue:用户每次编辑 dataList 条目时,先更新 WeakMap 缓存,
1033
- * 再通过 node.setPropValue 将值持久化到 schema
1034
- *
1035
- * ⚠️ 此引擎中 extraProps.setValue 完全接管写入逻辑,引擎不会自动持久化:
1036
- * 若不在此处显式调用 setPropValue,用户编辑的数据将只存于内存缓存,
1037
- * 页面刷新后丢失,同时 imgWidth/imgHeight.setValue 的快照–还原机制也因
1038
- * props.getPropValue('dataList') 返回 undefined 而失效,导致还原跳过,
1039
- * 进而触发引擎 initDefaultValue,画布回退默认图。
1040
- *
1041
- * 写入顺序:先缓存(供 initialValue/getValue 兜底),再写 schema(持久化)。
1042
- * 写入 schema 会触发引擎对 settings 的重评估,但此时 schema 已有值,
1043
- * initialValue 不会被调用,不会产生循环。
1043
+ * 用户编辑 dataList 时同步更新缓存并持久化到 schema。
1044
+ * 引擎 extraProps.setValue 完全接管写入,必须显式 setPropValue
1044
1045
  */
1045
1046
  setValue: (target: any, value: any) => {
1046
- const node = target?.node
1047
- if (!node) return
1047
+ const nodeId = target?.node?.id
1048
+ if (!nodeId) return
1048
1049
  if (value !== undefined) {
1049
- // 先写缓存,确保重评估期间 getValue 可从缓存返回有效值
1050
- _nodeDataListCache.set(node, value)
1051
- // 再持久化到 schema(引擎不会自动写入,必须显式调用)
1050
+ _dataListCacheById[nodeId] = value
1052
1051
  target.getProps?.()?.setPropValue?.('dataList', value)
1053
1052
  } else {
1054
- // clearValue 场景(value = undefined):清空缓存,使下次 initDefaultValue
1055
- // 可正常返回默认数组(仅用于组件被显式清除数据的情况)
1056
- _nodeDataListCache.delete(node)
1053
+ delete _dataListCacheById[nodeId]
1057
1054
  target.getProps?.()?.setPropValue?.('dataList', undefined)
1058
1055
  }
1059
1056
  },
@@ -117,7 +117,7 @@ function fillRealVersion(meta, packageName, version, basicLibraryVersion) {
117
117
  packageName = '@dckj-npm/dc-material';
118
118
  }
119
119
  if (version === void 0) {
120
- version = '0.1.371';
120
+ version = '0.1.373';
121
121
  }
122
122
  if (basicLibraryVersion === void 0) {
123
123
  basicLibraryVersion = {