@mybricks/to-code-taro 1.0.6 → 1.0.8

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 (57) hide show
  1. package/dist/cjs/core/utils/ComContext.js +11 -2
  2. package/dist/cjs/core/utils/hooks.js +13 -4
  3. package/dist/cjs/core/utils/index.js +9 -2
  4. package/dist/cjs/core/utils/slots.js +124 -0
  5. package/dist/cjs/core/utils/useContext.js +10 -6
  6. package/dist/cjs/core/utils/with.js +32 -5
  7. package/dist/cjs/generate/generateTaroProjectJson.js +2 -2
  8. package/dist/cjs/handleCom.d.ts +7 -30
  9. package/dist/cjs/handleCom.js +171 -61
  10. package/dist/cjs/handleSlot.d.ts +3 -0
  11. package/dist/cjs/handleSlot.js +27 -10
  12. package/dist/cjs/processors/processScene.js +34 -1
  13. package/dist/cjs/processors/processSceneLogic.js +1 -1
  14. package/dist/cjs/taro-template.json +17 -13
  15. package/dist/cjs/toCodeTaro.d.ts +2 -0
  16. package/dist/cjs/utils/logic/handleProcess.js +8 -13
  17. package/dist/cjs/utils/logic/processChildren.d.ts +1 -0
  18. package/dist/cjs/utils/logic/processChildren.js +16 -1
  19. package/dist/cjs/utils/style/converter.js +43 -15
  20. package/dist/cjs/utils/style/pxtransform.d.ts +2 -26
  21. package/dist/cjs/utils/style/pxtransform.js +27 -67
  22. package/dist/cjs/utils/templates/component.js +4 -3
  23. package/dist/cjs/utils/templates/index.d.ts +10 -0
  24. package/dist/cjs/utils/templates/index.js +31 -7
  25. package/dist/cjs/utils/templates/renderManager.d.ts +3 -11
  26. package/dist/cjs/utils/templates/renderManager.js +86 -21
  27. package/dist/cjs/utils/templates/scene.d.ts +2 -1
  28. package/dist/cjs/utils/templates/scene.js +4 -1
  29. package/dist/esm/core/utils/ComContext.js +5 -0
  30. package/dist/esm/core/utils/hooks.js +14 -5
  31. package/dist/esm/core/utils/index.js +4 -2
  32. package/dist/esm/core/utils/slots.js +108 -0
  33. package/dist/esm/core/utils/useContext.js +21 -11
  34. package/dist/esm/core/utils/with.js +50 -7
  35. package/dist/esm/generate/generateTaroProjectJson.js +2 -2
  36. package/dist/esm/handleCom.d.ts +7 -30
  37. package/dist/esm/handleCom.js +224 -81
  38. package/dist/esm/handleSlot.d.ts +3 -0
  39. package/dist/esm/handleSlot.js +34 -11
  40. package/dist/esm/processors/processScene.js +36 -1
  41. package/dist/esm/processors/processSceneLogic.js +3 -1
  42. package/dist/esm/taro-template.json +17 -13
  43. package/dist/esm/toCodeTaro.d.ts +2 -0
  44. package/dist/esm/utils/logic/handleProcess.js +12 -16
  45. package/dist/esm/utils/logic/processChildren.d.ts +1 -0
  46. package/dist/esm/utils/logic/processChildren.js +17 -1
  47. package/dist/esm/utils/style/converter.js +66 -31
  48. package/dist/esm/utils/style/pxtransform.d.ts +2 -26
  49. package/dist/esm/utils/style/pxtransform.js +31 -98
  50. package/dist/esm/utils/templates/component.js +3 -2
  51. package/dist/esm/utils/templates/index.d.ts +10 -0
  52. package/dist/esm/utils/templates/index.js +33 -9
  53. package/dist/esm/utils/templates/renderManager.d.ts +3 -11
  54. package/dist/esm/utils/templates/renderManager.js +92 -23
  55. package/dist/esm/utils/templates/scene.d.ts +2 -1
  56. package/dist/esm/utils/templates/scene.js +4 -2
  57. package/package.json +1 -1
@@ -8,15 +8,34 @@ var handleSlot = function handleSlot(ui, config) {
8
8
  var _meta, _props$style;
9
9
  var importManager = new ImportManager(config);
10
10
  var _ui$props = ui.props,
11
- props = _ui$props === void 0 ? {} : _ui$props,
12
- _ui$children = ui.children,
13
- children = _ui$children === void 0 ? [] : _ui$children;
11
+ props = _ui$props === void 0 ? {} : _ui$props;
12
+ // 支持 children comAry (DSL 常用名)
13
+ var children = ui.children || ui.comAry || [];
14
14
  var isRoot = config.checkIsRoot();
15
15
  var slotId = ((_meta = ui.meta) === null || _meta === void 0 ? void 0 : _meta.id) || ui.id;
16
16
 
17
17
  // 1. 初始化依赖与基础定义
18
18
  var addDependencyImport = config.addParentDependencyImport || importManager.addImport.bind(importManager);
19
19
  setupImports(addDependencyImport, config, isRoot);
20
+
21
+ // 鸿蒙规范:插槽组件内部需要使用 context 访问 comRefs/outputs
22
+ if (!isRoot) {
23
+ var utilsPkg = config.getUtilsPackageName({
24
+ isRoot: isRoot,
25
+ isPopup: config.isPopup
26
+ });
27
+ addDependencyImport({
28
+ packageName: utilsPkg,
29
+ dependencyNames: ["useAppContext", "ScopedComContextProvider"],
30
+ importType: "named"
31
+ });
32
+ // 补全 useEffect 导入(用于插槽逻辑驱动)
33
+ addDependencyImport({
34
+ packageName: "react",
35
+ dependencyNames: ["useEffect"],
36
+ importType: "named"
37
+ });
38
+ }
20
39
  var indent2 = indentation(config.codeStyle.indent);
21
40
  var envDefineCode = isRoot ? genRootDefineCode(indent2, config.getUtilsPackageName()) : genSlotDefineCode(indent2);
22
41
 
@@ -25,7 +44,9 @@ var handleSlot = function handleSlot(ui, config) {
25
44
  var childResults = processChildren(children, _objectSpread(_objectSpread({}, config), {}, {
26
45
  depth: config.depth + 1,
27
46
  addParentDependencyImport: addDependencyImport,
28
- renderManager: renderManager
47
+ renderManager: renderManager,
48
+ // 让插槽内部的组件知道当前处于哪个 slot(用于接收父容器 inputValues)
49
+ currentSlotId: isRoot ? undefined : config.slotKey || slotId
29
50
  }));
30
51
 
31
52
  // 3. 处理场景逻辑 (Start, Inputs 等)
@@ -33,15 +54,15 @@ var handleSlot = function handleSlot(ui, config) {
33
54
 
34
55
  // 4. 合并样式与代码
35
56
  var cssContent = (convertStyleAryToCss((_props$style = props.style) === null || _props$style === void 0 ? void 0 : _props$style.styleAry, slotId) || "") + (childResults.cssContent ? "\n" + childResults.cssContent : "");
36
- var renderCodeBlock = isRoot && renderManager ? renderManager.toCode(indentation(config.codeStyle.indent)) : "";
37
- var combinedJsCode = "".concat(envDefineCode).concat(childResults.js).concat(renderCodeBlock ? "\n".concat(renderCodeBlock) : "").concat(wrapInEffect(indent2, effectCode));
57
+ var combinedJsCode = "".concat(envDefineCode).concat(childResults.js).concat(wrapInEffect(indent2, effectCode));
38
58
 
39
59
  // 5. 生成 UI 结构
40
60
  var uiResult = generateSlotUi(ui, props, childResults.ui, config);
41
61
 
42
62
  // 6. 如果是根场景,生成完整文件
43
63
  if (isRoot) {
44
- finalizeRootComponent(ui, config, importManager, combinedJsCode, uiResult, cssContent);
64
+ var renderDefinitions = renderManager ? renderManager.toCode("") : ""; // 顶层定义不需要缩进
65
+ finalizeRootComponent(ui, config, importManager, combinedJsCode, renderDefinitions, uiResult, cssContent);
45
66
  }
46
67
  return {
47
68
  js: childResults.js,
@@ -49,7 +70,8 @@ var handleSlot = function handleSlot(ui, config) {
49
70
  ui: uiResult,
50
71
  cssContent: cssContent,
51
72
  slots: [],
52
- scopeSlots: []
73
+ scopeSlots: [],
74
+ childrenResults: childResults.childrenResults
53
75
  };
54
76
  };
55
77
 
@@ -72,7 +94,7 @@ var setupImports = function setupImports(addImport, config, isRoot) {
72
94
  dependencyNames: ["View"],
73
95
  importType: "named"
74
96
  });
75
- var dependencyNames = ["WithCom", "WithWrapper"];
97
+ var dependencyNames = ["WithCom", "WithWrapper", "SlotProvider"];
76
98
  if (isRoot && config.hasPopups) {
77
99
  dependencyNames.push("PopupRenderer");
78
100
  }
@@ -95,7 +117,7 @@ var setupImports = function setupImports(addImport, config, isRoot) {
95
117
  });
96
118
  }
97
119
  addImport({
98
- packageName: "./index.less",
120
+ packageName: "./index.global.less",
99
121
  dependencyNames: [],
100
122
  importType: "module"
101
123
  });
@@ -122,7 +144,7 @@ var generateSlotUi = function generateSlotUi(ui, props, childrenUi, config) {
122
144
  /**
123
145
  * 完成根组件的注册
124
146
  */
125
- var finalizeRootComponent = function finalizeRootComponent(ui, config, importManager, combinedJsCode, uiResult, cssContent) {
147
+ var finalizeRootComponent = function finalizeRootComponent(ui, config, importManager, combinedJsCode, renderDefinitions, uiResult, cssContent) {
126
148
  var _config$getFileName, _ui$meta, _ui$meta2;
127
149
  var fileName = ((_config$getFileName = config.getFileName) === null || _config$getFileName === void 0 ? void 0 : _config$getFileName.call(config, ui.meta.slotId)) || ui.meta.title || "index";
128
150
  var componentId = ((_ui$meta = ui.meta) === null || _ui$meta === void 0 ? void 0 : _ui$meta.id) || ui.id || ((_ui$meta2 = ui.meta) === null || _ui$meta2 === void 0 ? void 0 : _ui$meta2.slotId) || "Index";
@@ -130,6 +152,7 @@ var finalizeRootComponent = function finalizeRootComponent(ui, config, importMan
130
152
  var componentCode = genComponentTemplate({
131
153
  componentName: componentName,
132
154
  combinedJsCode: combinedJsCode,
155
+ renderDefinitions: renderDefinitions,
133
156
  uiResult: uiResult,
134
157
  isPopup: config.isPopup,
135
158
  hasPopups: config.hasPopups
@@ -5,6 +5,7 @@ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
5
5
  */
6
6
 
7
7
  import handleSlot from "../handleSlot";
8
+ import { RenderManager } from "../utils/templates/renderManager";
8
9
  import { createProvider, createProviderMap } from "../utils/context/createProvider";
9
10
  import { createEventQueries } from "../utils/context/createEventQueries";
10
11
  import { collectJSModulesFromScene } from "../utils/context/collectJSModules";
@@ -12,7 +13,7 @@ import { collectJSModulesFromScene } from "../utils/context/collectJSModules";
12
13
  * 处理单个场景
13
14
  */
14
15
  export var processScene = function processScene(params) {
15
- var _config$getFileName, _originalScene$deps;
16
+ var _config$getFileName, _originalScene$deps, _originalScene$slot;
16
17
  var _params$scene = params.scene,
17
18
  scene = _params$scene.scene,
18
19
  ui = _params$scene.ui,
@@ -57,10 +58,44 @@ export var processScene = function processScene(params) {
57
58
  // 创建事件查询函数
58
59
  var eventQueries = createEventQueries(event);
59
60
 
61
+ // 创建 RenderManager
62
+ var renderManager = new RenderManager();
63
+
64
+ // 鸿蒙规范:建立全局组件 ID -> DSL 名称映射表,确保在任何层级都能获取到稳定的名称
65
+ var dslComIdToNameMap = {};
66
+ if (originalScene !== null && originalScene !== void 0 && (_originalScene$slot = originalScene.slot) !== null && _originalScene$slot !== void 0 && _originalScene$slot.comAry) {
67
+ var scanComs = function scanComs(coms) {
68
+ if (!Array.isArray(coms)) return;
69
+ coms.forEach(function (com) {
70
+ var _com$def, _com$model;
71
+ if (com.name) dslComIdToNameMap[com.id] = com.name;
72
+ if (com.slots) {
73
+ var slotList = Array.isArray(com.slots) ? com.slots : Object.values(com.slots);
74
+ slotList.forEach(function (slot) {
75
+ if (slot.comAry) scanComs(slot.comAry);
76
+ if (slot.children) scanComs(slot.children);
77
+ });
78
+ }
79
+ // 特殊处理表单容器
80
+ if (((_com$def = com.def) === null || _com$def === void 0 ? void 0 : _com$def.namespace) === 'mybricks.taro.formContainer' && (_com$model = com.model) !== null && _com$model !== void 0 && (_com$model = _com$model.data) !== null && _com$model !== void 0 && _com$model.items) {
81
+ com.model.data.items.forEach(function (item) {
82
+ if (item.comName) dslComIdToNameMap[item.id] = item.comName;
83
+ });
84
+ }
85
+ });
86
+ };
87
+ scanComs(originalScene.slot.comAry);
88
+ }
89
+
60
90
  // 处理 Slot
61
91
  handleSlot(ui, _objectSpread(_objectSpread({}, config), {}, {
92
+ renderManager: renderManager,
93
+ // 显式传入 renderManager
62
94
  isPopup: isPopup,
63
95
  // 标记当前场景是否为弹窗
96
+ getDslComNameById: function getDslComNameById(id) {
97
+ return dslComIdToNameMap[id];
98
+ },
64
99
  getCurrentScene: function getCurrentScene() {
65
100
  var originalScene = getSceneById(scene.id);
66
101
  return _objectSpread(_objectSpread(_objectSpread({}, scene), originalScene), {}, {
@@ -137,7 +137,9 @@ var processSceneInputs = function processSceneInputs(currentScene, config, addDe
137
137
  var code = "";
138
138
  var sceneInputs = (currentScene === null || currentScene === void 0 ? void 0 : currentScene.inputs) || [];
139
139
  if (!Array.isArray(sceneInputs) || sceneInputs.length === 0) return code;
140
- code += "\n".concat(indent, " const inputs = comRefs.current.inputs;");
140
+
141
+ // 约定:场景级 inputs 挂载到 $inputs,避免与组件 runtime 的 inputs 冲突
142
+ code += "\n".concat(indent, " const inputs = comRefs.current.$inputs;");
141
143
  sceneInputs.forEach(function (input) {
142
144
  var event = config.getFrameInputEvent(input.id, currentScene.id);
143
145
  if (!event) return;
@@ -377,7 +377,7 @@
377
377
  "children": [
378
378
  {
379
379
  "path": "src/components/checkList/runtime/item.less",
380
- "content": ".item {\n width: 100%;\n overflow: hidden;\n padding: 6px;\n border: 1px solid rgb(200, 201, 204);\n border-radius: 3px;\n\n &.horizontal {\n display: flex;\n align-items: center;\n justify-content: center;\n .icon {\n margin-right: 6px;\n }\n\n .text {\n flex: 1;\n }\n }\n\n &.vertical {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n .icon {\n margin-bottom: 6px;\n }\n .text {\n width: 100%;\n }\n }\n\n .icon {\n display: block;\n width: 24px;\n height: 24px;\n }\n\n .text {\n font-size: 14px;\n line-height: 18px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n}\n\n.itemSelected {\n width: 100%;\n overflow: hidden;\n padding: 6px;\n border-radius: 3px;\n background: #fa6400;\n color: #ffffff;\n font-weight: 500;\n border: 1px solid #fa6400;\n}"
380
+ "content": ".item {\n width: 100%;\n overflow: hidden;\n padding: 6px;\n border: 1px solid rgb(200, 201, 204);\n border-radius: 3px;\n\n &.horizontal {\n display: flex;\n align-items: center;\n justify-content: center;\n .icon {\n margin-right: 6px;\n }\n\n .text {\n flex: 1;\n }\n }\n\n &.vertical {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n .icon {\n margin-bottom: 6px;\n }\n .text {\n width: 100%;\n }\n }\n\n .icon {\n display: block;\n width: 24px;\n height: 24px;\n }\n}\n\n.itemSelected {\n width: 100%;\n overflow: hidden;\n padding: 6px;\n border-radius: 3px;\n background: #fa6400;\n color: #ffffff;\n font-weight: 500;\n border: 1px solid #fa6400;\n}\n\n.item,\n.itemSelected {\n .text {\n font-size: 14px;\n line-height: 18px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n}"
381
381
  },
382
382
  {
383
383
  "path": "src/components/checkList/runtime/Item.tsx",
@@ -1943,7 +1943,7 @@
1943
1943
  },
1944
1944
  {
1945
1945
  "path": "src/components/filter-coms/sort/runtime.tsx",
1946
- "content": "import React, {\n useState,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n} from \"react\";\nimport { View, Image, Button } from \"@tarojs/components\";\nimport Taro from \"@tarojs/taro\";\nimport css from \"./style.less\";\nimport cx from \"classnames\";\nimport { isEmpty, isString } from \"./../../utils/core\";\nimport { useDiffValue, useFilterItemValue } from \"./../common\";\n\nconst UpSvg = ({ style }) => {\n return (\n <svg\n t=\"1717557925134\"\n class=\"icon\"\n viewBox=\"0 0 1024 1024\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n p-id=\"10247\"\n style={style}\n >\n <path\n d=\"M512 352L232 672h560L512 352z\"\n fill=\"currentColor\"\n p-id=\"10248\"\n ></path>\n </svg>\n );\n};\n\nconst UpSvg = ({ style }) => {\n const base64Svg = `data:image/svg+xml;base64,PHN2ZyB0PSIxNzE3NTU3OTI1MTM0IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjEwMjQ3Ij4KICA8cGF0aCBkPSJNNTEyIDM1MkwyMzIgNjcyaDU2MEw1MTIgMzUyeiIgZmlsbD0iY3VycmVudENvbG9yIiBwLWlkPSIxMDI0OCI+PC9wYXRoPgo8L3N2Zz4=`;\n\n return <Image src={base64Svg} svg={true} style={style} />;\n};\n\nconst DownSvg = ({ style }) => {\n return <UpSvg style={{ ...style, transform: \"rotate(180deg)\" }} />;\n};\n\nconst UNSET_VALUE = \"_UNSET_\";\n\nexport default (props) => {\n const { env, data, inputs, outputs, slots } = props;\n const { filterValue: selectMode, setFilterValue: setSelectMode } =\n useFilterItemValue(\n {\n defaultValue: UNSET_VALUE,\n onReceiveValue: (value) => {\n switch (true) {\n case isEmpty(value): {\n setSelectMode(UNSET_VALUE);\n break;\n }\n case isString(value):\n setSelectMode(value);\n break;\n default:\n break;\n }\n },\n onChangeValue: (value) => {\n return value === UNSET_VALUE ? \"\" : value;\n },\n },\n props\n );\n\n const _optionMap = useMemo(() => {\n return data.optionMap ? data.optionMap : {};\n }, [data.optionMap]);\n\n const status = useMemo(() => {\n if (_optionMap.asc?.value == selectMode) {\n return \"asc\";\n }\n if (_optionMap.desc?.value == selectMode) {\n return \"desc\";\n }\n return \"none\";\n }, [_optionMap, selectMode]);\n\n const handleClick = useCallback(() => {\n if (env.edit) {\n return;\n }\n\n // 点击按顺序选择下一个\n const valueQueue = [\n UNSET_VALUE,\n _optionMap.asc.value,\n _optionMap.desc.value,\n ];\n\n const done = valueQueue.some((v, index) => {\n if (selectMode == v) {\n setSelectMode(\n index + 1 === valueQueue.length\n ? valueQueue[0]\n : valueQueue[index + 1]\n );\n }\n return selectMode === v;\n });\n\n // 兼容数据不属于options的情况\n if (!done) {\n setSelectMode(valueQueue[1]);\n }\n }, [status, selectMode, _optionMap]);\n\n const actived = useMemo(() => {\n return status !== \"none\";\n }, [status]);\n\n return (\n <View\n className={`${css.sort} ${\n actived ? \"mbs-filter_sort--active\" : \"mbs-filter_sort\"\n }`}\n onClick={handleClick}\n data-id={_optionMap.none?.label}\n >\n {env.edit ? _optionMap.none?.label ?? \"暂未配置\" : _optionMap.none?.label}\n <View className={css.icons}>\n {status === \"none\" && (\n <>\n {data.modes?.length === 1 && data.modes?.includes(\"asc\") && (\n <UpSvg style={{ width: \"11px\", height: \"11px\" }} />\n )}\n {data.modes?.length === 1 && data.modes?.includes(\"desc\") && (\n <DownSvg style={{ width: \"11px\", height: \"11px\" }} />\n )}\n {data.modes?.length === 2 && (\n <>\n <UpSvg\n style={{\n width: \"11px\",\n height: \"11px\",\n marginBottom: \"-2px\",\n }}\n />\n <DownSvg\n style={{ width: \"11px\", height: \"11px\", marginTop: \"-2px\" }}\n />\n </>\n )}\n </>\n )}\n {status === \"asc\" && (\n <UpSvg style={{ width: \"11px\", height: \"11px\" }} />\n )}\n {status === \"desc\" && (\n <DownSvg style={{ width: \"11px\", height: \"11px\" }} />\n )}\n </View>\n </View>\n );\n};\n"
1946
+ "content": "import React, {\n useState,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n} from \"react\";\nimport { View, Image, Button } from \"@tarojs/components\";\nimport Taro from \"@tarojs/taro\";\nimport css from \"./style.less\";\nimport cx from \"classnames\";\nimport { isEmpty, isString } from \"./../../utils/core\";\nimport { useDiffValue, useFilterItemValue } from \"./../common\";\n\n// const UpSvg = ({ style }) => {\n// return (\n// <svg\n// t=\"1717557925134\"\n// class=\"icon\"\n// viewBox=\"0 0 1024 1024\"\n// version=\"1.1\"\n// xmlns=\"http://www.w3.org/2000/svg\"\n// p-id=\"10247\"\n// style={style}\n// >\n// <path\n// d=\"M512 352L232 672h560L512 352z\"\n// fill=\"currentColor\"\n// p-id=\"10248\"\n// ></path>\n// </svg>\n// );\n// };\n\nconst UpSvg = ({ style }) => {\n const base64Svg = `data:image/svg+xml;base64,PHN2ZyB0PSIxNzE3NTU3OTI1MTM0IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjEwMjQ3Ij4KICA8cGF0aCBkPSJNNTEyIDM1MkwyMzIgNjcyaDU2MEw1MTIgMzUyeiIgZmlsbD0iY3VycmVudENvbG9yIiBwLWlkPSIxMDI0OCI+PC9wYXRoPgo8L3N2Zz4=`;\n\n return <Image src={base64Svg} svg={true} style={style} />;\n};\n\nconst DownSvg = ({ style }) => {\n return <UpSvg style={{ ...style, transform: \"rotate(180deg)\" }} />;\n};\n\nconst UNSET_VALUE = \"_UNSET_\";\n\nexport default (props) => {\n const { env, data, inputs, outputs, slots } = props;\n const { filterValue: selectMode, setFilterValue: setSelectMode } =\n useFilterItemValue(\n {\n defaultValue: UNSET_VALUE,\n onReceiveValue: (value) => {\n switch (true) {\n case isEmpty(value): {\n setSelectMode(UNSET_VALUE);\n break;\n }\n case isString(value):\n setSelectMode(value);\n break;\n default:\n break;\n }\n },\n onChangeValue: (value) => {\n return value === UNSET_VALUE ? \"\" : value;\n },\n },\n props\n );\n\n const _optionMap = useMemo(() => {\n return data.optionMap ? data.optionMap : {};\n }, [data.optionMap]);\n\n const status = useMemo(() => {\n if (_optionMap.asc?.value == selectMode) {\n return \"asc\";\n }\n if (_optionMap.desc?.value == selectMode) {\n return \"desc\";\n }\n return \"none\";\n }, [_optionMap, selectMode]);\n\n const handleClick = useCallback(() => {\n if (env.edit) {\n return;\n }\n\n // 点击按顺序选择下一个\n const valueQueue = [\n UNSET_VALUE,\n _optionMap.asc.value,\n _optionMap.desc.value,\n ];\n\n const done = valueQueue.some((v, index) => {\n if (selectMode == v) {\n setSelectMode(\n index + 1 === valueQueue.length\n ? valueQueue[0]\n : valueQueue[index + 1]\n );\n }\n return selectMode === v;\n });\n\n // 兼容数据不属于options的情况\n if (!done) {\n setSelectMode(valueQueue[1]);\n }\n }, [status, selectMode, _optionMap]);\n\n const actived = useMemo(() => {\n return status !== \"none\";\n }, [status]);\n\n return (\n <View\n className={`${css.sort} ${\n actived ? \"mbs-filter_sort--active\" : \"mbs-filter_sort\"\n }`}\n onClick={handleClick}\n data-id={_optionMap.none?.label}\n >\n {env.edit ? _optionMap.none?.label ?? \"暂未配置\" : _optionMap.none?.label}\n <View className={css.icons}>\n {status === \"none\" && (\n <>\n {data.modes?.length === 1 && data.modes?.includes(\"asc\") && (\n <UpSvg style={{ width: \"11px\", height: \"11px\" }} />\n )}\n {data.modes?.length === 1 && data.modes?.includes(\"desc\") && (\n <DownSvg style={{ width: \"11px\", height: \"11px\" }} />\n )}\n {data.modes?.length === 2 && (\n <>\n <UpSvg\n style={{\n width: \"11px\",\n height: \"11px\",\n marginBottom: \"-2px\",\n }}\n />\n <DownSvg\n style={{ width: \"11px\", height: \"11px\", marginTop: \"-2px\" }}\n />\n </>\n )}\n </>\n )}\n {status === \"asc\" && (\n <UpSvg style={{ width: \"11px\", height: \"11px\" }} />\n )}\n {status === \"desc\" && (\n <DownSvg style={{ width: \"11px\", height: \"11px\" }} />\n )}\n </View>\n </View>\n );\n};\n"
1947
1947
  },
1948
1948
  {
1949
1949
  "path": "src/components/filter-coms/sort/style.less",
@@ -2081,7 +2081,7 @@
2081
2081
  },
2082
2082
  {
2083
2083
  "path": "src/components/formContainer/runtime.tsx",
2084
- "content": "import React, {\n useState,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useLayoutEffect,\n} from \"react\";\nimport { View, Button, Image } from \"@tarojs/components\";\nimport Taro from \"@tarojs/taro\";\nimport css from \"./style.less\";\nimport cx from \"classnames\";\nimport { isEmpty, isObject } from \"./../utils/core\";\nimport { Cell, Form, Field } from \"brickd-mobile\";\nimport { getFormItem, findFormItemIndex } from \"./utils\";\nimport { FormItems, RuleKeys } from \"./types\";\n\n// @ts-ignore\nconst isH5 = Taro.getEnv() === Taro.ENV_TYPE.WEB || Taro.getEnv() === \"Unknown\";\n\nconst formatRulesFromItem = (item) => {\n const rules = item?.rules ?? [];\n\n return rules\n .filter((rule) => rule.status)\n .map((rule) => {\n if (rule.key === RuleKeys.REQUIRED) {\n return {\n required: true,\n message: rule.message,\n };\n }\n /** TODO */\n return {\n required: true,\n message: rule.message,\n };\n });\n};\n\n/** 去除value为undefined场景的对象 */\nconst omitUndefinedKeys = (obj) => {\n obj = obj || {};\n\n const resWithoutUndefined = {};\n Object.keys(obj).forEach((key) => {\n if (obj[key] !== undefined) {\n resWithoutUndefined[key] = obj[key];\n }\n });\n return resWithoutUndefined;\n};\n\n/** 代理fomrRef,因为组件库的setValues居然是增量的,不合理,这里代理成全量的 */\nconst useForm = ({ items, childrenInputs }) => {\n const formRef: any = useRef(null);\n\n const ref = useMemo(() => {\n return {\n getValues: () => {\n const res = formRef?.current?.getValues();\n return omitUndefinedKeys(res);\n },\n setFieldValue: (name, value) => {\n const res = formRef?.current?.getValues();\n\n // 如果值相同,不广播更新\n if (res[name] === value) {\n return;\n }\n\n res[name] = value;\n formRef?.current?.setValues?.(res);\n },\n setValues: (val) => {\n const valuesWithUndefined = {};\n /** 设置表单项的value */\n items.forEach((item) => {\n const itemValue = { ...(val ?? {}) }[item.name ?? item.id];\n childrenInputs.current[item.comName ?? item.id]?.[\"setValue\"]?.(\n itemValue\n );\n valuesWithUndefined[item.name ?? item.id] =\n itemValue !== undefined ? itemValue : undefined;\n });\n\n formRef?.cxurrent?.setValues?.(valuesWithUndefined);\n },\n validate: () =>\n new Promise((resolve, reject) => {\n formRef?.current\n ?.validate()\n ?.then((res) => {\n resolve(omitUndefinedKeys(res));\n })\n .catch((e) => reject(e));\n }),\n };\n }, []);\n\n return [ref, formRef];\n};\n\nexport default function ({ env, data, inputs, outputs, slots }) {\n const childrenInputs = useRef({});\n const [form, formRef] = useForm({ items: data.items, childrenInputs });\n const [loading, setLoading] = useState(false);\n\n useLayoutEffect(() => {\n /** 下发表单项的onChange函数,用来收集表单项数据 */\n slots[\"content\"]._inputs[\"onChange\"](({ id, name, value }) => {\n const item = getFormItem(data.items, { id, name });\n if (item) {\n form.setFieldValue(item.name || item.label, value);\n }\n });\n\n /** 动态修改标题等属性 */\n slots[\"content\"]._inputs[\"setProps\"](({ id, name, value }) => {\n const item = getFormItem(data.items, { id, name });\n if (item) {\n Object.keys(value).forEach((key) => {\n item[key] = value[key];\n });\n }\n });\n\n // 提交表单\n inputs[\"submit\"]((val, outputRels) => {\n form\n ?.validate()\n .then((res) => {\n outputRels[\"onSubmit\"](res);\n })\n .catch((err) => {\n console.error(\"validate\", err);\n });\n });\n\n inputs[\"submitAndMerge\"]((val, outputRels) => {\n let _val = isObject(val) ? val : {};\n\n form\n ?.validate()\n .then((res) => {\n outputRels[\"onMergeSubmit\"]({\n ...res,\n ..._val,\n });\n })\n .catch((err) => {\n console.error(\"validate\", err);\n });\n });\n\n // 重置表单\n inputs[\"resetFields\"]((val, outputRels) => {\n form.setValues({});\n outputRels[\"onReset\"]();\n });\n\n // 异步提交完成\n inputs[\"finishLoading\"]?.(() => {\n setLoading(false);\n });\n\n inputs[\"setFieldsValue\"]((val) => {\n if (isEmpty(val) || !isObject(val)) {\n return;\n }\n\n form.setValues(val);\n // 触发「表单数据输入」\n slots[\"content\"].inputs[\"setFieldsValue\"](val);\n });\n\n inputs[\"getFieldsValue\"]((val, outputRels) => {\n const values = form.getValues();\n outputRels[\"returnValues\"](values);\n });\n }, []);\n\n const content = useMemo(() => {\n return (\n <View>\n {slots[\"content\"].render({\n itemWrap(com: { id; jsx; name }) {\n // todo name\n const idx = findFormItemIndex(data.items, com);\n const item = data.items[idx] ?? ({} as FormItems);\n let rules = formatRulesFromItem(item);\n\n if (data.skipValidation === \"hidden\" && item.visible === false) {\n rules = [];\n }\n\n const showRequired = rules.findIndex((rule) => rule.required) > -1;\n\n // const isLast = data.items.length - 1 === idx\n const isLast = data.items.length - 1 === item.index;\n\n const icon = item.icon ? (\n <Image mode=\"scaleToFill\" src={item.icon} />\n ) : null;\n\n const itemLayout =\n !item.itemLayout || item.itemLayout === \"unset\"\n ? data.itemLayout\n : item.itemLayout;\n\n return (\n <Field\n className={cx(\n \"mybricks-field\",\n { [\"border-bottom\"]: !isLast },\n { [\"border-none\"]: isLast },\n { [css.hidden]: !env?.edit && item.hidden },\n { [\"vertical\"]: itemLayout === \"vertical\" }\n )}\n required={showRequired}\n rules={rules}\n label={!item.hideLabel && item.label}\n name={item.name}\n icon={icon}\n >\n {com.jsx}\n </Field>\n );\n },\n wrap(comAray: { id; name; jsx; def; inputs; outputs; style }[]) {\n const items = data.items ?? [];\n\n const jsx = comAray?.map((com, idx) => {\n if (com) {\n let item = getFormItem(data.items, com);\n item.index = idx;\n item.visible = com.style.display !== \"none\";\n\n if (!item) {\n if (items.length === comAray.length) {\n console.warn(`formItem comId ${com.id} formItem not found`);\n }\n return;\n }\n\n if (item.comName) {\n childrenInputs.current[com.name] = com.inputs;\n } else {\n childrenInputs.current[com.id] = com.inputs;\n }\n\n return com.jsx;\n }\n });\n\n return jsx;\n },\n })}\n </View>\n );\n }, []);\n\n const onCustomSubmit = useCallback(() => {\n if (env.runtime) {\n // 异步提交中\n if (data.useLoading && loading) {\n return;\n }\n\n if (data.useLoading) {\n setLoading(true);\n }\n\n switch (data.skipValidation) {\n case false:\n case \"all\":\n // 校验所有表单项\n form\n ?.validate()\n .then((res) => {\n outputs[\"onSubmit\"](res);\n })\n .catch((err) => {\n // 遇到异常,自动回滚 loading 状态\n setLoading(false);\n console.error(\"validate\", err);\n });\n break;\n\n case \"hidden\":\n // 不校验隐藏的表单项\n form\n ?.validate()\n .then((res) => {\n outputs[\"onSubmit\"](res);\n })\n .catch((err) => {\n // 遇到异常,自动回滚 loading 状态\n setLoading(false);\n console.error(\"validate\", err);\n });\n break;\n\n case true:\n case \"none\":\n // 不校验所有的表单项\n outputs[\"onSubmit\"](form?.getValues());\n break;\n }\n\n // if (data.skipValidation) {\n // outputs[\"onSubmit\"](form?.getValues());\n // } else {\n // form\n // ?.validate()\n // .then((res) => {\n // outputs[\"onSubmit\"](res);\n // })\n // .catch((err) => {\n // // 遇到异常,自动回滚 loading 状态\n // setLoading(false);\n // console.error(\"validate\", err);\n // });\n // }\n }\n }, [data.useLoading, loading, data.skipValidation]);\n\n return (\n <Form className={cx(css.form, { [css.h5]: isH5 })} ref={formRef}>\n <Cell.Group bordered={false}>{content}</Cell.Group>\n {data.useSubmitButton ? (\n <View className={cx(css.foot, \"mybricks-submit\")}>\n <Button className=\"taroify-button\" onClick={onCustomSubmit}>\n {loading ? (\n // ... 的动画\n <View className={css.loading}>\n <View className={css.dot1}></View>\n <View className={css.dot2}></View>\n <View className={css.dot3}></View>\n </View>\n ) : (\n data.submitButtonText\n )}\n </Button>\n </View>\n ) : null}\n </Form>\n );\n}\n"
2084
+ "content": "import React, {\n useState,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useLayoutEffect,\n} from \"react\";\nimport { View, Button, Image } from \"@tarojs/components\";\nimport Taro from \"@tarojs/taro\";\nimport css from \"./style.less\";\nimport cx from \"classnames\";\nimport { isEmpty, isObject } from \"./../utils/core\";\nimport { Cell, Form, Field } from \"brickd-mobile\";\nimport { getFormItem, findFormItemIndex } from \"./utils\";\nimport { FormItems, RuleKeys } from \"./types\";\n\n// @ts-ignore\nconst isH5 = Taro.getEnv() === Taro.ENV_TYPE.WEB || Taro.getEnv() === \"Unknown\";\n\nconst formatRulesFromItem = (item) => {\n const rules = item?.rules ?? [];\n\n return rules\n .filter((rule) => rule.status)\n .map((rule) => {\n if (rule.key === RuleKeys.REQUIRED) {\n return {\n required: true,\n message: rule.message,\n };\n }\n /** TODO */\n return {\n required: true,\n message: rule.message,\n };\n });\n};\n\n/** 去除value为undefined场景的对象 */\nconst omitUndefinedKeys = (obj) => {\n obj = obj || {};\n\n const resWithoutUndefined = {};\n Object.keys(obj).forEach((key) => {\n if (obj[key] !== undefined) {\n resWithoutUndefined[key] = obj[key];\n }\n });\n return resWithoutUndefined;\n};\n\n/** 代理fomrRef,因为组件库的setValues居然是增量的,不合理,这里代理成全量的 */\nconst useForm = ({ items, childrenInputs }) => {\n const formRef: any = useRef(null);\n\n const ref = useMemo(() => {\n return {\n getValues: () => {\n const res = formRef?.current?.getValues();\n return omitUndefinedKeys(res);\n },\n setFieldValue: (name, value) => {\n const res = formRef?.current?.getValues();\n\n // 如果值相同,不广播更新\n if (res[name] === value) {\n return;\n }\n\n res[name] = value;\n formRef?.current?.setValues?.(res);\n },\n setValues: (val) => {\n const valuesWithUndefined = {};\n /** 设置表单项的value */\n items.forEach((item) => {\n const itemValue = { ...(val ?? {}) }[item.name ?? item.id];\n childrenInputs.current[item.comName ?? item.id]?.[\"setValue\"]?.(\n itemValue\n );\n valuesWithUndefined[item.name ?? item.id] =\n itemValue !== undefined ? itemValue : undefined;\n });\n\n formRef?.cxurrent?.setValues?.(valuesWithUndefined);\n },\n validate: () =>\n new Promise((resolve, reject) => {\n formRef?.current\n ?.validate()\n ?.then((res) => {\n resolve(omitUndefinedKeys(res));\n })\n .catch((e) => reject(e));\n }),\n };\n }, []);\n\n return [ref, formRef];\n};\n\nexport default function ({ env, data, inputs, outputs, slots }) {\n const childrenInputs = useRef({});\n const [form, formRef] = useForm({ items: data.items, childrenInputs });\n const [loading, setLoading] = useState(false);\n\n useLayoutEffect(() => {\n /** 下发表单项的onChange函数,用来收集表单项数据 */\n slots[\"content\"]._inputs[\"onChange\"](({ id, name, value }) => {\n const item = getFormItem(data.items, { id, name });\n if (item) {\n form.setFieldValue(item.name || item.label, value);\n }\n });\n\n /** 动态修改标题等属性 */\n slots[\"content\"]._inputs[\"setProps\"](({ id, name, value }) => {\n const item = getFormItem(data.items, { id, name });\n if (item) {\n Object.keys(value).forEach((key) => {\n item[key] = value[key];\n });\n }\n });\n\n // 提交表单\n inputs[\"submit\"]((val, outputRels) => {\n form\n ?.validate()\n .then((res) => {\n outputRels[\"onSubmit\"](res);\n })\n .catch((err) => {\n console.error(\"validate\", err);\n });\n });\n\n inputs[\"submitAndMerge\"]((val, outputRels) => {\n let _val = isObject(val) ? val : {};\n\n form\n ?.validate()\n .then((res) => {\n outputRels[\"onMergeSubmit\"]({\n ...res,\n ..._val,\n });\n })\n .catch((err) => {\n console.error(\"validate\", err);\n });\n });\n\n // 重置表单\n inputs[\"resetFields\"]((val, outputRels) => {\n form.setValues({});\n outputRels[\"onReset\"]();\n });\n\n // 异步提交完成\n inputs[\"finishLoading\"]?.(() => {\n setLoading(false);\n });\n\n inputs[\"setFieldsValue\"]((val) => {\n if (isEmpty(val) || !isObject(val)) {\n return;\n }\n\n form.setValues(val);\n // 触发「表单数据输入」\n slots[\"content\"].inputs[\"setFieldsValue\"](val);\n });\n\n inputs[\"getFieldsValue\"]((val, outputRels) => {\n const values = form.getValues();\n outputRels[\"returnValues\"](values);\n });\n }, []);\n\n const content = useMemo(() => {\n return (\n <View>\n {slots[\"content\"].render({\n itemWrap(com: { id; jsx; name }) {\n // todo name\n const idx = findFormItemIndex(data.items, com);\n const item = data.items[idx] ?? ({} as FormItems);\n let rules = formatRulesFromItem(item);\n\n if (data.skipValidation === \"hidden\" && item.visible === false) {\n rules = [];\n }\n\n const showRequired = rules.findIndex((rule) => rule.required) > -1;\n\n // const isLast = data.items.length - 1 === idx\n const isLast = data.items.length - 1 === item.index;\n\n const icon = item.icon ? (\n <Image mode=\"scaleToFill\" src={item.icon} />\n ) : null;\n\n const itemLayout =\n !item.itemLayout || item.itemLayout === \"unset\"\n ? data.itemLayout\n : item.itemLayout;\n\n return (\n <Field\n className={cx(\n \"mybricks-field\",\n com.id,\n { [\"border-bottom\"]: !isLast },\n { [\"border-none\"]: isLast },\n { [css.hidden]: !env?.edit && item.hidden },\n { [\"vertical\"]: itemLayout === \"vertical\" }\n )}\n required={showRequired}\n rules={rules}\n label={!item.hideLabel && item.label}\n name={item.name}\n icon={icon}\n >\n {com.jsx}\n </Field>\n );\n },\n wrap(comAray: { id; name; jsx; def; inputs; outputs; style }[]) {\n const items = data.items ?? [];\n\n const jsx = comAray?.map((com, idx) => {\n if (com) {\n let item = getFormItem(data.items, com);\n item.index = idx;\n item.visible = com.style.display !== \"none\";\n\n if (!item) {\n if (items.length === comAray.length) {\n console.warn(`formItem comId ${com.id} formItem not found`);\n }\n return;\n }\n\n if (item.comName) {\n childrenInputs.current[com.name] = com.inputs;\n } else {\n childrenInputs.current[com.id] = com.inputs;\n }\n\n return com.jsx;\n }\n });\n\n return jsx;\n },\n })}\n </View>\n );\n }, []);\n\n const onCustomSubmit = useCallback(() => {\n if (env.runtime) {\n // 异步提交中\n if (data.useLoading && loading) {\n return;\n }\n\n if (data.useLoading) {\n setLoading(true);\n }\n\n switch (data.skipValidation) {\n case false:\n case \"all\":\n // 校验所有表单项\n form\n ?.validate()\n .then((res) => {\n outputs[\"onSubmit\"](res);\n })\n .catch((err) => {\n // 遇到异常,自动回滚 loading 状态\n setLoading(false);\n console.error(\"validate\", err);\n });\n break;\n\n case \"hidden\":\n // 不校验隐藏的表单项\n form\n ?.validate()\n .then((res) => {\n outputs[\"onSubmit\"](res);\n })\n .catch((err) => {\n // 遇到异常,自动回滚 loading 状态\n setLoading(false);\n console.error(\"validate\", err);\n });\n break;\n\n case true:\n case \"none\":\n // 不校验所有的表单项\n outputs[\"onSubmit\"](form?.getValues());\n break;\n }\n\n // if (data.skipValidation) {\n // outputs[\"onSubmit\"](form?.getValues());\n // } else {\n // form\n // ?.validate()\n // .then((res) => {\n // outputs[\"onSubmit\"](res);\n // })\n // .catch((err) => {\n // // 遇到异常,自动回滚 loading 状态\n // setLoading(false);\n // console.error(\"validate\", err);\n // });\n // }\n }\n }, [data.useLoading, loading, data.skipValidation]);\n\n return (\n <Form className={cx(css.form, { [css.h5]: isH5 })} ref={formRef}>\n <Cell.Group bordered={false}>{content}</Cell.Group>\n {data.useSubmitButton ? (\n <View className={cx(css.foot, \"mybricks-submit\")}>\n <Button className=\"taroify-button\" onClick={onCustomSubmit}>\n {loading ? (\n // ... 的动画\n <View className={css.loading}>\n <View className={css.dot1}></View>\n <View className={css.dot2}></View>\n <View className={css.dot3}></View>\n </View>\n ) : (\n data.submitButtonText\n )}\n </Button>\n </View>\n ) : null}\n </Form>\n );\n}\n"
2085
2085
  },
2086
2086
  {
2087
2087
  "path": "src/components/formContainer/style.less",
@@ -2469,7 +2469,7 @@
2469
2469
  },
2470
2470
  {
2471
2471
  "path": "src/components/formPassword/runtime.tsx",
2472
- "content": "import React, { useCallback, useMemo, useState, useEffect } from \"react\";\nimport { isNumber, isObject, isString, isEmpty } from \"./../utils/core/type\";\nimport { View } from \"@tarojs/components\";\nimport css from \"./style.less\";\nimport cx from \"classnames\";\nimport { Input } from \"brickd-mobile\";\nimport { isH5 } from \"../utils/env\";\nimport cx from \"classnames\";\n\nexport default function (props) {\n const { env, data, inputs, outputs, slots, parentSlot } = props;\n\n const [value, setValue] = useState(data.value);\n const [paasword, setPassword] = useState(true);\n\n useEffect(() => {\n parentSlot?._inputs[\"setProps\"]?.({\n id: props.id,\n name: props.name,\n value: {\n visible: props.style.display !== \"none\",\n },\n });\n }, [props.style.display]);\n\n useEffect(() => {\n inputs[\"getValue\"]((val, outputRels) => {\n outputRels[\"returnValue\"](value);\n });\n }, [value]);\n\n useEffect(() => {\n inputs[\"setValue\"]((val) => {\n switch (true) {\n case isEmpty(val): {\n setValue(\"\");\n break;\n }\n case isString(val) || isNumber(val):\n setValue(val);\n break;\n case isObject(val):\n setValue(val[data.name]);\n break;\n default:\n break;\n }\n });\n\n // 设置禁用\n inputs[\"setDisabled\"]?.(() => {\n data.disabled = true;\n });\n\n // 设置启用\n inputs[\"setEnabled\"]?.(() => {\n data.disabled = false;\n });\n }, []);\n\n const buttonCx = useMemo(() => {\n return cx({\n [css.button]: true,\n [css.show]: !paasword,\n [css.hide]: paasword,\n });\n }, [paasword]);\n\n const onTogglePassword = useCallback(() => {\n setPassword(!paasword);\n }, [paasword]);\n\n const onChange = useCallback((e) => {\n let value = e.detail.value;\n setValue(value);\n\n parentSlot?._inputs[\"onChange\"]?.({\n id: props.id,\n name: props.name,\n value,\n });\n outputs[\"onChange\"](value);\n }, []);\n\n const onBlur = useCallback((e) => {\n let value = e.detail.value;\n outputs[\"onBlur\"](value);\n }, []);\n\n return (\n <View\n className={cx({\n [css.password]: true,\n \"mybricks-password\": !isH5(),\n \"mybricks-h5Password\": isH5(),\n })}\n >\n <Input\n value={value}\n password={paasword}\n type={data.type}\n placeholder={data.placeholder}\n onChange={onChange}\n disabled={data.disabled}\n onBlur={onBlur}\n maxlength={data.maxlength || 20}\n />\n <View className={buttonCx} onClick={onTogglePassword}></View>\n </View>\n );\n}\n"
2472
+ "content": "import React, { useCallback, useMemo, useState, useEffect } from \"react\";\nimport { isNumber, isObject, isString, isEmpty } from \"./../utils/core/type\";\nimport { View } from \"@tarojs/components\";\nimport css from \"./style.less\";\nimport cx from \"classnames\";\nimport { Input } from \"brickd-mobile\";\nimport { isH5 } from \"../utils/env\";\n\nexport default function (props) {\n const { env, data, inputs, outputs, slots, parentSlot } = props;\n\n const [value, setValue] = useState(data.value);\n const [paasword, setPassword] = useState(true);\n\n useEffect(() => {\n parentSlot?._inputs[\"setProps\"]?.({\n id: props.id,\n name: props.name,\n value: {\n visible: props.style.display !== \"none\",\n },\n });\n }, [props.style.display]);\n\n useEffect(() => {\n inputs[\"getValue\"]((val, outputRels) => {\n outputRels[\"returnValue\"](value);\n });\n }, [value]);\n\n useEffect(() => {\n inputs[\"setValue\"]((val) => {\n switch (true) {\n case isEmpty(val): {\n setValue(\"\");\n break;\n }\n case isString(val) || isNumber(val):\n setValue(val);\n break;\n case isObject(val):\n setValue(val[data.name]);\n break;\n default:\n break;\n }\n });\n\n // 设置禁用\n inputs[\"setDisabled\"]?.(() => {\n data.disabled = true;\n });\n\n // 设置启用\n inputs[\"setEnabled\"]?.(() => {\n data.disabled = false;\n });\n }, []);\n\n const buttonCx = useMemo(() => {\n return cx({\n [css.button]: true,\n [css.show]: !paasword,\n [css.hide]: paasword,\n });\n }, [paasword]);\n\n const onTogglePassword = useCallback(() => {\n setPassword(!paasword);\n }, [paasword]);\n\n const onChange = useCallback((e) => {\n let value = e.detail.value;\n setValue(value);\n\n parentSlot?._inputs[\"onChange\"]?.({\n id: props.id,\n name: props.name,\n value,\n });\n outputs[\"onChange\"](value);\n }, []);\n\n const onBlur = useCallback((e) => {\n let value = e.detail.value;\n outputs[\"onBlur\"](value);\n }, []);\n\n return (\n <View\n className={cx({\n [css.password]: true,\n \"mybricks-password\": !isH5(),\n \"mybricks-h5Password\": isH5(),\n })}\n >\n <Input\n value={value}\n password={paasword}\n type={data.type}\n placeholder={data.placeholder}\n onChange={onChange}\n disabled={data.disabled}\n onBlur={onBlur}\n maxlength={data.maxlength || 20}\n />\n <View className={buttonCx} onClick={onTogglePassword}></View>\n </View>\n );\n}\n"
2473
2473
  },
2474
2474
  {
2475
2475
  "path": "src/components/formPassword/style.less",
@@ -2537,7 +2537,7 @@
2537
2537
  },
2538
2538
  {
2539
2539
  "path": "src/components/formPhoneSMS/runtime.tsx",
2540
- "content": "import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { View, Button } from \"@tarojs/components\";\nimport { Input } from \"brickd-mobile\";\nimport css from \"./style.less\";\nimport cx from \"classnames\";\nimport * as Taro from \"@tarojs/taro\";\nimport useFormItemValue from \"../utils/hooks/useFormItemValue.ts\";\nimport { isEmpty, isString, isNumber, isObject } from \"./../utils/type\";\nimport { isH5 } from \"../utils/env\";\nimport cx from \"classnames\";\n\nexport default function (props) {\n const { env, data, inputs, outputs, slots, parentSlot } = props;\n\n const [value, setValue, getValue] = useFormItemValue(data.value, (val) => {\n //\n parentSlot?._inputs[\"onChange\"]?.({\n id: props.id,\n name: props.name,\n value: val,\n });\n\n //\n outputs[\"onChange\"](val);\n });\n\n //\n const timer = useRef(null);\n const countDownRef = useRef(null);\n\n useEffect(() => {\n parentSlot?._inputs[\"setProps\"]?.({\n id: props.id,\n name: props.name,\n value: {\n visible: props.style.display !== \"none\",\n },\n });\n }, [props.style.display]);\n\n useEffect(() => {\n /* 设置值 */\n inputs[\"setValue\"]((val, outputRels) => {\n let result;\n\n switch (true) {\n case isEmpty(val): {\n result = \"\";\n break;\n }\n case isString(val) || isNumber(val): {\n result = `${val}`;\n break;\n }\n default:\n // 其他类型的值,直接返回\n return;\n }\n\n setValue(result);\n outputRels[\"setValueComplete\"]?.(result); // 表单容器调用 setValue 时,没有 outputRels\n });\n\n /* 获取值 */\n inputs[\"getValue\"]((val, outputRels) => {\n outputRels[\"returnValue\"](getValue());\n });\n\n /* 重置值 */\n inputs[\"resetValue\"]((val, outputRels) => {\n setValue(\"\");\n outputRels[\"resetValueComplete\"]?.(\"\");\n });\n\n /* 设置标题 */\n inputs[\"setLabel\"]?.((val) => {\n if (!isString(val)) {\n return;\n }\n\n parentSlot?._inputs[\"setProps\"]?.({\n id: props.id,\n name: props.name,\n value: {\n label: val,\n },\n });\n });\n\n /* 设置提示内容 */\n inputs[\"setPlaceholder\"]((val) => {\n data.placeholder = val;\n });\n\n /* 清除倒计时 */\n inputs[\"clearCountDown\"]((val) => {\n clearTimeout(timer.current);\n countDownRef.current = 0;\n data.buttonText = data.buttonTextRetry;\n });\n\n /* 设置禁用 */\n inputs[\"setDisabled\"]?.((val, outputRels) => {\n data.disabled = !!val;\n outputRels[\"setDisabledComplete\"]?.(data.disabled);\n });\n }, []);\n\n const countDown = useCallback(\n (cd, callback) => {\n countDownRef.current = cd;\n data.buttonText = `${cd}s 后重试`;\n\n if (typeof callback === \"function\") {\n callback();\n }\n\n timer.current = setTimeout(() => {\n countDownRef.current--;\n\n if (countDownRef.current > 0) {\n countDown(countDownRef.current);\n } else {\n data.buttonText = data.buttonTextRetry;\n }\n }, 1000);\n },\n [data.buttonTextRetry]\n );\n\n const onChange = useCallback((e) => {\n let value = e.detail.value;\n setValue(value);\n }, []);\n\n const onBlur = useCallback((e) => {\n let value = e.detail.value;\n outputs[\"onBlur\"](value);\n }, []);\n\n const onCodeSend = useCallback(\n (e) => {\n if (!env.runtime) {\n return;\n }\n\n e.stopPropagation();\n\n // 禁用时不可点击\n if (data.disabled) {\n return;\n }\n\n // 倒计时中不可点击\n if (countDownRef.current > 0) {\n return;\n }\n\n // 发送验证码,并开始倒计时\n countDown(data.smsCountdown, () => {\n outputs[\"onCodeSend\"]();\n });\n },\n [countDownRef.current]\n );\n\n return (\n <View\n className={cx({\n [css.phoneSMS]: true,\n \"mybricks-phoneSMS\": !isH5(),\n \"mybricks-h5PhoneSMS\": isH5(),\n })}\n >\n <Input\n className={css.input}\n value={value}\n placeholder={data.placeholder}\n onChange={onChange}\n onBlur={onBlur}\n />\n <Button\n className={cx({\n [css.button]: true,\n [css.enabled]: !data.disabled && countDownRef.current <= 0,\n \"mybricks-button\": !data.disabled && countDownRef.current <= 0,\n [css.disabled]: data.disabled || countDownRef.current > 0,\n \"mybricks-button-disabled\": data.disabled || countDownRef.current > 0,\n })}\n onClick={onCodeSend}\n >\n {data.buttonText}\n </Button>\n </View>\n );\n}\n"
2540
+ "content": "import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { View, Button } from \"@tarojs/components\";\nimport { Input } from \"brickd-mobile\";\nimport css from \"./style.less\";\nimport cx from \"classnames\";\nimport * as Taro from \"@tarojs/taro\";\nimport useFormItemValue from \"../utils/hooks/useFormItemValue.ts\";\nimport { isEmpty, isString, isNumber, isObject } from \"./../utils/type\";\nimport { isH5 } from \"../utils/env\";\n\nexport default function (props) {\n const { env, data, inputs, outputs, slots, parentSlot } = props;\n\n const [value, setValue, getValue] = useFormItemValue(data.value, (val) => {\n //\n parentSlot?._inputs[\"onChange\"]?.({\n id: props.id,\n name: props.name,\n value: val,\n });\n\n //\n outputs[\"onChange\"](val);\n });\n\n //\n const timer = useRef(null);\n const countDownRef = useRef(null);\n\n useEffect(() => {\n parentSlot?._inputs[\"setProps\"]?.({\n id: props.id,\n name: props.name,\n value: {\n visible: props.style.display !== \"none\",\n },\n });\n }, [props.style.display]);\n\n useEffect(() => {\n /* 设置值 */\n inputs[\"setValue\"]((val, outputRels) => {\n let result;\n\n switch (true) {\n case isEmpty(val): {\n result = \"\";\n break;\n }\n case isString(val) || isNumber(val): {\n result = `${val}`;\n break;\n }\n default:\n // 其他类型的值,直接返回\n return;\n }\n\n setValue(result);\n outputRels[\"setValueComplete\"]?.(result); // 表单容器调用 setValue 时,没有 outputRels\n });\n\n /* 获取值 */\n inputs[\"getValue\"]((val, outputRels) => {\n outputRels[\"returnValue\"](getValue());\n });\n\n /* 重置值 */\n inputs[\"resetValue\"]((val, outputRels) => {\n setValue(\"\");\n outputRels[\"resetValueComplete\"]?.(\"\");\n });\n\n /* 设置标题 */\n inputs[\"setLabel\"]?.((val) => {\n if (!isString(val)) {\n return;\n }\n\n parentSlot?._inputs[\"setProps\"]?.({\n id: props.id,\n name: props.name,\n value: {\n label: val,\n },\n });\n });\n\n /* 设置提示内容 */\n inputs[\"setPlaceholder\"]((val) => {\n data.placeholder = val;\n });\n\n /* 清除倒计时 */\n inputs[\"clearCountDown\"]((val) => {\n clearTimeout(timer.current);\n countDownRef.current = 0;\n data.buttonText = data.buttonTextRetry;\n });\n\n /* 设置禁用 */\n inputs[\"setDisabled\"]?.((val, outputRels) => {\n data.disabled = !!val;\n outputRels[\"setDisabledComplete\"]?.(data.disabled);\n });\n }, []);\n\n const countDown = useCallback(\n (cd, callback) => {\n countDownRef.current = cd;\n data.buttonText = `${cd}s 后重试`;\n\n if (typeof callback === \"function\") {\n callback();\n }\n\n timer.current = setTimeout(() => {\n countDownRef.current--;\n\n if (countDownRef.current > 0) {\n countDown(countDownRef.current);\n } else {\n data.buttonText = data.buttonTextRetry;\n }\n }, 1000);\n },\n [data.buttonTextRetry]\n );\n\n const onChange = useCallback((e) => {\n let value = e.detail.value;\n setValue(value);\n }, []);\n\n const onBlur = useCallback((e) => {\n let value = e.detail.value;\n outputs[\"onBlur\"](value);\n }, []);\n\n const onCodeSend = useCallback(\n (e) => {\n if (!env.runtime) {\n return;\n }\n\n e.stopPropagation();\n\n // 禁用时不可点击\n if (data.disabled) {\n return;\n }\n\n // 倒计时中不可点击\n if (countDownRef.current > 0) {\n return;\n }\n\n // 发送验证码,并开始倒计时\n countDown(data.smsCountdown, () => {\n outputs[\"onCodeSend\"]();\n });\n },\n [countDownRef.current]\n );\n\n return (\n <View\n className={cx({\n [css.phoneSMS]: true,\n \"mybricks-phoneSMS\": !isH5(),\n \"mybricks-h5PhoneSMS\": isH5(),\n })}\n >\n <Input\n className={css.input}\n value={value}\n placeholder={data.placeholder}\n onChange={onChange}\n onBlur={onBlur}\n />\n <Button\n className={cx({\n [css.button]: true,\n [css.enabled]: !data.disabled && countDownRef.current <= 0,\n \"mybricks-button\": !data.disabled && countDownRef.current <= 0,\n [css.disabled]: data.disabled || countDownRef.current > 0,\n \"mybricks-button-disabled\": data.disabled || countDownRef.current > 0,\n })}\n onClick={onCodeSend}\n >\n {data.buttonText}\n </Button>\n </View>\n );\n}\n"
2541
2541
  },
2542
2542
  {
2543
2543
  "path": "src/components/formPhoneSMS/style.less",
@@ -5217,7 +5217,7 @@
5217
5217
  },
5218
5218
  {
5219
5219
  "path": "src/components/index.ts",
5220
- "content": "// 系统\nexport { default as SystemPage } from \"./system/systemPage/runtime\";\n\n// 基础\nexport { default as Image } from \"./image/runtime\";\nexport { default as Video } from \"./video/runtime\";\nexport { default as Button } from \"./button/runtime\";\nexport { default as Text } from \"./text/runtime\";\nexport { default as RichText } from \"./richText/runtime\";\nexport { default as Swiper } from \"./swiper/runtime\";\nexport { default as Icon } from \"./icon/runtime\";\n\n// 容器\nexport { default as ContainerBasic } from \"./containerBasic/runtime\";\n// export { default as Tabs2 } from \"./tabs2/runtime\";\nexport { default as ContainerList } from \"./containerList/runtime\";\n// export { default as ContainerWaterfall } from \"./containerWaterfall/runtime\";\n// export { default as ContainerCondition2 } from \"./containerCondition2/runtime\";\n// export { default as Sidebar2 } from \"./sidebar2/runtime\";\n\n// 数据录入\n// export { default as FormContainer } from \"./formContainer/runtime\";\nexport { default as FormInput } from \"./formInput/runtime\";\nexport { default as FormStepper } from \"./formStepper/runtime\";\n// export { default as FormTextarea } from \"./formTextarea/runtime\";\n// export { default as FormPassword } from \"./formPassword/runtime\";\n// export { default as FormRadio } from \"./formRadio/runtime\";\n// export { default as FormCheckbox } from \"./formCheckbox/runtime\";\n// export { default as FormSwitch } from \"./formSwitch/runtime\";\n// export { default as FormRate } from \"./formRate/runtime\";\n// export { default as FormSelect } from \"./formSelect/runtime\";\n// export { default as FormDatetime } from \"./formDatetime/runtime\";\n// export { default as FormLocation } from \"./formLocation/runtime\";\n// export { default as FormPhoneNumber } from \"./formPhoneNumber/runtime\";\n// export { default as FormPhoneSMS } from \"./formPhoneSMS/runtime\";\n// export { default as FormImageUploader } from \"./formImageUploader/runtime\";\n// export { default as FormFileUploader } from \"./formFileUploader/runtime\";\n// export { default as FormEditor } from \"./formEditor/runtime\";\n// export { default as SearchBar } from \"./searchBar/runtime\";\n// export { default as SmsInput } from \"./smsInput/runtime\";\n// export { default as FormItemContainer } from \"./formItemContainer/runtime\";\n// export { default as FormAdditionContainer } from \"./formAdditionContainer/runtime\";\n\n// 数据展示\n// export { default as Table } from \"./table/runtime\";\nexport { default as Cell } from \"./cell/runtime\";\n// export { default as CheckList } from \"./checkList/runtime\";\n// export { default as FilterContainer } from \"./filter-coms/contaniner/runtime\";\n// export { default as Calendar } from \"./calendar/runtime\";\n// export { default as Cascader } from \"./cascader/runtime\";\n// export { default as Qrcode } from \"./qrcode/runtime\";\n\n// 微信\n// export { default as Map } from \"./map/runtime\";\n// export { default as AdPopup } from \"./ad-popup/runtime\";\n// export { default as ChannelVideo } from \"./channelVideo/runtime\";\n\n// 其它\n// export { default as Line } from \"./line/runtime\";\n// export { default as Anchor } from \"./anchor/runtime\";\n// export { default as Support } from \"./support/runtime\";\n"
5220
+ "content": "// 系统\nexport { default as SystemPage } from \"./system/systemPage/runtime\";\n\n// 基础\nexport { default as Image } from \"./image/runtime\";\nexport { default as Video } from \"./video/runtime\";\nexport { default as Button } from \"./button/runtime\";\nexport { default as Text } from \"./text/runtime\";\nexport { default as RichText } from \"./richText/runtime\";\nexport { default as Swiper } from \"./swiper/runtime\";\nexport { default as Icon } from \"./icon/runtime\";\n\n// 容器\nexport { default as ContainerBasic } from \"./containerBasic/runtime\";\nexport { default as Tabs2 } from \"./tabs2/runtime\";\nexport { default as ContainerList } from \"./containerList/runtime\";\nexport { default as Popup } from \"./popup/runtime\";\n// export { default as ContainerWaterfall } from \"./containerWaterfall/runtime\";\n// export { default as ContainerCondition2 } from \"./containerCondition2/runtime\";\nexport { default as Sidebar2 } from \"./sidebar2/runtime\";\n\n// 数据录入\nexport { default as FormContainer } from \"./formContainer/runtime\";\nexport { default as FormInput } from \"./formInput/runtime\";\nexport { default as FormStepper } from \"./formStepper/runtime\";\nexport { default as FormTextarea } from \"./formTextarea/runtime\";\nexport { default as FormPassword } from \"./formPassword/runtime\";\nexport { default as FormRadio } from \"./formRadio/runtime\";\nexport { default as FormCheckbox } from \"./formCheckbox/runtime\";\nexport { default as FormSwitch } from \"./formSwitch/runtime\";\nexport { default as FormRate } from \"./formRate/runtime\";\nexport { default as FormSelect } from \"./formSelect/runtime\";\nexport { default as FormDatetime } from \"./formDatetime/runtime\";\nexport { default as FormLocation } from \"./formLocation/runtime\";\nexport { default as FormPhoneNumber } from \"./formPhoneNumber/runtime\";\nexport { default as FormPhoneSMS } from \"./formPhoneSMS/runtime\";\nexport { default as FormImageUploader } from \"./formImageUploader/runtime\";\n// export { default as FormFileUploader } from \"./formFileUploader/runtime\";\n// export { default as FormEditor } from \"./formEditor/runtime\";\nexport { default as SearchBar } from \"./searchBar/runtime\";\nexport { default as SmsInput } from \"./smsInput/runtime\";\n// export { default as FormItemContainer } from \"./formItemContainer/runtime\";\nexport { default as FormAdditionContainer } from \"./formAdditionContainer/runtime\";\n\n// 数据展示\nexport { default as Table } from \"./table/runtime\";\nexport { default as Cell } from \"./cell/runtime\";\n// export { default as CheckList } from \"./checkList/runtime\";\nexport { default as FilterContainer } from \"./filter-coms/contaniner/runtime\";\nexport { default as FilterSort } from \"./filter-coms/sort/runtime\";\nexport { default as FilterSwitch } from \"./filter-coms/switch/runtime\";\nexport { default as FilterCustom } from \"./filter-coms/custom/runtime\";\n// export { default as Calendar } from \"./calendar/runtime\";\n// export { default as Cascader } from \"./cascader/runtime\";\n// export { default as Qrcode } from \"./qrcode/runtime\";\n\n// 微信\nexport { default as Map } from \"./map/runtime\";\nexport { default as AdPopup } from \"./ad-popup/runtime\";\nexport { default as ChannelVideo } from \"./channelVideo/runtime\";\n\n// 其它\nexport { default as Line } from \"./line/runtime\";\n// export { default as Anchor } from \"./anchor/runtime\";\nexport { default as Support } from \"./support/runtime\";\n"
5221
5221
  }
5222
5222
  ]
5223
5223
  },
@@ -5399,15 +5399,15 @@
5399
5399
  "children": [
5400
5400
  {
5401
5401
  "path": "src/core/utils/ComContext.tsx",
5402
- "content": "import { createContext, useContext } from 'react'\nimport type { ComContextStore } from './useContext'\nexport { pageRouter } from './pageRouter'\n\nconst ComContext = createContext<ComContextStore | undefined>(undefined)\n\nexport function useAppContext(): ComContextStore {\n const context = useContext(ComContext)\n if (!context) {\n throw new Error('useAppContext must be used within a ComContext.Provider')\n }\n return context\n}\n\nexport default ComContext\n"
5402
+ "content": "import { createContext, useContext } from 'react'\nimport type { ComContextStore } from './useContext'\nexport { pageRouter } from './pageRouter'\n\nconst ComContext = createContext<ComContextStore | undefined>(undefined)\nconst SlotContext = createContext<any>(null)\n\nexport function useAppContext(): ComContextStore {\n const context = useContext(ComContext)\n if (!context) {\n throw new Error('useAppContext must be used within a ComContext.Provider')\n }\n return context\n}\n\nexport function useParentSlot<T = any>(): T | null {\n return useContext(SlotContext)\n}\n\nexport const SlotProvider = SlotContext.Provider\n\nexport default ComContext\n"
5403
5403
  },
5404
5404
  {
5405
5405
  "path": "src/core/utils/hooks.ts",
5406
- "content": "import { useState, useRef, useMemo } from 'react';\nimport { SUBJECT_SUBSCRIBE } from '../mybricks/constant';\nimport { createReactiveInputHandler } from '../mybricks/createReactiveInputHandler';\n\n/**\n * 深度代理,支持自动路径初始化和响应式更新(鸿蒙化处理方案)\n */\nexport function deepProxy(target: any, onSet?: () => void): any {\n if (target === null || typeof target !== 'object' || target.__isProxy) {\n return target;\n }\n\n return new Proxy(target, {\n get(obj, prop) {\n if (prop === '__isProxy') return true;\n if (prop === 'toJSON') return () => obj;\n\n let value = obj[prop];\n\n // 只代理已存在的对象属性,不自动创建空对象\n // 避免访问不存在的属性(如 disabled)时污染原始数据\n if (typeof value === 'object' && value !== null && !value.__isProxy) {\n obj[prop] = deepProxy(value, onSet);\n }\n\n return obj[prop];\n },\n set(obj, prop, value) {\n const result = Reflect.set(obj, prop, value);\n if (onSet) onSet();\n return result;\n }\n });\n}\n\nexport function useModel(rawData: any) {\n const [, forceUpdate] = useState({});\n const dataRef = useRef(rawData || {});\n\n return useMemo(() => {\n return deepProxy(dataRef.current, () => forceUpdate({}));\n }, []);\n}\n\nexport function useBindInputs(scope: any, id: string, initialHandlers?: Record<string, any>) {\n const handlersRef = useRef<Record<string, any>>({ ...initialHandlers });\n\n // 同步最新的 initialHandlers\n if (initialHandlers) {\n Object.assign(handlersRef.current, initialHandlers);\n }\n\n return useMemo(() => {\n const proxy = new Proxy({}, {\n get: (_target, pin: string) => {\n return (arg: any, ...args: any[]) => {\n if (typeof arg === 'function') {\n // 组件注册回调\n handlersRef.current[pin] = arg;\n } else {\n // 逻辑流触发输入\n const handler = handlersRef.current[pin];\n\n if (typeof handler === 'function') {\n if (pin === '_setData') {\n return handler(arg, ...args);\n }\n // 构造 createReactiveInputHandler 需要的参数\n return createReactiveInputHandler({\n input: handler,\n value: arg,\n rels: {}, // 这里可以扩展 output 关联\n title: id\n });\n }\n }\n };\n }\n });\n\n // 将代理对象挂载到作用域,供外部 comRefs.current.id.pin() 调用\n scope[id] = proxy;\n return proxy;\n }, [scope, id]);\n}\n\nexport function useBindEvents(props: any) {\n return useMemo(() => {\n const _events: Record<string, any> = {};\n\n // 预处理已存在的事件\n Object.keys(props).forEach(key => {\n if (key.startsWith('on') && typeof props[key] === 'function') {\n const handler = props[key];\n const wrapped = (...args: any[]) => handler(...args);\n wrapped.getConnections = () => [{ id: 'default' }];\n _events[key] = wrapped;\n }\n });\n\n return new Proxy(_events, {\n get(target, key: string) {\n if (typeof key === 'string' && key.startsWith('on')) {\n if (target[key]) {\n return target[key];\n }\n // 对未连接的事件返回兜底函数\n const emptyFn = () => { };\n emptyFn.getConnections = () => [];\n return emptyFn;\n }\n return target[key];\n }\n });\n }, [props]);\n}\n"
5406
+ "content": "import { useState, useRef, useMemo } from 'react';\nimport { SUBJECT_SUBSCRIBE } from '../mybricks/constant';\nimport { createReactiveInputHandler } from '../mybricks/createReactiveInputHandler';\n\n/**\n * 深度代理,支持自动路径初始化和响应式更新(鸿蒙化处理方案)\n */\nexport function deepProxy(target: any, onSet?: () => void): any {\n if (target === null || typeof target !== 'object' || target.__isProxy) {\n return target;\n }\n\n return new Proxy(target, {\n get(obj, prop) {\n if (prop === '__isProxy') return true;\n if (prop === 'toJSON') return () => obj;\n\n let value = obj[prop];\n\n // 只代理已存在的对象属性,不自动创建空对象\n // 避免访问不存在的属性(如 disabled)时污染原始数据\n if (typeof value === 'object' && value !== null && !value.__isProxy) {\n obj[prop] = deepProxy(value, onSet);\n }\n\n return obj[prop];\n },\n set(obj, prop, value) {\n const result = Reflect.set(obj, prop, value);\n if (onSet) onSet();\n return result;\n }\n });\n}\n\nexport function useModel(rawData: any) {\n const [, forceUpdate] = useState({});\n const dataRef = useRef(rawData || {});\n\n return useMemo(() => {\n return deepProxy(dataRef.current, () => forceUpdate({}));\n }, []);\n}\n\nexport function useBindInputs(scope: any, id: string, initialHandlers?: Record<string, any>) {\n const handlersRef = useRef<Record<string, any>>({ ...initialHandlers });\n\n // 同步最新的 initialHandlers\n if (initialHandlers) {\n Object.assign(handlersRef.current, initialHandlers);\n }\n\n return useMemo(() => {\n const proxy = new Proxy({}, {\n get: (_target, pin: string) => {\n return (arg: any, ...args: any[]) => {\n if (typeof arg === 'function') {\n // 组件注册回调\n handlersRef.current[pin] = arg;\n } else {\n // 逻辑流触发输入\n const handler = handlersRef.current[pin];\n\n if (typeof handler === 'function') {\n if (pin === '_setData') {\n return handler(arg, ...args);\n }\n // 构造 createReactiveInputHandler 需要的参数\n return createReactiveInputHandler({\n input: handler,\n value: arg,\n rels: {}, // 这里可以扩展 output 关联\n title: id\n });\n }\n }\n };\n }\n });\n\n // 将代理对象挂载到作用域,供外部 comRefs.current.id.pin() 调用\n if (scope && scope.current) {\n scope.current[id] = proxy;\n }\n return proxy;\n }, [scope, id]);\n}\n\nexport function useBindEvents(props: any, context?: { id: string, name: string, parentSlot?: any }) {\n return useMemo(() => {\n const _events: Record<string, any> = {};\n\n // 预处理已存在的事件\n Object.keys(props).forEach(key => {\n if (key.startsWith('on') && typeof props[key] === 'function') {\n const handler = props[key];\n const wrapped = (originalValue: any) => {\n // 鸿蒙/render-web 规范:如果是在插槽中触发事件,且存在父级协议,则自动封装元数据\n // 这解决了 FormContainer 等组件识别子项的需求\n const value = context ? {\n id: context.id,\n name: context.name,\n value: originalValue\n } : originalValue;\n \n return handler(value);\n };\n wrapped.getConnections = () => [{ id: 'default' }];\n _events[key] = wrapped;\n }\n });\n\n return new Proxy(_events, {\n get(target, key: string) {\n if (typeof key === 'string' && key.startsWith('on')) {\n if (target[key]) {\n return target[key];\n }\n // 对未连接的事件返回兜底函数\n const emptyFn = () => { };\n emptyFn.getConnections = () => [];\n return emptyFn;\n }\n return target[key];\n }\n });\n }, [props, context]);\n}\n"
5407
5407
  },
5408
5408
  {
5409
5409
  "path": "src/core/utils/index.ts",
5410
- "content": "export * from './hooks';\nexport { WithCom, WithWrapper } from './with';\nexport { PopupRenderer } from './PopupRenderer';\nexport { pageRouter, router } from './pageRouter';\nexport { popupRouter, subscribePopupRouter, closeActivePopupRouter } from './popupRouter';\nexport { useAppContext } from './ComContext';\nexport { createVariable, createFx, merge } from '../mybricks';\nexport { SUBJECT_SUBSCRIBE, SUBJECT_VALUE } from '../mybricks/constant';\n"
5410
+ "content": "export * from './hooks';\nexport { WithCom, WithWrapper } from './with';\nexport { PopupRenderer } from './PopupRenderer';\nexport { pageRouter, router } from './pageRouter';\nexport { popupRouter, subscribePopupRouter, closeActivePopupRouter } from './popupRouter';\nexport { useAppContext, SlotProvider } from './ComContext';\nexport { useAppCreateContext } from './useContext';\nexport { createVariable, createFx, merge } from '../mybricks';\nexport { SUBJECT_SUBSCRIBE, SUBJECT_VALUE } from '../mybricks/constant';\nexport * from './slots';\n"
5411
5411
  },
5412
5412
  {
5413
5413
  "path": "src/core/utils/pageRouter.ts",
@@ -5421,13 +5421,17 @@
5421
5421
  "path": "src/core/utils/popupRouter.ts",
5422
5422
  "content": "import { Page } from '../mybricks';\n\n/**\n * 弹窗状态管理(解耦版)\n * 弹窗在 Taro 中被视为组件,不走路由栈\n */\nclass PopupStore {\n private activePopup: any = null;\n private listeners: Set<(state: any) => void> = new Set();\n\n /** 订阅弹窗状态变化 */\n subscribe(listener: (state: any) => void) {\n this.listeners.add(listener);\n // 返回取消订阅函数\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n private notify() {\n this.listeners.forEach((l) =>\n l(\n this.activePopup || {\n visible: false,\n name: '',\n value: null,\n controller: null,\n },\n ),\n );\n }\n\n /** 获取弹窗参数 */\n getParams(name: string) {\n if (this.activePopup && this.activePopup.name === name) {\n return {\n value: this.activePopup.value,\n controller: this.activePopup.controller,\n };\n }\n return { value: null };\n }\n\n /** 获取当前激活的弹窗名称 */\n getActiveName(): string | undefined {\n return this.activePopup?.name;\n }\n\n /** 打开弹窗 */\n push(name: string, { value, controller }: any) {\n this.activePopup = { visible: true, name, value, controller };\n this.notify();\n }\n\n /** 行为同 push */\n replace(name: string, params: any) {\n this.push(name, params);\n }\n\n /** 关闭弹窗 */\n pop() {\n this.activePopup = null;\n this.notify();\n }\n}\n\nconst popupStore = new PopupStore();\n\n/**\n * 订阅弹窗状态变化(统一入口,避免外部依赖内部实现细节)\n */\nexport const subscribePopupRouter = (listener: (state: any) => void) => {\n return popupStore.subscribe(listener);\n};\n\n/** 弹窗控制器(命名与文件名保持一致) */\nexport const popupRouter = new Page(popupStore);\n\n/**\n * 关闭当前激活的弹窗(用于 TabBar 点击等场景)\n * 不需要知道弹窗 id\n */\nexport const closeActivePopupRouter = () => {\n const name = popupStore.getActiveName();\n if (!name) return;\n // 走 Page.close,保证 close/commit/cancel 等控制器语义保持一致\n popupRouter.close(name);\n};\n\n\n"
5423
5423
  },
5424
+ {
5425
+ "path": "src/core/utils/slots.tsx",
5426
+ "content": "import React, { useMemo, useRef, useEffect } from \"react\";\nimport ComContext, { SlotProvider, useAppContext, useParentSlot } from \"./ComContext\";\nimport { createReactiveInputHandler } from \"../mybricks/createReactiveInputHandler\";\n\ntype AnyRecord = Record<string, any>;\n\ntype SlotState = {\n inputs: any;\n outputs: any;\n _inputs: any;\n /** scopeId -> scoped comRefs(每个 scope 一套,避免列表多实例覆盖) */\n _scopedComRefs?: Record<string, any>;\n _render?: any;\n render: (params?: any) => any;\n};\n\nfunction createChannelProxy(title: string) {\n const handlersMap: Record<string, any> = {};\n return new Proxy(\n {},\n {\n get: (_t, pin: string) => {\n return (arg: any) => {\n if (typeof arg === \"function\") {\n handlersMap[pin] = arg;\n return;\n }\n const handler = handlersMap[pin];\n if (typeof handler === \"function\") {\n return createReactiveInputHandler({\n input: handler,\n value: arg,\n rels: {},\n title,\n });\n }\n };\n },\n },\n );\n}\n\n/**\n * 参考鸿蒙的 createSlotsIO:\n * - 确保每个 slot 都具备 inputs / outputs / _inputs 三套通道,避免 runtime 访问时报 undefined\n * - render 时通过 SlotProvider 注入 parentSlot(slot 内子组件可 useParentSlot 获取)\n */\nexport function useEnhancedSlots(rawSlots: any, id: string) {\n const slotStoreRef = useRef<Record<string, SlotState>>({});\n\n return useMemo(() => {\n if (!rawSlots) return {};\n const nextSlots: AnyRecord = {};\n\n Object.entries(rawSlots).forEach(([slotKey, slotDef]: any) => {\n const state =\n slotStoreRef.current[slotKey] ||\n (slotStoreRef.current[slotKey] = {\n inputs: createChannelProxy(`${id}.${slotKey}.inputs`),\n outputs: createChannelProxy(`${id}.${slotKey}.outputs`),\n _inputs: createChannelProxy(`${id}.${slotKey}._inputs`),\n _scopedComRefs: {},\n _render: undefined,\n render: (params?: any) => {\n const r = state._render;\n // 只有存在 key 或 index 时才认为是“多实例作用域插槽”,需要实例隔离\n const rawScope = params?.key ?? params?.inputValues?.index ?? params?.inputValues?.itemData?.id;\n \n const SlotComp = r;\n const content = r ? <SlotComp {...(params || {})} /> : null;\n\n if (rawScope === undefined || rawScope === null) {\n return (\n <SlotProvider value={{ ...state, params }}>\n {content}\n </SlotProvider>\n );\n }\n\n const scopeId = `${id}.${slotKey}::${String(rawScope)}`;\n const scopedComRefs =\n (state._scopedComRefs![scopeId] ||= { current: { $inputs: {} } });\n return (\n <SlotProvider value={{ ...state, params }}>\n <ScopedComContextProvider comRefs={scopedComRefs} scopeId={scopeId}>\n {content}\n </ScopedComContextProvider>\n </SlotProvider>\n );\n },\n });\n\n state._render = slotDef?.render;\n nextSlots[slotKey] = {\n ...(slotDef || {}),\n render: state.render,\n inputs: state.inputs,\n outputs: state.outputs,\n _inputs: state._inputs,\n };\n });\n\n return nextSlots;\n }, [rawSlots, id]);\n}\n\nexport function ScopedComContextProvider(props: {\n comRefs?: any;\n scopeId: string;\n children: React.ReactNode;\n}) {\n const parent = useAppContext();\n const value = useMemo(() => {\n // 如果没有显式传 comRefs,则沿用父级的,但依然带上新的 scopeId\n return {\n ...parent,\n comRefs: props.comRefs || parent.comRefs,\n $scopeId: props.scopeId,\n } as any;\n }, [parent, props.comRefs, props.scopeId]);\n\n return <ComContext.Provider value={value}>{props.children}</ComContext.Provider>;\n}\n\n/** parentSlot 解析:props 优先,其次用 SlotProvider 注入的 context */\nexport function useResolvedParentSlot(parentSlotProp: any) {\n const parentSlotFromCtx = useParentSlot();\n return parentSlotProp ?? parentSlotFromCtx;\n}\n"
5427
+ },
5424
5428
  {
5425
5429
  "path": "src/core/utils/useContext.ts",
5426
- "content": "import { useRef, useState } from 'react'\nimport { deepProxy } from './hooks'\n\nexport interface ComContextStore {\n comRefs: any;\n appContext: any; \n popupState: {\n visible: boolean;\n name: string;\n value: any;\n controller: any;\n };\n setPopupState: (state: any) => void;\n}\n\nexport function useAppCreateContext(): ComContextStore {\n const comRefs = useRef<any>(deepProxy({}));\n const [popupState, setPopupState] = useState({\n visible: false,\n name: '',\n value: null,\n controller: null\n });\n\n const appContext: any = {\n canvas: {\n id: \"u_7VvVn\", // 使用 data 中的 id\n },\n runtime: {\n debug: false,\n },\n edit: false,\n isH5: false,\n isDesigner: false,\n isPreview: false,\n isRelease: false,\n isDebug: false,\n isLocal: false,\n isTest: false,\n };\n return {\n comRefs,\n appContext,\n popupState,\n setPopupState\n }\n}\n"
5430
+ "content": "import { useRef, useState, useMemo } from 'react'\nimport { deepProxy } from './hooks'\n\nexport interface ComContextStore {\n comRefs: any;\n outputs: any;\n appContext: any; \n popupState: {\n visible: boolean;\n name: string;\n value: any;\n controller: any;\n };\n setPopupState: (state: any) => void;\n}\n\nexport function useAppCreateContext(): ComContextStore {\n // 约定:场景级 inputs 统一挂载到 $inputs,避免与组件 runtime 的 inputs 命名冲突\n // 同时可避免 `Cannot set property 'open' of undefined`\n const comRefs = useRef<any>(deepProxy({ $inputs: {} }));\n const outputs = useRef<any>(deepProxy({}));\n const [popupState, setPopupState] = useState({\n visible: false,\n name: '',\n value: null,\n controller: null\n });\n\n const appContext = useRef({\n canvas: {\n id: \"u_7VvVn\", // 使用 data 中的 id\n },\n runtime: {\n debug: false,\n },\n edit: false,\n isH5: false,\n isDesigner: false,\n isPreview: false,\n isRelease: false,\n isDebug: false,\n isLocal: false,\n isTest: false,\n tabBar: [],\n useTabBar: false,\n }).current;\n\n return useMemo(() => ({\n comRefs,\n outputs,\n appContext,\n popupState,\n setPopupState\n }), [popupState]);\n}\n"
5427
5431
  },
5428
5432
  {
5429
5433
  "path": "src/core/utils/with.tsx",
5430
- "content": "import React, { useState, useEffect } from 'react';\nimport { View } from '@tarojs/components';\nimport { useModel, useBindInputs, useBindEvents, subscribePopupRouter, closeActivePopupRouter } from './index';\nimport { useAppCreateContext } from './useContext';\nimport ComContext, { useAppContext } from './ComContext';\n// @ts-ignore 运行时由宿主项目提供 @tarojs/taro\nimport { useTabItemTap } from '@tarojs/taro';\n\ninterface WithComProps {\n component: React.ComponentType<any>;\n intputRef?: any;\n id?: string;\n data?: any;\n className?: string;\n style?: any;\n [key: string]: any;\n}\n\nexport const WithCom: React.FC<WithComProps> = (props) => {\n const { component: Component, id = '', data, className, style, ...rest } = props;\n const { comRefs, appContext } = useAppContext();\n const env = appContext;\n\n const isPopup = (Component as any).isPopup;\n const [show, setShow] = useState(true);\n const [dynamicStyle, setDynamicStyle] = useState({});\n\n // 数据模型\n const _data = useModel(data || {});\n\n // 内置通用能力\n const handlers = {\n _setStyle: (style: any) => {\n setDynamicStyle((prev) => ({ ...prev, ...style }));\n },\n _setData: (path: string, value: any) => {\n const paths = path.split('.');\n let current = _data;\n for (let i = 0; i < paths.length - 1; i++) {\n if (!current[paths[i]]) current[paths[i]] = {};\n current = current[paths[i]];\n }\n current[paths[paths.length - 1]] = value;\n }\n };\n\n if (!isPopup) {\n Object.assign(handlers, {\n show: () => setShow(true),\n hide: () => setShow(false),\n showOrHide: () => setShow((prev) => !prev),\n });\n }\n\n // 绑定输入\n const inputProxy = useBindInputs(comRefs, id, handlers);\n const eventProxy = useBindEvents(rest);\n\n comRefs.current[id] = inputProxy;\n\n return (\n show || isPopup ? (\n <View className={className} style={{ ...style, ...dynamicStyle }} >\n <Component\n {...rest}\n inputs={inputProxy}\n outputs={eventProxy}\n data={_data}\n env={env}\n id={id}\n style={style}\n />\n </View>\n ) : null\n );\n};\n\nexport const WithWrapper = (Component: React.ComponentType<any>) => {\n return function WrappedComponent(props: any) {\n const contextStore = useAppCreateContext();\n const { setPopupState } = contextStore;\n const isPopup = (Component as any).isPopup;\n\n // 通过发布订阅模式解耦弹窗状态变化\n useEffect(() => {\n return subscribePopupRouter((state) => setPopupState(state));\n }, [setPopupState]);\n\n // 点击 TabBar 时自动关闭弹窗(自定义 TabBar 或原生 TabBar 点击均会触发)\n useTabItemTap(() => {\n if (isPopup) return;\n closeActivePopupRouter();\n });\n\n return (\n <ComContext.Provider value={contextStore}>\n <Component {...props} />\n </ComContext.Provider>\n );\n };\n};\n"
5434
+ "content": "import React, { useState, useEffect } from 'react';\n// @ts-ignore 运行时由宿主项目提供 @tarojs/components\nimport { View } from '@tarojs/components';\nimport { useModel, useBindInputs, useBindEvents, subscribePopupRouter, closeActivePopupRouter } from './index';\nimport { useAppCreateContext } from './useContext';\nimport ComContext, { useAppContext } from './ComContext';\nimport { useEnhancedSlots, useResolvedParentSlot } from './slots';\n// @ts-ignore 运行时由宿主项目提供 @tarojs/taro\nimport { useTabItemTap } from '@tarojs/taro';\n\ninterface WithComProps {\n component: React.ComponentType<any>;\n intputRef?: any;\n id?: string;\n data?: any;\n className?: string;\n style?: any;\n /** 插槽传入的原始数据 */\n inputValues?: any;\n /** 插槽数据到组件输入的映射: { pinId: slotKey } */\n inputValuesMapping?: Record<string, string>;\n [key: string]: any;\n}\n\nexport const WithCom: React.FC<WithComProps> = (props) => {\n const { component: Component, id = '', data, className, style, inputValues, inputValuesMapping, ...rest } = props;\n const { comRefs, appContext } = useAppContext();\n const env = appContext; //TODO: 需要根据实际情况修改\n\n const isPopup = (Component as any).isPopup;\n const [show, setShow] = useState(true);\n const [dynamicStyle, setDynamicStyle] = useState({});\n\n\n //数据模型\n const _data = useModel(data || {});\n\n // 内置通用能力\n const handlers = {\n _setStyle: (style: any) => {\n setDynamicStyle((prev) => ({ ...prev, ...style }));\n },\n _setData: (path: string, value: any) => {\n const paths = path.split('.');\n let current = _data;\n for (let i = 0; i < paths.length - 1; i++) {\n if (!current[paths[i]]) current[paths[i]] = {};\n current = current[paths[i]];\n }\n current[paths[paths.length - 1]] = value;\n }\n };\n\n if (!isPopup) {\n Object.assign(handlers, {\n show: () => setShow(true),\n hide: () => setShow(false),\n showOrHide: () => setShow((prev) => !prev),\n });\n }\n\n // 绑定输入,传入初始 handlers\n const inputProxy = useBindInputs(comRefs, id, handlers);\n\n const { slots: rawSlots, parentSlot: parentSlotProp, ...restProps } = rest as any;\n const { outputs: globalOutputs } = useAppContext();\n const parentSlot = useResolvedParentSlot(parentSlotProp);\n\n // 绑定事件,带上上下文(用于事件流自动封装 id/name)\n const eventProxy = useBindEvents(restProps, { \n id, \n name: props.name || id, \n parentSlot \n });\n\n // 注册到全局 IO 管理\n if (globalOutputs && globalOutputs.current) {\n globalOutputs.current[id] = eventProxy;\n }\n\n // 鸿蒙规范:确保 comRefs 中挂载的是最新的 inputProxy\n comRefs.current[id] = inputProxy;\n\n const enhancedSlots = useEnhancedSlots(rawSlots, id);\n\n const jsx = (\n <Component\n {...restProps}\n inputs={inputProxy}\n outputs={eventProxy}\n slots={enhancedSlots}\n parentSlot={parentSlot}\n data={_data}\n env={env}\n id={id}\n style={style}\n />\n );\n\n // 鸿蒙化处理:支持 itemWrap 协议\n if (parentSlot?.params?.itemWrap) {\n return parentSlot.params.itemWrap({\n id,\n name: props.name || id,\n jsx,\n def: (Component as any).def,\n inputs: inputProxy,\n outputs: eventProxy,\n style\n });\n }\n\n return (\n show || isPopup ? (\n <View className={className} style={{ ...style, ...dynamicStyle }} >\n {jsx}\n </View>\n ) : null\n );\n};\n\nexport const WithWrapper = (Component: React.ComponentType<any>) => {\n return function WrappedComponent(props: any) {\n const contextStore = useAppCreateContext();\n const { setPopupState } = contextStore;\n const isPopup = (Component as any).isPopup;\n\n // 通过发布订阅模式解耦弹窗状态变化\n useEffect(() => {\n return subscribePopupRouter((state) => setPopupState(state));\n }, [setPopupState]);\n\n // 点击 TabBar 时自动关闭弹窗(自定义 TabBar 或原生 TabBar 点击均会触发)\n useTabItemTap(() => {\n if (isPopup) return;\n closeActivePopupRouter();\n });\n\n return (\n <ComContext.Provider value={contextStore}>\n <Component {...props} />\n </ComContext.Provider>\n );\n };\n};\n"
5431
5435
  }
5432
5436
  ]
5433
5437
  }
@@ -5443,11 +5447,11 @@
5443
5447
  },
5444
5448
  {
5445
5449
  "path": "src/app.less",
5446
- "content": "/* 隐藏 React Refresh 的全屏错误遮罩 */\n#react-refresh-overlay, \niframe[id=\"react-refresh-overlay\"] {\n display: none !important;\n}\n\n.mybricks_taro_systemPage {\n height: 100vh !important;\n}"
5450
+ "content": "/* 隐藏 React Refresh 的全屏错误遮罩 */\n#react-refresh-overlay, \niframe[id=\"react-refresh-overlay\"] {\n display: none !important;\n}\n\n.mybricks_taro_systemPage {\n height: 100vh !important;\n}\n\nview {\n box-sizing: border-box;\n}\n"
5447
5451
  },
5448
5452
  {
5449
5453
  "path": "src/app.ts",
5450
- "content": "import { PropsWithChildren } from 'react'\nimport { useLaunch } from '@tarojs/taro'\nimport 'brickd-mobile/lib/index.css' \nimport './app.less'\n\nfunction App({ children }: PropsWithChildren<any>) {\n useLaunch(() => {\n console.log('App launched.')\n })\n\n // children 是将要会渲染的页面\n return children\n}\n \n\n\nexport default App\n"
5454
+ "content": "import { PropsWithChildren } from 'react'\nimport { useLaunch } from '@tarojs/taro'\nimport 'brickd-mobile/lib/index.css' \nimport \"@taroify/icons/style\"\nimport './app.less'\n\nfunction App({ children }: PropsWithChildren<any>) {\n useLaunch(() => {\n console.log('App launched.')\n })\n\n // children 是将要会渲染的页面\n return children\n}\n \n\n\nexport default App\n"
5451
5455
  },
5452
5456
  {
5453
5457
  "path": "src/index.html",
@@ -147,5 +147,7 @@ export interface BaseConfig extends ToTaroCodeConfig {
147
147
  typeDef: any;
148
148
  schema: any;
149
149
  }) => void;
150
+ /** 根据 ID 获取 DSL 中的稳定组件名(参考鸿蒙实现) */
151
+ getDslComNameById?: (id: string) => string | undefined;
150
152
  }
151
153
  export default toCodeTaro;
@@ -190,18 +190,10 @@ export var handleProcess = function handleProcess(event, config) {
190
190
  }
191
191
  }
192
192
  } else {
193
- var _config$getComponentC;
194
193
  // UI 组件处理
195
- var _currentProvider2 = getCurrentProvider({
196
- isSameScope: isSameScope,
197
- props: props
198
- }, config);
199
- _currentProvider2.controllers.add(props.meta.id);
200
- var componentController = ((_config$getComponentC = config.getComponentController) === null || _config$getComponentC === void 0 ? void 0 : _config$getComponentC.call(config, {
201
- com: props.meta,
202
- scene: config.getCurrentScene()
203
- })) || "controller_".concat(props.meta.id);
204
- code += "".concat(indent, "/** \u8C03\u7528 ").concat(props.meta.title, " \u7684 ").concat(props.title, " */") + "\n".concat(indent).concat(nextCode, "this.").concat(_currentProvider2.name, ".").concat(componentController, ".").concat(props.id, "(").concat(nextValue, ")");
194
+ code += "".concat(indent, "/** \u8C03\u7528 ").concat(props.meta.title, " \u7684 ").concat(props.title, " */") + // 新架构:WithCom 会把 inputProxy 挂到 comRefs.current[comId]
195
+ // 因此这里直接调用 this.<comId>.<pinId>(...),后续会被 replace 成 comRefs.current.<comId>.<pinId>(...)
196
+ "\n".concat(indent).concat(nextCode, "this.").concat(props.meta.id, ".").concat(props.id, "(").concat(nextValue, ")");
205
197
  }
206
198
  });
207
199
  if (["fx", "extension-api", "extension-bus"].includes(event.type)) {
@@ -310,7 +302,7 @@ var getNextValueWithParam = function getNextValueWithParam(param, config, event)
310
302
  return "".concat(componentNameWithId, "_result.").concat(param.id);
311
303
  };
312
304
  var getCurrentProvider = function getCurrentProvider(params, config) {
313
- var _config$getProviderNa;
305
+ var _config$getProviderNa, _config$getCurrentPro;
314
306
  var providerMap = config.getProviderMap();
315
307
  var isSameScope = params.isSameScope,
316
308
  props = params.props;
@@ -321,11 +313,15 @@ var getCurrentProvider = function getCurrentProvider(params, config) {
321
313
  com: meta,
322
314
  scene: config.getCurrentScene()
323
315
  })) || (!parentComId ? "slot_Index" : "slot_".concat(frameId[0].toUpperCase() + frameId.slice(1), "_").concat(parentComId));
324
- var provider = providerMap[providerName];
325
- if (!isSameScope) {
326
- config.addConsumer(provider);
316
+ var provider = providerMap === null || providerMap === void 0 ? void 0 : providerMap[providerName];
317
+
318
+ // 兜底:如果 provider 不存在(例如新架构未构建 slot provider),回退到当前 provider
319
+ var safeProvider = provider || ((_config$getCurrentPro = config.getCurrentProvider) === null || _config$getCurrentPro === void 0 ? void 0 : _config$getCurrentPro.call(config));
320
+ if (!isSameScope && safeProvider) {
321
+ var _config$addConsumer;
322
+ (_config$addConsumer = config.addConsumer) === null || _config$addConsumer === void 0 || _config$addConsumer.call(config, safeProvider);
327
323
  }
328
- return provider;
324
+ return safeProvider;
329
325
  };
330
326
 
331
327
  /**
@@ -5,6 +5,7 @@ export type ChildResult = {
5
5
  cssContent: string;
6
6
  slots: string[];
7
7
  scopeSlots: string[];
8
+ childrenResults?: any[];
8
9
  };
9
10
  /**
10
11
  * 统一处理子节点(com, dom, module)
@@ -1,4 +1,5 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
2
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
3
  import handleCom from "../../handleCom";
3
4
  import handleDom from "../../handleDom";
4
5
  import handleModule from "../../handleModule";
@@ -11,6 +12,7 @@ export var processChildren = function processChildren(children, config) {
11
12
  var cssContent = "";
12
13
  var slots = [];
13
14
  var scopeSlots = [];
15
+ var allChildrenResults = [];
14
16
  children.forEach(function (child) {
15
17
  var result;
16
18
  if (child.type === "com") {
@@ -21,6 +23,19 @@ export var processChildren = function processChildren(children, config) {
21
23
  result = handleDom(child, config);
22
24
  }
23
25
  if (result) {
26
+ // 收集组件元数据(用于 RenderManager 的 wrap/itemWrap)
27
+ if (child.type === "com") {
28
+ var _meta, _props, _meta2;
29
+ var comId = child.id || ((_meta = child.meta) === null || _meta === void 0 ? void 0 : _meta.id);
30
+ allChildrenResults.push(_objectSpread(_objectSpread({}, result), {}, {
31
+ id: comId,
32
+ // 优先使用 handleCom 解析出的稳定名称 (如 comName 别名)
33
+ name: result.name || child.name || ((_props = child.props) === null || _props === void 0 || (_props = _props.data) === null || _props === void 0 ? void 0 : _props.name) || ((_meta2 = child.meta) === null || _meta2 === void 0 ? void 0 : _meta2.title) || comId,
34
+ type: child.type,
35
+ meta: child.meta,
36
+ props: child.props
37
+ }));
38
+ }
24
39
  if (result.ui) {
25
40
  uiCode += (uiCode ? "\n" : "") + result.ui;
26
41
  }
@@ -43,6 +58,7 @@ export var processChildren = function processChildren(children, config) {
43
58
  js: jsCode,
44
59
  cssContent: cssContent,
45
60
  slots: slots,
46
- scopeSlots: scopeSlots
61
+ scopeSlots: scopeSlots,
62
+ childrenResults: allChildrenResults
47
63
  };
48
64
  };