@mybricks/to-code-taro 1.1.4 → 1.1.5

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 (71) hide show
  1. package/dist/cjs/core/comlib/_Connector.js +49 -62
  2. package/dist/cjs/core/mybricks/createJSHandle.js +2 -1
  3. package/dist/cjs/core/utils/hooks.js +13 -18
  4. package/dist/cjs/core/utils/index.js +3 -0
  5. package/dist/cjs/core/utils/pool.js +63 -0
  6. package/dist/cjs/core/utils/slots.js +8 -8
  7. package/dist/cjs/core/utils/useContext.js +8 -6
  8. package/dist/cjs/generate/generateTaroProjectJson.js +8 -0
  9. package/dist/cjs/taro-template.json +16 -8
  10. package/dist/cjs/toCodeTaro.d.ts +1 -1
  11. package/dist/cjs/toCodeTaro.js +2 -0
  12. package/dist/cjs/utils/builder/buildResult.d.ts +1 -0
  13. package/dist/cjs/utils/builder/buildResult.js +53 -0
  14. package/dist/cjs/utils/context/buildContext.d.ts +7 -0
  15. package/dist/cjs/utils/context/buildContext.js +11 -0
  16. package/dist/cjs/utils/templates/renderManager.js +0 -2
  17. package/dist/esm/core/comlib/_Connector.js +71 -54
  18. package/dist/esm/core/mybricks/createJSHandle.js +2 -1
  19. package/dist/esm/core/utils/hooks.js +15 -22
  20. package/dist/esm/core/utils/index.js +1 -0
  21. package/dist/esm/core/utils/pool.js +52 -0
  22. package/dist/esm/core/utils/slots.js +8 -8
  23. package/dist/esm/core/utils/useContext.js +15 -6
  24. package/dist/esm/generate/generateTaroProjectJson.js +12 -0
  25. package/dist/esm/taro-template.json +16 -8
  26. package/dist/esm/toCodeTaro.d.ts +1 -1
  27. package/dist/esm/toCodeTaro.js +3 -1
  28. package/dist/esm/utils/builder/buildResult.d.ts +1 -0
  29. package/dist/esm/utils/builder/buildResult.js +41 -1
  30. package/dist/esm/utils/context/buildContext.d.ts +7 -0
  31. package/dist/esm/utils/context/buildContext.js +12 -0
  32. package/dist/esm/utils/templates/renderManager.js +2 -1
  33. package/package.json +1 -1
  34. package/dist/esm/abstractEventTypeDef.d.ts.map +0 -1
  35. package/dist/esm/generate/generateTaroTempalteJson.d.ts.map +0 -1
  36. package/dist/esm/generate/utils/appConfig.d.ts.map +0 -1
  37. package/dist/esm/generate/utils/fileNode.d.ts.map +0 -1
  38. package/dist/esm/generate/utils/index.d.ts.map +0 -1
  39. package/dist/esm/generate/utils/pageImages.d.ts.map +0 -1
  40. package/dist/esm/generate/utils/tabBarImages.d.ts.map +0 -1
  41. package/dist/esm/handleExtension.d.ts.map +0 -1
  42. package/dist/esm/handleModule.d.ts.map +0 -1
  43. package/dist/esm/index.d.ts.map +0 -1
  44. package/dist/esm/processors/processComEvents.d.ts.map +0 -1
  45. package/dist/esm/processors/processModule.d.ts.map +0 -1
  46. package/dist/esm/processors/processScene.d.ts.map +0 -1
  47. package/dist/esm/processors/processSceneLogic.d.ts.map +0 -1
  48. package/dist/esm/toCodeTaro.d.ts.map +0 -1
  49. package/dist/esm/utils/builder/buildResult.d.ts.map +0 -1
  50. package/dist/esm/utils/common/ImportManager.d.ts.map +0 -1
  51. package/dist/esm/utils/common/helper.d.ts.map +0 -1
  52. package/dist/esm/utils/common/object.d.ts.map +0 -1
  53. package/dist/esm/utils/common/string.d.ts.map +0 -1
  54. package/dist/esm/utils/config/content/index.d.ts.map +0 -1
  55. package/dist/esm/utils/config/content/types.d.ts.map +0 -1
  56. package/dist/esm/utils/config/content/validator.d.ts.map +0 -1
  57. package/dist/esm/utils/config/handlePageConfig.d.ts.map +0 -1
  58. package/dist/esm/utils/context/buildContext.d.ts.map +0 -1
  59. package/dist/esm/utils/context/buildFrameMap.d.ts.map +0 -1
  60. package/dist/esm/utils/context/buildGlobalData.d.ts.map +0 -1
  61. package/dist/esm/utils/context/collectJSModules.d.ts.map +0 -1
  62. package/dist/esm/utils/context/createEventQueries.d.ts.map +0 -1
  63. package/dist/esm/utils/context/createProvider.d.ts.map +0 -1
  64. package/dist/esm/utils/index.d.ts.map +0 -1
  65. package/dist/esm/utils/logic/convertNamespace.d.ts.map +0 -1
  66. package/dist/esm/utils/logic/genJSModules.d.ts.map +0 -1
  67. package/dist/esm/utils/style/color.d.ts.map +0 -1
  68. package/dist/esm/utils/style/getComponentClassName.d.ts.map +0 -1
  69. package/dist/esm/utils/style/pxtransform.d.ts.map +0 -1
  70. package/dist/esm/utils/style/types.d.ts.map +0 -1
  71. package/dist/esm/utils/templates/component.d.ts.map +0 -1
@@ -1,4 +1,5 @@
1
1
  export * from "./hooks";
2
+ export { TodoPool } from "./pool";
2
3
  export { WithCom, WithWrapper } from "./with";
3
4
  export { PopupRenderer } from "./PopupRenderer";
4
5
  export { pageRouter, router } from "./pageRouter";
@@ -0,0 +1,52 @@
1
+ import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
2
+ import _createClass from "@babel/runtime/helpers/esm/createClass";
3
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
4
+ /**
5
+ * 待执行指令池
6
+ * 结构:Map<组件ID, Map<索引, Record<方法名, 参数数组>>>
7
+ */
8
+ export var TodoPool = /*#__PURE__*/function () {
9
+ function TodoPool() {
10
+ _classCallCheck(this, TodoPool);
11
+ _defineProperty(this, "pool", new Map());
12
+ }
13
+ _createClass(TodoPool, [{
14
+ key: "push",
15
+ value: /** 存:记录待执行指令 */
16
+ function push(id, index, method, args) {
17
+ if (!this.pool.has(id)) {
18
+ this.pool.set(id, new Map());
19
+ }
20
+ var instances = this.pool.get(id);
21
+ if (!instances.has(index)) {
22
+ instances.set(index, {});
23
+ }
24
+ instances.get(index)[method] = args;
25
+ }
26
+
27
+ /** 取:获取并物理删除指令 */
28
+ }, {
29
+ key: "pop",
30
+ value: function pop(id, index, method) {
31
+ var instances = this.pool.get(id);
32
+ if (!instances) return undefined;
33
+ var todo = instances.get(index);
34
+ if (todo && todo[method]) {
35
+ var args = todo[method];
36
+ delete todo[method];
37
+
38
+ // 自动清理:如果当前索引下没指令了,删掉索引容器
39
+ if (Object.keys(todo).length === 0) {
40
+ instances.delete(index);
41
+ }
42
+ // 如果当前组件下没索引了,删掉整个 ID
43
+ if (instances.size === 0) {
44
+ this.pool.delete(id);
45
+ }
46
+ return args;
47
+ }
48
+ return undefined;
49
+ }
50
+ }]);
51
+ return TodoPool;
52
+ }();
@@ -7,7 +7,7 @@ import { proxyRefs } from "./hooks";
7
7
  /**
8
8
  * 创建一个具有“向上渗透”和“隔离 Todo 池”能力的 comRefs 对象
9
9
  */
10
- function createPenetratingComRefs(parentComRefs, globalTodoPool) {
10
+ function createPenetratingComRefs(parentComRefs, todoPool) {
11
11
  var index = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
12
12
  var localTarget = {
13
13
  $inputs: {},
@@ -15,7 +15,7 @@ function createPenetratingComRefs(parentComRefs, globalTodoPool) {
15
15
  $index: index
16
16
  };
17
17
  return {
18
- current: proxyRefs(localTarget, parentComRefs, globalTodoPool)
18
+ current: proxyRefs(localTarget, parentComRefs, todoPool)
19
19
  };
20
20
  }
21
21
  function SlotParamsBridge(props) {
@@ -57,7 +57,7 @@ function createChannelProxy(title) {
57
57
  export function useEnhancedSlots(rawSlots, id) {
58
58
  var _useAppContext = useAppContext(),
59
59
  parentComRefs = _useAppContext.comRefs,
60
- globalTodoInputs = _useAppContext.globalTodoInputs;
60
+ todoPool = _useAppContext.todoPool;
61
61
  var slotStoreRef = useRef({});
62
62
  return useMemo(function () {
63
63
  if (!rawSlots) return {};
@@ -73,10 +73,10 @@ export function useEnhancedSlots(rawSlots, id) {
73
73
  _scopedComRefs: {},
74
74
  _render: undefined,
75
75
  render: function render(params) {
76
- var _ref3, _params$key, _params$inputValues, _params$inputValues2, _params$inputValues$i, _params$inputValues3, _ref4;
76
+ var _params$inputValues$i, _params$inputValues, _params$inputValues$i2, _params$inputValues2, _ref3;
77
77
  var r = state._render;
78
78
  // 只有存在 key 或 index 时才认为是“多实例作用域插槽”,需要实例隔离
79
- var rawScope = (_ref3 = (_params$key = params === null || params === void 0 ? void 0 : params.key) !== null && _params$key !== void 0 ? _params$key : params === null || params === void 0 || (_params$inputValues = params.inputValues) === null || _params$inputValues === void 0 ? void 0 : _params$inputValues.index) !== null && _ref3 !== void 0 ? _ref3 : params === null || params === void 0 || (_params$inputValues2 = params.inputValues) === null || _params$inputValues2 === void 0 || (_params$inputValues2 = _params$inputValues2.itemData) === null || _params$inputValues2 === void 0 ? void 0 : _params$inputValues2.id;
79
+ var rawScope = (_params$inputValues$i = params === null || params === void 0 || (_params$inputValues = params.inputValues) === null || _params$inputValues === void 0 ? void 0 : _params$inputValues.index) !== null && _params$inputValues$i !== void 0 ? _params$inputValues$i : params === null || params === void 0 ? void 0 : params.key;
80
80
  if (rawScope === undefined || rawScope === null) {
81
81
  return /*#__PURE__*/React.createElement(SlotParamsBridge, {
82
82
  state: state,
@@ -85,8 +85,8 @@ export function useEnhancedSlots(rawSlots, id) {
85
85
  });
86
86
  }
87
87
  var scopeId = "".concat(id, ".").concat(slotKey, "::").concat(String(rawScope));
88
- var index = (_params$inputValues$i = params === null || params === void 0 || (_params$inputValues3 = params.inputValues) === null || _params$inputValues3 === void 0 ? void 0 : _params$inputValues3.index) !== null && _params$inputValues$i !== void 0 ? _params$inputValues$i : 0;
89
- var scopedComRefs = (_ref4 = state._scopedComRefs)[scopeId] || (_ref4[scopeId] = createPenetratingComRefs(parentComRefs, globalTodoInputs, index));
88
+ var index = (_params$inputValues$i2 = params === null || params === void 0 || (_params$inputValues2 = params.inputValues) === null || _params$inputValues2 === void 0 ? void 0 : _params$inputValues2.index) !== null && _params$inputValues$i2 !== void 0 ? _params$inputValues$i2 : 0;
89
+ var scopedComRefs = (_ref3 = state._scopedComRefs)[scopeId] || (_ref3[scopeId] = createPenetratingComRefs(parentComRefs, todoPool, index));
90
90
  return /*#__PURE__*/React.createElement(ScopedComContextProvider, {
91
91
  comRefs: scopedComRefs,
92
92
  scopeId: scopeId
@@ -106,7 +106,7 @@ export function useEnhancedSlots(rawSlots, id) {
106
106
  });
107
107
  });
108
108
  return nextSlots;
109
- }, [rawSlots, id, parentComRefs, globalTodoInputs]);
109
+ }, [rawSlots, id, parentComRefs, todoPool]);
110
110
  }
111
111
  export function ScopedComContextProvider(props) {
112
112
  var parent = useAppContext();
@@ -1,13 +1,17 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
2
  import { useRef, useState, useMemo } from 'react';
3
3
  import { proxyRefs } from "./hooks";
4
- var GLOBAL_TODO_POOL = new Map();
4
+ import { TodoPool } from "./pool";
5
+ // @ts-ignore
6
+ import { request as _request } from '@/common/request';
5
7
  export function useAppCreateContext(id) {
6
- var globalTodoInputs = useRef(GLOBAL_TODO_POOL);
8
+ var todoPool = useMemo(function () {
9
+ return new TodoPool();
10
+ }, []);
7
11
  var comRefs = useRef(proxyRefs({
8
12
  $inputs: {},
9
13
  $outputs: {}
10
- }, undefined, globalTodoInputs.current));
14
+ }, undefined, todoPool));
11
15
  var $vars = useRef({});
12
16
  var $fxs = useRef({});
13
17
  var _useState = useState({
@@ -23,8 +27,13 @@ export function useAppCreateContext(id) {
23
27
  canvas: {
24
28
  id: id
25
29
  },
26
- runtime: {
27
- debug: false
30
+ env: {
31
+ runtime: true,
32
+ request: function request(connector, params, config) {
33
+ return _request(connector, params, config, {
34
+ $vars: $vars
35
+ });
36
+ }
28
37
  },
29
38
  edit: false,
30
39
  isH5: false,
@@ -42,7 +51,7 @@ export function useAppCreateContext(id) {
42
51
  comRefs: comRefs,
43
52
  $vars: $vars,
44
53
  $fxs: $fxs,
45
- globalTodoInputs: globalTodoInputs.current,
54
+ todoPool: todoPool,
46
55
  appContext: appContext,
47
56
  popupState: popupState,
48
57
  setPopupState: setPopupState
@@ -167,6 +167,18 @@ var generateTaroProjectJson = function generateTaroProjectJson(result) {
167
167
  // 处理 common 目录下的文件
168
168
  handleCommonDir(commonDir, files);
169
169
 
170
+ // 处理 common 目录下的 api.ts
171
+ var apiItem = files.find(function (item) {
172
+ return item.type === 'connector-api';
173
+ });
174
+ if (apiItem) {
175
+ commonDir.children = commonDir.children || [];
176
+ commonDir.children.push({
177
+ path: 'src/common/api.ts',
178
+ content: apiItem.content
179
+ });
180
+ }
181
+
170
182
  // 处理 popup 汇总文件 (type 为 popup 且无 meta)
171
183
  var popupFile = files.find(function (f) {
172
184
  return f.type === "popup" && !f.meta;
@@ -28,6 +28,10 @@
28
28
  {
29
29
  "path": "src/common/pageLife.ts",
30
30
  "content": "import Taro, { useDidShow, useDidHide, useRouter } from '@tarojs/taro';\n\n/**\n * 页面生命周期 Hook\n * 用于监听页面的 DidShow 和 DidHide 事件,并通过 Taro.eventCenter 触发全局事件\n */\nexport const usePageLife = () => {\n const router = useRouter();\n\n useDidShow(() => {\n Taro.eventCenter.trigger('pageDidShow', {\n path: router.path,\n query: router.params\n });\n });\n\n useDidHide(() => {\n Taro.eventCenter.trigger('pageDidHide', {\n path: router.path,\n query: router.params\n });\n });\n};\n\n"
31
+ },
32
+ {
33
+ "path": "src/common/request.ts",
34
+ "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport Taro from '@tarojs/taro';\n// @ts-ignore\nimport { api, baseConfig } from './api';\n\nexport function request(connector: any, params: any, config: any = {}, appContext?: any) {\n const connectorId = connector.id;\n const def = api[connectorId];\n\n if (!def) {\n return Promise.reject(`未找到连接器定义: ${connectorId}`);\n }\n\n return new Promise((resolve, reject) => {\n try {\n const method = def.method;\n const path = def.path?.trim();\n const headers = def.headers || {};\n\n const url = path;\n const extraParams = {\n globalVars: appContext?.$vars?.current\n };\n\n /** 1. 全局入参处理 */\n const globalParams = baseConfig.globalParamsFn(\n method.startsWith('GET')\n ? { params, url, method, headers }\n : { data: params, url, method, headers },\n extraParams\n );\n\n /** 2. 局部入参处理 (Connector Script) */\n const options = def.input(globalParams, extraParams);\n\n const requestConfig: Taro.request.Option = {\n url: options.url || url,\n method: (options.method || method) as any,\n header: options.headers || options.header || headers,\n data: options.data || options.params || params,\n timeout: options.timeout || config.timeout,\n dataType: options.dataType || config.dataType || 'json',\n responseType: options.responseType || config.responseType || 'text',\n };\n\n const onError = (error: any) => {\n const errorResult = baseConfig.globalErrorResultFn(\n { error, response: error?.response, config: options },\n { throwError: (msg: any) => reject(msg) }\n );\n if (errorResult !== undefined) {\n reject(errorResult);\n }\n };\n\n Taro.request({\n ...requestConfig,\n success: (res) => {\n /** 3. 全局响应值处理 */\n Promise.resolve()\n .then(() => {\n return baseConfig.globalResultFn(\n { response: res.data, config: options },\n { \n throwStatusCodeError: (msg: any) => reject(msg),\n throwError: (msg: any) => reject(msg)\n }\n );\n })\n .then((globalResult) => {\n /** 4. 局部响应值处理 (Connector Script) */\n const result = def.output(\n globalResult,\n { ...options },\n { \n throwStatusCodeError: (msg: any) => reject(msg),\n throwError: (msg: any) => reject(msg)\n }\n );\n\n // 处理 markList (多分支输出)\n const markList = def.markList || [];\n let outputId = 'then';\n\n if (markList.length > 0) {\n for (const mark of markList) {\n const { id, predicate } = mark;\n if (!predicate || !predicate.key || predicate.value === undefined) {\n outputId = id === 'default' ? 'then' : id;\n break;\n }\n\n let curResult = result;\n const keys = predicate.key.split('.');\n while (curResult && keys.length) {\n curResult = curResult[keys.shift()];\n }\n\n if (!keys.length && (\n predicate.operator === '=' \n ? curResult === predicate.value \n : curResult !== predicate.value\n )) {\n outputId = id === 'default' ? 'then' : id;\n break;\n }\n }\n }\n\n // 返回包含 OUTPUT_ID 的结果,供 _Connector.ts 使用\n resolve({\n __OUTPUT_ID__: outputId,\n __ORIGIN_RESPONSE__: result\n });\n })\n .catch(onError);\n },\n fail: (err) => {\n onError(err);\n },\n });\n } catch (error: any) {\n console.error('连接器执行失败:', error);\n reject(error?.message || '连接器执行失败');\n }\n });\n}\n"
31
35
  }
32
36
  ]
33
37
  },
@@ -3309,7 +3313,7 @@
3309
3313
  },
3310
3314
  {
3311
3315
  "path": "src/components/image/runtime.tsx",
3312
- "content": "import React, {\n useCallback,\n useEffect,\n useRef,\n useMemo,\n useState,\n} from \"react\";\nimport css from \"./style.less\";\nimport cx from \"classnames\";\nimport { View, Image } from \"@tarojs/components\";\nimport SkeletonImage from \"./../components/skeleton-image\";\nimport { useRedirectedImageUrl } from \"./../utils/hooks\";\nimport * as Taro from \"@tarojs/taro\";\n\nexport default function ({ env, data, inputs, outputs, title, style, extra }) {\n const ele = useRef(null);\n const [h5PolyfillClass, setH5PolyfillClass] = useState(\n css[\"h5-polyfill-aspectfill-width\"]\n );\n\n useEffect(() => {\n if (data.mode !== \"aspectFill\") {\n return;\n }\n if (!ele.current && !ele.current.getBoundingClientRect) {\n return;\n }\n const { width, height } = ele.current.getBoundingClientRect?.() ?? {};\n setH5PolyfillClass(\n width > height\n ? css[\"h5-polyfill-aspectfill-width\"]\n : css[\"h5-polyfill-aspectfill-height\"]\n );\n }, [style.width, style.height, data.mode]);\n\n /** TODO 写在useEffect里时序有延迟,容易出现闪屏,先试试这样先 */\n useMemo(() => {\n inputs[\"setSrc\"]((src) => {\n data.src = src;\n });\n }, []);\n\n useRedirectedImageUrl(env?.edit ? data.src : undefined, (redirectedUrl) => {\n data.src = redirectedUrl\n })\n\n const onLoad = useCallback(() => {\n if (!env.runtim) {\n return;\n }\n outputs[\"onLoad\"](data.src);\n }, []);\n\n const onClick = useCallback(\n (e) => {\n if (!env.runtime) {\n return;\n }\n\n if (data.clickType === \"previewImage\") {\n Taro.previewImage({\n urls: [data.src],\n current: data.src,\n });\n e.stopPropagation();\n return;\n }\n // 当配置了单击事件,阻止事件冒泡\n if (outputs[\"onClick\"].getConnections().length) {\n e.stopPropagation();\n }\n outputs[\"onClick\"](data.src);\n },\n [data.clickType, data.src,data.stopPropagation]\n );\n\n const onError = useCallback(() => {\n if (!env.runtime) {\n return;\n }\n outputs[\"onError\"](data.src);\n }, []);\n\n const src = useMemo(() => {\n let src = data.svgPolyfill || data.src || extra?.imageUrl;\n return src;\n }, [data.svgPolyfill, data.src, extra?.imageUrl]);\n\n const svgProps = useMemo(() => {\n if (data.svgPolyfill) {\n return {\n svg: true,\n mode: \"aspectFit\",\n };\n } else {\n return {};\n }\n }, [data.svgPolyfill]);\n\n return (\n <View className={css.com} ref={ele}>\n <SkeletonImage\n useHtml={env.edit}\n skeleton={env.edit ? false : !!data?.loadSmooth}\n className={cx(css.image, h5PolyfillClass, \"mybricks-image\")}\n // src={!!data.src ? data.src : extra?.imageUrl}\n src={src}\n mode={data.mode}\n onClick={onClick}\n onLoad={onLoad}\n onError={onError}\n showMenuByLongpress={data.showMenuByLongpress ?? false}\n cdnCut=\"auto\"\n cdnCutOption={{ width: style.width, height: style.height }}\n {...svgProps}\n />\n </View>\n );\n}\n"
3316
+ "content": "import React, {\n useCallback,\n useEffect,\n useRef,\n useMemo,\n useState,\n} from \"react\";\nimport css from \"./style.less\";\nimport cx from \"classnames\";\nimport { View, Image } from \"@tarojs/components\";\nimport SkeletonImage from \"./../components/skeleton-image\";\nimport { useRedirectedImageUrl } from \"./../utils/hooks\";\nimport * as Taro from \"@tarojs/taro\";\n\nexport default function ({ env, data, inputs, outputs, title, style, extra }) {\n const ele = useRef(null);\n const [h5PolyfillClass, setH5PolyfillClass] = useState(\n css[\"h5-polyfill-aspectfill-width\"]\n );\n\n useEffect(() => {\n if (data.mode !== \"aspectFill\") {\n return;\n }\n if (!ele.current && !ele.current.getBoundingClientRect) {\n return;\n }\n const { width, height } = ele.current.getBoundingClientRect?.() ?? {};\n setH5PolyfillClass(\n width > height\n ? css[\"h5-polyfill-aspectfill-width\"]\n : css[\"h5-polyfill-aspectfill-height\"]\n );\n }, [style.width, style.height, data.mode]);\n\n /** TODO 写在useEffect里时序有延迟,容易出现闪屏,先试试这样先 */\n useMemo(() => {\n inputs[\"setSrc\"]((src) => {\n data.src = src;\n });\n }, []);\n\n useRedirectedImageUrl(env?.edit ? data.src : undefined, (redirectedUrl) => {\n data.src = redirectedUrl\n })\n\n const onLoad = useCallback(() => {\n if (!env.runtime) {\n return;\n }\n outputs[\"onLoad\"](data.src);\n }, []);\n\n const onClick = useCallback(\n (e) => {\n if (!env.runtime) {\n return;\n }\n\n if (data.clickType === \"previewImage\") {\n Taro.previewImage({\n urls: [data.src],\n current: data.src,\n });\n e.stopPropagation();\n return;\n }\n // 当配置了单击事件,阻止事件冒泡\n if (outputs[\"onClick\"].getConnections().length) {\n e.stopPropagation();\n }\n outputs[\"onClick\"](data.src);\n },\n [data.clickType, data.src,data.stopPropagation]\n );\n\n const onError = useCallback(() => {\n if (!env.runtime) {\n return;\n }\n outputs[\"onError\"](data.src);\n }, []);\n\n const src = useMemo(() => {\n let src = data.svgPolyfill || data.src || extra?.imageUrl;\n return src;\n }, [data.svgPolyfill, data.src, extra?.imageUrl]);\n\n const svgProps = useMemo(() => {\n if (data.svgPolyfill) {\n return {\n svg: true,\n mode: \"aspectFit\",\n };\n } else {\n return {};\n }\n }, [data.svgPolyfill]);\n\n return (\n <View className={css.com} ref={ele}>\n <SkeletonImage\n useHtml={env.edit}\n skeleton={env.edit ? false : !!data?.loadSmooth}\n className={cx(css.image, h5PolyfillClass, \"mybricks-image\")}\n // src={!!data.src ? data.src : extra?.imageUrl}\n src={src}\n mode={data.mode}\n onClick={onClick}\n onLoad={onLoad}\n onError={onError}\n showMenuByLongpress={data.showMenuByLongpress ?? false}\n cdnCut=\"auto\"\n cdnCutOption={{ width: style.width, height: style.height }}\n {...svgProps}\n />\n </View>\n );\n}\n"
3313
3317
  },
3314
3318
  {
3315
3319
  "path": "src/components/image/style.less",
@@ -5527,7 +5531,7 @@
5527
5531
  },
5528
5532
  {
5529
5533
  "path": "src/core/comlib/_Connector.ts",
5530
- "content": "import Taro from '@tarojs/taro';\n\nexport type DataType = {\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';\n url?: string;\n headers?: Record<string, string>;\n data?: any;\n timeout?: number;\n dataType?: 'json' | 'text' | 'base64';\n responseType?: 'text' | 'arraybuffer';\n};\n\nexport interface Inputs {\n request?: (fn: (config: DataType, relOutputs?: any) => void) => void;\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void;\n onFail: (value?: any) => void;\n}\n\ninterface IOContext {\n data: DataType;\n inputs: Inputs;\n outputs: Outputs;\n}\n\nexport default (context: IOContext) => {\n const data: DataType = context.data;\n const inputs: Inputs = context.inputs;\n const outputs: Outputs = context.outputs;\n\n inputs.request?.((val: DataType) => {\n try {\n const config = {\n method: val?.method || data.method || 'GET',\n url: val?.url || data.url,\n header: val?.headers || data.headers || {},\n data: val?.data || data.data,\n timeout: val?.timeout || data.timeout,\n dataType: val?.dataType || data.dataType || 'json',\n responseType: val?.responseType || data.responseType || 'text',\n };\n\n if (!config.url) {\n outputs.onFail('请求URL不能为空');\n return;\n }\n\n // 检查URL格式\n if (!/^https?:\\/\\//.test(config.url)) {\n outputs.onFail('URL格式不正确,请以http://或https://开头');\n return;\n }\n\n Taro.request({\n ...config,\n success: (res) => {\n if (res.statusCode >= 200 && res.statusCode < 300) {\n outputs.onSuccess({\n data: res.data,\n statusCode: res.statusCode,\n header: res.header,\n });\n } else {\n outputs.onFail({\n message: `请求失败: ${res.statusCode}`,\n statusCode: res.statusCode,\n data: res.data,\n });\n }\n },\n fail: (err) => {\n outputs.onFail({\n message: err.errMsg || '网络请求失败',\n error: err,\n });\n },\n });\n } catch (error: any) {\n console.error('网络请求失败:', error);\n outputs.onFail({\n message: error?.message || '网络请求失败',\n error,\n });\n }\n });\n};\n"
5534
+ "content": "function callCon({ env, data, inputs, outputs, onError }, params = {}) {\n if (data.connector || data.dynamicConfig) {\n try {\n let finnalConnector = {\n ...(data.connector || {}),\n outputSchema: data.outputSchema,\n };\n\n if (data.dynamicConfig) {\n finnalConnector = data.dynamicConfig;\n }\n\n if (data.timeout) {\n finnalConnector.timeout = data.timeout;\n }\n\n env\n .request(finnalConnector, params, {\n ...(data.connectorConfig || {}),\n outputSchema: finnalConnector?.outputSchema,\n isMultipleOutputs: true,\n })\n .then((val) => {\n outputs[val?.__OUTPUT_ID__ ?? \"then\"](\n val?.__ORIGIN_RESPONSE__ ?? val\n );\n })\n .catch((err) => {\n outputs[\"catch\"](err);\n });\n } catch (ex) {\n console.error(ex);\n\n outputs[\"catch\"](`执行错误 ${ex.message || ex}`);\n //onError(ex.message)\n }\n } else {\n outputs[\"catch\"](`没有选择接口`);\n }\n}\n\nfunction isPlainObject(value) {\n if (typeof value !== \"object\" || value === null) return false;\n\n let proto = Object.getPrototypeOf(value);\n if (proto === null) return true; // 没有原型的对象也视为普通对象\n\n // 检查对象是否是由Object构造函数创建的\n return proto === Object.prototype;\n}\n\nexport default function ({ env, data, inputs, outputs, onError }) {\n if (!env.runtime) {\n return;\n }\n\n if (data.immediate) {\n callCon({ env, data, outputs });\n } else {\n inputs[\"call\"]((params) => {\n // 如果 params 不是 对象,则转换为空对象\n if (!isPlainObject(params)) {\n params = {};\n }\n\n callCon({ env, data, outputs, onError }, params);\n });\n }\n}\n"
5531
5535
  },
5532
5536
  {
5533
5537
  "path": "src/core/comlib/_ConnectorGlobalHeaders.ts",
@@ -5587,7 +5591,7 @@
5587
5591
  },
5588
5592
  {
5589
5593
  "path": "src/core/comlib/_ShowToast.ts",
5590
- "content": "import Taro from '@tarojs/taro';\n\nexport type DataType = {\n dynamic?: boolean;\n title?: string;\n duration?: number;\n mask?: boolean;\n asynchronous?: boolean;\n icon?: 'success' | 'error' | 'loading' | 'none';\n image?: string;\n};\n\nexport interface Inputs {\n showToast?: (fn: (config: DataType | string, relOutputs?: any) => void) => void;\n}\n\nexport interface Outputs {\n afterShowToast: (value?: any) => void;\n}\n\ninterface IOContext {\n data: DataType;\n inputs: Inputs;\n outputs: Outputs;\n}\n\nexport default (context: IOContext) => {\n const data: DataType = context.data;\n const inputs: Inputs = context.inputs;\n const outputs: Outputs = context.outputs;\n\n inputs.showToast?.((val: DataType | string) => {\n try {\n // 构建 Toast 配置\n const toastConfig: any = {\n title: typeof val === 'string' ? val : val?.title || data.title || '',\n duration: Number(typeof val === 'object' && val?.duration ? val.duration : data.duration || 1000),\n mask: typeof val === 'object' && val?.mask !== undefined ? val.mask : data.mask || false,\n };\n\n // 图标配置\n if (typeof val === 'object' && val?.icon) {\n toastConfig.icon = val.icon;\n } else if (data.icon) {\n toastConfig.icon = data.icon;\n }\n\n // 图片配置\n if (typeof val === 'object' && val?.image) {\n toastConfig.image = val.image;\n } else if (data.image) {\n toastConfig.image = data.image;\n }\n\n Taro.showToast(toastConfig);\n\n // 处理输出回调\n const triggerOutput = () => outputs.afterShowToast(val);\n\n if (data.asynchronous) {\n setTimeout(triggerOutput, toastConfig.duration);\n } else {\n triggerOutput();\n }\n } catch (error) {\n console.error('显示 Toast 失败:', error);\n }\n });\n};\n\n"
5594
+ "content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {\n dynamic?: boolean;\n title?: string;\n duration?: number;\n mask?: boolean;\n asynchronous?: boolean;\n icon?: \"success\" | \"error\" | \"loading\" | \"none\";\n image?: string;\n};\n\nexport interface Inputs {\n showToast?: (\n fn: (config: DataType | string, relOutputs?: any) => void,\n ) => void;\n}\n\nexport interface Outputs {\n afterShowToast: (value?: any) => void;\n}\n\ninterface IOContext {\n data: DataType;\n inputs: Inputs;\n outputs: Outputs;\n}\n\nexport default (context: IOContext) => {\n const data: DataType = context.data;\n const inputs: Inputs = context.inputs;\n const outputs: Outputs = context.outputs;\n\n inputs.showToast?.((val: DataType | string) => {\n console.log(111, context);\n try {\n /** 动态输入 */\n if (data?.dynamic) {\n Taro.showToast({\n ...(typeof val === \"string\"\n ? {\n title: val ?? \"\",\n duration: 1000,\n }\n : {\n ...val,\n title: val.title ?? \"\",\n duration: !val.duration\n ? 1000\n : typeof val.duration === \"string\"\n ? Number(val.duration)\n : val.duration,\n }),\n complete: () => {\n if (data.asynchronous) {\n setTimeout(() => {\n outputs[\"afterShowToast\"]();\n }, data?.duration); //提示结束后触发\n } else {\n outputs[\"afterShowToast\"](val);\n }\n },\n });\n } else {\n /** 非动态输入 */\n Taro.showToast({\n ...data,\n title: data.title ?? \"\",\n complete: () => {\n if (data.asynchronous) {\n setTimeout(() => {\n outputs[\"afterShowToast\"]();\n }, data?.duration); //提示结束后触发\n } else {\n outputs[\"afterShowToast\"](val);\n }\n },\n });\n }\n } catch (error) {\n console.error(\"显示 Toast 失败:\", error);\n }\n });\n};\n"
5591
5595
  },
5592
5596
  {
5593
5597
  "path": "src/core/comlib/_TextToSpeech.ts",
@@ -5633,7 +5637,7 @@
5633
5637
  },
5634
5638
  {
5635
5639
  "path": "src/core/mybricks/createJSHandle.js",
5636
- "content": "import { EXE_TITLE_MAP, SUBJECT_NEXT, SUBJECT_SUBSCRIBE } from \"./constant\"\nimport { Subject } from \"./Subject\"\nimport { log, logger } from \"./log\"\nimport { createReactiveInputHandler } from \"./createReactiveInputHandler\"\n\n/** utils */\n/**\n * 判断是否js多输入\n */\nexport const validateJsMultipleInputs = (input) => {\n return input.match(/\\./); // input.xxx 为多输入模式\n}\n\n// JS\nexport const createJSHandle = (fn, options) => {\n let controller\n\n const { props, appContext } = options\n\n const inputs = new Proxy({}, {\n getOwnPropertyDescriptor() {\n return {\n enumerable: true,\n configurable: true,\n }\n },\n ownKeys() {\n return props.inputs\n },\n get() {\n return (input) => {\n // 约定只有一个输入\n controller = input\n }\n }\n })\n\n const rels = {}\n\n const outputs = new Proxy({}, {\n getOwnPropertyDescriptor() {\n return {\n enumerable: true,\n configurable: true,\n }\n },\n ownKeys() {\n return props.outputs\n },\n get(_, key) {\n return (value) => {\n (rels[key] ||\n (rels[key] = new Subject({ log: `${EXE_TITLE_MAP[\"output\"]} ${props.title} | ${key}` })))[SUBJECT_NEXT](value)\n }\n }\n })\n\n fn({\n data: props.data,\n inputs,\n outputs,\n logger,\n env: appContext?.env\n })\n\n const isJsMultipleInputs = props.inputs[0]\n ? validateJsMultipleInputs(props.inputs[0])\n : false;\n\n const exeOutputs = new Proxy(\n {},\n {\n get(_, key) {\n return rels[key] || (rels[key] = new Subject({ log: `${EXE_TITLE_MAP[\"output\"]} ${props.title} | ${key}` }))\n },\n },\n )\n\n const exe = (...args) => {\n if (args.length) {\n // 调用输入\n if (isJsMultipleInputs) {\n // 多输入模式\n const length = args.length;\n let valueAry = {};\n args.forEach((value, index) => {\n if (value?.[SUBJECT_SUBSCRIBE]) {\n value[SUBJECT_SUBSCRIBE]((value) => {\n log(`${EXE_TITLE_MAP[\"input\"]} ${props.title} | ${props.inputs[index]}`, JSON.stringify(value));\n valueAry[props.inputs[index]] = value\n if (Object.keys(valueAry).length === length) {\n createReactiveInputHandler({\n input: controller,\n value: valueAry,\n rels,\n title: props.title\n })\n // 触发输入后清除\n valueAry = {}\n }\n })\n } else {\n log(`${EXE_TITLE_MAP[\"input\"]} ${props.title} | ${props.inputs[index]}`, JSON.stringify(value));\n valueAry[props.inputs[index]] = value\n\n if (Object.keys(valueAry).length === length) {\n createReactiveInputHandler({\n input: controller,\n value: valueAry,\n rels,\n title: props.title\n })\n // 触发输入后清除\n valueAry = {}\n }\n }\n })\n } else {\n // 非多输入\n const value = args[0]\n if (value?.[SUBJECT_SUBSCRIBE]) {\n value[SUBJECT_SUBSCRIBE]((value) => {\n log(`${EXE_TITLE_MAP[\"input\"]} ${props.title} | ${props.inputs[0]}`, JSON.stringify(value));\n createReactiveInputHandler({\n input: controller,\n value,\n rels,\n title: props.title\n })\n })\n } else {\n log(`${EXE_TITLE_MAP[\"input\"]} ${props.title} | ${props.inputs[0]}`, JSON.stringify(value));\n createReactiveInputHandler({\n input: controller,\n value,\n rels,\n title: props.title\n })\n }\n }\n }\n\n return exeOutputs;\n }\n\n return exe;\n}\n\n"
5640
+ "content": "import { EXE_TITLE_MAP, SUBJECT_NEXT, SUBJECT_SUBSCRIBE } from \"./constant\"\nimport { Subject } from \"./Subject\"\nimport { log, logger } from \"./log\"\nimport { createReactiveInputHandler } from \"./createReactiveInputHandler\"\n\n/** utils */\n/**\n * 判断是否js多输入\n */\nexport const validateJsMultipleInputs = (input) => {\n return input.match(/\\./); // input.xxx 为多输入模式\n}\n\n// JS\nexport const createJSHandle = (fn, options) => {\n let controller\n\n const { props, appContext } = options\n\n const inputs = new Proxy({}, {\n getOwnPropertyDescriptor() {\n return {\n enumerable: true,\n configurable: true,\n }\n },\n ownKeys() {\n return props.inputs\n },\n get() {\n return (input) => {\n // 约定只有一个输入\n controller = input\n }\n }\n })\n\n const rels = {}\n\n const outputs = new Proxy({}, {\n getOwnPropertyDescriptor() {\n return {\n enumerable: true,\n configurable: true,\n }\n },\n ownKeys() {\n return props.outputs\n },\n get(_, key) {\n return (value) => {\n (rels[key] ||\n (rels[key] = new Subject({ log: `${EXE_TITLE_MAP[\"output\"]} ${props.title} | ${key}` })))[SUBJECT_NEXT](value)\n }\n }\n })\n\n fn({\n data: props.data,\n inputs,\n outputs,\n logger,\n env: appContext?.env,\n appContext\n })\n\n const isJsMultipleInputs = props.inputs[0]\n ? validateJsMultipleInputs(props.inputs[0])\n : false;\n\n const exeOutputs = new Proxy(\n {},\n {\n get(_, key) {\n return rels[key] || (rels[key] = new Subject({ log: `${EXE_TITLE_MAP[\"output\"]} ${props.title} | ${key}` }))\n },\n },\n )\n\n const exe = (...args) => {\n if (args.length) {\n // 调用输入\n if (isJsMultipleInputs) {\n // 多输入模式\n const length = args.length;\n let valueAry = {};\n args.forEach((value, index) => {\n if (value?.[SUBJECT_SUBSCRIBE]) {\n value[SUBJECT_SUBSCRIBE]((value) => {\n log(`${EXE_TITLE_MAP[\"input\"]} ${props.title} | ${props.inputs[index]}`, JSON.stringify(value));\n valueAry[props.inputs[index]] = value\n if (Object.keys(valueAry).length === length) {\n createReactiveInputHandler({\n input: controller,\n value: valueAry,\n rels,\n title: props.title\n })\n // 触发输入后清除\n valueAry = {}\n }\n })\n } else {\n log(`${EXE_TITLE_MAP[\"input\"]} ${props.title} | ${props.inputs[index]}`, JSON.stringify(value));\n valueAry[props.inputs[index]] = value\n\n if (Object.keys(valueAry).length === length) {\n createReactiveInputHandler({\n input: controller,\n value: valueAry,\n rels,\n title: props.title\n })\n // 触发输入后清除\n valueAry = {}\n }\n }\n })\n } else {\n // 非多输入\n const value = args[0]\n if (value?.[SUBJECT_SUBSCRIBE]) {\n value[SUBJECT_SUBSCRIBE]((value) => {\n log(`${EXE_TITLE_MAP[\"input\"]} ${props.title} | ${props.inputs[0]}`, JSON.stringify(value));\n createReactiveInputHandler({\n input: controller,\n value,\n rels,\n title: props.title\n })\n })\n } else {\n log(`${EXE_TITLE_MAP[\"input\"]} ${props.title} | ${props.inputs[0]}`, JSON.stringify(value));\n createReactiveInputHandler({\n input: controller,\n value,\n rels,\n title: props.title\n })\n }\n }\n }\n\n return exeOutputs;\n }\n\n return exe;\n}\n\n"
5637
5641
  },
5638
5642
  {
5639
5643
  "path": "src/core/mybricks/createModuleEventsHandle.js",
@@ -5683,16 +5687,20 @@
5683
5687
  },
5684
5688
  {
5685
5689
  "path": "src/core/utils/hooks.ts",
5686
- "content": "import { useState, useRef, useMemo, useEffect } from 'react';\nimport { createReactiveInputHandler } from '../mybricks/createReactiveInputHandler';\nimport { useAppContext, useParentSlot } from './ComContext';\n\n/** 深度代理:支持响应式更新 */\nexport function deepProxy(target: any, onSet?: () => void): any {\n if (target === null || typeof target !== 'object' || target.__isProxy) return target;\n\n return new Proxy(target, {\n get(obj, prop) {\n if (prop === '__isProxy') return true;\n if (prop === 'toJSON') return () => obj;\n\n const value = obj[prop];\n if (typeof value === 'object' && value !== null && !value.__isProxy) {\n obj[prop] = deepProxy(value, onSet);\n }\n return obj[prop];\n },\n set(obj, prop, value) {\n const result = Reflect.set(obj, prop, value);\n onSet?.();\n return result;\n }\n });\n}\n\n/** 状态 Hook:提供响应式数据能力 */\nexport function useModel(rawData: any) {\n const [, forceUpdate] = useState({});\n const dataRef = useRef(rawData || {});\n\n return useMemo(() => deepProxy(dataRef.current, () => forceUpdate({})), []);\n}\n\n/** \n * 组件引用代理:\n * 1. 自动缓冲:访问未渲染组件时返回影子对象,缓冲后续指令\n * 2. 引用渗透:子作用域注册的真实引用自动同步至父级\n * 3. 自动同步清理:卸载时从作用域链中彻底移除,防止僵尸引用\n */\nexport function proxyRefs(target: any, parentComRefs?: any, globalTodoPool?: Map<string, any[]>): any {\n return new Proxy(target, {\n get(obj, prop) {\n if (prop === '__isProxy') return true;\n if (prop === 'toJSON') return () => obj;\n\n if (typeof prop === 'string' && prop.startsWith('u_') && obj[prop] === undefined) {\n // 懒加载影子对象\n return (obj[prop] = new Proxy({ __isShadow: true }, {\n get(_, method: string) {\n if (method === '__isShadow') return true;\n return (...args: any[]) => {\n if (!(globalTodoPool instanceof Map)) return;\n\n const instances = globalTodoPool.get(prop) || [];\n if (!globalTodoPool.has(prop)) globalTodoPool.set(prop, instances);\n\n const index = obj.$index ?? 0;\n const todo = instances[index] || (instances[index] = {});\n todo[method] = args;\n };\n }\n }));\n }\n return obj[prop];\n },\n set(obj, prop, value) {\n const result = Reflect.set(obj, prop, value);\n const isRealRef = typeof prop === 'string' && !prop.startsWith('$') && value?.__isShadow !== true;\n\n if (isRealRef && parentComRefs?.current) {\n try { parentComRefs.current[prop] = value; } catch {}\n }\n return result;\n },\n deleteProperty(obj, prop) {\n const result = Reflect.deleteProperty(obj, prop);\n const isRealRef = typeof prop === 'string' && !prop.startsWith('$');\n\n if (isRealRef && parentComRefs?.current) {\n try { delete parentComRefs.current[prop]; } catch {}\n }\n return result;\n }\n });\n}\n\n/** \n * 组件输入绑定 Hook:\n * 1. 注册输入执行器\n * 2. 自动重放缓冲指令(精准索引匹配)\n * 3. 生命周期自动化:卸载时自动注销引用渗透路径\n */\nexport function useBindInputs(scope: any, id: string, initialHandlers?: Record<string, any>) {\n const handlersRef = useRef<Record<string, any>>({ ...initialHandlers });\n const { globalTodoInputs } = useAppContext();\n const parentSlot = useParentSlot();\n const index = parentSlot?.params?.inputValues?.index ?? 0;\n\n useEffect(() => {\n return () => {\n if (scope?.current) {\n delete scope.current[id];\n }\n };\n }, [scope, id]);\n\n return useMemo(() => {\n const proxy = new Proxy({}, {\n get: (target, pin: string) => {\n if (pin === '__isShadow') return false;\n if (pin === 'toJSON') return () => target;\n\n return (arg: any, ...args: any[]) => {\n if (typeof arg === 'function') {\n handlersRef.current[pin] = arg;\n\n // 处理指令重放\n const instances = globalTodoInputs?.get(id);\n const todo = instances?.[index] || instances?.[0];\n if (todo?.[pin]) {\n const pendingArgs = todo[pin];\n if (pin === '_setData') {\n arg(...pendingArgs);\n } else {\n createReactiveInputHandler({ input: arg, value: pendingArgs[0], rels: {}, title: id });\n }\n delete todo[pin];\n\n // 检查全局清理\n const hasTasks = instances?.some((inst: any) => inst && Object.keys(inst).length > 0);\n if (!hasTasks) globalTodoInputs.delete(id);\n }\n } else {\n const handler = handlersRef.current[pin];\n if (typeof handler === 'function') {\n return pin === '_setData' \n ? handler(arg, ...args) \n : createReactiveInputHandler({ input: handler, value: arg, rels: {}, title: id });\n }\n }\n };\n }\n });\n\n if (scope?.current) scope.current[id] = proxy;\n if (initialHandlers) {\n Object.keys(initialHandlers).forEach(pin => (proxy as any)[pin](initialHandlers[pin]));\n }\n\n return proxy;\n }, [scope, id, globalTodoInputs, index]);\n}\n\n/** 组件事件绑定 Hook */\nexport function useBindEvents(props: any, context?: { id: string, name: string, parentSlot?: any }) {\n return useMemo(() => {\n const events: Record<string, any> = {};\n\n Object.keys(props).forEach(key => {\n if (typeof props[key] === 'function') {\n const handler = props[key];\n const wrapped = (original: any) => {\n const value = context?.parentSlot?.params?.itemWrap \n ? { id: context.id, name: context.name, value: original } \n : original;\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]) return target[key];\n const fn: any = () => {};\n fn.getConnections = () => [];\n return fn;\n }\n return target[key];\n }\n });\n }, [props, context]);\n}\n"
5690
+ "content": "import { useState, useRef, useMemo, useEffect } from 'react';\nimport { createReactiveInputHandler } from '../mybricks/createReactiveInputHandler';\nimport { useAppContext, useParentSlot } from './ComContext';\nimport { TodoPool } from './pool';\n\n/** 深度代理:支持响应式更新 */\nexport function deepProxy(target: any, onSet?: () => void): any {\n if (target === null || typeof target !== 'object' || target.__isProxy) return target;\n\n return new Proxy(target, {\n get(obj, prop) {\n if (prop === '__isProxy') return true;\n if (prop === 'toJSON') return () => obj;\n\n const value = obj[prop];\n if (typeof value === 'object' && value !== null && !value.__isProxy) {\n obj[prop] = deepProxy(value, onSet);\n }\n return obj[prop];\n },\n set(obj, prop, value) {\n const result = Reflect.set(obj, prop, value);\n onSet?.();\n return result;\n }\n });\n}\n\n/** 状态 Hook:提供响应式数据能力 */\nexport function useModel(rawData: any) {\n const [, forceUpdate] = useState({});\n const dataRef = useRef(rawData || {});\n\n return useMemo(() => deepProxy(dataRef.current, () => forceUpdate({})), []);\n}\n\n/** \n * 组件引用代理:\n * 1. 自动缓冲:访问未渲染组件时返回影子对象,缓冲后续指令\n * 2. 引用渗透:子作用域注册的真实引用自动同步至父级\n * 3. 自动同步清理:卸载时从作用域链中彻底移除,防止僵尸引用\n */\nexport function proxyRefs(target: any, parentComRefs?: any, todoPool?: TodoPool): any {\n return new Proxy(target, {\n get(obj, prop) {\n if (prop === '__isProxy') return true;\n if (prop === 'toJSON') return () => obj;\n\n if (typeof prop === 'string' && prop.startsWith('u_') && obj[prop] === undefined) {\n // 先检查父级是否有真实引用(非影子对象)\n if (parentComRefs?.current?.[prop] && !parentComRefs.current[prop].__isShadow) {\n return parentComRefs.current[prop];\n }\n // 在当前作用域创建影子对象,使用当前作用域的 $index\n const currentIndex = obj.$index ?? 0;\n return (obj[prop] = new Proxy({ __isShadow: true }, {\n get(_, method: string) {\n if (method === '__isShadow') return true;\n return (...args: any[]) => {\n if (!(todoPool instanceof TodoPool)) return;\n todoPool.push(prop, currentIndex, method, args);\n };\n }\n }));\n }\n return obj[prop];\n },\n set(obj, prop, value) {\n const result = Reflect.set(obj, prop, value);\n const isRealRef = typeof prop === 'string' && !prop.startsWith('$') && value?.__isShadow !== true;\n\n if (isRealRef && parentComRefs?.current) {\n try { parentComRefs.current[prop] = value; } catch {}\n }\n return result;\n },\n deleteProperty(obj, prop) {\n const result = Reflect.deleteProperty(obj, prop);\n const isRealRef = typeof prop === 'string' && !prop.startsWith('$');\n\n if (isRealRef && parentComRefs?.current) {\n try { delete parentComRefs.current[prop]; } catch {}\n }\n return result;\n }\n });\n}\n\n/** \n * 组件输入绑定 Hook:\n * 1. 注册输入执行器\n * 2. 自动重放缓冲指令(精准索引匹配)\n * 3. 生命周期自动化:卸载时自动注销引用渗透路径\n */\nexport function useBindInputs(scope: any, id: string, initialHandlers?: Record<string, any>) {\n const handlersRef = useRef<Record<string, any>>({ ...initialHandlers });\n const { todoPool } = useAppContext();\n const parentSlot = useParentSlot();\n const index = parentSlot?.params?.inputValues?.index ?? 0;\n\n useEffect(() => {\n return () => {\n if (scope?.current) {\n delete scope.current[id];\n }\n };\n }, [scope, id]);\n\n return useMemo(() => {\n const proxy = new Proxy({}, {\n get: (target, pin: string) => {\n if (pin === '__isShadow') return false;\n if (pin === 'toJSON') return () => target;\n\n return (arg: any, ...args: any[]) => {\n if (typeof arg === 'function') {\n handlersRef.current[pin] = arg;\n\n // 处理指令重放\n const pendingArgs = todoPool?.pop(id, index, pin);\n if (pendingArgs) {\n if (pin === '_setData') {\n arg(...pendingArgs);\n } else {\n createReactiveInputHandler({ input: arg, value: pendingArgs[0], rels: {}, title: id });\n }\n }\n } else {\n const handler = handlersRef.current[pin];\n if (typeof handler === 'function') {\n return pin === '_setData' \n ? handler(arg, ...args) \n : createReactiveInputHandler({ input: handler, value: arg, rels: {}, title: id });\n }\n }\n };\n }\n });\n\n if (scope?.current) scope.current[id] = proxy;\n if (initialHandlers) {\n Object.keys(initialHandlers).forEach(pin => (proxy as any)[pin](initialHandlers[pin]));\n }\n\n return proxy;\n }, [scope, id, todoPool, index]);\n}\n\n/** 组件事件绑定 Hook */\nexport function useBindEvents(props: any, context?: { id: string, name: string, parentSlot?: any }) {\n return useMemo(() => {\n const events: Record<string, any> = {};\n\n Object.keys(props).forEach(key => {\n if (typeof props[key] === 'function') {\n const handler = props[key];\n const wrapped = (original: any) => {\n const value = context?.parentSlot?.params?.itemWrap \n ? { id: context.id, name: context.name, value: original } \n : original;\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]) return target[key];\n const fn: any = () => {};\n fn.getConnections = () => [];\n return fn;\n }\n return target[key];\n }\n });\n }, [props, context]);\n}\n"
5687
5691
  },
5688
5692
  {
5689
5693
  "path": "src/core/utils/index.ts",
5690
- "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"
5694
+ "content": "export * from './hooks';\nexport { TodoPool } from './pool';\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"
5691
5695
  },
5692
5696
  {
5693
5697
  "path": "src/core/utils/pageRouter.ts",
5694
5698
  "content": "// @ts-ignore 运行时由宿主项目提供 @tarojs/taro\nimport Taro from '@tarojs/taro';\nimport { Page } from '../mybricks';\n\n/**\n * Taro 路由驱动 (纯粹版)\n * 只负责处理真正的 Taro 页面跳转\n */\nclass TaroRouter {\n private paramsBackup: Record<string, any> = {};\n\n getParams(name: string) {\n const instance = Taro.getCurrentInstance();\n let params = instance.router?.params || {};\n \n // 备份参数,解决某些生命周期下 Taro 获取不到 params 的问题\n if (!params.data && this.paramsBackup[name]) {\n params = { data: this.paramsBackup[name] };\n }\n\n return { value: params };\n }\n\n push(name: string, { value }: any) {\n const url = `/pages/${name}/index`;\n const dataStr = value ? encodeURIComponent(JSON.stringify(value)) : '';\n \n if (dataStr) {\n this.paramsBackup[name] = dataStr;\n }\n\n Taro.navigateTo({\n url: `${url}${dataStr ? `?data=${dataStr}` : ''}`\n });\n }\n\n replace(name: string, { value }: any) {\n const url = `/pages/${name}/index`;\n const dataStr = value ? encodeURIComponent(JSON.stringify(value)) : '';\n \n if (dataStr) {\n this.paramsBackup[name] = dataStr;\n }\n\n Taro.redirectTo({\n url: `${url}${dataStr ? `?data=${dataStr}` : ''}`\n });\n }\n\n pop() {\n Taro.navigateBack();\n }\n}\n\nexport const router = new TaroRouter();\nexport const pageRouter = new Page(router);\n"
5695
5699
  },
5700
+ {
5701
+ "path": "src/core/utils/pool.ts",
5702
+ "content": "/**\n * 待执行指令池\n * 结构:Map<组件ID, Map<索引, Record<方法名, 参数数组>>>\n */\nexport class TodoPool {\n private pool = new Map<string, Map<number, Record<string, any[]>>>();\n\n /** 存:记录待执行指令 */\n push(id: string, index: number, method: string, args: any[]) {\n if (!this.pool.has(id)) {\n this.pool.set(id, new Map());\n }\n const instances = this.pool.get(id)!;\n if (!instances.has(index)) {\n instances.set(index, {});\n }\n instances.get(index)![method] = args;\n }\n\n /** 取:获取并物理删除指令 */\n pop(id: string, index: number, method: string): any[] | undefined {\n const instances = this.pool.get(id);\n if (!instances) return undefined;\n\n const todo = instances.get(index);\n if (todo && todo[method]) {\n const args = todo[method];\n delete todo[method];\n\n // 自动清理:如果当前索引下没指令了,删掉索引容器\n if (Object.keys(todo).length === 0) {\n instances.delete(index);\n }\n // 如果当前组件下没索引了,删掉整个 ID\n if (instances.size === 0) {\n this.pool.delete(id);\n }\n return args;\n }\n return undefined;\n }\n}\n"
5703
+ },
5696
5704
  {
5697
5705
  "path": "src/core/utils/PopupRenderer.tsx",
5698
5706
  "content": "import React from 'react';\nimport { View } from '@tarojs/components';\nimport { useAppContext } from './ComContext';\n\ninterface PopupRendererProps {\n popupMap: Record<string, any>;\n}\n\nexport const PopupRenderer: React.FC<PopupRendererProps> = ({ popupMap }) => {\n const { popupState } = useAppContext();\n\n const ActivePopup = popupState.visible && popupMap[popupState.name] \n ? popupMap[popupState.name] \n : null;\n\n if (!ActivePopup) return <View></View>;\n\n return (\n <View \n className=\"global-popup-container\" \n style={{ \n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 999999,\n pointerEvents: 'auto',\n }}\n >\n <View style={{ width: '100%', height: '100%' }}>\n <ActivePopup />\n </View>\n </View>\n );\n};\n\n"
@@ -5703,11 +5711,11 @@
5703
5711
  },
5704
5712
  {
5705
5713
  "path": "src/core/utils/slots.tsx",
5706
- "content": "import React, { useMemo, useRef } from \"react\";\nimport ComContext, { SlotProvider, useAppContext, useParentSlot } from \"./ComContext\";\nimport { createReactiveInputHandler } from \"../mybricks/createReactiveInputHandler\";\nimport { proxyRefs } from \"./hooks\";\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\n/**\n * 创建一个具有“向上渗透”和“隔离 Todo 池”能力的 comRefs 对象\n */\nfunction createPenetratingComRefs(parentComRefs: any, globalTodoPool?: Map<string, any>, index: number = 0) {\n const localTarget = { $inputs: {}, $outputs: {}, $index: index };\n return { current: proxyRefs(localTarget, parentComRefs, globalTodoPool) };\n}\n\nfunction SlotParamsBridge(props: {\n state: SlotState;\n params: any;\n render?: any;\n children?: React.ReactNode;\n}) {\n const parentSlot = useParentSlot<any>();\n const mergedParams =\n props.params?.inputValues === undefined && parentSlot?.params?.inputValues\n ? { ...(props.params || {}), inputValues: parentSlot.params.inputValues }\n : props.params;\n\n const SlotComp = props.render;\n const content = SlotComp ? <SlotComp {...(mergedParams || {})} /> : props.children ?? null;\n\n return <SlotProvider value={{ ...props.state, params: mergedParams }}>{content}</SlotProvider>;\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\nexport function useEnhancedSlots(rawSlots: any, id: string) {\n const { comRefs: parentComRefs, globalTodoInputs } = useAppContext();\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 if (rawScope === undefined || rawScope === null) {\n return (\n <SlotParamsBridge state={state} params={params} render={r} />\n );\n }\n\n const scopeId = `${id}.${slotKey}::${String(rawScope)}`;\n const index = params?.inputValues?.index ?? 0;\n const scopedComRefs =\n (state._scopedComRefs![scopeId] ||= createPenetratingComRefs(parentComRefs, globalTodoInputs, index));\n\n return (\n <ScopedComContextProvider comRefs={scopedComRefs} scopeId={scopeId}>\n <SlotParamsBridge state={state} params={params} render={r} />\n </ScopedComContextProvider>\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, parentComRefs, globalTodoInputs]);\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 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"
5714
+ "content": "import React, { useMemo, useRef } from \"react\";\nimport ComContext, { SlotProvider, useAppContext, useParentSlot } from \"./ComContext\";\nimport { createReactiveInputHandler } from \"../mybricks/createReactiveInputHandler\";\nimport { proxyRefs } from \"./hooks\";\nimport { TodoPool } from \"./pool\";\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\n/**\n * 创建一个具有“向上渗透”和“隔离 Todo 池”能力的 comRefs 对象\n */\nfunction createPenetratingComRefs(parentComRefs: any, todoPool?: TodoPool, index: number = 0) {\n const localTarget = { $inputs: {}, $outputs: {}, $index: index };\n return { current: proxyRefs(localTarget, parentComRefs, todoPool) };\n}\n\nfunction SlotParamsBridge(props: {\n state: SlotState;\n params: any;\n render?: any;\n children?: React.ReactNode;\n}) {\n const parentSlot = useParentSlot<any>();\n const mergedParams =\n props.params?.inputValues === undefined && parentSlot?.params?.inputValues\n ? { ...(props.params || {}), inputValues: parentSlot.params.inputValues }\n : props.params;\n\n const SlotComp = props.render;\n const content = SlotComp ? <SlotComp {...(mergedParams || {})} /> : props.children ?? null;\n\n return <SlotProvider value={{ ...props.state, params: mergedParams }}>{content}</SlotProvider>;\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\nexport function useEnhancedSlots(rawSlots: any, id: string) {\n const { comRefs: parentComRefs, todoPool } = useAppContext();\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?.inputValues?.index ?? params?.key; \n if (rawScope === undefined || rawScope === null) {\n return (\n <SlotParamsBridge state={state} params={params} render={r} />\n );\n }\n\n const scopeId = `${id}.${slotKey}::${String(rawScope)}`;\n const index = params?.inputValues?.index ?? 0;\n const scopedComRefs =\n (state._scopedComRefs![scopeId] ||= createPenetratingComRefs(parentComRefs, todoPool, index));\n\n return (\n <ScopedComContextProvider comRefs={scopedComRefs} scopeId={scopeId}>\n <SlotParamsBridge state={state} params={params} render={r} />\n </ScopedComContextProvider>\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, parentComRefs, todoPool]);\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 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"
5707
5715
  },
5708
5716
  {
5709
5717
  "path": "src/core/utils/useContext.ts",
5710
- "content": "import { useRef, useState, useMemo } from 'react'\nimport { proxyRefs } from './hooks'\n\nconst GLOBAL_TODO_POOL = new Map<string, any[]>();\n\nexport interface ComContextStore {\n comRefs: any;\n $vars: any;\n $fxs: 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 globalTodoInputs: Map<string, any[]>;\n}\n\nexport function useAppCreateContext(id: string): ComContextStore {\n const globalTodoInputs = useRef<Map<string, any[]>>(GLOBAL_TODO_POOL);\n const comRefs = useRef<any>(proxyRefs({ $inputs: {}, $outputs: {} }, undefined, globalTodoInputs.current));\n const $vars = useRef<any>({});\n const $fxs = useRef<any>({});\n\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,\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 $vars,\n $fxs,\n globalTodoInputs: globalTodoInputs.current,\n appContext,\n popupState,\n setPopupState\n }), [popupState]);\n}\n"
5718
+ "content": "import { useRef, useState, useMemo } from 'react'\nimport { proxyRefs } from './hooks'\nimport { TodoPool } from './pool'\n// @ts-ignore\nimport { request } from '@/common/request'\n\nexport interface ComContextStore {\n comRefs: any;\n $vars: any;\n $fxs: 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 todoPool: TodoPool;\n}\n\nexport function useAppCreateContext(id: string): ComContextStore {\n const todoPool = useMemo(() => new TodoPool(), []);\n const comRefs = useRef<any>(proxyRefs({ $inputs: {}, $outputs: {} }, undefined, todoPool));\n const $vars = useRef<any>({});\n const $fxs = useRef<any>({});\n\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,\n },\n runtime: {\n debug: false,\n },\n env: {\n runtime: true,\n request: (connector: any, params: any, config: any) => request(connector, params, config, { $vars }),\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 $vars,\n $fxs,\n todoPool,\n appContext,\n popupState,\n setPopupState\n }), [popupState]);\n}\n"
5711
5719
  },
5712
5720
  {
5713
5721
  "path": "src/core/utils/with.tsx",
@@ -64,7 +64,7 @@ export interface GeneratedFile {
64
64
  /** 当前页面/弹窗内用到的 JS 计算组件(用于生成 index.jsModules.ts) */
65
65
  jsModules?: import("./utils/context/collectJSModules").JSModule[];
66
66
  importManager: ImportManager;
67
- type: "normal" | "popup" | "module" | "global" | "extension-config" | "extension-api" | "extension-bus" | "abstractEventTypeDef" | "fx" | "api" | "extension-event" | "jsModulesRuntime" | "tabBarConfig" | "customTabBar";
67
+ type: "normal" | "popup" | "module" | "global" | "extension-config" | "extension-api" | "extension-bus" | "abstractEventTypeDef" | "fx" | "api" | "connector-api" | "extension-event" | "jsModulesRuntime" | "tabBarConfig" | "customTabBar";
68
68
  meta?: ReturnType<typeof toCode>["scenes"][0]["scene"];
69
69
  name: string;
70
70
  tabBarConfig?: string;
@@ -15,7 +15,7 @@ import { replaceBase64InText } from "./utils/config/content";
15
15
 
16
16
  // 工具函数
17
17
  import { buildFrameMap } from "./utils/context/buildFrameMap";
18
- import { buildSceneMap, buildEventsMap, createGetSceneById, createGetExtensionEventById, createGetFrameById } from "./utils/context/buildContext";
18
+ import { buildSceneMap, buildEventsMap, buildConnectorMap, createGetSceneById, createGetExtensionEventById, createGetFrameById } from "./utils/context/buildContext";
19
19
  import { createJSModulesCollector } from "./utils/context/collectJSModules";
20
20
  import { buildGlobalVarTypeDef, buildDefaultFxsMap } from "./utils/context/buildGlobalData";
21
21
  import { buildFinalResults } from "./utils/builder/buildResult";
@@ -63,6 +63,7 @@ var getCode = function getCode(params, config) {
63
63
  var eventsMap = buildEventsMap(tojson.frames);
64
64
  var getSceneById = createGetSceneById(sceneMap);
65
65
  var getExtensionEventById = createGetExtensionEventById(eventsMap);
66
+ var connectorMap = buildConnectorMap(tojson.plugins);
66
67
 
67
68
  // ========== 第二步:处理扩展事件 ==========
68
69
  files.push.apply(files, _toConsumableArray(handleExtension({
@@ -224,6 +225,7 @@ var getCode = function getCode(params, config) {
224
225
  var finalResultData = buildFinalResults({
225
226
  abstractEventTypeDefMap: abstractEventTypeDefMap,
226
227
  jsModulesMap: jsModulesCollector.getMap(),
228
+ connectorMap: connectorMap,
227
229
  globalTabBarConfig: pageConfigHandler.getTabBarConfig(),
228
230
  tabBarImageFiles: pageConfigHandler.getTabBarImageFiles(),
229
231
  customTabBarFileContent: pageConfigHandler.getCustomTabBarFileContent(),
@@ -7,6 +7,7 @@ import type { JSModulesMap } from "../context/collectJSModules";
7
7
  interface BuildResultParams {
8
8
  abstractEventTypeDefMap: Record<string, any>;
9
9
  jsModulesMap: JSModulesMap;
10
+ connectorMap: any;
10
11
  globalTabBarConfig: string | null;
11
12
  tabBarImageFiles: any[];
12
13
  popupIds: string[];
@@ -12,6 +12,7 @@ import { genJSModulesRuntime } from "../logic/genJSModules";
12
12
  export var buildFinalResults = function buildFinalResults(params) {
13
13
  var abstractEventTypeDefMap = params.abstractEventTypeDefMap,
14
14
  jsModulesMap = params.jsModulesMap,
15
+ connectorMap = params.connectorMap,
15
16
  globalTabBarConfig = params.globalTabBarConfig,
16
17
  tabBarImageFiles = params.tabBarImageFiles,
17
18
  popupIds = params.popupIds,
@@ -37,6 +38,16 @@ export var buildFinalResults = function buildFinalResults(params) {
37
38
  });
38
39
  }
39
40
 
41
+ // 生成 API 定义
42
+ if (connectorMap) {
43
+ files.push({
44
+ type: "connector-api",
45
+ content: generateApi(connectorMap),
46
+ importManager: new ImportManager(config),
47
+ name: "api"
48
+ });
49
+ }
50
+
40
51
  // 生成弹窗汇总文件 (popup.ts)
41
52
  if (popupIds.length > 0) {
42
53
  var registryContent = "";
@@ -77,4 +88,33 @@ export var buildFinalResults = function buildFinalResults(params) {
77
88
  files: files,
78
89
  tabBarImageFiles: tabBarImageFiles
79
90
  };
80
- };
91
+ };
92
+
93
+ /**
94
+ * 生成 API 定义代码
95
+ */
96
+ function generateApi(connectorMap) {
97
+ var connectors = connectorMap.connectors,
98
+ config = connectorMap.config;
99
+ var code = "/* eslint-disable @typescript-eslint/no-explicit-any */\n\n";
100
+ code += "export const api: Record<string, any> = {\n";
101
+ connectors.forEach(function (conn) {
102
+ code += " '".concat(conn.id, "': {\n");
103
+ code += " type: '".concat(conn.type, "',\n");
104
+ code += " input: ".concat(conn.input || 'function _RT_(params) { return params; }', ",\n");
105
+ code += " output: ".concat(conn.output || 'function _RT_(result) { return result; }', ",\n");
106
+ code += " method: '".concat(conn.method, "',\n");
107
+ code += " path: '".concat(conn.path, "',\n");
108
+ code += " globalMock: ".concat(conn.globalMock || false, ",\n");
109
+ code += " markList: ".concat(JSON.stringify(conn.markList || []), "\n");
110
+ code += " },\n";
111
+ });
112
+ code += "};\n\n";
113
+ code += "export const baseConfig = {\n";
114
+ code += " globalParamsFn: ".concat(config.paramsFn || 'function _RT_(params) { return params; }', ",\n");
115
+ code += " globalResultFn: ".concat(config.resultFn || 'function _RT_(response) { return response; }', ",\n");
116
+ code += " globalErrorResultFn: ".concat(config.errorResultFn || 'function _RT_(error) { throw error; }', ",\n");
117
+ code += " globalMock: ".concat(config.globalMock || false, "\n");
118
+ code += "};\n";
119
+ return code;
120
+ }
@@ -10,6 +10,13 @@ export declare const buildSceneMap: (scenes: any[]) => any;
10
10
  * 构建扩展事件映射表
11
11
  */
12
12
  export declare const buildEventsMap: (frames: any[]) => any;
13
+ /**
14
+ * 构建连接器映射表
15
+ */
16
+ export declare const buildConnectorMap: (plugins: any) => {
17
+ connectors: any;
18
+ config: any;
19
+ };
13
20
  /**
14
21
  * 创建场景查询函数
15
22
  */
@@ -25,6 +25,18 @@ export var buildEventsMap = function buildEventsMap(frames) {
25
25
  }, {});
26
26
  };
27
27
 
28
+ /**
29
+ * 构建连接器映射表
30
+ */
31
+ export var buildConnectorMap = function buildConnectorMap(plugins) {
32
+ var servicePlugin = plugins === null || plugins === void 0 ? void 0 : plugins["@mybricks/plugins/service"];
33
+ if (!servicePlugin) return null;
34
+ return {
35
+ connectors: servicePlugin.connectors || [],
36
+ config: servicePlugin.config || {}
37
+ };
38
+ };
39
+
28
40
  /**
29
41
  * 创建场景查询函数
30
42
  */
@@ -58,7 +58,8 @@ export var RenderManager = /*#__PURE__*/function () {
58
58
  // render 函数内的事件处理代码可能会用到 appContext(例如 jsModules.xxx(..., appContext))
59
59
  // outputs 统一从 comRefs.current.$outputs 读取(不再通过 context.outputs 透出)
60
60
  code += "".concat(indent).concat(indent2, "const { comRefs, $vars, $fxs, appContext } = useAppContext();\n");
61
- code += "".concat(indent).concat(indent2, "const outputs = comRefs.current.$outputs;\n");
61
+ // code += `${indent}${indent2}const outputs = comRefs.current.$outputs;\n`;
62
+
62
63
  if (logicCode) {
63
64
  code += logicCode.split("\n").map(function (line) {
64
65
  return "".concat(indent).concat(line);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mybricks/to-code-taro",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "description": "To code for Taro",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"file":"abstractEventTypeDef.d.ts","sourceRoot":"","sources":["abstractEventTypeDef.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGrD,KAAK,uBAAuB,GAAG,MAAM,CACnC,MAAM,EACN;IACE,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACzB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KAC7B,CAAC;CACH,CACF,CAAC;AAEF,QAAA,MAAM,oBAAoB,4BACC,uBAAuB,UACxC,gBAAgB,WA6EzB,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"generateTaroTempalteJson.d.ts","sourceRoot":"","sources":["generateTaroTempalteJson.ts"],"names":[],"mappings":"AAGA,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAKD;;;GAGG;AACH,QAAA,MAAM,wBAAwB,iBAAiB,MAAM,KAAkB,YAqFtE,CAAC;AAEF,eAAe,wBAAwB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"appConfig.d.ts","sourceRoot":"","sources":["appConfig.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE;QACL,EAAE,EAAE,MAAM,CAAC;KACZ,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,aAAa,EAAE,QAAQ,EACvB,WAAW,EAAE,YAAY,EAAE,EAC3B,KAAK,EAAE,YAAY,EAAE,GACpB,IAAI,CAuBN"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"fileNode.d.ts","sourceRoot":"","sources":["fileNode.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAW9E;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,CAaxE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"pageImages.d.ts","sourceRoot":"","sources":["pageImages.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,QAAQ,EACnB,UAAU,EAAE,aAAa,EAAE,GAC1B,IAAI,CAON"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"tabBarImages.d.ts","sourceRoot":"","sources":["tabBarImages.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,QAAQ,EACnB,UAAU,EAAE,aAAa,EAAE,GAC1B,IAAI,CAON"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"handleExtension.d.ts","sourceRoot":"","sources":["handleExtension.ts"],"names":[],"mappings":"AACA;;GAEG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEpE,UAAU,qBAAqB;IAC7B,MAAM,EAAE,GAAG,CAAC;IACZ,eAAe,EAAE,GAAG,EAAE,CAAC;CACxB;AAED,QAAA,MAAM,eAAe,WACX,qBAAqB,UACrB,gBAAgB,KACvB,aAAa,EAsEf,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"handleModule.d.ts","sourceRoot":"","sources":["handleModule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,aAAa,EAAiG,MAAM,SAAS,CAAC;AAGvI,KAAK,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAC;AAE7D,UAAU,kBAAmB,SAAQ,UAAU;IAC7C,yBAAyB,EAAE,CAAC,OAAO,aAAa,CAAC,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,CAAC;IAC5E,WAAW,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC,KAAK,IAAI,CAAC;IAC9E,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,QAAA,MAAM,YAAY,WAAY,MAAM,UAAU,kBAAkB;;;CAqG/D,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AACxF,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,qCAAqC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"processComEvents.d.ts","sourceRoot":"","sources":["processComEvents.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,gBAAgB,QACtB,GAAG,UACA,eAAe;kBAET,MAAM;mBACL,OAAO,MAAM,EAAE,GAAG,CAAC;iBACrB,OAAO,MAAM,EAAE,GAAG,CAAC;CA8HjC,CAAC"}