@mybricks/to-code-taro 1.1.5 → 1.1.7
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.
- package/dist/cjs/core/mybricks/Subject.js +9 -5
- package/dist/cjs/core/mybricks/createJSHandle.js +43 -3
- package/dist/cjs/core/utils/comRefResolver.js +112 -0
- package/dist/cjs/core/utils/event.js +53 -0
- package/dist/cjs/core/utils/hooks.js +71 -29
- package/dist/cjs/core/utils/index.js +3 -0
- package/dist/cjs/core/utils/pageRouter.js +34 -11
- package/dist/cjs/core/utils/slots.js +55 -9
- package/dist/cjs/core/utils/tabbar.js +56 -0
- package/dist/cjs/core/utils/useContext.js +42 -2
- package/dist/cjs/core/utils/with.js +9 -34
- package/dist/cjs/generate/generateTaroProjectJson.js +3 -18
- package/dist/cjs/generate/utils/appConfig.d.ts +1 -1
- package/dist/cjs/generate/utils/appConfig.js +22 -12
- package/dist/cjs/generate/utils/commonDir.js +9 -0
- package/dist/cjs/generate/utils/customTabBar.d.ts +11 -0
- package/dist/cjs/generate/utils/customTabBar.js +73 -0
- package/dist/cjs/generate/utils/fileNode.d.ts +4 -0
- package/dist/cjs/generate/utils/fileNode.js +12 -2
- package/dist/cjs/handleCom.js +15 -16
- package/dist/cjs/handleGlobal.d.ts +1 -1
- package/dist/cjs/handleGlobal.js +6 -0
- package/dist/cjs/handleSlot.js +5 -10
- package/dist/cjs/processors/processScene.js +13 -1
- package/dist/cjs/processors/processSceneLogic.js +2 -6
- package/dist/cjs/taro-template.json +364 -66
- package/dist/cjs/toCodeTaro.d.ts +1 -2
- package/dist/cjs/utils/builder/buildResult.js +1 -2
- package/dist/cjs/utils/common/ImportManager.d.ts +7 -0
- package/dist/cjs/utils/common/ImportManager.js +19 -1
- package/dist/cjs/utils/logic/genJSModules.js +2 -2
- package/dist/cjs/utils/logic/handleProcess.js +59 -13
- package/dist/cjs/utils/templates/index.js +1 -1
- package/dist/cjs/utils/templates/renderManager.js +5 -5
- package/dist/cjs/utils/templates/scene.js +4 -4
- package/dist/esm/core/mybricks/Subject.js +11 -5
- package/dist/esm/core/mybricks/createJSHandle.js +55 -5
- package/dist/esm/core/utils/comRefResolver.js +134 -0
- package/dist/esm/core/utils/event.js +32 -0
- package/dist/esm/core/utils/hooks.js +109 -39
- package/dist/esm/core/utils/index.js +1 -0
- package/dist/esm/core/utils/pageRouter.js +56 -13
- package/dist/esm/core/utils/slots.js +78 -12
- package/dist/esm/core/utils/tabbar.js +47 -0
- package/dist/esm/core/utils/useContext.js +42 -2
- package/dist/esm/core/utils/with.js +19 -53
- package/dist/esm/generate/generateTaroProjectJson.js +2 -20
- package/dist/esm/generate/utils/appConfig.d.ts +1 -1
- package/dist/esm/generate/utils/appConfig.js +28 -9
- package/dist/esm/generate/utils/commonDir.js +13 -0
- package/dist/esm/generate/utils/customTabBar.d.ts +11 -0
- package/dist/esm/generate/utils/customTabBar.js +52 -0
- package/dist/esm/generate/utils/fileNode.d.ts +4 -0
- package/dist/esm/generate/utils/fileNode.js +13 -0
- package/dist/esm/handleCom.js +24 -21
- package/dist/esm/handleGlobal.d.ts +1 -1
- package/dist/esm/handleGlobal.js +6 -1
- package/dist/esm/handleSlot.js +7 -12
- package/dist/esm/processors/processScene.js +23 -3
- package/dist/esm/processors/processSceneLogic.js +3 -5
- package/dist/esm/taro-template.json +364 -66
- package/dist/esm/toCodeTaro.d.ts +1 -2
- package/dist/esm/toCodeTaro.js +1 -1
- package/dist/esm/utils/builder/buildResult.js +1 -2
- package/dist/esm/utils/common/ImportManager.d.ts +7 -0
- package/dist/esm/utils/common/ImportManager.js +42 -14
- package/dist/esm/utils/logic/genJSModules.js +2 -2
- package/dist/esm/utils/logic/handleProcess.js +73 -12
- package/dist/esm/utils/templates/index.js +1 -1
- package/dist/esm/utils/templates/renderManager.js +4 -7
- package/dist/esm/utils/templates/scene.js +2 -2
- package/package.json +1 -1
- package/dist/cjs/core/comlib/Index.js +0 -114
- package/dist/cjs/core/comlib/_AesEncode.js +0 -115
- package/dist/cjs/core/comlib/_BackTo.js +0 -80
- package/dist/cjs/core/comlib/_CallPhone.js +0 -58
- package/dist/cjs/core/comlib/_ChooseFile.js +0 -103
- package/dist/cjs/core/comlib/_ChooseMedia.js +0 -70
- package/dist/cjs/core/comlib/_Connector.js +0 -79
- package/dist/cjs/core/comlib/_ConnectorGlobalHeaders.js +0 -79
- package/dist/cjs/core/comlib/_Format.js +0 -123
- package/dist/cjs/core/comlib/_GetLocation.js +0 -60
- package/dist/cjs/core/comlib/_GetStorage.js +0 -68
- package/dist/cjs/core/comlib/_GetSystemInfo.js +0 -62
- package/dist/cjs/core/comlib/_Modal.js +0 -68
- package/dist/cjs/core/comlib/_OpenCamera.js +0 -73
- package/dist/cjs/core/comlib/_OpenPetalMap.js +0 -49
- package/dist/cjs/core/comlib/_OpenUrl.js +0 -62
- package/dist/cjs/core/comlib/_RemoveStorage.js +0 -68
- package/dist/cjs/core/comlib/_Router.js +0 -100
- package/dist/cjs/core/comlib/_ScanQrcode.js +0 -59
- package/dist/cjs/core/comlib/_SetStorage.js +0 -67
- package/dist/cjs/core/comlib/_Share.js +0 -58
- package/dist/cjs/core/comlib/_ShowToast.js +0 -69
- package/dist/cjs/core/comlib/_TextToSpeech.js +0 -120
- package/dist/cjs/core/comlib/_TimerDebounce.js +0 -72
- package/dist/cjs/core/comlib/_TimerDelay.js +0 -88
- package/dist/cjs/core/comlib/_TimerThrottle.js +0 -75
- package/dist/cjs/core/comlib/_Vibrate.js +0 -60
- package/dist/esm/core/comlib/Index.js +0 -39
- package/dist/esm/core/comlib/_AesEncode.js +0 -85
- package/dist/esm/core/comlib/_BackTo.js +0 -66
- package/dist/esm/core/comlib/_CallPhone.js +0 -30
- package/dist/esm/core/comlib/_ChooseFile.js +0 -81
- package/dist/esm/core/comlib/_ChooseMedia.js +0 -38
- package/dist/esm/core/comlib/_Connector.js +0 -77
- package/dist/esm/core/comlib/_ConnectorGlobalHeaders.js +0 -56
- package/dist/esm/core/comlib/_Format.js +0 -102
- package/dist/esm/core/comlib/_GetLocation.js +0 -26
- package/dist/esm/core/comlib/_GetStorage.js +0 -44
- package/dist/esm/core/comlib/_GetSystemInfo.js +0 -32
- package/dist/esm/core/comlib/_Modal.js +0 -51
- package/dist/esm/core/comlib/_OpenCamera.js +0 -44
- package/dist/esm/core/comlib/_OpenPetalMap.js +0 -28
- package/dist/esm/core/comlib/_OpenUrl.js +0 -36
- package/dist/esm/core/comlib/_RemoveStorage.js +0 -42
- package/dist/esm/core/comlib/_Router.js +0 -113
- package/dist/esm/core/comlib/_ScanQrcode.js +0 -26
- package/dist/esm/core/comlib/_SetStorage.js +0 -40
- package/dist/esm/core/comlib/_Share.js +0 -28
- package/dist/esm/core/comlib/_ShowToast.js +0 -45
- package/dist/esm/core/comlib/_TextToSpeech.js +0 -117
- package/dist/esm/core/comlib/_TimerDebounce.js +0 -66
- package/dist/esm/core/comlib/_TimerDelay.js +0 -79
- package/dist/esm/core/comlib/_TimerThrottle.js +0 -69
- package/dist/esm/core/comlib/_Vibrate.js +0 -34
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
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
|
|
34
|
+
"content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport Taro from '@tarojs/taro';\n// @ts-ignore\nimport { api, baseConfig } from './api';\n// @ts-ignore\nimport rootConfig from './rootConfig';\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 let headers = def.headers || {};\n\n const url = path;\n const extraParams = {\n globalVars: appContext?.$vars?.current\n };\n\n // 设置全局请求头逻辑组件\n let mybricksGlobalHeaders = Taro.getStorageSync(\n \"_MYBRICKS_GLOBAL_HEADERS_\"\n );\n if (mybricksGlobalHeaders) {\n headers = {\n ...mybricksGlobalHeaders,\n ...headers,\n };\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 /**\n * 如果 url 不以 http 开头,添加默认域名\n */\n const defaultCallServiceHost = rootConfig?.status?.defaultCallServiceHost\n if (\n !/^(http|https):\\/\\/.*/.test(requestConfig.url) &&\n defaultCallServiceHost\n ) {\n requestConfig.url = `${defaultCallServiceHost}${requestConfig.url}`;\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 reject(err?.errMsg || \"连接器执行失败\");\n },\n });\n } catch (error: any) {\n console.error('连接器执行失败:', error);\n reject(error?.message || '连接器执行失败');\n }\n });\n}\n"
|
|
35
35
|
}
|
|
36
36
|
]
|
|
37
37
|
},
|
|
@@ -163,7 +163,7 @@
|
|
|
163
163
|
},
|
|
164
164
|
{
|
|
165
165
|
"path": "src/components/anchor/runtime.tsx",
|
|
166
|
-
"content": "import React, { useCallback, useEffect, useRef } from \"react\";\nimport { View } from \"@tarojs/components\";\nimport * as Taro from \"@tarojs/taro\";\nimport css from \"./style.less\";\nimport cx from \"classnames\";\nimport { isH5 } from \"../utils/env\";\n\nexport default function ({ id, env, data, inputs, outputs }) {\n const io = Taro.createIntersectionObserver(Taro.getCurrentInstance().page);\n\n const connect = useCallback(() => {\n io.relativeToViewport().observe(`#${id} .mybricks-anchor`, (res) => {\n if (res.intersectionRatio > 0) {\n outputs[\"onExposure\"]?.(res);\n } else {\n outputs[\"onUnexposure\"]?.(res);\n }\n });\n }, []);\n\n useEffect(() => {\n Taro.nextTick(() => {\n connect();\n });\n\n inputs[\"scrollTo\"](() => {\n env?.rootScroll.scrollTo?.({\n id: `aaaa`,\n });\n setTimeout(()=>{\n env?.rootScroll.scrollTo?.({\n id: `#${id}`,\n });\n },50)\n\n });\n\n return () => {\n io.disconnect();\n };\n });\n\n return (\n <View style={{ position: \"relative\" }}>\n <View className={cx(css.anchor, \"mybricks-anchor\")}></View>\n </View>\n );\n}\n"
|
|
166
|
+
"content": "import React, { useCallback, useEffect, useRef } from \"react\";\nimport { View } from \"@tarojs/components\";\nimport * as Taro from \"@tarojs/taro\";\nimport css from \"./style.less\";\nimport cx from \"classnames\";\nimport { isH5 } from \"../utils/env\";\n\nexport default function ({ id, env, data, inputs, outputs }) {\n const io = Taro.createIntersectionObserver(Taro.getCurrentInstance().page);\n\n const connect = useCallback(() => {\n io.relativeToViewport().observe(`#${id} .mybricks-anchor`, (res) => {\n if (res.intersectionRatio > 0) {\n outputs[\"onExposure\"]?.(res);\n } else {\n outputs[\"onUnexposure\"]?.(res);\n }\n });\n }, [io, id, outputs]);\n\n useEffect(() => {\n Taro.nextTick(() => {\n connect();\n });\n\n inputs[\"scrollTo\"](() => {\n env?.rootScroll.scrollTo?.({\n id: `aaaa`,\n });\n setTimeout(()=>{\n env?.rootScroll.scrollTo?.({\n id: `#${id}`,\n });\n },50)\n\n });\n\n return () => {\n io.disconnect();\n };\n });\n\n return (\n <View style={{ position: \"relative\" }}>\n <View className={cx(css.anchor, \"mybricks-anchor\")}></View>\n </View>\n );\n}\n"
|
|
167
167
|
},
|
|
168
168
|
{
|
|
169
169
|
"path": "src/components/anchor/style.less",
|
|
@@ -2893,7 +2893,11 @@
|
|
|
2893
2893
|
},
|
|
2894
2894
|
{
|
|
2895
2895
|
"path": "src/components/formRate/runtime.tsx",
|
|
2896
|
-
"content": "import React, { useState, useCallback, useMemo, useEffect } from \"react\";\nimport { View } from \"@tarojs/components\";\nimport cx from \"classnames\";\nimport { isObject, isString, isNumber, isEmpty } from \"./../utils/core/type\";\nimport { Rate, Field } from \"brickd-mobile\";\n\nexport default function (props) {\n const { env, data, inputs, outputs, slots, parentSlot } = props;\n const [value, setValue] = useState(\"\");\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[\"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\"]?.((val, outputRels) => {\n data.disabled = !!val;\n outputRels[\"setDisabledComplete\"]?.(data.disabled);\n });\n }, []);\n\n const onChange = useCallback((value) => {\n setValue(value);\n parentSlot?._inputs[\"onChange\"]?.({\n id: props.id,\n name: props.name,\n value,\n });\n outputs[\"onChange\"](value);\n }, []);\n\n return (\n // <Field label={data.label} name={data.name}>\n <Rate\n
|
|
2896
|
+
"content": "import React, { useState, useCallback, useMemo, useEffect } from \"react\";\nimport { View } from \"@tarojs/components\";\nimport cx from \"classnames\";\nimport { isObject, isString, isNumber, isEmpty } from \"./../utils/core/type\";\nimport { Rate, Field } from \"brickd-mobile\";\nimport css from \"./style.less\";\n\nexport default function (props) {\n const { env, data, inputs, outputs, slots, parentSlot } = props;\n const [value, setValue] = useState(\"\");\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[\"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\"]?.((val, outputRels) => {\n data.disabled = !!val;\n outputRels[\"setDisabledComplete\"]?.(data.disabled);\n });\n }, []);\n\n const onChange = useCallback((value) => {\n setValue(value);\n parentSlot?._inputs[\"onChange\"]?.({\n id: props.id,\n name: props.name,\n value,\n });\n outputs[\"onChange\"](value);\n }, []);\n\n return (\n // <Field label={data.label} name={data.name}>\n <View className={css.rate}>\n <Rate\n value={value}\n onChange={onChange}\n count={data.count}\n allowHalf={data.allowHalf}\n disabled={data.disabled}\n />\n </View>\n // </Field>\n );\n}\n"
|
|
2897
|
+
},
|
|
2898
|
+
{
|
|
2899
|
+
"path": "src/components/formRate/style.less",
|
|
2900
|
+
"content": ".rate {\n :global {\n .taroify-rate__icon--half {\n position: absolute;\n }\n }\n}\n"
|
|
2897
2901
|
}
|
|
2898
2902
|
]
|
|
2899
2903
|
},
|
|
@@ -3075,7 +3079,7 @@
|
|
|
3075
3079
|
},
|
|
3076
3080
|
{
|
|
3077
3081
|
"path": "src/components/formTextarea/style.less",
|
|
3078
|
-
"content": ".textarea {\n}\n\n:global {\n .taroify-textarea__wrapper {\n display: flex;\n flex-direction: column;\n\n .taroify-textarea {\n min-height: 48px;\n flex: 1;\n }\n\n .taroify-textarea__placeholder {\n line-height: 24px;\n }\n }\n}\n"
|
|
3082
|
+
"content": ".textarea {\n}\n\n:global {\n .taroify-textarea__wrapper {\n display: flex;\n flex-direction: column;\n\n .taroify-textarea {\n min-height: 48px;\n // flex: 1;\n height: auto;\n }\n\n .taroify-textarea__placeholder {\n line-height: 24px;\n }\n }\n}\n"
|
|
3079
3083
|
}
|
|
3080
3084
|
]
|
|
3081
3085
|
},
|
|
@@ -4383,7 +4387,7 @@
|
|
|
4383
4387
|
},
|
|
4384
4388
|
{
|
|
4385
4389
|
"path": "src/components/table/style.less",
|
|
4386
|
-
"content": ".table-wrapper {\n width: 100%;\n height: 100%;\n overflow: hidden;\n \n .table-track {\n width: 100%;\n height: 100%;\n overflow: auto;\n -webkit-overflow-scrolling: touch; /* 保持惯性滚动 */\n overscroll-behavior: none; /* 防止滚动到边缘时的反弹效果 */\n &::-webkit-scrollbar {\n display: none;\n }\n }\n}\n\n.table {\n display: inline-flex;\n flex-direction: column;\n min-width: 100%;\n background: #ffffff;\n}\n\n.table.bordered {\n border: 1px solid rgba(5, 5, 5, 0.06);\n border-bottom: none;\n\n .thead.tr {\n .td {\n &::before {\n display: none;\n }\n }\n }\n\n .tr {\n .td {\n border-right: 1px solid rgba(5, 5, 5, 0.06);\n &:last-child {\n border-right: none;\n }\n }\n }\n}\n\n.placeholder {\n width: 100%;\n height: 100%;\n min-height: 60px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #f9f9f9;\n font-size: 12px;\n color: rgba(0, 0, 0, 0.85);\n}\n\n.loading {\n display: flex;\n align-items: center;\n justify-content: center;\n color: #5e5e5e;\n height: 60px;\n font-size: 13px;\n}\n"
|
|
4390
|
+
"content": ".table-wrapper {\n width: 100%;\n height: 100%;\n overflow: hidden;\n \n .table-track {\n width: 100%;\n height: 100%;\n overflow: auto;\n -webkit-overflow-scrolling: touch; /* 保持惯性滚动 */\n // overscroll-behavior: none; /* 防止滚动到边缘时的反弹效果 */\n &::-webkit-scrollbar {\n display: none;\n }\n }\n}\n\n.table {\n display: inline-flex;\n flex-direction: column;\n min-width: 100%;\n background: #ffffff;\n}\n\n.table.bordered {\n border: 1px solid rgba(5, 5, 5, 0.06);\n border-bottom: none;\n\n .thead.tr {\n .td {\n &::before {\n display: none;\n }\n }\n }\n\n .tr {\n .td {\n border-right: 1px solid rgba(5, 5, 5, 0.06);\n &:last-child {\n border-right: none;\n }\n }\n }\n}\n\n.placeholder {\n width: 100%;\n height: 100%;\n min-height: 60px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #f9f9f9;\n font-size: 12px;\n color: rgba(0, 0, 0, 0.85);\n}\n\n.loading {\n display: flex;\n align-items: center;\n justify-content: center;\n color: #5e5e5e;\n height: 60px;\n font-size: 13px;\n}\n"
|
|
4387
4391
|
}
|
|
4388
4392
|
]
|
|
4389
4393
|
},
|
|
@@ -5497,7 +5501,7 @@
|
|
|
5497
5501
|
},
|
|
5498
5502
|
{
|
|
5499
5503
|
"path": "src/components/index.ts",
|
|
5500
|
-
"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\";\nexport { default as ContainerWaterfall } from \"./containerWaterfall/runtime\";\nexport { 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\";\nexport { default as FormFileUploader } from \"./formFileUploader/runtime\";\nexport { default as FormEditor } from \"./formEditor/runtime\";\nexport { default as SearchBar } from \"./searchBar/runtime\";\nexport { default as SmsInput } from \"./smsInput/runtime\";\nexport { 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\";\nexport { 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\";\nexport { default as Calendar } from \"./calendar/runtime\";\nexport { default as Cascader } from \"./cascader/runtime\";\nexport { 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\";\nexport { default as Anchor } from \"./anchor/runtime\";\nexport { default as Support } from \"./support/runtime\";\n\n// 图表组件\nexport { default as ChartColumn } from \"./chart/chart-column/runtime\";\nexport { default as ChartLine } from \"./chart/chart-line/runtime\";\nexport { default as ChartPie } from \"./chart/chart-pie/runtime\";\nexport { default as ChartRadar } from \"./chart/chart-radar/runtime\";\nexport { default as ChartRingProgress } from \"./chart/chart-ringProgress/runtime\";\n"
|
|
5504
|
+
"content": "// 系统\nexport { default as SystemPage } from \"./system/systemPage/runtime\";\nexport { default as SystemWebview } from \"./system/systemWebview/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\";\nexport { default as ContainerWaterfall } from \"./containerWaterfall/runtime\";\nexport { 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\";\nexport { default as FormFileUploader } from \"./formFileUploader/runtime\";\nexport { default as FormEditor } from \"./formEditor/runtime\";\nexport { default as SearchBar } from \"./searchBar/runtime\";\nexport { default as SmsInput } from \"./smsInput/runtime\";\nexport { 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\";\nexport { 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\";\nexport { default as Calendar } from \"./calendar/runtime\";\nexport { default as Cascader } from \"./cascader/runtime\";\nexport { 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\";\nexport { default as Anchor } from \"./anchor/runtime\";\nexport { default as Support } from \"./support/runtime\";\n\n// 图表组件\nexport { default as ChartColumn } from \"./chart/chart-column/runtime\";\nexport { default as ChartLine } from \"./chart/chart-line/runtime\";\nexport { default as ChartPie } from \"./chart/chart-pie/runtime\";\nexport { default as ChartRadar } from \"./chart/chart-radar/runtime\";\nexport { default as ChartRingProgress } from \"./chart/chart-ringProgress/runtime\";\n"
|
|
5501
5505
|
}
|
|
5502
5506
|
]
|
|
5503
5507
|
},
|
|
@@ -5509,9 +5513,13 @@
|
|
|
5509
5513
|
"path": "src/core/comlib",
|
|
5510
5514
|
"content": null,
|
|
5511
5515
|
"children": [
|
|
5516
|
+
{
|
|
5517
|
+
"path": "src/core/comlib/_AesDecode.ts",
|
|
5518
|
+
"content": "import CryptoJS from 'crypto-js'\n\nexport type DataType = {\n key?: string\n iv?: string\n}\n\nexport interface Inputs {\n call?: (fn: (config: string) => void) => void\n}\n\nexport interface Outputs {\n result: (value?: string) => 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.call?.((val) => {\n try {\n //\n if (!val || !data.key || !data.iv) {\n outputs['result']('')\n return\n }\n\n // 密钥修复:超长截取/不足补0\n const fixedKey = CryptoJS.enc.Utf8.parse(\n data.key.padEnd(32, '0').slice(0, 32),\n )\n const fixedIv = CryptoJS.enc.Utf8.parse(\n data.iv.padEnd(16, '0').slice(0, 16),\n )\n\n // AES 解密\n const decrypted = CryptoJS.AES.decrypt(val, fixedKey, {\n iv: fixedIv,\n mode: CryptoJS.mode.CBC,\n padding: CryptoJS.pad.Pkcs7,\n })\n\n // 输出解密后的结果\n const decryptedText = decrypted.toString(CryptoJS.enc.Utf8)\n\n // 输出解密结果\n outputs['result'](decryptedText)\n } catch (error: any) {\n console.error('AES加密失败:', error)\n }\n })\n}\n"
|
|
5519
|
+
},
|
|
5512
5520
|
{
|
|
5513
5521
|
"path": "src/core/comlib/_AesEncode.ts",
|
|
5514
|
-
"content": "import CryptoJS from 'crypto-js'
|
|
5522
|
+
"content": "import CryptoJS from 'crypto-js'\n\nexport type DataType = {\n key?: string\n iv?: string\n}\n\nexport interface Inputs {\n call?: (fn: (config: string) => void) => void\n}\n\nexport interface Outputs {\n result: (value?: string) => 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.call?.((val) => {\n try {\n if (!val || !data.key || !data.iv) {\n outputs['result']('')\n return\n }\n\n // 密钥修复:超长截取/不足补0\n const fixedKey = CryptoJS.enc.Utf8.parse(\n data.key.padEnd(32, '0').slice(0, 32),\n )\n const fixedIv = CryptoJS.enc.Utf8.parse(\n data.iv.padEnd(16, '0').slice(0, 16),\n )\n\n // AES 加密\n const encrypted = CryptoJS.AES.encrypt(val, fixedKey, {\n iv: fixedIv,\n mode: CryptoJS.mode.CBC,\n padding: CryptoJS.pad.Pkcs7,\n })\n\n // 输出 Base64 编码的加密结果\n const encryptedBase64 = encrypted.ciphertext.toString(CryptoJS.enc.Base64)\n\n // 输出加密结果\n outputs['result'](encryptedBase64)\n } catch (error: any) {\n console.error('AES加密失败:', error)\n }\n })\n}\n"
|
|
5515
5523
|
},
|
|
5516
5524
|
{
|
|
5517
5525
|
"path": "src/core/comlib/_BackTo.ts",
|
|
@@ -5519,15 +5527,23 @@
|
|
|
5519
5527
|
},
|
|
5520
5528
|
{
|
|
5521
5529
|
"path": "src/core/comlib/_CallPhone.ts",
|
|
5522
|
-
"content": "import Taro from '@tarojs/taro'
|
|
5530
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {}\n\nexport interface Inputs {\n callPhone?: (fn: (config: string, relOutputs?: any) => void) => void\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void\n onFail: (value?: any) => void\n}\n\ninterface IOContext {\n inputs: Inputs\n outputs: Outputs\n}\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs\n const outputs: Outputs = context.outputs\n\n inputs.callPhone?.((val: string) => {\n try {\n const phoneNumber = String(val)\n\n if (!phoneNumber) {\n outputs.onFail?.('电话号码不能为空')\n return\n }\n\n Taro.makePhoneCall({\n phoneNumber,\n success: () => outputs.onSuccess?.(true),\n fail: ({ errMsg }: any) => outputs.onFail?.({ errMsg }),\n })\n } catch (error: any) {\n console.error('拨打电话失败:', error)\n outputs.onFail?.({\n errMsg: error?.message || '拨打电话失败',\n })\n }\n })\n}\n"
|
|
5523
5531
|
},
|
|
5524
5532
|
{
|
|
5525
|
-
"path": "src/core/comlib/
|
|
5526
|
-
"content": "import Taro from
|
|
5533
|
+
"path": "src/core/comlib/_ChooseAddress.ts",
|
|
5534
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {};\n\nexport interface Inputs {\n chooseAddress?: (fn: () => void) => void;\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void;\n onFail: (value?: any) => void;\n}\n\ninterface IOContext {\n inputs: Inputs;\n outputs: Outputs;\n}\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs;\n const outputs: Outputs = context.outputs;\n\n inputs.chooseAddress?.(() => {\n try {\n Taro.chooseAddress({\n success(res: any) {\n outputs[\"onSuccess\"](res);\n },\n fail(err: any) {\n outputs[\"onFail\"](err);\n },\n });\n } catch (error: any) {\n console.error(\"获取收货地址失败:\", error);\n outputs.onFail({\n errMsg: error?.message || \"获取收货地址失败\",\n });\n }\n });\n};\n"
|
|
5535
|
+
},
|
|
5536
|
+
{
|
|
5537
|
+
"path": "src/core/comlib/_ChooseLocation.ts",
|
|
5538
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {};\n\nexport type ValType = {\n latitude?: number;\n longitude?: number;\n};\n\nexport interface Inputs {\n open?: (fn: (val: ValType) => void) => void;\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void;\n onFail: (value?: any) => void;\n}\n\ninterface IOContext {\n inputs: Inputs;\n outputs: Outputs;\n}\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs;\n const outputs: Outputs = context.outputs;\n\n inputs.open?.((val) => {\n try {\n Taro.chooseLocation({\n latitude: val?.latitude,\n longitude: val?.longitude,\n success: (res: any) => {\n outputs[\"onSuccess\"]?.({\n name: res.name,\n address: res.address,\n latitude: res.latitude,\n longitude: res.longitude,\n });\n },\n fail: (err: any) => {\n outputs[\"onFail\"]?.(err);\n },\n });\n } catch (error: any) {\n console.error(\"地图选点失败:\", error);\n outputs.onFail(error?.message || \"地图选点失败\");\n }\n });\n};\n"
|
|
5527
5539
|
},
|
|
5528
5540
|
{
|
|
5529
5541
|
"path": "src/core/comlib/_ChooseMedia.ts",
|
|
5530
|
-
"content": "import Taro from '@tarojs/taro'
|
|
5542
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {\n mediaType?: ('image' | 'video')[]\n sourceType?: ('album' | 'camera')[]\n count?: number\n sizeType?: ('original' | 'compressed')[]\n maxDuration?: number\n camera?: 'back' | 'front'\n}\n\nexport interface Inputs {\n chooseMedia?: (fn: () => 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.chooseMedia?.(() => {\n try {\n let params = {\n count: data.count,\n mediaType: data.mediaType,\n sourceType: data.sourceType,\n maxDuration: data.maxDuration,\n sizeType: data.sizeType,\n camera: data.camera,\n }\n\n console.log('params', params)\n\n Taro.chooseMedia({\n ...params,\n success(res: any) {\n outputs['onSuccess'](res)\n },\n fail(err: any) {\n outputs['onFail'](err)\n },\n })\n } catch (error: any) {\n console.error('选择媒体失败:', error)\n outputs.onFail(error?.message || '选择媒体失败')\n }\n })\n}\n"
|
|
5543
|
+
},
|
|
5544
|
+
{
|
|
5545
|
+
"path": "src/core/comlib/_ChooseMessageFile.ts",
|
|
5546
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {\n SelectType?: 'all' | 'video' | 'image' | 'file' // 选择的文件类型\n SelectCount?: number // 选择的文件数量\n}\n\nexport interface Inputs {\n chooseFile?: (fn: () => void) => void\n}\n\nexport interface Outputs {\n onComplete: (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.chooseFile?.(() => {\n try {\n Taro.chooseMessageFile({\n count: data.SelectCount,\n type: data.SelectType,\n success: function (res: any) {\n outputs['onComplete']({\n ...res,\n })\n },\n })\n } catch (error: any) {\n console.error('文件选择失败:', error)\n }\n })\n}\n"
|
|
5531
5547
|
},
|
|
5532
5548
|
{
|
|
5533
5549
|
"path": "src/core/comlib/_Connector.ts",
|
|
@@ -5535,87 +5551,167 @@
|
|
|
5535
5551
|
},
|
|
5536
5552
|
{
|
|
5537
5553
|
"path": "src/core/comlib/_ConnectorGlobalHeaders.ts",
|
|
5538
|
-
"content": "
|
|
5554
|
+
"content": "import * as Taro from \"@tarojs/taro\";\n\nexport type DataType = {\n dynamic?: boolean;\n header?: Record<string, string>;\n};\n\nexport interface Inputs {\n call?: (fn: (config: DataType[\"header\"], relOutputs?: any) => void) => void;\n}\n\ninterface IOContext {\n data: DataType;\n inputs: Inputs;\n}\n\nexport default (context: IOContext) => {\n const data: DataType = context.data;\n const inputs: Inputs = context.inputs;\n\n inputs.call?.((obj, outputRels) => {\n try {\n if (data.dynamic == true || data.dynamic == void 0) {\n if (typeof obj === \"object\" && obj !== null && !Array.isArray(obj)) {\n Taro.setStorageSync(\"_MYBRICKS_GLOBAL_HEADERS_\", obj);\n outputRels[\"then\"](obj);\n }\n } else {\n if (\n typeof data.header === \"object\" &&\n data.header !== null &&\n !Array.isArray(data.header)\n ) {\n Taro.setStorageSync(\"_MYBRICKS_GLOBAL_HEADERS_\", data.header);\n outputRels[\"then\"](data.header);\n }\n }\n } catch (error: any) {\n console.error(\"设置全局请求头失败:\", error);\n }\n });\n};\n"
|
|
5539
5555
|
},
|
|
5540
5556
|
{
|
|
5541
5557
|
"path": "src/core/comlib/_Format.ts",
|
|
5542
|
-
"content": "
|
|
5558
|
+
"content": "import dayjs from \"dayjs\";\nimport { FormatType } from \"../tools/data-format\";\nimport { isUndef, isString, isNumber, isDate } from \"../tools/core\";\n\nexport type DataType = {\n formatData: {\n voidHandle: boolean;\n voidTo: string;\n formatterName: keyof typeof FormatType;\n values: Record<keyof typeof FormatType, any>;\n };\n};\n\nexport interface Inputs {\n call?: (fn: (config: any) => void) => void;\n}\n\nexport interface Outputs {\n success: (value?: any) => void;\n}\n\ninterface IOContext {\n data: DataType;\n inputs: Inputs;\n outputs: Outputs;\n}\n\nconst transfromData = (value, formatType, config) => {\n let result = value;\n if (formatType === FormatType.NONE) {\n return result;\n }\n\n if (formatType === FormatType.KEYMAP) {\n return config?.[result] ?? result;\n }\n\n if (\n formatType === FormatType.TIME_TEMPLATE ||\n formatType === FormatType.TIME_CUSTOM\n ) {\n return dayjs(value).format(config);\n }\n\n return result;\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?.[\"call\"]?.((inputValue) => {\n let resValue = inputValue;\n\n const { formatterName, values } = data.formatData ?? {};\n\n if (isUndef(inputValue) && data?.formatData?.voidHandle) {\n resValue = data?.formatData?.voidTo;\n outputs[\"success\"](resValue);\n return;\n }\n\n if (!isString(inputValue) && !isNumber(inputValue) && !isDate(inputValue)) {\n outputs[\"success\"](resValue);\n return;\n }\n\n resValue = transfromData(\n inputValue,\n formatterName,\n values?.[formatterName],\n );\n outputs[\"success\"](resValue);\n return;\n });\n};\n"
|
|
5559
|
+
},
|
|
5560
|
+
{
|
|
5561
|
+
"path": "src/core/comlib/_GenerateScheme.ts",
|
|
5562
|
+
"content": "export type DataType = {};\n\nexport interface Inputs {\n generate?: (fn: (config: any, relOutputs?: any) => void) => void;\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void;\n onFail: (value?: any) => void;\n}\n\ninterface IOContext {\n inputs: Inputs;\n outputs: Outputs;\n}\n\nexport default (context: IOContext) => {\n};\n"
|
|
5563
|
+
},
|
|
5564
|
+
{
|
|
5565
|
+
"path": "src/core/comlib/_GetAddress.ts",
|
|
5566
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {};\n\nexport type ValType = {\n latitude?: number;\n longitude?: number;\n};\n\nexport interface Inputs {\n open?: (fn: (val: ValType) => void) => void;\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void;\n onFail: (value?: any) => void;\n}\n\nexport interface Env {\n apiKey?: string;\n}\n\ninterface IOContext {\n env: Env;\n inputs: Inputs;\n outputs: Outputs;\n}\n\nexport default (context: IOContext) => {\n const env: Env = context.env;\n const inputs: Inputs = context.inputs;\n const outputs: Outputs = context.outputs;\n\n inputs.open?.((val) => {\n try {\n if (!val?.longitude || !val?.latitude) {\n outputs[\"onFail\"]?.({ errMsg: \"不合法的经纬度信息\" });\n return;\n }\n const url = `https://apis.map.qq.com/ws/geocoder/v1/?key=${env?.apiKey ?? \"WDOBZ-7WZWL-NFJPE-EKBHS-PBEEK-U4FA5\"}&location=${val?.latitude},${val?.longitude}&get_poi=0`;\n Taro.request({\n url,\n success: (res: any) => {\n if (res.statusCode === 200 && res.data.status === 0) {\n const { result } = res.data ?? {};\n outputs[\"onSuccess\"]?.({\n name: result?.formatted_addresses?.recommend,\n address: result?.address,\n longitude: val.longitude,\n latitude: val.latitude,\n ...(result?.address_component ?? {}),\n });\n } else {\n outputs[\"onFail\"]?.({\n errMsg: res.data?.message ?? res.errMsg ?? \"网络错误\",\n });\n }\n },\n fail: ({ errMsg }: any) => {\n outputs[\"onFail\"]?.({ errMsg });\n },\n });\n } catch (error: any) {\n console.error(\"地图选点失败:\", error);\n outputs.onFail(error?.message || \"地图选点失败\");\n }\n });\n};\n"
|
|
5567
|
+
},
|
|
5568
|
+
{
|
|
5569
|
+
"path": "src/core/comlib/_GetDrivePath.ts",
|
|
5570
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {\n width: number;\n color: string;\n dottedLine: boolean;\n arrowLine: boolean;\n borderColor: string;\n borderWidth: number;\n autofit: boolean;\n start: {\n icon: string;\n width: number;\n height: number;\n };\n end: {\n icon: string;\n width: number;\n height: number;\n };\n};\n\nexport type ValType = {\n from: {\n latitude?: number;\n longitude?: number;\n };\n to: {\n latitude?: number;\n longitude?: number;\n };\n};\n\nexport interface Inputs {\n getWithPos?: (fn: (val: ValType) => void) => void;\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void;\n onFail: (value?: any) => void;\n}\n\nexport interface Env {\n apiKey?: string;\n}\n\ninterface IOContext {\n data: DataType;\n env: Env;\n inputs: Inputs;\n outputs: Outputs;\n}\n\nexport default (context: IOContext) => {\n const env: Env = context.env;\n const data: DataType = context.data;\n const inputs: Inputs = context.inputs;\n const outputs: Outputs = context.outputs;\n\n inputs.getWithPos?.((val) => {\n try {\n if (!val?.from || !val?.to) {\n outputs[\"onFail\"]?.({ errMsg: \"不合法的起点和终点\" });\n return;\n }\n\n const url = `https://apis.map.qq.com/ws/direction/v1/driving/?key=${\n env?.apiKey ?? \"WDOBZ-7WZWL-NFJPE-EKBHS-PBEEK-U4FA5\"\n }&from=${val?.from?.latitude},${val?.from?.longitude}&to=${\n val?.to?.latitude\n },${val?.to?.longitude}&policy=TRIP,AVOID_HIGHWAY,NAV_POINT_FIRST`;\n Taro.request({\n url,\n success: (res: any) => {\n if (res.statusCode === 200 && res.data.status === 0) {\n const { result } = res.data ?? {};\n if (Array.isArray(result.routes)) {\n const polylines = result.routes.map((route: any) => {\n let points = [] as { latitude: number; longitude: number }[];\n /** 解压坐标 */\n for (var i = 2; i < route.polyline.length; i++) {\n route.polyline[i] =\n route.polyline[i - 2] + route.polyline[i] / 1000000;\n }\n\n for (let i = 0; i < route.polyline.length / 2; i++) {\n points[i] = {\n latitude: route.polyline[i * 2],\n longitude: route.polyline[i * 2 + 1],\n };\n }\n return {\n points,\n width: data.width,\n color: data.color,\n dottedLine: data.dottedLine,\n arrowLine: data.arrowLine,\n borderColor: data.borderColor,\n borderWidth: data.borderWidth,\n\n distance: route.distance,\n duration: route.duration,\n };\n });\n\n const markers = [\n {\n id: 0,\n width: data.start?.width,\n height: data.start?.height,\n iconPath: data.start?.icon,\n latitude: val.from?.latitude,\n longitude: val.from?.longitude,\n },\n {\n id: 1,\n width: data.end?.width,\n height: data.end?.height,\n iconPath: data.end?.icon,\n latitude: val.to?.latitude,\n longitude: val.to?.longitude,\n },\n ];\n\n outputs[\"onSuccess\"]?.({\n markers,\n polylines,\n autofit: data.autofit,\n });\n }\n } else {\n outputs[\"onFail\"]?.({\n errMsg: res.data?.message ?? res.errMsg ?? \"网络错误\",\n });\n }\n },\n fail: ({ errMsg }: any) => {\n outputs[\"onFail\"]?.({ errMsg });\n },\n });\n } catch (error: any) {\n console.error(\"路线规划失败:\", error);\n outputs.onFail({\n errMsg: error?.message || \"路线规划失败\",\n });\n }\n });\n};\n"
|
|
5543
5571
|
},
|
|
5544
5572
|
{
|
|
5545
5573
|
"path": "src/core/comlib/_GetLocation.ts",
|
|
5546
|
-
"content": "import Taro from '@tarojs/taro'
|
|
5574
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {\n isHighAccuracy?: boolean\n}\n\nexport interface Inputs {\n getLocation?: (fn: () => 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.getLocation?.(() => {\n try {\n Taro.getLocation({\n type: 'gcj02', //返回可以用于 Taro.openLocation的经纬度\n isHighAccuracy: data?.isHighAccuracy ?? false,\n success: function ({ latitude, longitude }: any) {\n outputs['onSuccess']?.({ latitude, longitude })\n },\n fail: ({ errMsg }: any) => {\n outputs['onFail']?.({ errMsg })\n },\n })\n } catch (error: any) {\n console.error('获取地理位置失败:', error)\n outputs.onFail?.({\n errMsg: error?.message || '获取地理位置失败',\n })\n }\n })\n}\n"
|
|
5575
|
+
},
|
|
5576
|
+
{
|
|
5577
|
+
"path": "src/core/comlib/_GetRouter.ts",
|
|
5578
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {}\n\nexport interface Inputs {\n call?: (fn: (config: DataType, relOutputs?: any) => void) => void\n}\n\nexport interface Outputs {\n onComplete: (value?: any) => void\n}\n\ninterface IOContext {\n inputs: Inputs\n outputs: Outputs\n}\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs\n const outputs: Outputs = context.outputs\n\n inputs.call?.(() => {\n try {\n let router = Taro.getCurrentInstance()?.router\n\n let path = router?.path || ''\n let query = router?.params || {}\n let scene = Taro.getEnterOptionsSync().scene || 0\n outputs['onComplete']({ path, query, scene })\n } catch (error: any) {\n console.error('获取路由信息失败:', error)\n }\n })\n}\n"
|
|
5547
5579
|
},
|
|
5548
5580
|
{
|
|
5549
5581
|
"path": "src/core/comlib/_GetStorage.ts",
|
|
5550
|
-
"content": "import Taro from
|
|
5582
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {\n key?: string;\n useDynamicKey?: boolean;\n};\n\nexport interface Inputs {\n getStorage?: (fn: (key: string, relOutputs?: any) => void) => void;\n}\n\nexport interface Outputs {\n onComplete: (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.getStorage?.((key) => {\n let myKey = data.useDynamicKey ? key : data.key;\n\n if (!myKey || typeof myKey !== \"string\") {\n outputs[\"onComplete\"](null);\n return;\n }\n\n try {\n let value = Taro.getStorageSync(myKey);\n outputs[\"onComplete\"](value);\n } catch (e) {\n outputs[\"onComplete\"](null);\n }\n });\n};\n"
|
|
5583
|
+
},
|
|
5584
|
+
{
|
|
5585
|
+
"path": "src/core/comlib/_GetWeRunData.ts",
|
|
5586
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {}\n\nexport interface Inputs {\n call?: (fn: () => void) => void\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void\n onFail: (value?: any) => void\n}\n\ninterface IOContext {\n inputs: Inputs\n outputs: Outputs\n}\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs\n const outputs: Outputs = context.outputs\n\n inputs.call?.(() => {\n try {\n Taro.getWeRunData({\n success: (res: any) => {\n outputs['onSuccess']({\n encryptedData: res.encryptedData,\n iv: res.iv,\n })\n },\n fail: (res: any) => {\n switch (res.err_code) {\n // 用户未授权,需要引导用户授权\n case '-12006':\n case -12006:\n Taro.showModal({\n title: '提示',\n content: '请先授权获取微信运动数据',\n showCancel: true,\n confirmText: '去授权',\n cancelText: '取消',\n success: (res: any) => {\n if (res.confirm) {\n Taro.openSetting({\n success: (res: any) => {\n if (res.authSetting['scope.werun']) {\n Taro.getWeRunData({\n success: (res: any) => {\n outputs['onSuccess']({\n encryptedData: res.encryptedData,\n iv: res.iv,\n })\n },\n fail: (err: any) => {\n outputs['onFail'](err)\n },\n })\n } else {\n outputs['onFail'](res)\n }\n },\n })\n } else {\n outputs['onFail']()\n }\n },\n })\n break\n\n default:\n outputs['onFail'](res)\n break\n }\n },\n })\n } catch (error: any) {\n console.error('获取运动步数失败:', error)\n outputs.onFail({\n errMsg: error?.message || '获取运动步数失败',\n })\n }\n })\n}\n"
|
|
5587
|
+
},
|
|
5588
|
+
{
|
|
5589
|
+
"path": "src/core/comlib/_Goto.ts",
|
|
5590
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {\n action?: \"redirectTo\" | \"navigateTo\" | \"reLaunch\";\n};\n\nexport interface Inputs {\n goto?: (fn: (config: string, relOutputs?: any) => void) => void;\n}\n\ninterface IOContext {\n data: DataType;\n inputs: Inputs;\n}\n\nexport default (context: IOContext) => {\n const data: DataType = context.data;\n const inputs: Inputs = context.inputs;\n\n inputs.goto?.((val) => {\n try {\n if (data.action === \"redirectTo\") {\n Taro.redirectTo({\n url: val,\n });\n } else if (data.action === \"navigateTo\") {\n Taro.navigateTo({\n url: val,\n });\n } else if (data.action === \"reLaunch\") {\n Taro.reLaunch({\n url: val,\n });\n }\n } catch (error: any) {\n console.error(\"路由跳转失败:\", error);\n }\n });\n};\n"
|
|
5591
|
+
},
|
|
5592
|
+
{
|
|
5593
|
+
"path": "src/core/comlib/_HideLoading.ts",
|
|
5594
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {};\n\nexport interface Inputs {\n hideLoading?: (fn: (config: any, relOutputs?: any) => void) => void;\n}\n\nexport interface Outputs {\n afterHideLoading: (value?: any) => void;\n}\n\ninterface IOContext {\n inputs: Inputs;\n outputs: Outputs;\n}\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs;\n const outputs: Outputs = context.outputs;\n\n inputs.hideLoading?.((val) => {\n Taro.hideLoading({\n noConflict: true,\n complete: (e) => {\n outputs[\"afterHideLoading\"](val);\n },\n });\n });\n};\n"
|
|
5595
|
+
},
|
|
5596
|
+
{
|
|
5597
|
+
"path": "src/core/comlib/_HideToast.ts",
|
|
5598
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {\n};\n\nexport interface Inputs {\n hideToast?: (\n fn: (config: any, relOutputs?: any) => void,\n ) => void;\n}\n\nexport interface Outputs {\n afterHideToast: (value?: any) => void;\n}\n\ninterface IOContext {\n inputs: Inputs;\n outputs: Outputs;\n}\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs;\n const outputs: Outputs = context.outputs;\n\n inputs.hideToast?.((val) => {\n Taro.hideToast({\n noConflict: true,\n complete: () => {\n outputs[\"afterHideToast\"](val);\n },\n });\n });\n};\n"
|
|
5551
5599
|
},
|
|
5552
5600
|
{
|
|
5553
|
-
"path": "src/core/comlib/
|
|
5554
|
-
"content": "import Taro from
|
|
5601
|
+
"path": "src/core/comlib/_Login.ts",
|
|
5602
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {\n timeout?: number;\n};\n\nexport interface Inputs {\n call?: (fn: () => void) => void;\n}\n\nexport interface Outputs {\n success: (value?: any) => void;\n fail: (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.call?.(() => {\n try {\n let params = {};\n\n if (!!data.timeout) {\n params[\"timeout\"] = data.timeout;\n }\n\n Taro.login({\n ...params,\n success: (res) => {\n if (res.code) {\n outputs[\"success\"]({\n code: res.code,\n });\n } else {\n outputs[\"fail\"]({\n ...res,\n });\n }\n },\n fail: (res) => {\n outputs[\"fail\"]({\n ...res,\n });\n },\n });\n } catch (error) {\n console.error(\"获取登录凭证失败:\", error);\n }\n });\n};\n"
|
|
5555
5603
|
},
|
|
5556
5604
|
{
|
|
5557
5605
|
"path": "src/core/comlib/_Modal.ts",
|
|
5558
|
-
"content": "import Taro from '@tarojs/taro'
|
|
5606
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {\n dynamic?: boolean\n title?: string\n content?: string\n /** 微信/部分端支持,可编辑输入框 */\n // editable?: boolean;\n showCancel?: boolean\n cancelText?: string\n cancelColor?: string\n confirmText?: string\n confirmColor?: string\n}\n\nexport interface Inputs {\n /** 显示模态对话框 */\n show?: (fn: (config?: DataType, relOutputs?: any) => void) => void\n}\n\nexport interface Outputs {\n onConfirm: (value?: any) => void\n onCancel: (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.show?.(async (val) => {\n try {\n let param = {\n ...data,\n success: (res: any) => {\n if (res.confirm) {\n // if (data.editable) {\n // outputs[\"onConfirm\"](res.content);\n // } else {\n outputs['onConfirm'](val)\n // }\n } else {\n outputs['onCancel'](val)\n }\n },\n }\n\n if (data?.dynamic && val) {\n //开启了动态输入\n param.content = val.content ?? ''\n param.title = val.title ?? ''\n } else {\n if (data.content) {\n param.content = data.content.replace(/\\n/g, '\\r\\n')\n }\n }\n\n Taro.showModal(param)\n } catch (error: any) {\n console.error('显示 Modal 失败:', error)\n }\n })\n}\n"
|
|
5607
|
+
},
|
|
5608
|
+
{
|
|
5609
|
+
"path": "src/core/comlib/_Open.ts",
|
|
5610
|
+
"content": "import Taro from \"@tarojs/taro\";\nimport { isObject } from \"../tools/core\";\n\nexport enum ExtLinkype {\n miniapp_open = \"miniapp_open\",\n parent_open = \"parent_open\",\n parent_back = \"parent_back\",\n web_open = \"web_open\",\n}\n\nexport enum OpenType {\n navigate = \"navigate\",\n redirect = \"redirect\",\n relaunch = \"relaunch\",\n}\n\nexport type DataType = {\n url?: string;\n dynamic?: boolean;\n type: ExtLinkype;\n openType: OpenType;\n};\n\nexport type ValType = {\n url?: string;\n} & Record<string, any>;\n\nexport interface Inputs {\n open?: (fn: (config: ValType, 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\nconst runtimeEnv = () => {\n const isH5 =\n Taro.getEnv() === Taro.ENV_TYPE.WEB || Taro.getEnv() === \"Unknown\";\n if (isH5) {\n if (window.__wxjs_environment === \"miniprogram\") {\n return \"IN_WEAPP\";\n }\n if (/(MicroMessenger)/i.test(navigator.userAgent)) {\n return \"IN_WEIXIN\";\n }\n return Taro.ENV_TYPE.WEB;\n } else {\n return Taro.getEnv();\n }\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?.[\"open\"]?.((value) => {\n const validValue = isObject(value) ? value : {};\n const finalUrl = validValue?.url ?? data.url;\n\n const _env = runtimeEnv();\n switch (true) {\n case data.type === ExtLinkype.parent_open: {\n const params = {\n url: finalUrl,\n success: () => {\n outputs[\"onSuccess\"]();\n },\n fail: () => {\n outputs[\"onFail\"]();\n },\n };\n if (_env === \"IN_WEAPP\" && wx?.miniProgram) {\n if (data.openType === OpenType.redirect) {\n wx.miniProgram?.redirectTo?.(params);\n } else {\n wx.miniProgram?.navigateTo?.(params);\n }\n }\n break;\n }\n case data.type === ExtLinkype.parent_back: {\n if (_env === \"IN_WEAPP\" && wx?.miniProgram?.navigateBack) {\n wx.miniProgram.navigateBack({\n success: () => {\n outputs[\"onSuccess\"]();\n },\n fail: () => {\n outputs[\"onFail\"]();\n },\n });\n }\n break;\n }\n case data.type === ExtLinkype.web_open: {\n // H5环境下\n if (\n (Taro.getEnv() === Taro.ENV_TYPE.WEB ||\n Taro.getEnv() === \"Unknown\") &&\n finalUrl\n ) {\n if (data.openType === OpenType.redirect) {\n window.location.href = finalUrl;\n outputs[\"onSuccess\"]();\n } else {\n // 微信小程序内不支持 window.open\n window.open(finalUrl);\n outputs[\"onSuccess\"]();\n }\n }\n break;\n }\n\n case data.type === ExtLinkype.miniapp_open: {\n Taro.navigateToMiniProgram({\n ...validValue,\n success(e) {\n outputs[\"onSuccess\"](e);\n },\n fail(e) {\n outputs[\"onFail\"](e);\n },\n });\n\n // if (_env === \"IN_WEIXIN\") {\n // Taro.navigateToMiniProgram({\n // ...validValue,\n // success(e) {\n // outputs[\"onSuccess\"](e);\n // },\n // fail(e) {\n // outputs[\"onFail\"](e);\n // },\n // });\n // }\n break;\n }\n default:\n break;\n }\n });\n};\n"
|
|
5559
5611
|
},
|
|
5560
5612
|
{
|
|
5561
5613
|
"path": "src/core/comlib/_OpenCamera.ts",
|
|
5562
|
-
"content": "import Taro from '@tarojs/taro'
|
|
5614
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {\n selectMethodConfig?: 'both' | 'camera' | 'album' // 照片选取方式\n photoCount?: number // 选择的照片数量\n}\n\nexport interface Inputs {\n takePhotos?: (fn: () => 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.takePhotos?.(() => {\n try {\n Taro.chooseImage({\n count: data.photoCount, // 默认9\n sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有\n sourceType: data.selectMethodConfig, // 可以指定来源是相册还是相机,默认二者都有,在H5浏览器端支持使用 `user` 和 `environment`分别指定为前后摄像头\n success: function (res: any) {\n // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片\n // var tempFilePaths = res.tempFilePaths;\n // outputs[\"onSuccess\"]?.(tempFilePaths);\n outputs['onSuccess']?.(res)\n },\n fail: ({ errMsg }: any) => {\n outputs['onFail']?.({ errMsg })\n },\n })\n } catch (error: any) {\n console.error('打开相机失败:', error)\n outputs.onFail(error?.message || '打开相机失败')\n }\n })\n}\n"
|
|
5615
|
+
},
|
|
5616
|
+
{
|
|
5617
|
+
"path": "src/core/comlib/_OpenChannelsActivity.ts",
|
|
5618
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {}\n\nexport type ValType = {\n finderUserName: string\n feedId: string\n}\n\nexport interface Inputs {\n openChannelsActivity?: (fn: (val: ValType) => void) => void\n}\n\nexport interface Outputs {\n openChannelsActivitySuccess: (value?: any) => void\n openChannelsActivityFail: (value?: any) => void\n}\n\ninterface IOContext {\n inputs: Inputs\n outputs: Outputs\n}\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs\n const outputs: Outputs = context.outputs\n\n inputs.openChannelsActivity?.((val) => {\n try {\n Taro.openChannelsActivity({\n finderUserName: val.finderUserName,\n feedId: val.feedId,\n success: function (res: any) {\n console.log('接口调用成功', res)\n outputs['openChannelsActivitySuccess']?.(res)\n },\n fail: function (err: any) {\n console.error('接口调用失败', err)\n outputs['openChannelsActivityFail']?.(err)\n },\n })\n } catch (error: any) {\n console.error('打开视频号失败:', error)\n outputs.openChannelsActivityFail({\n errMsg: error?.message || '打开视频号失败',\n })\n }\n })\n}\n"
|
|
5563
5619
|
},
|
|
5564
5620
|
{
|
|
5565
|
-
"path": "src/core/comlib/
|
|
5566
|
-
"content": "
|
|
5621
|
+
"path": "src/core/comlib/_OpenChannelsUserProfile.ts",
|
|
5622
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {}\n\nexport type ValType = {\n finderUserName: string\n}\n\nexport interface Inputs {\n openChannelsUserProfile?: (fn: (val: ValType) => void) => void\n}\n\nexport interface Outputs {\n openChannelsUserProfileSuccess: (value?: any) => void\n openChannelsUserProfileFail: (value?: any) => void\n}\n\ninterface IOContext {\n inputs: Inputs\n outputs: Outputs\n}\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs\n const outputs: Outputs = context.outputs\n\n inputs.openChannelsUserProfile?.((val) => {\n try {\n Taro.openChannelsUserProfile({\n finderUserName: val.finderUserName,\n success: function (res: any) {\n outputs['openChannelsUserProfileSuccess']?.(res)\n },\n fail: function (err: any) {\n outputs['openChannelsUserProfileFail']?.(err)\n },\n })\n } catch (error: any) {\n console.error('打开视频号主页失败:', error)\n outputs.openChannelsUserProfileFail({\n errMsg: error?.message || '打开视频号主页失败',\n })\n }\n })\n}\n"
|
|
5567
5623
|
},
|
|
5568
5624
|
{
|
|
5569
|
-
"path": "src/core/comlib/
|
|
5570
|
-
"content": "import Taro from '@tarojs/taro'
|
|
5625
|
+
"path": "src/core/comlib/_OpenDocument.ts",
|
|
5626
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {}\n\nexport interface Inputs {\n url?: (fn: (path: string) => void) => void\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void\n onFail: (value?: any) => void\n}\n\ninterface IOContext {\n inputs: Inputs\n outputs: Outputs\n}\n\nconst parseFileInfo = (url: string) => {\n try {\n // 解码URL中的中文字符\n const decodedUrl = decodeURIComponent(url)\n\n // 获取URL的最后一部分作为文件名\n const fileName = decodedUrl.split('/').pop()\n\n // 获取文件扩展名\n const fileExtension = fileName?.split('.')?.pop()?.toLowerCase()\n\n return {\n fileName: fileName, // 完整文件名\n extension: fileExtension, // 文件扩展名\n }\n } catch (error) {\n console.error('URL解析失败:', error)\n return null\n }\n}\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs\n const outputs: Outputs = context.outputs\n\n inputs.url?.((path) => {\n try {\n // 判断是否为远程文件地址\n const isRemoteImage =\n path.startsWith('http://') || path.startsWith('https://')\n const fileInfo = parseFileInfo(path)\n\n const openDocument = (filePath: string) => {\n Taro.openDocument({\n filePath,\n showMenu: true,\n success: (res: any) => {\n outputs['onSuccess'](res)\n },\n fail: (res: any) => {\n console.error(res)\n outputs['onFail'](res)\n },\n })\n }\n\n if (isRemoteImage) {\n // 远程地址,先下载\n Taro.downloadFile({\n url: path,\n filePath: `${Taro.env.USER_DATA_PATH}/${fileInfo?.fileName}`,\n success: (res: any) => {\n if (res.statusCode === 200) {\n openDocument(res.filePath)\n } else {\n outputs['onFail'](res)\n }\n },\n fail: (err: any) => {\n outputs['onFail'](err)\n },\n })\n } else {\n // 本地地址,直接打开文件预览\n openDocument(path)\n }\n } catch (error: any) {\n console.error('打开文档失败:', error)\n outputs.onFail?.({\n errMsg: error?.message || '打开文档失败',\n })\n }\n })\n}\n"
|
|
5571
5627
|
},
|
|
5572
5628
|
{
|
|
5573
|
-
"path": "src/core/comlib/
|
|
5574
|
-
"content": "import Taro from
|
|
5629
|
+
"path": "src/core/comlib/_OpenLocation.ts",
|
|
5630
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {};\n\nexport type ValType = {\n latitude: number;\n longitude: number;\n address?: string;\n name?: string;\n scale?: number;\n};\n\nexport interface Inputs {\n open?: (fn: (val: ValType) => void) => void;\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void;\n onFail: (value?: any) => void;\n}\n\ninterface IOContext {\n inputs: Inputs;\n outputs: Outputs;\n}\n\nconst getNumber = (target: string | number) => {\n const _result = typeof target === \"number\" ? target : parseFloat(target);\n return isNaN(_result) ? 0 : _result;\n};\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs;\n const outputs: Outputs = context.outputs;\n\n inputs.open?.((val) => {\n try {\n Taro.openLocation({\n latitude: getNumber(val?.latitude),\n longitude: getNumber(val?.longitude),\n address: val?.address,\n name: val?.name,\n scale: val?.scale ?? 10,\n success: () => {\n outputs[\"onSuccess\"]?.(true);\n },\n fail: ({ errMsg }: any) => {\n outputs[\"onFail\"]?.({ errMsg });\n },\n });\n } catch (error: any) {\n console.error(\"获取收货地址失败:\", error);\n outputs.onFail({\n errMsg: error?.message || \"获取收货地址失败\",\n });\n }\n });\n};\n"
|
|
5575
5631
|
},
|
|
5576
5632
|
{
|
|
5577
|
-
"path": "src/core/comlib/
|
|
5578
|
-
"content": "import Taro from '@tarojs/taro'
|
|
5633
|
+
"path": "src/core/comlib/_Poster.ts",
|
|
5634
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {\n canvasWidth: number\n canvasHeight: number\n}\n\nexport type ElementType = {\n // 绘制类型,支持的值:text, image, shape\n type: string\n // 绘制的左上角 X 坐标值\n x: number\n // 绘制的左上角 Y 坐标值\n y: number\n // 绘制的宽度。(如果是文本类型,宽度达到width 会自动换行)\n width: number\n // 绘制的高度。(如果是文本类型,超过高度会显示省略号)\n height: number\n // 文字颜色(仅文本类型时生效)\n color: string\n // 文字字号(仅文本类型时生效)\n fontSize: number\n // 文字粗细,(仅文本类型时生效)\n fontWeight: string\n // 行高(仅文本类型时生效)\n lineHeight: number\n // 文字对齐方式,支持的值:left, right, center(仅文本类型时生效)\n textAlign: string\n // 绘制的内容(文本类型时为文本内容,图片类型时为图片 URL 地址)\n content: string\n // 角大小(仅图片,形状类型时生效)\n borderRadius: number\n // 边框宽度(仅图片,形状类型时生效)\n borderWidth: number\n // 边框颜色(仅图片,形状类型时生效)\n borderColor: string\n // 颜色(仅形状类型时生效)\n backgroundColor: string\n //\n imageObj?: string\n}\n\nexport type ValType = ElementType[]\n\nexport interface Inputs {\n call?: (fn: (val: ValType) => void) => void\n}\n\nexport interface Outputs {\n success: (value?: any) => void\n fail: (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.call?.(async (val) => {\n try {\n let elements = val\n\n // 创建离屏 2D canvas 实例\n let canvas = Taro.createOffscreenCanvas({\n type: '2d',\n width: data.canvasWidth,\n height: data.canvasHeight,\n })\n\n // 获取 context\n const context = canvas.getContext('2d')\n\n // 预加载所有图片\n for (let i = 0; i < elements.length; i++) {\n let element = elements[i]\n if (element.type === 'image') {\n const image = canvas.createImage()\n await new Promise((resolve) => {\n image.onload = resolve\n image.src = element.content\n })\n elements[i].imageObj = image\n }\n }\n\n // 把元素画到离屏 canvas 上\n for (let i = 0; i < elements.length; i++) {\n let element = elements[i]\n\n switch (element.type) {\n case 'text':\n await drawText(context, element)\n break\n case 'image':\n await drawImage(context, element)\n break\n case 'shape':\n await drawShape(context, element)\n break\n default:\n break\n }\n }\n\n // 获取离屏 canvas 的内容\n const base64 = context.canvas.toDataURL('image/png')\n outputs['success'](base64)\n\n /**\n * 绘制形状\n *\n * x: 0\n * y: 0\n * width: 375\n * height: 30\n * borderRadius: 50\n * borderWidth: 2\n * borderColor: \"#000000\"\n * backgroundColor: \"#000000\"\n *\n */\n async function drawShape(context: any, element: ElementType) {\n const {\n x = 0,\n y = 0,\n width,\n height,\n borderRadius = 0,\n borderWidth = 0,\n borderColor,\n backgroundColor,\n } = element\n\n // 调整绘制路径的位置,确保边框不会超出 width 和 height 的范围\n const halfBorderWidth = borderWidth / 2\n const adjustedX = x + halfBorderWidth\n const adjustedY = y + halfBorderWidth\n const adjustedWidth = width - borderWidth\n const adjustedHeight = height - borderWidth\n\n // 限制 borderRadius 的最大值\n const maxBorderRadius = Math.min(adjustedWidth, adjustedHeight) / 2\n const effectiveBorderRadius = Math.min(borderRadius, maxBorderRadius)\n\n // 绘制圆角矩形边框\n context.save()\n context.beginPath()\n context.moveTo(adjustedX + effectiveBorderRadius, adjustedY)\n context.arcTo(\n adjustedX + adjustedWidth,\n adjustedY,\n adjustedX + adjustedWidth,\n adjustedY + adjustedHeight,\n effectiveBorderRadius,\n )\n context.arcTo(\n adjustedX + adjustedWidth,\n adjustedY + adjustedHeight,\n adjustedX,\n adjustedY + adjustedHeight,\n effectiveBorderRadius,\n )\n context.arcTo(\n adjustedX,\n adjustedY + adjustedHeight,\n adjustedX,\n adjustedY,\n effectiveBorderRadius,\n )\n context.arcTo(\n adjustedX,\n adjustedY,\n adjustedX + adjustedWidth,\n adjustedY,\n effectiveBorderRadius,\n )\n context.closePath()\n\n // 设置边框样式\n context.lineWidth = borderWidth\n context.strokeStyle = borderColor\n context.stroke()\n\n // 设置背景颜色\n context.fillStyle = backgroundColor\n context.fill()\n\n // 恢复裁剪区域\n context.restore()\n }\n\n /**\n * 绘制图片\n *\n * x: 0\n * y: 30\n * width: 375\n * height: 30\n * borderRadius: 50\n * borderWidth: 2\n * borderColor: \"#000000\"\n * imageObj: Image\n *\n */\n async function drawImage(context: any, element: ElementType) {\n const {\n x = 0,\n y = 0,\n width,\n height,\n borderRadius = 0,\n borderWidth = 0,\n borderColor,\n imageObj,\n } = element\n\n // 调整绘制路径的位置,确保边框不会超出 width 和 height 的范围\n const halfBorderWidth = borderWidth / 2\n const adjustedX = x + halfBorderWidth\n const adjustedY = y + halfBorderWidth\n const adjustedWidth = width - borderWidth\n const adjustedHeight = height - borderWidth\n\n // 限制 borderRadius 的最大值\n const maxBorderRadius = Math.min(adjustedWidth, adjustedHeight) / 2\n const effectiveBorderRadius = Math.min(borderRadius, maxBorderRadius)\n\n // 绘制圆角矩形边框\n context.save()\n context.beginPath()\n context.moveTo(adjustedX + effectiveBorderRadius, adjustedY)\n context.arcTo(\n adjustedX + adjustedWidth,\n adjustedY,\n adjustedX + adjustedWidth,\n adjustedY + adjustedHeight,\n effectiveBorderRadius,\n )\n context.arcTo(\n adjustedX + adjustedWidth,\n adjustedY + adjustedHeight,\n adjustedX,\n adjustedY + adjustedHeight,\n effectiveBorderRadius,\n )\n context.arcTo(\n adjustedX,\n adjustedY + adjustedHeight,\n adjustedX,\n adjustedY,\n effectiveBorderRadius,\n )\n context.arcTo(\n adjustedX,\n adjustedY,\n adjustedX + adjustedWidth,\n adjustedY,\n effectiveBorderRadius,\n )\n context.closePath()\n\n // 设置边框样式\n if (borderWidth > 0) {\n context.lineWidth = borderWidth\n context.strokeStyle = borderColor\n context.stroke()\n }\n\n // 裁剪到圆角矩形区域\n context.clip()\n\n // 绘制图片\n context.drawImage(\n imageObj,\n adjustedX,\n adjustedY,\n adjustedWidth,\n adjustedHeight,\n )\n\n // 恢复裁剪区域\n context.restore()\n }\n\n /**\n * 绘制文本\n *\n * x: 0\n * y: 30\n * width: 375\n * height: 30\n * color: #000000\n * fontSize: 30\n * fontWeight: normal | bold\n * lineHeight: 30\n * textAlign: center | left | right\n * content: \"Hello World\"\n *\n */\n async function drawText(context: any, element: ElementType) {\n let {\n x = 0,\n y = 0,\n width = 999999999,\n height = 999999999,\n color = '#000000',\n fontSize = 12,\n fontWeight = 'normal',\n lineHeight,\n textAlign = 'left',\n content = '',\n } = element\n\n // 设置字体\n context.font = `${fontWeight} ${fontSize}px system-ui`\n context.fillStyle = color\n context.textBaseline = 'bottom'\n\n // 计算行高\n lineHeight = lineHeight || fontSize\n\n // 文本最大行数\n const maxLines = Math.floor(height / lineHeight) // 向下取整\n\n // 文本的行数\n const lines = [] as string[]\n let line = ''\n\n // 拆分文本\n for (let i = 0; i < content.length; i++) {\n let char = content[i]\n\n if (context.measureText(line + char).width > width) {\n lines.push(line)\n line = char\n } else {\n line += char\n }\n }\n lines.push(line)\n\n // 绘制文本\n for (let i = 0; i < Math.min(lines.length, maxLines); i++) {\n let line = lines[i]\n let textX = x\n\n // 如果是最后一行,且超过了 width,就显示省略号\n if (i === maxLines - 1 && i < lines.length - 1) {\n while (context.measureText(line + '...').width > width) {\n line = line.slice(0, -1)\n }\n line += '...'\n }\n\n switch (textAlign) {\n case 'left':\n textX = x\n break\n case 'center':\n textX = x + (width - context.measureText(line).width) / 2\n break\n case 'right':\n textX = x + width - context.measureText(line).width\n break\n default:\n break\n }\n\n context.fillText(line, textX, y + lineHeight * (i + 1))\n }\n }\n } catch (error: any) {\n console.error('图片绘制失败:', error)\n outputs.fail({\n errMsg: error?.message || '图片绘制失败',\n })\n }\n })\n}\n"
|
|
5635
|
+
},
|
|
5636
|
+
{
|
|
5637
|
+
"path": "src/core/comlib/_PreviewImage.ts",
|
|
5638
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {}\n\nexport type ValType = {\n urls: string[]\n current?: number\n}\n\nexport interface Inputs {\n call?: (fn: (val: ValType) => void) => void\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void\n onFail: (value?: any) => void\n}\n\ninterface IOContext {\n inputs: Inputs\n outputs: Outputs\n}\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs\n const outputs: Outputs = context.outputs\n\n inputs.call?.((val) => {\n try {\n let params = {\n urls: val.urls,\n current: val.urls?.[0],\n }\n\n if (val.current) {\n params['current'] = val.urls?.[val.current ?? 0]\n }\n\n Taro.previewImage({\n ...params,\n success: () => {\n outputs['onSuccess']()\n },\n fail: (error: any) => {\n outputs['onFail'](error)\n },\n })\n } catch (error: any) {\n console.error('预览图片失败:', error)\n outputs.onFail({\n errMsg: error?.message || '预览图片失败',\n })\n }\n })\n}\n"
|
|
5639
|
+
},
|
|
5640
|
+
{
|
|
5641
|
+
"path": "src/core/comlib/_RemoveTabBarBadge.ts",
|
|
5642
|
+
"content": "import { isUndef } from '../tools/core'\n\nexport type DataType = {\n index: number\n}\n\nexport interface Inputs {\n delete?: (fn: (config: DataType, relOutputs?: any) => void) => void\n}\n\nexport interface Outputs {\n success: (value?: any) => void\n}\n\nexport interface Env {\n tabbar?: {\n removeTabBarBadge: (params: { index: number }) => Promise<void>\n }\n}\n\ninterface IOContext {\n env: Env\n data: DataType\n inputs: Inputs\n outputs: Outputs\n}\n\nexport default (context: IOContext) => {\n const data: DataType = context.data\n const env: Env = context.env\n const inputs: Inputs = context.inputs\n const outputs: Outputs = context.outputs\n\n inputs.delete?.((val) => {\n let params = { index: data.index }\n if (!isUndef(val?.index)) {\n params = val\n }\n env?.tabbar\n ?.removeTabBarBadge?.({ index: parseFloat(params.index + '') - 1 })\n .then(() => {\n outputs['success']?.(val)\n })\n })\n}\n"
|
|
5643
|
+
},
|
|
5644
|
+
{
|
|
5645
|
+
"path": "src/core/comlib/_RequestSubscribeMessage.ts",
|
|
5646
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {\n tmplId: string\n}\n\nexport interface Inputs {\n requestSubscribeMessage?: (fn: () => 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.requestSubscribeMessage?.(() => {\n const { tmplId } = data\n\n // tmplId 为模板 ID,必填\n if (!tmplId) {\n outputs['onFail']({\n tmplId: data.tmplId,\n errMsg: '模板ID不能为空',\n })\n return\n }\n try {\n // 通过 Taro.requestSubscribeMessage 接口订阅消息\n Taro.requestSubscribeMessage({\n tmplIds: [tmplId],\n success: (res: any) => {\n if (res.errMsg === 'requestSubscribeMessage:ok') {\n outputs['onSuccess'](res)\n } else {\n outputs['onFail'](res)\n }\n },\n fail: (err: any) => {\n outputs['onFail'](err)\n },\n })\n } catch (error: any) {\n console.error('订阅消息失败:', error)\n outputs.onFail({\n errMsg: error?.message || '订阅消息失败',\n })\n }\n })\n}\n"
|
|
5647
|
+
},
|
|
5648
|
+
{
|
|
5649
|
+
"path": "src/core/comlib/_SaveImageToPhotosAlbum.ts",
|
|
5650
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {}\n\nexport type ValType = string\n\nexport interface Inputs {\n call?: (fn: (val: ValType) => void) => void\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void\n onFail: (value?: any) => void\n}\n\ninterface IOContext {\n inputs: Inputs\n outputs: Outputs\n}\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs\n const outputs: Outputs = context.outputs\n\n inputs.call?.((imagePath) => {\n try {\n // 判断是否为远程图片地址\n const isRemoteImage =\n imagePath.startsWith('http://') || imagePath.startsWith('https://')\n\n const saveImage = (filePath: string) => {\n Taro.saveImageToPhotosAlbum({\n filePath,\n success: (res: any) => {\n Taro.showToast({\n title: '保存成功',\n icon: 'none',\n duration: 1000,\n })\n\n outputs['onSuccess'](res)\n },\n fail: (res: any) => {\n switch (res.errno) {\n // 用户未授权,需要引导用户授权\n case 103: // 用户拒绝了授权\n Taro.showModal({\n title: '提示',\n content: '请先授权保存图片到相册',\n showCancel: true,\n confirmText: '去授权',\n cancelText: '取消',\n success: (res: any) => {\n if (res.confirm) {\n Taro.openSetting({\n success: (res: any) => {\n if (res.authSetting['scope.writePhotosAlbum']) {\n // 用户已授权,重新尝试保存图片\n Taro.saveImageToPhotosAlbum({\n filePath,\n success: (res: any) => {\n Taro.showToast({\n title: '保存成功',\n icon: 'none',\n duration: 1000,\n })\n\n outputs['onSuccess'](res)\n },\n fail: (err: any) => {\n outputs['onFail'](err)\n },\n })\n } else {\n outputs['onFail']()\n }\n },\n fail: (err: any) => {\n outputs['onFail'](err)\n },\n })\n } else {\n outputs['onFail']()\n }\n },\n fail: (err: any) => {\n outputs['onFail'](err)\n },\n })\n break\n\n default:\n outputs['onFail'](res)\n break\n }\n },\n })\n }\n\n if (isRemoteImage) {\n // 远程图片地址,先下载图片\n Taro.downloadFile({\n url: imagePath,\n success: (res: any) => {\n if (res.statusCode === 200) {\n saveImage(res.tempFilePath)\n } else {\n outputs['onFail'](res)\n }\n },\n fail: (err: any) => {\n outputs['onFail'](err)\n },\n })\n } else {\n // 本地图片地址,直接保存\n saveImage(imagePath)\n }\n } catch (error: any) {\n console.error('保存图片到系统相册失败:', error)\n outputs.onFail({\n errMsg: error?.message || '保存图片到系统相册失败',\n })\n }\n })\n}\n"
|
|
5651
|
+
},
|
|
5652
|
+
{
|
|
5653
|
+
"path": "src/core/comlib/_SaveVideoToPhotosAlbum.ts",
|
|
5654
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {}\n\nexport type ValType = string\n\nexport interface Inputs {\n call?: (fn: (val: ValType) => void) => void\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void\n onFail: (value?: any) => void\n}\n\ninterface IOContext {\n inputs: Inputs\n outputs: Outputs\n}\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs\n const outputs: Outputs = context.outputs\n\n inputs.call?.((imagePath) => {\n try {\n // 判断是否为远程图片地址\n const isRemoteImage =\n imagePath.startsWith('http://') || imagePath.startsWith('https://')\n\n const saveVideo = (filePath: string) => {\n Taro.saveVideoToPhotosAlbum({\n filePath,\n success: (res: any) => {\n Taro.showToast({\n title: '保存成功',\n icon: 'none',\n duration: 1000,\n })\n\n outputs['onSuccess'](res)\n },\n fail: (res: any) => {\n switch (res.errno) {\n // 用户未授权,需要引导用户授权\n case 103: // 用户拒绝了授权\n Taro.showModal({\n title: '提示',\n content: '请先授权保存视频到相册',\n showCancel: true,\n confirmText: '去授权',\n cancelText: '取消',\n success: (res: any) => {\n if (res.confirm) {\n Taro.openSetting({\n success: (res: any) => {\n if (res.authSetting['scope.writePhotosAlbum']) {\n // 用户已授权,重新尝试保存图片\n Taro.saveVideoToPhotosAlbum({\n filePath,\n success: (res: any) => {\n Taro.showToast({\n title: '保存成功',\n icon: 'none',\n duration: 1000,\n })\n\n outputs['onSuccess'](res)\n },\n fail: (err: any) => {\n outputs['onFail'](err)\n },\n })\n } else {\n outputs['onFail']()\n }\n },\n fail: (err: any) => {\n outputs['onFail'](err)\n },\n })\n } else {\n outputs['onFail']()\n }\n },\n fail: (err: any) => {\n outputs['onFail'](err)\n },\n })\n break\n\n default:\n outputs['onFail'](res)\n break\n }\n },\n })\n }\n\n if (isRemoteImage) {\n // 远程图片地址,先下载图片\n Taro.downloadFile({\n url: imagePath,\n success: (res: any) => {\n if (res.statusCode === 200) {\n saveVideo(res.tempFilePath)\n } else {\n outputs['onFail'](res)\n }\n },\n fail: (err: any) => {\n outputs['onFail'](err)\n },\n })\n } else {\n // 本地图片地址,直接保存\n saveVideo(imagePath)\n }\n } catch (error: any) {\n console.error('保存视频到系统相册失败:', error)\n outputs.onFail({\n errMsg: error?.message || '保存视频到系统相册失败',\n })\n }\n })\n}\n"
|
|
5579
5655
|
},
|
|
5580
5656
|
{
|
|
5581
5657
|
"path": "src/core/comlib/_ScanQrcode.ts",
|
|
5582
|
-
"content": "import Taro from
|
|
5658
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {\n onlyFromCamera?: boolean;\n};\n\nexport interface Inputs {\n scan?: (fn: () => 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.scan?.(() => {\n try {\n Taro.scanCode({\n onlyFromCamera: data.onlyFromCamera,\n success: ({ result, scanType }) => {\n if (result) {\n outputs[\"onSuccess\"]?.({ result, scanType });\n } else {\n outputs[\"onFail\"]?.({});\n }\n },\n fail: ({ errMsg }) => {\n outputs[\"onFail\"]?.({ errMsg });\n },\n });\n } catch (error: any) {\n console.error(\"扫码失败:\", error);\n outputs.onFail(error?.message || \"扫码失败\");\n }\n });\n};\n"
|
|
5659
|
+
},
|
|
5660
|
+
{
|
|
5661
|
+
"path": "src/core/comlib/_SetClipboardData.ts",
|
|
5662
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {\n text: string;\n};\n\nexport interface Inputs {\n /** 显示模态对话框 */\n setClipboardData?: (fn: (config?: string, 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.setClipboardData?.(async (val) => {\n let copyText = data.text;\n\n if (val) {\n copyText = val;\n }\n\n // 非字符串尝试转换\n if (typeof copyText !== \"string\") {\n try {\n copyText = JSON.stringify(copyText);\n } catch (error) {\n outputs[\"onFail\"](\"请输入字符串\");\n }\n }\n\n Taro.setClipboardData({\n data: copyText,\n success: () => {\n outputs[\"onSuccess\"](copyText);\n },\n fail: (err: any) => {\n outputs[\"onFail\"](err);\n },\n });\n });\n};\n"
|
|
5663
|
+
},
|
|
5664
|
+
{
|
|
5665
|
+
"path": "src/core/comlib/_SetNavigationBarTitle.ts",
|
|
5666
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {};\n\nexport interface Inputs {\n setTitle?: (fn: (config: string) => void) => void;\n}\n\nexport interface Outputs {\n complete: (value?: string) => void;\n}\n\ninterface IOContext {\n inputs: Inputs;\n outputs: Outputs;\n}\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs;\n const outputs: Outputs = context.outputs;\n\n inputs.setTitle?.((value: string) => {\n try {\n if (value && typeof value === \"string\") {\n Taro.setNavigationBarTitle({\n title: value,\n success: () => {\n outputs.complete(value);\n },\n fail: (err: any) => {\n console.error(\"设置标题失败:\", err);\n },\n });\n }\n } catch (error: any) {\n console.error(\"设置标题失败:\", error);\n }\n });\n};\n"
|
|
5583
5667
|
},
|
|
5584
5668
|
{
|
|
5585
5669
|
"path": "src/core/comlib/_SetStorage.ts",
|
|
5586
|
-
"content": "import Taro from
|
|
5670
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {};\n\nexport interface Inputs {\n setStorage?: (fn: (config: any, relOutputs?: any) => void) => void;\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void;\n onFail: (value?: any) => void;\n}\n\ninterface IOContext {\n inputs: Inputs;\n outputs: Outputs;\n}\n\nexport default (context: IOContext) => {\n const inputs: Inputs = context.inputs;\n const outputs: Outputs = context.outputs;\n\n inputs.setStorage?.((props: any) => {\n try {\n Object.keys(props).forEach((key) => {\n Taro.setStorageSync(key, props[key]);\n });\n\n outputs[\"onSuccess\"](props);\n } catch (e) {\n outputs[\"onFail\"](props);\n }\n });\n};\n"
|
|
5587
5671
|
},
|
|
5588
5672
|
{
|
|
5589
|
-
"path": "src/core/comlib/
|
|
5590
|
-
"content": "import
|
|
5673
|
+
"path": "src/core/comlib/_SetTabbarBadge.ts",
|
|
5674
|
+
"content": "import { isUndef } from '../tools/core'\n\nexport type DataType = {\n index: number\n text: string\n}\n\nexport interface Inputs {\n show?: (fn: (config: DataType, relOutputs?: any) => void) => void\n}\n\nexport interface Outputs {\n success: (value?: any) => void\n}\n\nexport interface Env {\n tabbar?: {\n setTabBarBadge: (params: { index: number; text: string }) => Promise<void>\n }\n}\n\ninterface IOContext {\n env: Env\n data: DataType\n inputs: Inputs\n outputs: Outputs\n}\n\nexport default (context: IOContext) => {\n const data: DataType = context.data\n const env: Env = context.env\n const inputs: Inputs = context.inputs\n const outputs: Outputs = context.outputs\n\n inputs.show?.((val) => {\n let params = { index: data.index, text: data.text }\n if (!isUndef(val?.index) && !isUndef(val?.text)) {\n params = val\n }\n env?.tabbar\n ?.setTabBarBadge?.({\n index: parseFloat(params.index + '') - 1,\n text: params.text,\n })\n .then(() => {\n outputs['success']?.(val)\n })\n })\n}\n"
|
|
5675
|
+
},
|
|
5676
|
+
{
|
|
5677
|
+
"path": "src/core/comlib/_ShowActionSheet.ts",
|
|
5678
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type Item = {\n label: string;\n value?: any;\n};\n\nexport type SelectItem = Item & {\n index?: number;\n};\n\nexport type DataType = {\n itemList?: Item[];\n};\n\nexport interface Inputs {\n showActionSheet?: (fn: (config?: DataType, relOutputs?: any) => void) => void;\n}\n\nexport interface Outputs {\n onSelect: (value?: SelectItem) => void;\n onCancel: () => 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.showActionSheet?.(async (val) => {\n let itemList: Item[] = data.itemList || [];\n try {\n if (Array.isArray(val)) {\n itemList = val;\n }\n\n Taro.showActionSheet({\n itemList: itemList.map((item) => item.label).slice(0, 6),\n })\n .then((res: any) => {\n // 点击按钮\n outputs[\"onSelect\"]({\n index: res.tapIndex,\n label: itemList[res.tapIndex].label,\n value: itemList[res.tapIndex].value,\n });\n })\n .catch(() => {\n // 点击取消\n outputs[\"onCancel\"]();\n });\n } catch (error: any) {\n console.error(\"显示 ActionSheet 失败:\", error);\n }\n });\n};\n"
|
|
5679
|
+
},
|
|
5680
|
+
{
|
|
5681
|
+
"path": "src/core/comlib/_ShowLoading.ts",
|
|
5682
|
+
"content": "import Taro from \"@tarojs/taro\";\n\nexport type DataType = {\n title?: string;\n mask?: boolean;\n};\n\nexport interface Inputs {\n showLoading?: (fn: (config: any, relOutputs?: any) => void) => void;\n}\n\nexport interface Outputs {\n afterShowLoading: (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.showLoading?.((val) => {\n Taro.showLoading({\n ...data,\n complete: () => {\n outputs[\"afterShowLoading\"](val);\n },\n });\n });\n};\n"
|
|
5591
5683
|
},
|
|
5592
5684
|
{
|
|
5593
5685
|
"path": "src/core/comlib/_ShowToast.ts",
|
|
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
|
|
5686
|
+
"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};\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 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"
|
|
5595
5687
|
},
|
|
5596
5688
|
{
|
|
5597
|
-
"path": "src/core/comlib/
|
|
5598
|
-
"content": "export type DataType = {
|
|
5689
|
+
"path": "src/core/comlib/_StartFacialRecognitionVerify.ts",
|
|
5690
|
+
"content": "export type DataType = {};\n\nexport interface Inputs {\n call?: (fn: (config: any, relOutputs?: any) => void) => void;\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void;\n onFail: (value?: any) => void;\n}\n\ninterface IOContext {\n inputs: Inputs;\n outputs: Outputs;\n}\n\nexport default (context: IOContext) => {\n};\n"
|
|
5599
5691
|
},
|
|
5600
5692
|
{
|
|
5601
5693
|
"path": "src/core/comlib/_TimerDebounce.ts",
|
|
5602
|
-
"content": "
|
|
5694
|
+
"content": "import debounce from 'lodash/debounce'\n\nexport type DataType = {\n delay?: number // 防抖延迟时间(毫秒)\n isleading?: boolean // 是否在开始时执行\n}\n\nexport interface Inputs {\n trigger?: (fn: (config: any, relOutputs?: any) => void) => void\n}\n\nexport interface Outputs {\n trigger: (value?: any) => void\n}\n\ninterface IOContext {\n data: DataType\n inputs: Inputs\n outputs: Outputs\n}\n\nconst handler = (context: IOContext) => {\n const data: DataType = context.data\n const inputs: Inputs = context.inputs\n const outputs: Outputs = context.outputs\n\n // 防抖\n const debounceOutput = debounce(\n (val: any) => {\n outputs['trigger'](val)\n },\n data.delay,\n data.isleading ? { leading: true } : void 0,\n )\n\n inputs.trigger?.((val) => {\n try {\n debounceOutput(val)\n } catch (error: any) {\n console.error('防抖执行失败:', error)\n }\n })\n}\n\n;(handler as any).__useCache = true\nexport default handler\n"
|
|
5603
5695
|
},
|
|
5604
5696
|
{
|
|
5605
5697
|
"path": "src/core/comlib/_TimerDelay.ts",
|
|
5606
|
-
"content": "export type DataType = {\n delay?: number; // 延迟时间(毫秒)\n};\n\nexport interface Inputs {\n delay?: (fn: (config: DataType, relOutputs?: any) => void) => void;\n cancel?: (fn: (config: {}, relOutputs?: any) => void) => void;\n /**\n * 兼容老协议:直接传入任意 payload,延迟后从 outputs.trigger 原样输出\n *(生成器里常见 inputs:[\"trigger\"], outputs:[\"trigger\"])\n */\n trigger?: (fn: (payload: any, relOutputs?: any) => void) => void;\n}\n\nexport interface Outputs {\n onStart: (value?: any) => void;\n onExecute: (value?: any) => void;\n onCancel: (value?: any) => void;\n /** 兼容老协议 */\n trigger?: (value?: any) => void;\n}\n\ninterface IOContext {\n data: DataType;\n inputs: Inputs;\n outputs: Outputs;\n}\n\
|
|
5698
|
+
"content": "export type DataType = {\n delay?: number; // 延迟时间(毫秒)\n};\n\nexport interface Inputs {\n delay?: (fn: (config: DataType, relOutputs?: any) => void) => void;\n cancel?: (fn: (config: {}, relOutputs?: any) => void) => void;\n /**\n * 兼容老协议:直接传入任意 payload,延迟后从 outputs.trigger 原样输出\n *(生成器里常见 inputs:[\"trigger\"], outputs:[\"trigger\"])\n */\n trigger?: (fn: (payload: any, relOutputs?: any) => void) => void;\n}\n\nexport interface Outputs {\n onStart: (value?: any) => void;\n onExecute: (value?: any) => void;\n onCancel: (value?: any) => void;\n /** 兼容老协议 */\n trigger?: (value?: any) => void;\n}\n\ninterface IOContext {\n data: DataType;\n inputs: Inputs;\n outputs: Outputs;\n}\n\nconst handler = (context: IOContext) => {\n const data: DataType = context.data;\n const inputs: Inputs = context.inputs;\n const outputs: Outputs = context.outputs;\n\n let timeoutId: any = null;\n const inputPins = new Set(Object.keys(inputs as any));\n const outputPins = new Set(Object.keys(outputs as any));\n const hasIn = (pin: string) => inputPins.has(pin);\n const hasOut = (pin: string) => outputPins.has(pin);\n\n const clear = () => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n };\n\n // 兼容:inputs.trigger(payload) -> 延迟后 outputs.trigger(payload)\n if (hasIn(\"trigger\")) inputs.trigger?.((payload: any) => {\n try {\n // 允许 payload 自带 delay 覆盖;否则用 data.delay;再否则 1000\n const delay = payload?.delay || data.delay || 1000;\n\n clear();\n\n outputs.onStart?.({ delay, timestamp: Date.now() });\n\n timeoutId = setTimeout(() => {\n if (hasOut(\"trigger\")) outputs.trigger?.(payload);\n outputs.onExecute?.({ delay, timestamp: Date.now() });\n timeoutId = null;\n }, delay);\n } catch (error: any) {\n console.error('延迟执行失败:', error);\n clear();\n }\n });\n\n if (hasIn(\"delay\")) inputs.delay?.((val: DataType) => {\n try {\n const delay = val?.delay || data.delay || 1000;\n\n clear();\n\n outputs.onStart({ delay, timestamp: Date.now() });\n\n timeoutId = setTimeout(() => {\n outputs.onExecute({ delay, timestamp: Date.now() });\n timeoutId = null;\n }, delay);\n } catch (error: any) {\n console.error('延迟执行失败:', error);\n clear();\n }\n });\n\n if (hasIn(\"cancel\")) inputs.cancel?.(() => {\n try {\n if (timeoutId) {\n clear();\n outputs.onCancel('延迟任务已取消');\n } else {\n outputs.onCancel('没有正在执行的延迟任务');\n }\n } catch (error: any) {\n console.error('取消延迟失败:', error);\n }\n });\n};\n\n;(handler as any).__useCache = true\nexport default handler\n"
|
|
5607
5699
|
},
|
|
5608
5700
|
{
|
|
5609
5701
|
"path": "src/core/comlib/_TimerThrottle.ts",
|
|
5610
|
-
"content": "
|
|
5702
|
+
"content": "import throttle from 'lodash/throttle'\n\nexport type DataType = {\n delay?: number // 节流间隔时间(毫秒)\n leading?: boolean // 是否在开始时执行\n trailing?: boolean // 是否在结束时执行\n}\n\nexport interface Inputs {\n trigger?: (fn: (config: any, relOutputs?: any) => void) => void\n}\n\nexport interface Outputs {\n trigger: (value?: any) => void\n}\n\ninterface IOContext {\n data: DataType\n inputs: Inputs\n outputs: Outputs\n}\n\nconst handler = (context: IOContext) => {\n const data: DataType = context.data\n const inputs: Inputs = context.inputs\n const outputs: Outputs = context.outputs\n\n // 节流\n const throttleOutput = throttle(\n (val: any) => {\n outputs?.trigger?.(val)\n },\n data.delay,\n { leading: data.leading, trailing: data.trailing },\n )\n\n inputs.trigger?.((val: any) => {\n try {\n throttleOutput(val)\n } catch (error: any) {\n console.error('节流执行失败:', error)\n }\n })\n}\n\n;(handler as any).__useCache = true\nexport default handler\n"
|
|
5611
5703
|
},
|
|
5612
5704
|
{
|
|
5613
|
-
"path": "src/core/comlib/
|
|
5614
|
-
"content": "import
|
|
5705
|
+
"path": "src/core/comlib/_UploadFile.ts",
|
|
5706
|
+
"content": "import UploadOssHelper from '../tools/oss'\n\nexport type DataType = {\n mode?: 'custom' | 'quick';\n platform?: 'oss';\n custom?: {\n url: string;\n name: string;\n };\n oss?: {\n accessKeyId: string;\n accessKeySecret: string;\n host: string;\n };\n};\n\nexport interface Inputs {\n upload?: (fn: (config: any, relOutputs?: any) => void) => void;\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void;\n onFail: (value?: any) => void;\n}\n\nexport default function ({ env, data, inputs, outputs }: { env: any; data: DataType; inputs: Inputs; outputs: Outputs }) {\n if (!env.runtime) {\n return;\n }\n\n inputs[\"upload\"]?.((value: any) => {\n /** 自定义上传 */\n if (data.mode === \"custom\") {\n let params: any = {\n withCredentials: false,\n url: data.custom!.url,\n filePath: value.filePath,\n name: data.custom!.name,\n formData: {\n ...(value.formData || {}),\n },\n };\n\n if (typeof value.fileName === \"string\") {\n params.fileName = value.fileName;\n }\n\n env.uploadFile({\n ...params,\n success(res: any) {\n let resData = res.data;\n if (resData) {\n try {\n resData = JSON.parse(resData);\n } catch (err) {}\n }\n outputs[\"onSuccess\"](resData);\n },\n fail(err: any) {\n outputs[\"onFail\"](err);\n },\n });\n return;\n }\n\n /** 阿里云 OSS 上传 */\n if (data.mode === \"quick\" && data.platform === \"oss\") {\n const ossHelper = new UploadOssHelper({\n accessKeyId: data.oss!.accessKeyId,\n accessKeySecret: data.oss!.accessKeySecret,\n });\n\n const ossParams = ossHelper.createUploadParams();\n\n env.uploadFile({\n withCredentials: false,\n url: data.oss!.host,\n filePath: value.filePath,\n name: \"file\",\n formData: {\n ...(value.formData || {}),\n policy: ossParams.policy,\n OSSAccessKeyId: ossParams.OSSAccessKeyId,\n signature: ossParams.signature,\n },\n success(res: any) {\n if (res.statusCode === 204) {\n outputs[\"onSuccess\"](`${data.oss!.host}/${value.formData.key}`);\n } else {\n outputs[\"onFail\"](res);\n }\n },\n fail(err: any) {\n outputs[\"onFail\"](err);\n },\n });\n return;\n }\n });\n};\n"
|
|
5707
|
+
},
|
|
5708
|
+
{
|
|
5709
|
+
"path": "src/core/comlib/_WxPay.ts",
|
|
5710
|
+
"content": "import Taro from '@tarojs/taro'\n\nexport type DataType = {}\n\nexport type ValType = {\n nonce_str?: string\n nonceStr?: string\n timestamp?: string\n timeStamp?: string\n pay_sign?: string\n paySign?: string\n prepay_id?: string\n}\n\nexport interface Inputs {\n wx_requestPayment_body?: (fn: (val: ValType) => 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 inputs: Inputs = context.inputs\n const outputs: Outputs = context.outputs\n\n inputs.wx_requestPayment_body?.((val) => {\n const signType = 'RSA' //签名算法\n try {\n Taro.requestPayment({\n nonceStr: val.nonce_str ?? val.nonceStr, //兼容之前的下划线参数\n timeStamp: val.timestamp ?? val.timeStamp,\n signType,\n paySign: val.pay_sign ?? val.paySign,\n package: `prepay_id=${val.prepay_id}`,\n success: (res: any) => {\n outputs['onSuccess'](res)\n },\n fail: (err: any) => {\n outputs['onFail'](err)\n },\n })\n } catch (error: any) {\n console.error('微信支付弹窗失败:', error)\n outputs.onFail({\n errMsg: error?.message || '微信支付弹窗失败',\n })\n }\n })\n}\n"
|
|
5615
5711
|
},
|
|
5616
5712
|
{
|
|
5617
5713
|
"path": "src/core/comlib/Index.ts",
|
|
5618
|
-
"content": "//
|
|
5714
|
+
"content": "// 服务接口\nexport { default as mybricks_taro_connector } from './_Connector'\nexport type { DataType as mybricks_taro_connector_DataType } from './_Connector'\n\nexport { default as mybricks_taro_connectorGlobalHeaders } from './_ConnectorGlobalHeaders'\nexport type { DataType as mybricks_taro_connectorGlobalHeaders_DataType } from './_ConnectorGlobalHeaders'\n\n// 字符格式化\nexport { default as mybricks_taro_format } from './_Format'\nexport type { DataType as mybricks_taro_format_DataType } from './_Format'\n\n// 延迟执行\nexport { default as mybricks_taro_timerDelay } from './_TimerDelay'\nexport type { DataType as mybricks_taro_timerDelay_DataType } from './_TimerDelay'\n\n// 写入本地缓存\nexport { default as mybricks_taro_setStorage } from './_SetStorage'\nexport type { DataType as mybricks_taro_setStorage_DataType } from './_SetStorage'\n\n// 读取本地缓存\nexport { default as mybricks_taro_getStorage } from './_GetStorage'\nexport type { DataType as mybricks_taro_getStorage_DataType } from './_GetStorage'\n\n// 使用外链\nexport { default as mybricks_taro_open } from './_Open'\nexport type { DataType as mybricks_taro_open_DataType } from './_Open'\n\n// 跳转到\nexport { default as mybricks_taro_goto } from './_Goto'\nexport type { DataType as mybricks_taro_goto_DataType } from './_Goto'\n\n// 页面返回\nexport { default as mybricks_taro_navigateBack } from './_BackTo'\nexport type { DataType as mybricks_taro_navigateBack_DataType } from './_BackTo'\n\n// 获取路由信息\nexport { default as mybricks_taro_getRouter } from './_GetRouter'\nexport type { DataType as mybricks_taro_getRouter_DataType } from './_GetRouter'\n\n// 显示 Toast\nexport { default as mybricks_taro_showToast } from './_ShowToast'\nexport type { DataType as mybricks_taro_showToast_DataType } from './_ShowToast'\n\n// 隐藏 Toast\nexport { default as mybricks_taro_hideToast } from './_HideToast'\nexport type { DataType as mybricks_taro_hideToast_DataType } from './_HideToast'\n\n// 显示 Loading\nexport { default as mybricks_taro_showLoading } from './_ShowLoading'\nexport type { DataType as mybricks_taro_showLoading_DataType } from './_ShowLoading'\n\n// 隐藏 Loading\nexport { default as mybricks_taro_hideLoading } from './_HideLoading'\nexport type { DataType as mybricks_taro_hideLoading_DataType } from './_HideLoading'\n\n// 模态对话框\nexport { default as mybricks_taro_modal } from './_Modal'\nexport type { DataType as mybricks_taro_modal_DataType } from './_Modal'\n\n// 显示操作菜单\nexport { default as mybricks_taro_showActionSheet } from './_ShowActionSheet'\nexport type { DataType as mybricks_taro_showActionSheet_DataType } from './_ShowActionSheet'\n\n// 写入剪贴板\nexport { default as mybricks_taro_setClipboardData } from './_SetClipboardData'\nexport type { DataType as mybricks_taro_setClipboardData_DataType } from './_SetClipboardData'\n\n// 单文件上传\nexport { default as mybricks_taro_uploadFile } from './_UploadFile'\nexport type { DataType as mybricks_taro_uploadFile_DataType } from './_UploadFile'\n\n// 获取登录凭证\nexport { default as mybricks_taro_login } from './_Login'\nexport type { DataType as mybricks_taro_login_DataType } from './_Login'\n\n// 获取 scheme\nexport { default as mybricks_taro_generateScheme } from './_GenerateScheme'\nexport type { DataType as mybricks_taro_generateScheme_DataType } from './_GenerateScheme'\n\n// 设置当前页标题\nexport { default as mybricks_taro_setNavigationBarTitle } from './_SetNavigationBarTitle'\nexport type { DataType as mybricks_taro_setNavigationBarTitle_DataType } from './_SetNavigationBarTitle'\n\n// 扫码\nexport { default as mybricks_taro_scanQrcode } from './_ScanQrcode'\nexport type { DataType as mybricks_taro_scanQrcode_DataType } from './_ScanQrcode'\n\n// 选择图片或视频\nexport { default as mybricks_taro_chooseMedia } from './_ChooseMedia'\nexport type { DataType as mybricks_taro_chooseMedia_DataType } from './_ChooseMedia'\n\n// 文件选择\nexport { default as mybricks_taro_choosemessagefile } from './_ChooseMessageFile'\nexport type { DataType as mybricks_taro_choosemessagefile_DataType } from './_ChooseMessageFile'\n\n// 打开相机/相册\nexport { default as mybricks_taro_open_camera } from './_OpenCamera'\nexport type { DataType as mybricks_taro_open_camera_DataType } from './_OpenCamera'\n\n// 拨打电话\nexport { default as mybricks_taro_callPhone } from './_CallPhone'\nexport type { DataType as mybricks_taro_callPhone_DataType } from './_CallPhone'\n\n// 获取用户定位\nexport { default as mybricks_taro_getLocation } from './_GetLocation'\nexport type { DataType as mybricks_taro_getLocation_DataType } from './_GetLocation'\n\n// 地图选点\nexport { default as mybricks_taro_chooseLocation } from './_ChooseLocation'\nexport type { DataType as mybricks_taro_chooseLocation_DataType } from './_ChooseLocation'\n\n// 查询地址信息\nexport { default as mybricks_taro_mapservice_geocoder } from './_GetAddress'\nexport type { DataType as mybricks_taro_mapservice_geocoder_DataType } from './_GetAddress'\n\n// 路线规划\nexport { default as mybricks_taro_mapservice_drive } from './_GetDrivePath'\nexport type { DataType as mybricks_taro_mapservice_drive_DataType } from './_GetDrivePath'\n\n// 获取收货地址\nexport { default as mybricks_taro_chooseAddress } from './_ChooseAddress'\nexport type { DataType as mybricks_taro_chooseAddress_DataType } from './_ChooseAddress'\n\n// 查看位置\nexport { default as mybricks_taro_openLocation } from './_OpenLocation'\nexport type { DataType as mybricks_taro_openLocation_DataType } from './_OpenLocation'\n\n// 预览图片\nexport { default as mybricks_taro_previewImage } from './_PreviewImage'\nexport type { DataType as mybricks_taro_previewImage_DataType } from './_PreviewImage'\n\n// 保存图片到系统相册\nexport { default as mybricks_taro_saveImageToPhotosAlbum } from './_SaveImageToPhotosAlbum'\nexport type { DataType as mybricks_taro_saveImageToPhotosAlbum_DataType } from './_SaveImageToPhotosAlbum'\n\n// 保存视频到系统相册\nexport { default as mybricks_taro_saveVideoToPhotosAlbum } from './_SaveVideoToPhotosAlbum'\nexport type { DataType as mybricks_taro_saveVideoToPhotosAlbum_DataType } from './_SaveVideoToPhotosAlbum'\n\n// 图片绘制\nexport { default as mybricks_taro_poster } from './_Poster'\nexport type { DataType as mybricks_taro_poster_DataType } from './_Poster'\n\n// 订阅消息\nexport { default as mybricks_taro_requestSubscribeMessage } from './_RequestSubscribeMessage'\nexport type { DataType as mybricks_taro_requestSubscribeMessage_DataType } from './_RequestSubscribeMessage'\n\n// 设置底导红点\nexport { default as mybricks_taro_setTabbarBadge } from './_SetTabbarBadge'\nexport type { DataType as mybricks_taro_setTabbarBadge_DataType } from './_SetTabbarBadge'\n\n// 删除底导红点\nexport { default as mybricks_taro_removeTabBarBadge } from './_RemoveTabBarBadge'\nexport type { DataType as mybricks_taro_removeTabBarBadge_DataType } from './_RemoveTabBarBadge'\n\n// 微信支付弹窗\nexport { default as mybricks_taro_wxPay } from './_WxPay'\nexport type { DataType as mybricks_taro_wxPay_DataType } from './_WxPay'\n\n// 打开视频号\nexport { default as mybricks_taro_openChannelsActivity } from './_OpenChannelsActivity'\nexport type { DataType as mybricks_taro_openChannelsActivity_DataType } from './_OpenChannelsActivity'\n\n// 打开视频号主页\nexport { default as mybricks_taro_openChannelsUserProfile } from './_OpenChannelsUserProfile'\nexport type { DataType as mybricks_taro_openChannelsUserProfile_DataType } from './_OpenChannelsUserProfile'\n\n// 获取运动步数\nexport { default as mybricks_taro_getWeRunData } from './_GetWeRunData'\nexport type { DataType as mybricks_taro_getWeRunData_DataType } from './_GetWeRunData'\n\n// 人脸识别认证\nexport { default as mybricks_taro_startFacialRecognitionVerify } from './_StartFacialRecognitionVerify'\nexport type { DataType as mybricks_taro_startFacialRecognitionVerify_DataType } from './_StartFacialRecognitionVerify'\n\n// 防抖\nexport { default as mybricks_normalPc_timerDebounce } from './_TimerDebounce'\nexport type { DataType as mybricks_normalPc_timerDebounce_DataType } from './_TimerDebounce'\n\n// 节流\nexport { default as mybricks_normalPc_timerThrottle } from './_TimerThrottle'\nexport type { DataType as mybricks_normalPc_timerThrottle_DataType } from './_TimerThrottle'\n\n// AES加密\nexport { default as mybricks_taro_aesEncode } from './_AesEncode'\nexport type { DataType as mybricks_taro_aesEncode_DataType } from './_AesEncode'\n\n// AES解密\nexport { default as mybricks_taro_aesDecode } from './_AesDecode'\nexport type { DataType as mybricks_taro_aesDecode_DataType } from './_AesDecode'\n\n// 打开文档\nexport { default as mybricks_taro_openDocument } from './_OpenDocument'\nexport type { DataType as mybricks_taro_openDocument_DataType } from './_OpenDocument'\n"
|
|
5619
5715
|
}
|
|
5620
5716
|
]
|
|
5621
5717
|
},
|
|
@@ -5637,7 +5733,7 @@
|
|
|
5637
5733
|
},
|
|
5638
5734
|
{
|
|
5639
5735
|
"path": "src/core/mybricks/createJSHandle.js",
|
|
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//
|
|
5736
|
+
"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// 全局缓存,用于防抖/节流等需要保持状态的组件\nconst handleCache = new Map();\n\n/** 尝试从缓存获取 exe,命中时重置输出 Subject 状态 */\nconst getFromCache = (handleKey) => {\n if (!handleKey || !handleCache.has(handleKey)) return null;\n const cached = handleCache.get(handleKey);\n if (cached._rels) {\n Object.values(cached._rels).forEach((subject) => {\n subject._observers?.clear?.();\n subject._values = [];\n subject._empty = true;\n });\n }\n return cached;\n}\n\n/** 将 exe 存入缓存 */\nconst setToCache = (handleKey, exe, rels, needsCache) => {\n exe._rels = rels;\n if (handleKey && needsCache) {\n handleCache.set(handleKey, exe);\n }\n}\n\n// JS\nexport const createJSHandle = (fn, options, handleKey) => {\n const { props, appContext } = options\n\n const cached = getFromCache(handleKey);\n if (cached) return cached;\n\n const needsCache = fn.__useCache === true\n let controller\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 // 缓存 exeOutputs 的属性访问结果,避免每次访问 .trigger 等属性时创建新的 SubjectNext\n const exeOutputsCache = {}\n const exeOutputs = new Proxy(\n {},\n {\n get(_, key) {\n if (!exeOutputsCache[key]) {\n const subject = rels[key] || (rels[key] = new Subject({ log: `${EXE_TITLE_MAP[\"output\"]} ${props.title} | ${key}` }))\n exeOutputsCache[key] = subject\n }\n return exeOutputsCache[key]\n },\n },\n )\n\n // 记录已订阅的 Subject,避免重复订阅\n const subscribedSubjects = new Set()\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 // 如果已经订阅过这个 Subject,跳过\n if (subscribedSubjects.has(value)) {\n return\n }\n subscribedSubjects.add(value)\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 // 如果已经订阅过这个 Subject,跳过\n if (subscribedSubjects.has(value)) {\n return exeOutputs\n }\n subscribedSubjects.add(value)\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 setToCache(handleKey, exe, rels, needsCache);\n\n return exe;\n}\n\n"
|
|
5641
5737
|
},
|
|
5642
5738
|
{
|
|
5643
5739
|
"path": "src/core/mybricks/createModuleEventsHandle.js",
|
|
@@ -5665,7 +5761,7 @@
|
|
|
5665
5761
|
},
|
|
5666
5762
|
{
|
|
5667
5763
|
"path": "src/core/mybricks/Subject.js",
|
|
5668
|
-
"content": "import { log } from \"./log\"\nimport {\n SUBJECT_NEXT,\n SUBJECT_VALUE,\n SUBJECT_EMPTY,\n SUBJECT_SETVALUE,\n SUBJECT_SUBSCRIBE,\n SUBJECT_UNSUBSCRIBE\n} from \"./constant\"\n\n/** 数据流 */\nexport class Subject {\n _values = []\n _observers = new Set()\n _log = undefined\n _empty = true;\n\n constructor(params = {}) {\n this._log = params.log\n return new Proxy(this, {\n get(target, prop) {\n if (prop in target) {\n return target[prop];\n }\n\n const subjectNext = new SubjectNext(prop)\n\n
|
|
5764
|
+
"content": "import { log } from \"./log\"\nimport {\n SUBJECT_NEXT,\n SUBJECT_VALUE,\n SUBJECT_EMPTY,\n SUBJECT_SETVALUE,\n SUBJECT_SUBSCRIBE,\n SUBJECT_UNSUBSCRIBE\n} from \"./constant\"\n\n/** 数据流 */\nexport class Subject {\n _values = []\n _observers = new Set()\n _log = undefined\n _empty = true;\n\n constructor(params = {}) {\n this._log = params.log\n this._subjectNextCache = {}\n return new Proxy(this, {\n get(target, prop) {\n if (prop in target) {\n return target[prop];\n }\n\n // 缓存 SubjectNext,避免重复访问同一属性时创建新实例和新订阅\n if (!target._subjectNextCache[prop]) {\n const subjectNext = new SubjectNext(prop)\n\n target[SUBJECT_SUBSCRIBE]((value, extra) => {\n subjectNext[SUBJECT_NEXT](value, extra)\n })\n\n target._subjectNextCache[prop] = subjectNext\n }\n\n return target._subjectNextCache[prop]\n }\n })\n }\n\n get [SUBJECT_VALUE]() {\n return this._values[0]\n }\n\n get [SUBJECT_EMPTY]() {\n return this._empty;\n }\n\n [SUBJECT_SETVALUE](value) {\n this._values[0] = value;\n this._empty = false;\n }\n\n [SUBJECT_NEXT](value, extra) {\n log(this._log, JSON.stringify(value))\n this._values[0] = value\n this._empty = false\n this._observers.forEach((observer) => observer(value, extra))\n }\n\n [SUBJECT_SUBSCRIBE](observer) {\n if (this._values.length) {\n observer(this._values[0])\n }\n this._observers.add(observer)\n }\n\n [SUBJECT_UNSUBSCRIBE](observer) {\n this._observers.delete(observer)\n }\n}\n\nfunction getValueNextByPath(params) {\n const { value, path } = params\n let current = value\n for (const key of path) {\n if (current === null || current === undefined) {\n return undefined\n }\n current = current[key]\n }\n return current\n}\n\nclass SubjectNext extends Subject {\n _path = []\n\n constructor(path) {\n super()\n\n this._path.push(path)\n\n return new Proxy(this, {\n get(target, prop) {\n if (prop in target) {\n return target[prop];\n }\n\n target._path.push(prop)\n\n return target;\n }\n })\n }\n\n [SUBJECT_NEXT](value, extra) {\n this._values[0] = value\n this._empty = false\n const nextValue = getValueNextByPath({ value, path: this._path })\n this._observers.forEach((observer) => observer(nextValue, extra))\n }\n\n [SUBJECT_SUBSCRIBE](observer) {\n if (this._values.length) {\n observer(getValueNextByPath({ value: this._values[0], path: this._path }))\n }\n this._observers.add(observer)\n }\n}\n"
|
|
5669
5765
|
},
|
|
5670
5766
|
{
|
|
5671
5767
|
"path": "src/core/mybricks/utils.js",
|
|
@@ -5677,6 +5773,210 @@
|
|
|
5677
5773
|
}
|
|
5678
5774
|
]
|
|
5679
5775
|
},
|
|
5776
|
+
{
|
|
5777
|
+
"path": "src/core/tools",
|
|
5778
|
+
"content": null,
|
|
5779
|
+
"children": [
|
|
5780
|
+
{
|
|
5781
|
+
"path": "src/core/tools/com-utils",
|
|
5782
|
+
"content": null,
|
|
5783
|
+
"children": [
|
|
5784
|
+
{
|
|
5785
|
+
"path": "src/core/tools/com-utils/expressionSandbox.ts",
|
|
5786
|
+
"content": "type Options = Partial<{\n prefix: string;\n context: Record<string, any>;\n}>;\n\nexport default class Sandbox {\n private options: Options = {};\n constructor(options: Options) {\n this.options = options;\n }\n private unscopeCompileCode(prefix: string = 'context', expression: string) {\n return new Function(\n prefix,\n `with(${prefix}){\n return ${expression}\n }`\n );\n }\n private scopeCompileCode(expression: string) {\n const fn = this.unscopeCompileCode(this.options.prefix, expression);\n return (sandbox) => {\n const _target = this.options.prefix ? { [this.options.prefix]: sandbox } : sandbox;\n const proxy = new Proxy(_target, {\n // 拦截所有属性,防止到 Proxy 对象以外的作用域链查找\n has(target, key) {\n return true;\n },\n get(target, key, receiver) {\n // 防止沙箱逃逸逃逸\n if (key === Symbol.unscopables) {\n return undefined;\n }\n return Reflect.get(target, key, receiver);\n }\n });\n return fn(proxy);\n };\n }\n execute(expression: string) {\n const fn = this.scopeCompileCode(expression);\n const _context = this.options.context ?? {};\n return fn.call(this, _context);\n }\n executeWithTemplate(expression: string) {\n const reg = /\\{([^\\{\\}]*?|.+)\\}/g;\n const matchIterator = expression.matchAll(reg);\n const iteratorArray = Array.from(matchIterator);\n if (!iteratorArray.length) return expression;\n const retGroup = iteratorArray.map((it) => {\n const match = it[0];\n const input = it.input;\n let ret = it[1];\n if (!!ret.trim()) {\n ret = this.execute(ret);\n }\n return {\n match,\n ret,\n input\n };\n });\n const retStr = retGroup.reduce((pre, cur) => {\n const { match, ret } = cur;\n if (match === expression && ret === undefined) {\n return ret;\n }\n return pre.replace(match, typeof ret === 'string' ? ret : JSON.stringify(ret));\n }, expression);\n try {\n return JSON.parse(retStr);\n } catch (error) {\n return retStr;\n }\n }\n}\n"
|
|
5787
|
+
},
|
|
5788
|
+
{
|
|
5789
|
+
"path": "src/core/tools/com-utils/index.ts",
|
|
5790
|
+
"content": "import Sandbox from './sandbox';\nimport utils from './utils';\n\ninterface Props {\n env?: any;\n callback?: () => any;\n}\nexport function runJs(scriptText: string | any, model?: any[], props?: Props) {\n const { env, callback = () => {} } = props || {};\n const isRuntime = env?.runtime && !env?.runtime?.debug;\n if (typeof scriptText === 'object') {\n scriptText = isRuntime ? scriptText?.transformCode || scriptText?.code : scriptText?.code;\n }\n\n let fn = null;\n if (model && model.length) {\n const sandBox = new Sandbox({ module: true });\n let sourceStr = decodeURIComponent(scriptText);\n if (/export\\s+default.*async.*function.*\\(/g.test(sourceStr)) {\n fn = sandBox.compile(\n `${sourceStr.replace(/export\\s+default.*function.*\\(/g, 'async function _RT_(')}`\n );\n } else {\n fn = sandBox.compile(\n `${sourceStr.replace(/export\\s+default.*function.*\\(/g, 'function _RT_(')}`\n );\n }\n } else {\n const sandBox = new Sandbox();\n fn = sandBox.compile(`${decodeURIComponent(scriptText)}`);\n }\n\n return fn.run(model, callback);\n}\n\nexport { utils };\nexport { default as ExpressionSandbox } from './expressionSandbox';\n"
|
|
5791
|
+
},
|
|
5792
|
+
{
|
|
5793
|
+
"path": "src/core/tools/com-utils/sandbox.ts",
|
|
5794
|
+
"content": "const rawWindowInterval = window.setInterval\nconst rawWindowClearInterval = window.clearInterval\nconst rawWindowTimeout = window.setTimeout\nconst rawWindowClearTimeout = window.clearTimeout\nconst originWindow = window\n\nconst constructableMap = new WeakMap<any | FunctionConstructor, boolean>()\nfunction isConstructable(fn: () => any | FunctionConstructor) {\n if (constructableMap.has(fn)) {\n return constructableMap.get(fn)\n }\n\n const constructableFunctionRegex = /^function\\b\\s[A-Z].*/;\n const classRegex = /^class\\b/;\n\n const constructable =\n (fn.prototype && fn.prototype.constructor === fn && Object.getOwnPropertyNames(fn.prototype).length > 1) ||\n constructableFunctionRegex.test(fn.toString()) ||\n classRegex.test(fn.toString());\n constructableMap.set(fn, constructable)\n return constructable\n}\n\nconst isCallable = (fn: any) => typeof fn === 'function';\n\nconst boundedMap = new WeakMap<CallableFunction, boolean>();\nfunction isBoundedFunction(fn: CallableFunction) {\n if (boundedMap.has(fn)) {\n return boundedMap.get(fn);\n }\n const bounded = fn.name.indexOf('bound ') === 0 && !fn.hasOwnProperty('prototype')\n boundedMap.set(fn, bounded);\n return bounded;\n}\n\nconst functionBoundedValueMap = new WeakMap<CallableFunction, CallableFunction>()\nfunction getTargetValue(target: any, value: any): any {\n const cachedBoundFunction = functionBoundedValueMap.get(value);\n if (cachedBoundFunction) {\n return cachedBoundFunction;\n }\n\n const boundValue = Function.prototype.bind.call(value, target);\n for (const key in value) {\n boundValue[key] = value[key];\n }\n if (value.hasOwnProperty('prototype') && !boundValue.hasOwnProperty('prototype'))\n boundValue.prototype = value.prototype;\n\n functionBoundedValueMap.set(value, boundValue);\n return boundValue;\n}\n\ntype FakeWindow = Window & Record<PropertyKey, any>\n\nconst unscopables = {\n undefined: true,\n Array: true,\n Object: true,\n String: true,\n Boolean: true,\n Math: true,\n Number: true,\n Symbol: true,\n parseFloat: true,\n Float32Array: true,\n}\n\nfunction getModuleScript(scriptText: string) {\n return `(\n function(window, params, cb) {\n with(window) {\n return (${scriptText})(...params, cb)\n }\n }\n )`\n}\n\n\nfunction getScript(scriptText: string) {\n return `(\n function(window) {\n with(window){\n ${scriptText}\n } \n }\n ).bind(window.proxy)\n `\n}\n\n/**\n * 创建fakeWindow\n * @returns fakeWindow\n */\nfunction createFakeWindow() {\n const fakeWindow = {};\n Object.getOwnPropertyNames(originWindow).forEach((key) => {\n const descriptor = Object.getOwnPropertyDescriptor(originWindow, key)\n if (descriptor && !descriptor.configurable) {\n const hasGetter = Object.prototype.hasOwnProperty.call(descriptor, 'get')\n if (key === 'top' || key === 'parent' || key === 'self' || key === 'window') {\n descriptor.configurable = true;\n if (!hasGetter) {\n descriptor.writable = true;\n }\n }\n Object.defineProperty(fakeWindow, key, Object.freeze(descriptor));\n }\n })\n return fakeWindow;\n}\n\n/**\n * 将 window 的属性 p 拷贝到 fakeWindow\n * @param p \n * @param fakeWindow \n */\nfunction copyFromWindow(p: string, fakeWindow: FakeWindow) {\n const descriptor = Object.getOwnPropertyDescriptor(window, p);\n if (descriptor && descriptor.writable) {\n Object.defineProperty(fakeWindow, p, {\n configurable: descriptor.configurable,\n enumerable: descriptor.enumerable,\n writable: descriptor.writable,\n value: descriptor.value\n });\n }\n}\n\nclass Sandbox {\n proxy: Window;\n hasDisposed = false;\n fakeWindow = createFakeWindow();\n timeoutList = [];\n intervalList = [];\n options = {};\n // @ts-ignore\n constructor(options = {}) {\n this.options = options || {};\n this.proxy = new Proxy(window, {\n set: (target, key, value) => {\n if (!this.hasDisposed) {\n try {\n if (!this.fakeWindow.hasOwnProperty(key) && target.hasOwnProperty(key)) {\n // @ts-ignore\n copyFromWindow(key, this.fakeWindow);\n }\n // @ts-ignore\n this.fakeWindow[key] = value; // 赋值\n } catch (error) {\n console.error('set-key-error', key, error)\n throw error\n }\n }\n return true;\n },\n get: (target, key) => {\n if (key === Symbol.unscopables) {\n return unscopables;\n }\n if (key === 'window' || key === 'self') {\n return this.proxy;\n }\n if (key === 'document') {\n return undefined;\n }\n if (key === 'hasOwnProperty') {\n return target.hasOwnProperty;\n }\n if (key === 'eval') {\n return target.eval;\n }\n\n if (key === 'location') {\n return target.location;\n }\n\n try {\n // @ts-ignore\n var value = key in this.fakeWindow ? this.fakeWindow[key] : target[key];\n\n // 仅绑定 isCallable && !isBoundedFunction && !isConstructable 的函数对象,如 window.console、window.atob 这类,\n // 不然微应用中调用时会抛出 Illegal invocation 异常\n if (isCallable(value) && !isBoundedFunction(value) && !isConstructable(value)) {\n value = Function.prototype.bind.call(value, target);\n return getTargetValue(window, value);\n }\n\n return value;\n } catch (error) {\n console.error('get-key-error', key, error)\n throw error\n }\n },\n has: (target, key) => {\n // @ts-ignore\n if (this.options.module) { //参数允许逃逸到函数局部变量\n if (key === 'params' || key === 'cb') {\n return false;\n }\n }\n return true; // 伪造属性的存在性阻止沙盒逃逸\n },\n })\n\n this.proxy.setTimeout = (handler, timeout, ...args) => {\n if (!this.hasDisposed) {\n const timeoutId = rawWindowTimeout(handler, timeout, ...args)\n // @ts-ignore\n this.timeoutList.push(timeoutId)\n return timeoutId;\n } else {\n return 0\n }\n }\n\n this.proxy.clearTimeout = (timeoutId) => {\n // @ts-ignore\n const timeoutIndex = this.timeoutList.indexOf(timeoutId)\n if (timeoutIndex !== -1) {\n this.timeoutList.splice(timeoutIndex, 1)\n }\n return rawWindowClearTimeout(timeoutId)\n }\n\n this.proxy.setInterval = (handler, timeout, ...args) => {\n if (!this.hasDisposed) {\n const intervalId = rawWindowInterval(handler, timeout, ...args);\n // @ts-ignore\n this.intervalList.push(intervalId)\n return intervalId;\n } else {\n return 0\n }\n }\n\n this.proxy.clearInterval = (intervalId) => {\n // @ts-ignore\n const intervalIndex = this.intervalList.indexOf(intervalId)\n if (intervalIndex !== -1) {\n this.intervalList.splice(intervalIndex, 1)\n }\n return rawWindowClearInterval(intervalId)\n }\n\n // @ts-ignore\n originWindow.proxy = this.proxy;\n }\n\n // @ts-ignore\n compile(scriptText) {\n if (this.hasDisposed) {\n throw new Error('sandbox has been destroyed')\n }\n\n // @ts-ignore\n var isModule = this.options.module;\n var scriptTextWithSandbox;\n if (isModule) {\n scriptTextWithSandbox = getModuleScript(scriptText);\n } else {\n scriptTextWithSandbox = getScript(scriptText);\n }\n\n const fn = originWindow.eval(`${scriptTextWithSandbox};//@ sourceURL=sandbox-code.js`);\n\n return {\n // @ts-ignore\n run: function (model, cb) {\n try {\n if (isModule) {\n // @ts-ignore\n return fn(window.proxy, model, cb);\n } else {\n // @ts-ignore\n return fn(window.proxy);\n }\n } catch (err) {\n console.error(\"js sandbox error occur:\", err);\n throw err;\n }\n }\n }\n }\n\n //沙箱销毁功能\n dispose() {\n this.timeoutList.forEach((timeoutId) => {\n window.clearTimeout(timeoutId);\n });\n this.timeoutList = [];\n\n this.intervalList.forEach((intervalId) =>\n rawWindowClearInterval(intervalId)\n )\n this.intervalList = []\n\n this.fakeWindow = createFakeWindow();\n this.options = {};\n\n // @ts-ignore\n delete originWindow.proxy;\n this.hasDisposed = true;\n console.log('Sandbox was successfully destroyed')\n }\n}\n\nexport default Sandbox;\n\n\n"
|
|
5795
|
+
},
|
|
5796
|
+
{
|
|
5797
|
+
"path": "src/core/tools/com-utils/utils.ts",
|
|
5798
|
+
"content": "\nfunction isEmailPrefix(str: string) {\n return /^[a-zA-Z]+[\\d\\w_-]*$/.test(str)\n}\n\nfunction isNumber(str: string) {\n return /^\\d+$/.test(str)\n}\n\nfunction isCommaNumber(str: string) {\n return /^\\d+(,\\d+)*$/.test(str)\n}\n\nfunction numToPercent(num: number, bit: number) {\n if(num === void 0) return 'input error';\n return `${(num * 100).toFixed(bit || 2)}%`\n}\n\nfunction isUrl (url: string) {\n return /^((https?):\\/\\/)?((?:[\\w-]+\\.)+[a-z0-9]+)((?:\\/[^/?#]*)+)?(\\?[^#]+)?(#.+)?$/i.test(url)\n}\n\nfunction getCookies() {\n return document.cookie.split('; ').reduce((s: any, e) => {\n const p = e.indexOf('=');\n s[e.slice(0, p)] = e.slice(p + 1);\n return s;\n }, {});\n}\n\nfunction getParams() {\n return location.search\n .slice(1)\n .split('&')\n .reduce(function (s: any, a) {\n let m = a.split('=');\n if (m[0]) {\n s[m[0]] = decodeURIComponent(m[1]);\n }\n return s;\n }, {});\n}\n\ninterface Props {\n presets?: string[];\n errorCallback?: (val: any) => void;\n babelInstance?: any;\n}\nconst transformCodeByBabel = (val: string, props?: Props) => {\n const {\n presets,\n errorCallback,\n babelInstance = (window as any)?.Babel\n } = props || {};\n if (\n typeof babelInstance?.transform !== 'function' ||\n typeof val !== 'string'\n ) {\n return val;\n }\n const res = {\n code: val,\n transformCode: ''\n };\n try {\n let temp = decodeURIComponent(val);\n if (/export\\s+default.*async.*function.*\\(/g.test(temp)) {\n temp = temp.replace(\n /export\\s+default.*function.*\\(/g,\n '_RTFN_ = async function _RT_('\n );\n } else if (/export\\s+default.*function.*\\(/g.test(temp)) {\n temp = temp.replace(\n /export\\s+default.*function.*\\(/g,\n '_RTFN_ = function _RT_('\n );\n } else {\n temp = `_RTFN_ = ${temp} `\n }\n res.transformCode = encodeURIComponent(\n babelInstance.transform(temp, {\n presets: presets || ['env'],\n comments: false,\n }).code\n );\n res.transformCode = `${encodeURIComponent(`(function() { var _RTFN_; \\n`)}${\n res.transformCode\n }${encodeURIComponent(`\\n; return _RTFN_; })()`)}`;\n } catch (e) {\n if (typeof errorCallback === 'function') {\n errorCallback(e);\n }\n return val;\n }\n return res;\n};\n\nexport default {\n isEmailPrefix,\n isCommaNumber,\n numToPercent,\n isNumber,\n isUrl,\n getCookies,\n getParams,\n transformCodeByBabel\n};\n"
|
|
5799
|
+
}
|
|
5800
|
+
]
|
|
5801
|
+
},
|
|
5802
|
+
{
|
|
5803
|
+
"path": "src/core/tools/connector",
|
|
5804
|
+
"content": null,
|
|
5805
|
+
"children": [
|
|
5806
|
+
{
|
|
5807
|
+
"path": "src/core/tools/connector/constants.ts",
|
|
5808
|
+
"content": "export const ConnectorFiledName = '_connector'"
|
|
5809
|
+
},
|
|
5810
|
+
{
|
|
5811
|
+
"path": "src/core/tools/connector/editor.ts",
|
|
5812
|
+
"content": "import { ConnectorFiledName } from './constants'\n\nexport const connectorEditor = <T>(params: {\n set?: (params: any, result: { schema: any }) => void;\n remove?: (params: any) => void;\n}) => {\n\n const { set, remove } = params;\n\n return {\n \"@connector\": {\n get: ({ data }) => {\n return data[ConnectorFiledName]?.connector;\n },\n async set(params, connector) {\n const outputSchema = connector.markList[0].outputSchema;\n params.data[ConnectorFiledName] = {\n // globalMock: connector.globalMock\n outputSchema,\n connector: {\n id: connector.id,\n title: connector.title,\n type: connector.type,\n connectorName: connector.connectorName,\n script: connector.script\n }\n }\n\n set?.(params as T, { schema: outputSchema });\n },\n remove(params) {\n Reflect.deleteProperty(params.data, ConnectorFiledName);\n remove?.(params as T);\n }\n }\n }\n}\n"
|
|
5813
|
+
},
|
|
5814
|
+
{
|
|
5815
|
+
"path": "src/core/tools/connector/runtime.ts",
|
|
5816
|
+
"content": "import { useRef, useEffect, useMemo } from \"react\";\nimport { ConnectorFiledName } from './constants'\n\nexport const useConnector = ({ env, data }, callback) => {\n const stateRef = useRef({\n init: false,\n stop: false,\n });\n\n const connector = data[ConnectorFiledName]\n\n useEffect(() => {\n if (connector && !stateRef.current.stop) {\n callback(new Promise((resolve, reject) => {\n env.callConnector(\n connector.connector,\n {},\n { \n outputSchema: connector.outputSchema,\n isMultipleOutputs: false,\n },\n ).then((res) => {\n if (!stateRef.current.stop) {\n resolve(res);\n }\n }).catch((err) => {\n if (!stateRef.current.stop) {\n reject(err);\n }\n })\n }), stateRef.current);\n }\n }, [connector])\n\n return stateRef.current;\n}"
|
|
5817
|
+
}
|
|
5818
|
+
]
|
|
5819
|
+
},
|
|
5820
|
+
{
|
|
5821
|
+
"path": "src/core/tools/core",
|
|
5822
|
+
"content": null,
|
|
5823
|
+
"children": [
|
|
5824
|
+
{
|
|
5825
|
+
"path": "src/core/tools/core/array.ts",
|
|
5826
|
+
"content": "/**\n * array like to realy array\n * @param value 类数组\n * @returns 数组\n */\nexport function toArray(value: unknown) {\n return Array.prototype.slice.call(value)\n}\n"
|
|
5827
|
+
},
|
|
5828
|
+
{
|
|
5829
|
+
"path": "src/core/tools/core/function.ts",
|
|
5830
|
+
"content": "import { toArray } from './array'\n\nexport function noop(..._args: unknown[]): any\n/**\n * 空函数\n */\n// tslint:disable-next-line\nexport function noop(): void {}\n\n/**\n * 防抖函数\n * @param fn 执行函数\n * @param delay 延迟时间\n * @returns 防抖函数\n */\nexport function debounce(fn: (...args: unknown[]) => any, delay = 200) {\n let timer: any\n return function(this: any) {\n const args = arguments\n\n clearTimeout(timer)\n timer = setTimeout(() => {\n fn.apply(this, toArray(args))\n }, delay)\n return timer\n } as (...args: unknown[]) => NodeJS.Timeout\n}\n\n/**\n * 节流函数\n * @param fn 执行函数\n * @param delay: 延迟时间\n * @returns 节流函数\n */\nexport function throttle(fn: (...args: unknown[]) => any, delay = 200) {\n let timer: any\n return function(this: any) {\n if (timer) {\n return\n }\n\n const args = arguments\n timer = setTimeout(() => {\n fn.apply(this, toArray(args))\n timer = null\n }, delay)\n return timer\n } as (...args: unknown[]) => NodeJS.Timeout\n}\n\n/**\n * 缓存函数结果\n * @param fn\n * @returns function\n */\nexport function cached<T>(fn: (value: string) => T): (value: string) => T {\n // create no prototype object\n const cache = Object.create(null)\n return function cachedFn(value: string) {\n const hit = cache[value]\n return hit || (cache[value] = fn(value))\n }\n}\n"
|
|
5831
|
+
},
|
|
5832
|
+
{
|
|
5833
|
+
"path": "src/core/tools/core/index.ts",
|
|
5834
|
+
"content": "export * from './type'\nexport * from './array'\nexport * from './object'\nexport * from './function'\nexport * from './string'\nexport * from './interator'\nexport * from './merge'\nexport * from './json'\n"
|
|
5835
|
+
},
|
|
5836
|
+
{
|
|
5837
|
+
"path": "src/core/tools/core/interator.ts",
|
|
5838
|
+
"content": "import { isArray, isObject } from './type'\nimport { hasOwn } from './object'\n\n// interface Obj {\n// [key: number]: any\n// [key: string]: any\n// }\n\n/**\n * 循环对象和数组\n * @param obj 对象或者数组\n * @param fn 回调函数\n */\nexport function forEach<T = Record<number | string, any>>(\n obj: T,\n fn: (value: any, index?: number | string, obj?: T) => void\n): void {\n if (isArray(obj)) {\n // Iterate over array values\n for (let i = 0, l = obj.length; i < l; i++) {\n fn.call(null, obj[i], i, obj)\n }\n } else if (isObject(obj)) {\n // Iterate over object keys\n for (const key in obj) {\n if (hasOwn(obj, key)) {\n fn.call(null, obj[key], key, obj)\n }\n }\n }\n}\n"
|
|
5839
|
+
},
|
|
5840
|
+
{
|
|
5841
|
+
"path": "src/core/tools/core/json.ts",
|
|
5842
|
+
"content": "/**\n * 将JSON转为JavaScript对象\n * @param value string 合法的JSON字符串\n * @param reviver function 对结果进行转换的函数。该函数会被对象中的每一个成员调用,如果一个成员的值是一个嵌套对象,则嵌套对象会先于父对象被转换\n * @return any\n */\nexport function parseJSON(\n value: string,\n reviver?: (this: any, key: string, value: any) => any\n): any {\n try {\n return JSON.parse(value, reviver)\n } catch (error) {\n return undefined\n }\n}\n\nexport type ReplacerType =\n | ((this: any, key: string, value: any) => any)\n | Array<number | string>\n | null\n\n/**\n * 将JavaScript值转为JSON字符串\n * @param value 将被转换的JavaScript值,通常是一个对象或数组\n * @param replacer\n * 1. 可以是一个函数,用来转换结果\n * 2. 也可以是一个字符串或数字数组,用作选择要进行字符串化的对象属性的允许列表\n * @param space 添加缩进,空格和换行符到返回值JSON文本中,增加可读性\n */\nexport function stringifyJSON(\n value: any,\n replacer?: ReplacerType,\n space?: string | number\n): string | undefined {\n try {\n return JSON.stringify(\n value,\n replacer as Array<number | string> | null,\n space\n )\n } catch (error) {\n return undefined\n }\n}\n"
|
|
5843
|
+
},
|
|
5844
|
+
{
|
|
5845
|
+
"path": "src/core/tools/core/merge.ts",
|
|
5846
|
+
"content": "import { isBoolean, isArray, isObject } from './type'\nimport { forEach } from './interator'\n\n/**\n * 深拷贝\n * @param deep 是否是深度拷贝\n * @param target 目标对象\n * @param sources 多个源对象\n * @returns target 目标对象\n */\nexport function merge(deep: boolean, target: any, ...sources: unknown[]): any\n\n/**\n * 浅拷贝\n * @param target 目标对象\n * @param sources 多个源对象\n * @returns target 目标对象\n */\nexport function merge(target: any, ...sources: unknown[]): any\n\n/**\n * 合并多个对象\n * @param targetOrDeep 目标对象或者是否深度合并\n * @param sources 多个源对象\n * @returns target 目标对象\n */\nexport function merge(\n targetOrDeep: boolean | Record<string | number, any>,\n ...sources: unknown[]\n): Record<string | number, any> {\n let deep: boolean\n let target: any\n\n if (isBoolean(targetOrDeep)) {\n deep = targetOrDeep\n target = sources.shift()\n } else {\n target = targetOrDeep\n }\n forEach(sources, (source: unknown) => {\n forEach(source, (value, key) => {\n if (deep && (isArray(value) || isObject(value))) {\n if (isArray(value)) {\n if (!isArray(target[key!])) {\n target[key!] = []\n }\n } else {\n if (!isObject(target[key!])) {\n target[key!] = {}\n }\n }\n merge(deep, target[key!], value)\n } else {\n target[key!] = value\n }\n })\n })\n return target\n}\n"
|
|
5847
|
+
},
|
|
5848
|
+
{
|
|
5849
|
+
"path": "src/core/tools/core/object.ts",
|
|
5850
|
+
"content": "/**\n * 对象是否有某个实例属性\n * @param obj 对象\n * @param key 对象的属性\n */\nexport function hasOwn(obj: Record<string | number, any>, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\n\ntype ValueOf<T> = T[keyof T];\n\nexport function reverseKV<T extends { [key: string]: any }, K extends keyof T>(obj: T): { [V in T[K]]: K } {\n return Object.keys(obj).reduce((res, item) => {\n res[obj[item]] = item;\n return res;\n }, {} as { [V in T[K]]: K });\n}\n"
|
|
5851
|
+
},
|
|
5852
|
+
{
|
|
5853
|
+
"path": "src/core/tools/core/string.ts",
|
|
5854
|
+
"content": "import { isEmpty } from './type'\nimport { cached } from './function'\n\n/**\n * 比较两个版本\n * @param a 版本a\n * @param b 版本b\n * @returns 0:a===b,1:a>b,-1:a<b,其余异常情况均为undefined\n */\nexport function compareVersion(a: string, b: string): 0 | 1 | -1 | void {\n if (isEmpty(a) || isEmpty(b)) {\n return\n }\n if (a === b) {\n return 0\n }\n const sa = a.split('.')\n const sb = b.split('.')\n const min = Math.min(sa.length, sb.length)\n\n // loop while the components are equal\n for (let i = 0; i < min; i++) {\n const ai = parseInt(sa[i], 10)\n const bi = parseInt(sb[i], 10)\n\n if (isNaN(ai) || isNaN(bi)) {\n return\n }\n // A bigger than B\n if (ai > bi) {\n return 1\n }\n // B bigger than A\n if (ai < bi) {\n return -1\n }\n }\n // If one's a prefix of the other, the longer one is greater.\n // 1.2.0 > 1.2\n if (sa.length > sb.length) {\n return 1\n }\n if (sa.length < sb.length) {\n return -1\n }\n}\n\nconst camelizeRE = /-(\\w)/g\n/**\n * 驼峰\n * @param str\n * @returns aBC\n * 例如 输入a-b-c 返回aBC\n */\nexport function camelize(str: string): string {\n const cache = cached(str => {\n return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''))\n })\n return cache(str)\n}\n\nconst decamelizeRE = /([A-Z])/g\n/**\n * 取消驼峰\n * @param str\n * @returns a-b-c\n * 例如 输入aBC 返回a-b-c\n */\nexport function decamelize(str: string): string {\n const cache = cached((str: string): string => {\n return str.replace(decamelizeRE, '-$1').toLowerCase()\n })\n return cache(str)\n}\n"
|
|
5855
|
+
},
|
|
5856
|
+
{
|
|
5857
|
+
"path": "src/core/tools/core/type.ts",
|
|
5858
|
+
"content": "type IsType = (value: any) => boolean\n\nfunction isType(type: string): IsType {\n return value => Object.prototype.toString.call(value) === `[object ${type}]`\n}\n\n/**\n * 判断是否是未定义\n * @param value 入参cd\n * @returns true/false,undefined、null返回true\n */\nexport function isUndef(value: unknown): value is undefined | null {\n return value === undefined || value === null\n}\n\n/**\n * 判断是否为空 undefined、null、空字符串返回true\n * @param value 入参\n */\nexport function isEmpty(value: unknown): value is undefined | null | '' {\n return value === undefined || value === null || value === ''\n}\n\n/**\n * 判断是否为Number类型\n * @param value 入参\n */\nexport function isNumber(value: unknown): value is number {\n return isType('Number')(value)\n}\n\n/**\n * 判断是否为String类型\n * @param value 入参\n */\nexport function isString(value: unknown): value is string {\n return isType('String')(value)\n}\n\n/**\n * 判断是否为Error类型\n * @param value 入参\n */\nexport function isError(value: unknown): value is Error {\n return isType('Error')(value)\n}\n\n/**\n * 判断是否为Array类型\n * @param value 入参\n */\nexport function isArray(value: unknown): value is unknown[] {\n return isType('Array')(value)\n}\n\n/**\n * 判断是否为Function类型,async function为true\n * @param value 入参\n */\nexport function isFunction(value: unknown): value is Function {\n return typeof value === 'function'\n}\n\n/**\n * 判断是否为Date类型\n * @param value 入参\n */\nexport function isDate(value: unknown): value is Date {\n return isType('Date')(value)\n}\n\n/**\n * 判断是否为Boolean 类型\n * @param value 入参\n */\nexport function isBoolean(value: unknown): value is boolean {\n return isType('Boolean')(value)\n}\n\n/**\n * 判断是否为严格Object类型\n * @param value 入参\n */\nexport function isObject(value: unknown): value is Object {\n return isType('Object')(value)\n}\n\n/**\n * 判断是否为泛object,不包括null\n * @param value 入参\n */\nexport function isWideObject(value: unknown): boolean {\n return value !== null && typeof value === 'object'\n}\n\n/**\n * 是否为FormData实例 不支持FormData时返回false\n * @param value - 入参\n */\nexport function isFormData(value: unknown): value is FormData {\n return typeof FormData !== 'undefined' && value instanceof FormData\n}\n\n/**\n * 是否为URLSearchParams实例 不支持URLSearchParams时返回false\n * @param value - 入参\n */\nexport function isURLSearchParams(value: unknown): value is URLSearchParams {\n return (\n typeof URLSearchParams !== 'undefined' &&\n value instanceof URLSearchParams\n )\n}\n"
|
|
5859
|
+
}
|
|
5860
|
+
]
|
|
5861
|
+
},
|
|
5862
|
+
{
|
|
5863
|
+
"path": "src/core/tools/dynamic-array",
|
|
5864
|
+
"content": null,
|
|
5865
|
+
"children": [
|
|
5866
|
+
{
|
|
5867
|
+
"path": "src/core/tools/dynamic-array/index.tsx",
|
|
5868
|
+
"content": "import * as React from \"react\";\n\nconst DynamicEditors = ({ data, keyName, onSwitch }) => {\n return (\n <div style={{ position: \"relative\", marginTop: -15 }}>\n {data[keyName] ? (\n <div>\n <div>关闭动态数据源</div>\n <button\n onClick={() => {\n data[keyName] = false;\n onSwitch?.(data[keyName]);\n }}\n >\n 关闭\n </button>\n </div>\n ) : (\n <div>\n <div>开启动态数据源</div>\n <button\n onClick={() => {\n data[keyName] = true;\n onSwitch?.(data[keyName]);\n }}\n >\n 开启\n </button>\n </div>\n )}\n </div>\n );\n};\n\nexport class DynamicArrayData {\n keyName: string;\n\n constructor({ keyName }) {\n this.keyName = keyName;\n }\n\n init = () => {};\n\n editors = ({ data }, { title = \"数据源\", array, effects }) => {\n const keyName = this.keyName;\n\n const modeKeyName = `${keyName}_dynamic`;\n\n const onSwitch = (value) => {\n if (value) {\n effects?.onSwitchToDynamic?.(data[keyName])\n } else {\n effects?.onSwitchToStatic?.(data[keyName])\n }\n };\n\n return {\n title,\n items: [\n {\n title: \"\",\n type: \"editorRender\",\n options: {\n render: () => {\n return (\n <div style={{ marginTop: -36 }}></div>\n );\n },\n },\n },\n {\n title: \"数据源\",\n type: \"array\",\n ifVisible({ data }) {\n return !!!data[modeKeyName];\n },\n options: array.options,\n value: {\n get({ data }) {\n return data[keyName];\n },\n set(context, value) {\n const { data } = context;\n let action = computedAction({\n before: data[keyName],\n after: value,\n });\n\n switch (action?.name) {\n case \"remove\":\n effects.onRemove?.(context, action);\n break;\n case \"add\":\n effects.onAdd?.(context, action);\n break;\n case \"update\":\n effects.onUpdate?.(context, action);\n break;\n }\n data[keyName] = value;\n },\n },\n },\n // {\n // title: \"\",\n // type: \"editorRender\",\n // options: {\n // render: () => {\n // return (\n // <DynamicEditors\n // data={data}\n // keyName={modeKeyName}\n // onSwitch={onSwitch}\n // />\n // );\n // },\n // },\n // },\n ],\n };\n };\n}\n\nfunction computedAction({ before = [], after = [] }) {\n let beforeIds = before.map((item) => item._id);\n let afterIds = after.map((item) => item._id);\n\n switch (true) {\n case before.length > after.length: {\n let diffId = beforeIds.filter((x) => !afterIds.includes(x))[0];\n let diffItem = before.filter((x) => diffId.includes(x._id))[0];\n return {\n name: \"remove\",\n value: diffItem,\n };\n }\n case before.length < after.length: {\n let diffId = afterIds.filter((x) => !beforeIds.includes(x))[0];\n let diffItem = after.filter((x) => diffId.includes(x._id))[0];\n return {\n name: \"add\",\n value: diffItem,\n };\n }\n\n case before.length === after.length: {\n let diffItem = null;\n\n for (let i = 0; i < before.length; i++) {\n if (JSON.stringify(before[i]) !== JSON.stringify(after[i])) {\n diffItem = after[i];\n break;\n }\n }\n\n return {\n name: \"update\",\n value: diffItem,\n };\n }\n }\n}\n"
|
|
5869
|
+
}
|
|
5870
|
+
]
|
|
5871
|
+
},
|
|
5872
|
+
{
|
|
5873
|
+
"path": "src/core/tools/hooks",
|
|
5874
|
+
"content": null,
|
|
5875
|
+
"children": [
|
|
5876
|
+
{
|
|
5877
|
+
"path": "src/core/tools/hooks/index.ts",
|
|
5878
|
+
"content": "import useUpdateEffect from './useUpdateEffect'\nimport useParentFocus from './useParentFocus'\nexport { default as usePersistFn } from './usePersistFn';\nimport useInterval from './useInterval';\nimport useNodeBoundingRect from './useNodeBoundingRect';\nexport * from './useImageUrl'\nexport * from './useDisabledArea'\n\nexport {\n useUpdateEffect,\n useParentFocus,\n useInterval,\n useNodeBoundingRect,\n}"
|
|
5879
|
+
},
|
|
5880
|
+
{
|
|
5881
|
+
"path": "src/core/tools/hooks/useCountDown.ts",
|
|
5882
|
+
"content": "import { useEffect, useMemo, useState } from 'react'\nimport usePersistFn from './usePersistFn'\n\nexport type TDate = number\n\nexport type Options = {\n targetDate?: TDate\n interval?: number\n onEnd?: () => void\n}\n\nexport interface FormattedRes {\n days: number\n hours: number\n minutes: number\n seconds: number\n milliseconds: number\n}\n\nconst calcLeft = (t?: TDate) => {\n if (!t) {\n return 0\n }\n const left = t - new Date().getTime()\n if (left < 0) {\n return 0\n }\n return left\n}\n\nconst parseMs = (milliseconds: number): FormattedRes => {\n return {\n days: Math.floor(milliseconds / 86400000),\n hours: Math.floor(milliseconds / 3600000) % 24,\n minutes: Math.floor(milliseconds / 60000) % 60,\n seconds: Math.floor(milliseconds / 1000) % 60,\n milliseconds: Math.floor(milliseconds) % 1000,\n }\n}\n\nconst useCountdown = (options?: Options) => {\n const { targetDate = 0, interval = 1000, onEnd } = options || {}\n\n const [target, setTargetDate] = useState<TDate>(targetDate)\n const [timeLeft, setTimeLeft] = useState(() => calcLeft(target))\n\n const onEndPersistFn = usePersistFn(() => {\n if (onEnd) {\n onEnd()\n }\n })\n\n useEffect(() => {\n if (!target) {\n // for stop\n setTimeLeft(0)\n return\n }\n\n // 立即执行一次\n setTimeLeft(calcLeft(target))\n\n const timer = setInterval(() => {\n const targetLeft = calcLeft(target)\n setTimeLeft(targetLeft)\n if (targetLeft === 0) {\n clearInterval(timer)\n onEndPersistFn()\n }\n }, interval)\n\n return () => clearInterval(timer)\n }, [target, interval])\n\n const formattedRes = useMemo(() => {\n return parseMs(timeLeft)\n }, [timeLeft])\n\n return [timeLeft, setTargetDate, formattedRes] as const\n}\n\nexport default useCountdown\n"
|
|
5883
|
+
},
|
|
5884
|
+
{
|
|
5885
|
+
"path": "src/core/tools/hooks/useDeadline.ts",
|
|
5886
|
+
"content": "import { useState, useEffect, useRef } from 'react'\nimport dayjs from 'dayjs'\n\nconst checkTimeFormat = (timeStr: string) => {\n return /\\d{4}\\-\\d{1,2}\\-\\d{1,2}\\s\\d{1,2}\\:\\d{1,2}/.test(timeStr)\n}\n\nconst hasArriveDeadLine = (time: string) => {\n return dayjs().isAfter(time)\n}\n\n/**\n * 是否到达截止时间,传入空字符串,则表示时间已到\n * @param timeStr 2022-10-1 08:00\n */\nconst useDeadline = (timeStr: string, interval = 100) => {\n const [overTime, setOverTime] = useState(hasArriveDeadLine(timeStr))\n\n useEffect(() => {\n if (!timeStr) {\n setOverTime(true)\n return\n }\n\n // 兼容ios的时间格式\n if (!checkTimeFormat(timeStr)) {\n console.error(`${timeStr} 不符合时间格式, 请按照格式 2022-10-1 08:00 书写`)\n return\n }\n\n const timer = setInterval(() => {\n if (hasArriveDeadLine(timeStr)) {\n setOverTime(true)\n clearInterval(timer)\n } else if (overTime) {\n setOverTime(false)\n }\n }, interval)\n\n return () => {\n clearInterval(timer)\n }\n }, [timeStr, overTime])\n\n return overTime\n}\n\nexport default useDeadline\n"
|
|
5887
|
+
},
|
|
5888
|
+
{
|
|
5889
|
+
"path": "src/core/tools/hooks/useDisabledArea.tsx",
|
|
5890
|
+
"content": "import React, { useEffect } from 'react';\nimport { uuid } from '..';\n\nclass DisabledStyle {\n styleEle;\n styleEleId = `for_disable_focus_${uuid()}`;\n\n constructor({ root, id1, id2 }) {\n const _styleEle = document.createElement('style');\n _styleEle.id = this.styleEleId;\n _styleEle.innerText = `\n #${id1} #${id2} .disabled-area, #${id1} #${id2} .disabled-area * {\n pointer-events: none !important;\n }\n .disabled-area {\n opacity: 0.4;\n filter: blur(0.8px);\n }\n `;\n \n root.appendChild(_styleEle);\n this.styleEle = _styleEle;\n }\n\n unmount() {\n if (this.styleEle) {\n try {\n // 尝试直接移除元素\n this.styleEle.remove();\n } catch (e) {\n // 降级处理:如果 remove 不可用,使用父节点移除\n this.styleEle.parentNode?.removeChild(this.styleEle);\n }\n this.styleEle = null;\n }\n }\n}\n\nexport const useDisabledArea = () => {\n // 直接生成 id\n const id1 = uuid();\n const id2 = uuid();\n \n useEffect(() => {\n const shadowDom = document.getElementById('_mybricks-geo-webview_');\n const shadowRoot = shadowDom?.shadowRoot;\n \n if (!shadowRoot) {\n console.warn('找不到shadowroot');\n return;\n }\n\n const disabledStyle = new DisabledStyle({ \n root: shadowRoot,\n id1,\n id2\n });\n\n // 清理函数\n return () => {\n disabledStyle.unmount();\n }\n }, []);\n\n // 返回一个组件\n const DisabledArea = ({ children }) => (\n <div id={id1}>\n <div id={id2}>\n {children}\n </div>\n </div>\n );\n\n return DisabledArea;\n}"
|
|
5891
|
+
},
|
|
5892
|
+
{
|
|
5893
|
+
"path": "src/core/tools/hooks/useFormItemValue",
|
|
5894
|
+
"content": ""
|
|
5895
|
+
},
|
|
5896
|
+
{
|
|
5897
|
+
"path": "src/core/tools/hooks/useFormItemValue.ts",
|
|
5898
|
+
"content": "import { useState, useEffect, useRef, useCallback } from \"react\";\n\nconst useFormItemValue = (initialValue, onChange) => {\n const [value, setValue] = useState(initialValue);\n const valueRef = useRef(initialValue);\n const valueRefProxy = useRef(initialValue);\n\n useEffect(() => {\n if (value !== valueRef.current) {\n valueRef.current = value;\n if (typeof onChange === \"function\") {\n onChange(value);\n }\n }\n }, [value, onChange]);\n\n const setValueProxy = useCallback((val) => {\n valueRefProxy.current = val;\n setValue(val);\n }, []);\n\n const getValueImmediately = useCallback(() => {\n return valueRefProxy.current;\n }, []);\n\n return [value, setValueProxy, getValueImmediately];\n};\n\nexport default useFormItemValue;\n"
|
|
5899
|
+
},
|
|
5900
|
+
{
|
|
5901
|
+
"path": "src/core/tools/hooks/useImageUrl.ts",
|
|
5902
|
+
"content": "import { useState, useEffect, useRef, useCallback } from \"react\";\n\nconst urlCache = new Map();\n\nfunction getFinalUrl(url) {\n // 先检查缓存\n if (urlCache.has(url)) {\n console.log('从缓存中获取URL');\n return Promise.resolve(urlCache.get(url));\n }\n\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n // 不要真正下载资源,只需要头信息\n xhr.open('HEAD', url);\n\n xhr.onreadystatechange = function () {\n if (xhr.readyState === 4) {\n if (xhr.status >= 200 && xhr.status < 400) {\n const finalUrl = xhr.responseURL;\n urlCache.set(url, finalUrl); // 存入缓存\n resolve(finalUrl);\n } else {\n reject(new Error('Request failed'));\n }\n }\n };\n\n xhr.onerror = function () {\n reject(new Error('Network error'));\n };\n\n xhr.send();\n });\n}\n\n/** 获取被重定向后的真正url */\nexport const useRedirectedImageUrl = (url, onSuccess) => {\n useEffect(() => {\n if (!url || new URL(url).host !== 'ai.mybricks.world') {\n return \n }\n getFinalUrl(url).then((finalUrl) => {\n onSuccess(finalUrl)\n })\n }, [url])\n}"
|
|
5903
|
+
},
|
|
5904
|
+
{
|
|
5905
|
+
"path": "src/core/tools/hooks/useInterval.ts",
|
|
5906
|
+
"content": "import React, {\n useRef,\n useCallback,\n useEffect,\n} from 'react'\n\nexport default (callback: () => void, delay: number | null) => {\n const savedCallback = useRef(callback)\n const timmerId = useRef({ id: 0 })\n\n useEffect(() => {\n savedCallback.current = callback\n }, [callback])\n\n const play = useCallback(() => {\n if (delay === null) {\n return\n }\n timmerId.current.id = setInterval(() => savedCallback.current(), delay)\n }, [delay])\n\n const clear = useCallback(() => {\n clearInterval(timmerId.current.id)\n }, [timmerId])\n\n useEffect(() => {\n play()\n return () => clear()\n }, [play, clear])\n\n return [play, clear]\n}"
|
|
5907
|
+
},
|
|
5908
|
+
{
|
|
5909
|
+
"path": "src/core/tools/hooks/useNodeBoundingRect.ts",
|
|
5910
|
+
"content": "import React, {\n useState,\n useEffect,\n RefObject,\n} from 'react'\ninterface Size {\n width: number\n height: number\n}\n\nexport default function useNodeBoundingRect<T extends HTMLElement = HTMLDivElement>(\n elementRef: RefObject<T>\n) {\n const [rect, setRect] = useState<DOMRectReadOnly | Size>({\n width: 0,\n height: 0,\n })\n\n useEffect(() => {\n if (!window.ResizeObserver) {\n return\n }\n const resizeObserver = new window.ResizeObserver((entries) => {\n setRect(entries[0].contentRect)\n })\n\n if (elementRef.current !== null) {\n resizeObserver.observe(elementRef.current)\n }\n\n return () => {\n resizeObserver.disconnect()\n }\n }, [])\n\n useEffect(() => {\n if (!elementRef.current) {\n return\n }\n \n if (elementRef.current.getBoundingClientRect) {\n setRect(elementRef.current.getBoundingClientRect())\n } else {\n setRect({\n width: elementRef.current.clientWidth,\n height: elementRef.current.clientHeight\n })\n }\n }, [elementRef.current])\n\n return rect\n}\n"
|
|
5911
|
+
},
|
|
5912
|
+
{
|
|
5913
|
+
"path": "src/core/tools/hooks/useParentFocus.ts",
|
|
5914
|
+
"content": "import { useEffect, useState } from 'react'\n\nconst usParentFocus = ({ isEdit = false, nodeRef }) => {\n const [bool, setBool] = useState(false);\n\n useEffect(() => {\n const node = nodeRef.current;\n if (!isEdit || !nodeRef) {\n return;\n }\n\n const wrapperEle = node?.parentNode?.parentNode;\n if (!wrapperEle) {\n return;\n }\n\n const observer = new MutationObserver((mutationsList, observer) => {\n mutationsList.forEach((item) => {\n if (item.attributeName === 'class') {\n setBool(item.target.className.indexOf('focus-') > -1 ? true : false);\n }\n });\n });\n\n observer.observe(wrapperEle, {\n attributes: true,\n attributeOldValue: true,\n });\n\n return () => {\n observer.disconnect();\n };\n }, [isEdit]);\n\n return bool;\n};\n\nexport default usParentFocus"
|
|
5915
|
+
},
|
|
5916
|
+
{
|
|
5917
|
+
"path": "src/core/tools/hooks/usePersistFn.ts",
|
|
5918
|
+
"content": "import { useRef } from 'react';\n\nexport type noop = (...args: any[]) => any;\n\nfunction usePersistFn<T extends noop>(fn: T) {\n const fnRef = useRef<T>(fn);\n fnRef.current = fn;\n\n const persistFn = useRef<T>();\n if (!persistFn.current) {\n persistFn.current = function (...args) {\n // @ts-ignore\n return fnRef.current!.apply(this, args);\n } as T;\n }\n\n return persistFn.current!;\n}\n\nexport default usePersistFn;"
|
|
5919
|
+
},
|
|
5920
|
+
{
|
|
5921
|
+
"path": "src/core/tools/hooks/useUpdateEffect.ts",
|
|
5922
|
+
"content": "import { useEffect, useRef } from 'react'\n\nconst useUpdateEffect: typeof useEffect = (effect, deps) => {\n const isMounted = useRef(false)\n\n useEffect(() => {\n if (!isMounted.current) {\n isMounted.current = true\n } else {\n return effect()\n }\n }, deps)\n}\n\nexport default useUpdateEffect"
|
|
5923
|
+
}
|
|
5924
|
+
]
|
|
5925
|
+
},
|
|
5926
|
+
{
|
|
5927
|
+
"path": "src/core/tools/data-format.ts",
|
|
5928
|
+
"content": "\n\n\nexport enum FormatType {\n NONE = 'NONE',\n KEYMAP = 'KEYMAP',\n TIME_TEMPLATE = 'TIME_TEMPLATE',\n TIME_CUSTOM = 'TIME_CUSTOM',\n // PRICE_CUSTOM = 'PRICE_CUSTOM'\n}\n\nconst builtInFormatters = {\n [FormatType.NONE]: {\n label: '保持原值',\n name: FormatType.NONE,\n },\n [FormatType.KEYMAP]: {\n label: '枚举映射',\n name: FormatType.KEYMAP,\n genEditor() {\n return {\n type: 'map'\n }\n },\n },\n [FormatType.TIME_TEMPLATE]: {\n label: '时间戳转化',\n name: FormatType.TIME_TEMPLATE,\n genEditor(options) {\n return {\n type: 'select',\n description: '待转换数据格式为字符串或数字型时间戳',\n options: {\n options: [\n {\n label: '年-月-日 时:分:秒',\n value: 'YYYY-MM-DD HH:mm:ss'\n },\n {\n label: '月-日 时:分:秒',\n value: 'MM-DD HH:mm:ss'\n },\n {\n label: '年-月-日',\n value: 'YYYY-MM-DD'\n },\n {\n label: '月-日',\n value: 'MM-DD'\n },\n {\n label: '时:分:秒',\n value: 'HH:mm:ss'\n }\n ],\n ...options\n }\n };\n },\n },\n [FormatType.TIME_CUSTOM]: {\n label: '自定义时间戳转化',\n name: FormatType.TIME_CUSTOM,\n genEditor(options) {\n return {\n type: 'text',\n description: '待转换数据格式为字符串或数字型时间戳',\n options: {\n placeholder: 'YYYY-MM-DD HH:mm:ss',\n ...options\n }\n };\n },\n }\n}\n\nconst createFormatterSelector = (formatters, accessor) => {\n return {\n title: '格式化类型',\n type: 'select',\n options: formatters.map((item) => ({\n label: item.label,\n value: item.name\n })),\n value: {\n get(info) {\n let data = accessor?.get(info) || {}\n return data?.formatterName || FormatType.NONE\n },\n set(info, v) {\n const data = accessor?.get(info) || {}\n // 设置当前格式化方法\n data.formatterName = v\n accessor.set(info, data)\n }\n }\n }\n}\n\n\nexport const createDataFormatEditor = ({ title, value, formatters }) => {\n\n const editors = (formatters ?? []).map(item => {\n const findFormatter = builtInFormatters[item.formatter];\n\n const name = item.formatter;\n const accessor = value;\n const defaultValue = item.defaultValue;\n\n if (!findFormatter?.genEditor) {\n return null\n }\n \n return {\n title: '格式化参数配置',\n ifVisible(info) {\n const data = value.get(info)\n return data?.formatterName === name;\n },\n value: {\n get(info) {\n // 获取到存储在组件上当前格式器的数据\n const values = accessor?.get(info)?.values || {}\n if (typeof values?.[name] === 'undefined') {\n values[name] = defaultValue\n }\n return values[name]\n },\n set(info, value) {\n const data = accessor?.get(info) || {};\n if (!data.values) {\n data.values = {};\n }\n const values = data.values\n // 设置当前格式器的数据\n values[name] = value\n\n console.warn('name', name)\n // 设置当前格式化方法\n accessor.set(info, data)\n }\n },\n ...findFormatter?.genEditor(item.options ?? {}),\n };\n }).filter(t => !!t)\n\n return {\n title,\n items: [\n {\n title: '空值处理',\n type: 'Switch',\n description: '开启后,可将输入值为undefined、null、空字符串转换成预期值',\n value: {\n get(info) {\n const values = value?.get(info) || {}\n return values?.['voidHandle'] || false;\n },\n set(info, switchValue: boolean) {\n const values = value?.get(info) || {}\n values['voidHandle'] = switchValue\n value.set(info, values)\n }\n }\n },\n {\n title: '空值替代字符',\n type: 'Text',\n description: '将空值用配置的字符替代',\n ifVisible(info) {\n const values = value?.get(info) || {}\n return values?.['voidHandle'] || false;\n },\n value: {\n get(info) {\n const values = value?.get(info) || {}\n if (typeof values?.['voidTo'] === 'undefined') {\n values['voidTo'] = '';\n }\n return values?.['voidTo'];\n },\n set(info, textValue: string) {\n const values = value?.get(info) || {}\n values['voidTo'] = textValue\n value.set(info, values)\n }\n }\n },\n createFormatterSelector((formatters ?? []).map(item => builtInFormatters[item.formatter]), value),\n ...editors,\n ]\n }\n}"
|
|
5929
|
+
},
|
|
5930
|
+
{
|
|
5931
|
+
"path": "src/core/tools/empty.png",
|
|
5932
|
+
"content": "�PNG\r\n\u001a\n\u0000\u0000\u0000\rIHDR\u0000\u0000\u0002.\u0000\u0000\u0002.\b\u0006\u0000\u0000\u0000�J��\u0000\u0000\u0000\u0001sRGB\u0000��\u001c�\u0000\u0000\u0000DeXIfMM\u0000*\u0000\u0000\u0000\b\u0000\u0001�i\u0000\u0004\u0000\u0000\u0000\u0001\u0000\u0000\u0000\u001a\u0000\u0000\u0000\u0000\u0000\u0003�\u0001\u0000\u0003\u0000\u0000\u0000\u0001\u0000\u0001\u0000\u0000�\u0002\u0000\u0004\u0000\u0000\u0000\u0001\u0000\u0000\u0002.�\u0003\u0000\u0004\u0000\u0000\u0000\u0001\u0000\u0000\u0002.\u0000\u0000\u0000\u0000\u001a��\u0000\u0000?cIDATx\u0001�݉v�F�\u0005P%\u001dlj�����\u001fؙ<�\u0019:/�i8�-�\u0014\tT�\u00026��(S@a_�8�*�_�}���+\u000b\u0001\u0002\u0004\b\u0010 @`\u0000�/\u0007h�&\u0012 @�\u0000\u0001\u0002\u0004\u000e\u0002��\u0003�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011\u0010\\�)��\u0012 @�\u0000\u0001\u0002��c�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011\u0010\\�)��\u0012 @�\u0000\u0001\u0002��c�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011\u0010\\�)��\u0012 @�\u0000\u0001\u0002��c�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011\u0010\\�)��\u0012 @�\u0000\u0001\u0002��c�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011\u0010\\�)��\u0012 @�\u0000\u0001\u0002��c�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011\u0010\\�)��\u0012 @�\u0000\u0001\u0002��c�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011\u0010\\�)��\u0012 @�\u0000\u0001\u0002��c�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011\u0010\\�)��\u0012 @�\u0000\u0001\u0002��c�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011\u0010\\�)��\u0012 @�\u0000\u0001\u0002��c�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011\u0010\\�)��\u0012 @�\u0000\u0001\u0002��c�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011\u0010\\�)��\u0012 @�\u0000\u0001\u0002��c�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011\u0010\\�)��\u0012 @�\u0000\u0001\u0002��c�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011\u0010\\�)��\u0012 @�\u0000\u0001\u0002��c�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011\u0010\\�)��\u0012 @�\u0000\u0001\u0002��c�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011\u0010\\�)��\u0012 @�\u0000\u0001\u0002��c�\u0000\u0001\u0002\u0004\b\u0010\u0018F@p\u0019�T\u001aJ�\u0000\u0001\u0002\u0004\b\b.�\u0001\u0002\u0004\b\u0010 @`\u0018\u0001�e�Ri(\u0001\u0002\u0004\b\u0010 �8\u0006\b\u0010 @�\u0000�a\u0004\u0004�aJ��\u0004\b\u0010 @����\u0018 @�\u0000\u0001\u0002\u0004�\u0011�j��j(\u0001\u0002W���\u000f����*�?�����?�<�,<��<�\u001e�ٗ_����/���#���ꫯ\u000e_�����>��\u0010 @����R�:ڶk���_���J~v�%��%a&!�Ν;���_}x~��z\r\u0001\u0002\u0004Z\t|����?[m�v\b\u0010�Y`\n*�;��S\u0003��k��_\u0012f�{\b2�|���ޛ��l\r\u0004\b\u00108O@p9��o\u0011XD ��͛7W��8\f�,��\u0015W�ޘ\u0004���\f5Y\b\u0010 �Z@pi-n{�\u0017H�JzU\u0012X2\u00144�\u0010����\u001e\u001e�;c!@�@\u000b\u0001����m\u0010�K��~�z����w%�g��$��\u0007&!&�b,\u0004\b\u0010XS@pYS\t�%�ޕ�/_\u001e���A\u0012\\�ݻw\b2[�W�G�@\u001f\u0001������@ �V^�z����a93������^�\u000f��s\u0002\u0004\b\\\" �\\��w\t\\#���\u001e�\\¼�%\u0001��Ç�\t�{���\u0004\b,# �,�h-\u0004\u000e7�{���ah\b�\\ CH�\u001e=r%Ҝ�3\u0002\u0004�\u0010\u0010\\�@�+\u0004�\u00052�6CByli���>.�}&�f\u0002oz`\\����u\u0010ا��Ϻ��\u00042,��ŋCo�B���jrw����~0\u0016\u0002\u0004\b�V@p����\u0013�K =+\u0019\u0016ʽX,�\tL�/�;��\u0000\u0001\u0002�\n\b.�Jy\u001d��\t�~,Ϟ=3�v�#\"�/�}���#\u0005\u0016X�U\u0010 �\u0003\u0001�e\u0007E���\t�\u0006r\u0019\u001a2�e9��wy��������jM\u0004\blU@p�je�ע\u0002�M��2�Ų�@����c\u0013w��V\u0002�\u0011�)i�)�\u001dYK \u001f����?\u001b\u001aZ\u000b��M(��ӧO��������\u0002fō\\=m_] 7����\u001f��ե��@�\u000f�;=\\\u0016\u0002\u0004\b\\' �\\��g\u0004�\u0012�'7���ON���\u0006a�1��\u0011\u0018L�\u001c��\n��m\u00042l�+�L�m�}�Vr�t�8��'N�X:~dR�t)�\u001b�]w\u0004�\u0019��\u0005\u0004��]�t�\u0002�7K&�\n-�\u000f���3a7\u0013w+/9V�S�9:\u001f~��ʧڟ��\u001e�D<��4=�<\u000f\u000b\u0001\u0002\u000b\b.�\u0004\u0002G\u0002zZ�0�|[1�$�d(1����c͠\u001b��<ݹs�p��|�\u0010ث������\u0004r\u0012��Ck��>ڨ\u001f�$�\u0013w�6�y�NOJ���w�\u000e�*=��\f1M!&�QӐ�I�^D`p\u0001�e�\u0002j�2\u00029)�����Zk�pI�K�a�\f�d�0a%�*\u0015��7&\u001f����s\u000b�-\u000b\b.[��};I �%=-9IYj\u000bd�������9A%���^�����$�ܿ�0Gf��k+�S\u0005\u0004�S��n�\u0002�_H�\u001b\"��S�\f�$�,�d�'CA\t,\t��/S���UY��C��\u0013\u0010\\����\u0001\u00052<4ڻ�\u0001�\u0017or�Er��RK�J\u001e[��]�^>\u000b*A�B`\u000b\u0002��\u0016�h\u001f�\u0012x���U\u001e�1\u0005r2��%=,���=������Ç]'8_R+�K`\u0012\u0010\\&\t_w%��+�2�!s>��|��,�y&h��<���\f��$�G��~>j�s��s�\t,{�m�1�ު\u0004>W\"�z�k���\u0018؝@N�?���p'�i�e�9���5\t09y�\t��\u0005�\u0018d�˩'ᄸ\u0004�\\)������ѣGg������:\u0002�K�ZhI#����\u0004�w�yL=*k2�\u0017���ׇ\u00103��I�n<y��,�e��8la��gw��\u0017�.�V.�>\u0011��J\b\b.%ʠ\u0011�\u0004rR����/9�ܻw��ʑ.\tN�A�nZ2�6����r�M��>\u0013�����\b\b.۩�=��@�!���M`�=8z�!�C��P䤟 S�ğ�o��>\u001c>K�s���7��к��\u001c{9�.��ܫ���/\u0001�e_����f� s\u001b*.���^�\u0016�A��\u0002Lz��Nh�$��\u001cLK��Ƃ��i_s\u001cf����i^^�G@p��n��\u0005r��ܖjKz\nr�j氌��\u0012�\u0004��\u0013ys�M�Uz�\u0012T+��z�\u0013���a�U�vk�~\u0004\u0004���z�{����M�LXI/ˈ�n3d��R�\u0007+'۸fNK�a�\u0011�\u0010\u0013�\u0013^*\rY�m\u0004\u0004�6ζ�Q '�\\\u0002[e\u0019���&�ʽ/7���O\u0013�qj��iV^�V�˶��5\u0002m\u00052T��Re�>gg���O�e^I&�zg�)�1�m�a7\u000b�J\u0002�K�jh��\u0002\u0019ʨ2�!s/�>}���\u0003\u0019��~eb�e[\u0002\u0019n��_\\����\u000e�7���%�\u00037\t�?�ܷ�\u001e�-_��y:\t/[�I�p�TiC��\\R^�\u001a�\u0011\u0001��q�Y���\nw͍і�$��\u0005�~~�Fp�ۮm7\u000bL�F\u0015��nn�ً�ಗJ�l?�.��ܖ�@�ʡ=-��s>�pOF#�k�Kn)��-\u000b��\u0002�KO}�^M��ܖ�i�KOˇ�t5ʇ\"�x�\u001e�\f\u001bY\b�\u0014\u0010\\z���j\u0002���*�㻸����W�> ��sA�r3�\n��\u0017�_\u001d\\@p\u0019�����@>������_�xc��5��I�?�-\u001e�m\t䳫�~�ö���u\u0002�G�N�φ\u0016�}7���p���\u000f�8�m���<'6>�\\r�t�[\r��l/ۈ�Bڍ\u0004z�0+WԘ��O-�]<\\&=7�³��|\u001e��@k\u0001������*������.�\u0003\u0013-\u001f\u000b��Ő�?.[\u0019F��[>��B���W-7f[\u0004�\u0016�9L�в�\u0013��u�K�K�\u0017��$�e�v\u001e����i��8�e�%=\u0017\tۙ�������(�\u001d��6s\u0005�c\u000fGv�}\u0014\\j�A+\u0016\u0010������\u001f�!�O\u00171>�X��N�L0�Pa����n��~\n5�\u001f��c9N���1]y.Iږ\u000f15���ǿ]N@pY�Қ:\u000b�z����!�ӊ���\u000f?�pڋ\u0007xUj�@��rjX9e��ބ�<�@�K�s�W\\�әyLK\u001aT�Om�! �Ԩ�V, г�%�\u0001��\u000b�)'���E$X�D}����C@����^1���%��R�^��M{�p�!�|R����\u0002��][���\t�\u001a����r���\u0007\u000f�\u000e.�\u0005I��4g��=�����ȍ�\u0012\\\u0012\u0014zMD�nO\u0012��7x<�u������\u0002�*�T��\u0010�8{����$�{�v�@z]�6ڒI���^�C��r�\u0015���߇\u001e����>�A\u0016\u0002k\u000b\b.k\u000b[\u0013�^�[|\u0012�y�\u001d��.\t[O�>-5\u0001;CH�[�����\u0015���T��S�G\u001b�\u0011\u0010\\�q���\u0002=���\u000e|Ğ�Υ:l>�5�/\u000b�Ц�ڐ\u001a'�T�ǔ\u0010����\u0005����L\u0012��% ��%k�M\u0005z��\u001b�נiAN�X�K�%�24T=de�2\u0013c+\f[�MD����ǒ�-' �,giM\u001d\u0005zLR\u0014\\.+xu�L�\u001d�2�����\n��� /;*��\b\u0002��\bU��O\n�R��7�J�|ա�Ob\u0015���\u000eT��ȕO��_�\u0004��W��\u0018�-thk��\u0002����V��@���*tɯ/��\u0016z�`���\u0004�\u0004���\fo�<F�\u0003:��zF����.�l��;ؿ\u001e���\tw�RWsL{�p��\\e����=Z�ˈ�c�Yp\u0019�NZ�\t\u0001��\u00138���Rp��_N�[Y�?=CX��2�k!�����5\u0017h=17�f�oY��q�r\u000f�L���C���|-���k\u0012��\u0019K�\u0016yF�r\u0001��rCk�,�cbn�]���+�$=?\u0015��Y���u�\u0015�z}\f�\u001a��YG@p�S\u000b-9S�up��rf�n��ޞ����g��d�zM6vu�V����%�����\u0005\u0004Z���>�.@Vj\u0015�{\\��һ\rk\u0017$WJ���\f�\u001e�]����\u000b\b.�k�\u0005\u0017\n�\u000e.���/d*��=={�F�.H�O1��Һ��ߞ��\u001ao~\u000f[\u0007�*�I�R؞�{�m���L��\u0011\u0012�s�*��R\u0002��R���E �Ep�B��F{�L�����f�~˯\t�=����\nZ��V{\u0001����-.(�:���={\b\u0016�+��^���Q�>2-\n���)s\\ZTv_�\u0010\\�Uo{K���\u0004z��{��c\u0000ZO.ϛ\u000b�.�+���\u000b.۪����ǻ�\u001e�<[.l/ϻw�n���}�߂ˍ��\u000fg\b\b.g���:\u0002�K�Z�ے\u001e�%�M�\u000f!<�j���1<&�,Q9�\u0004\u0004�I��a\u0005ZO��q�\u001d�8'4��\r\u0004Ӥ��\u001e��\u0004��_�#���zYw�\u0001�eW嶳K\b�8�.����\u0011\u0004{܌��\u0002[��o�J���\u000e�e\u001bu��^��Oػ�e\u000f�\u001e�\b�'�.+v��Z��ryͬ�\u001f\u0001��\u001f\u000b�\r*к˿ljv�Ҝ��\u001e��O�'A4|����!�M� ���j�m\u0005Z���8Ѷ\u0015m��\u001e=X�������Z�������x��\u0002���V^YT�������q�-�Q���c�K�^���V����ߣ�+�Ye\u0011\u0001��H!4�|���%-��+����7{9�>q\u001f�s��[��R���i�ಝZ�vOz\\!�넻�\"s�ZE�\u000f��\u0005\u0004���mae�\u001e=.�[y����^�{�\u0001h���{x��׳߽\u0014\\�[���y&\u001a��lh��e�P�zM�l}�Lj��n����>�\u0017��J\u0002�K�jh��\u0002=z]}{v{���՛7o�1�}ru������P��\u0005�M�u;�#��<�n��=�Z���ի��\u000b.Վ���#��]?���@��_1���C0n�����\u000f���弿\u0013�u���r���\u000e&�#���g��`%�5���׳筟��qh���^淴\u000e��|�\"���\u0002��mż��@�c�1\\�y.{>\t�s0��~��������o]n|7m���\u001e�=�6{\u001a���\u0002�˺���P��ݻ\r��������˗ͷ;�\u0006������\u000f����\u000e���o���#��K\u0004\u0004�K��n)�^�Ez]N?\f�;Uex�G���R뽲�~��I�z���[@p�]\u0001�_L�Ν;W=&\u0001�u9������2�v���g����f�&��LG��K\b\b.K(ZG\t��s���^�\u001e]�%�OlD|����ə�ڣ��D�U^��_o�*���J\u0005�]�{;����v۩�ϟw��\b\u001b����DޫV����˔�P\u000b�%\u0005\u0004�%5���@&����2W˼z���A�\u0006d����CNqH�K�v���۾&��[_\u0006�6��\u0005���# ��S+-=A ��=�.���\u0013�!�I���\u001a��\u000bQ�ms�˞��O�����\u0005\u0004��M�dp���E9A���/e&��.e��W���I&�ny��ے�-�l���o�K\u001fw[]Q ��z�g����?���\u001e��ꄖ\u001e�\u0013�\u0011J�|���m~e��ƿW��ޖ�\u000e�a\u001a+�\fS*\r��@�^��3�#Ϟ=�M�7����(�fi�V'�fRt���s�vsPv轀���7[\u0012�w�^�I��cN�[~'?��u_�ߣ\u0005����=N��[�g�A�+��\u000f��-�h]�\u0004\u0004�Z�К�\u0004reQ�K�%]����{�����^���qnS�\\-��\u0012�o����\r!oc�c\n\b.c�M�O\u0010��~�^�43����yF��<F]2I���~)�\n��\u0013\\,\u0004�\u0010\u0010\\�P��\u0012\u0002��=�e�Hp������\u0016z�F\u001f�Kh�����I���-�_��K\u000b\b.K�Z_)���$�TXrB�\t%'�--ٟ�~�i�9-�����]Sh�=)��\u001b�O�ؿ�+ ��[;-?A��\\����S�\u000f?������\u0004����g����:��5C^�E\u001a%hfbq\u0002d��R���:{�x\u0002��x5��[\n<x��\\����\tf�y/�H\u000fR�Km'�5�N�d��1a%���2D�Ӡ�<*����.��V���\u0012�F '��sL�\u0001t�\u001e=�\u001a��\t�\u0015N�הz�\u001f����ӧ%Oȹ+nz���\f}���C\u001dϫ\u001c0V����*��W\u0012�Ѝ~�G�\u0004$�T��s];��^��(���6\u000f\u001f>,q�}�S�\u0004���*Kz[�<yR�9ڱQ\u0001�e���[\u001f\u000bd�&�K��3���yW�\u0000S�2�}9AfX('��C&S������'d�\u001c\u000e�M�z�\u0011�&_�-7����\u0002�˒��U^ =\u0006��L�\u001bs\u0003��'�\\N����dհ��K�r���̖5J-R���tz[z\u001d��ۮಿ��z�s\u0002�2��Bd�KN��I���KzTҳ�\u0013dœ�����s�N���5�\u001c��I��zޛ�S�� �ޖ�!�S��o�\u0016\u0010\\�]_{w�@��~��ǡ�=rbH��0E\u001e�>?�t�I1\u0001%W��������O$Ox�#5��>\t��G\u0002d.��^�\\����@\u000b\u0001����m�\u0013�\t!�K3꒓b���\u0013��5�����{\u001e9��1�MIh˻�<�\u0014G�Q�\u0013.���k�2=&�>�5Ix�ڳr]-r������(�]�^?#p���r���o^ �\u001b�z���k\u0007�\t�*���ɚ�\r\r%����P\u001c\u001a�'�\\ښw�\u0016\u0002\u0004�\u0013��+��<;�u���r���\u001c\\ ���}�]�I��Si>��\u00042D����~�\u0007\u0004�\u0016\u0010\\�\u0016���\u0002��7]�\t1��\u0002�S��[�\nL���M�:�u��^+o��\u000bd�(=/�\u0013~OR��d�Z\u0019��[�\\Ad��o\r��u�e�շ��\u0005r\"������7\t-��\u0014X\u0012^r�����t��[�E\u0002\u000b\b.�\u0004\u0002�\u0013�ș�k�%0���!��,C|-n�WK�ok�˒�;�\u0010�) ��Է�r\u0002���\u001bi�*K��qh�Z��I��&���N������m��\u0002�˧}��\u000e\u0005\u0012\\r�̻zK_��!�ӿi�\u001dj��ݤ���\u0013V�>}��k9Rk�@@p�\u0000ϯnW =/�S!����4<�:|nI�1|�9���=�%�r�q�\u0010� `v[�*hCI�\fO�?�|4�t���\r�X��!��\\���!O���\u0018K������ԢKCmtW\u0002z\\vUn;{[�\fE�\u0004z[��_�+�2$qΉ2�����|�\u000fs�i�߀�@%\u0001�UT�\u001a�RV \u001fH��ٳ�'��m��\r�B��s�\u0000��J���\u0007Dz�\u0012 \r\u000f�o�7�\u0013\u0010\\ֳ��\r\n�x���իW\u001bܳ��4��,Պw��\u001d!�ۋ��K/����F;\u0001����-mD '�̥H/��2�\fG\u001c�X�;�����~�m�\u000f��(�y]��n��\u000fE\u0004\u0004�\"�Ќ�\u0004�N>'�_�u��\u0017jm��d��\u00122ySh��5%�s����^��h�\u0002��^+o�\u0017\u0011ȰQ\u001e�$N�L/K._��r���v�̼�\u0004\u0018u��-\u0013���r΄���'\u0004�\u0017\u0010\\�7���\u000b�d��/�����gB%��^~���C/Y�Z�\u0016�ܢ��K'D�$�R@pi�m[�\u0016ȰQ��;1~\\漛�\u001d��\u000fI��\u0015�~����p�P\u0002K�z���-mE@p�J%�G\u0019\u0001'�J��i3w���?[�������g%\u0001r�a��B��@]\u0001��nm�l`�L\n}���n�d(h:AV.c�8J/�\u001e�<J�JzYܛ��\u0011�m�\b\b.�(y\r�3\u0005\u0012`2�%�0{�|:'�̛�g\f�4ob��\u0016���ە\u0010�I�\u0016\u0002[\u0010\u0010\\�PE�0�@�lI/��.�N@�]o3�0���ܣ'5�ב��$�%\u0001R`\u0019���~���r���\u0011XQ =/y���Ƚ0\u0019\u000eJXɣ�UB+��0�:�d\t�#}t@�\u001e��ĐКG�u�\u0014\u0010\\z����\u00052�bz�?�=Fr2L����z\u0001���\u0004�Ԫb�IXI=\u0012X| �֏H�\u0017\u0001��q@��@N�\u0019���\f'U8IN�@91椸�a�\u0004��%5ʣg�L�L=�\u00009�|�\"n�1���2p�4}�\u0002S���2�Fs�\\3���\u0013b��GN�N��\u001fg�Kj�G�a���3���\u001ey\u0018\u0006��&~�\u000f\u0001�e\u001fu��\u001b\u0010�I1'ǜ$�\u0013�t��BM^s��3'�\u0004�<���5�$'�)�l���.�}�M��T��|��u�4\u001f��Ú�>�c���pA\u0001��`Q4���\u0002�'�\u0004\u0014K\u001d��6S`��2-!0��\u000b�Ǩ�V\u0012����r+��/V���6�A\u0001o�6XT�D�\u0000\u0001\u0002\u0004�* �l����\u0000\u0001\u0002\u0004\blP@p�`Q�\u0012\u0001\u0002\u0004\b\u0010ت�����/\u0002\u0004\b\u0010 �A\u0001�e�E�K\u0004\b\u0010 @`�\u0002��V+k�\b\u0010 @��\u0006\u0005\u0004�\r\u0016�.\u0011 @�\u0000��\n\b.[���\"@�\u0000\u0001\u0002\u001b\u0014\u0010\\6XT�D�\u0000\u0001\u0002\u0004�* �l����\u0000\u0001\u0002\u0004\blP�-�7XT�D��@>'\u001f*8}\b��a��\u0007>N_[�k��M�e����\u0004L\u001f�����F�Gm'p���r���!�c�|\u0002r>�8��{���\u0001��2}���_}u��]�\"ݾ\f��A��Cw@�I\u0002#\t$��{������_\u000f�*#�Om�s��UB�\u0014d����u?\u0002��~jmO\t�J !�͛7Wo߾�ңr+�\u0012/N�̷�~{��7�\\%�X\blE@p�J%�\u0007�\u0005\u0004\u0012P^�zu\b,��bن@���ݻw\b2�3c!0���2r����B\u0002\t)S`ѻ�\u0010j�դ\u0017�����\u0010#�\u0014,�&�$ ����E\u0004�)����ŋC\u000f����\u001a_�W\t0�I�\u0011`�\u0013��\u0002�K��h\u001b�\u0015\u0005�ÒG.e��S �W?|��0\u000ff�\u0002�zD\u0001�eĪi3�\u000b\u0004r\u0019�g�\u000e�2_�\u001a��!�\\J��ѣ�\u0004\u0019\u000b��\u0002�K�\ni\u001f��\u00042\u0014���˫ׯ_�Jh!�-�&CF\u000f\u001e<8\f\u001fmi����\u0004\u0004���t�{���t��4'#��y\u0018�����Q�/�����f\"��?���|��w��\u001c\u0011e\u0005\u0004���Ѱ\b䄛���\"��S�1�͝�U���ܻ\"_-W������);N\u0004�\u0005����/�*��\" �T��v�\u0017HHIX�㒓m���\r�r�Dzd��$�d\u0002���m\u0005҃������\u0010�$ �T���ےI�9�&�,��?������=��dh(��B�\u0012��{��B����R�\u0012;nG��2i��I6\u0001&�\to9�d���?��x\u0000��!��]O���Ǐw�\u0000����R�\u000e�mE�pI/�4Ѷ\u0005Dz`2\u0001q�\u0001Fhiq\u0004�s\u001b\t���b!�[@p�]�\u001do����Ks{\u0011lm\bIh�u$�g�����X\b�\u0014\u0010\\z��t��N�[\t0\u0019\u001ez���N�*��J s�2i�B�����K~���UB?��S����\u001c`r'�7o�����ۭ\u0005\u0012\\\u0012`,\u0004z\b\b.=�w��\u0011z\u0005F\u000b0���@K��wɼ\u0017\u000b��\u0002���Z|���$�\u0011�22��ދ\\�T�2�\\:�>-;���뙣�\u001b��|��E������w;A �\u0019#.U{`��\u0007\u0019v�>\u0002aD[m\u001e[ ����\u001f{'�~8�}�Nt�2����`��e�e����\u001f\u000f�JPH\u0010�ҖQk�ݗ\t䦑�y�\u0010h) �����\u0012Z.�u\u0015�)����\u000f�\u0003L���\u001d��8k�X\u00029\u0016G\u0018\u0002\u001eKUk?% �|Jǿ],�\u001e��]�r\u001c`�n�u�G�g2�Ň�\u0015,(����]X\b�\u0010\u0010\\Z(�x\u001b��ے:�Q��fz`Z\u0006�\f\u0011m�\u0007�e�lk]��i���5��\u0004\\U��\u0016\u0016�g\u0010������}��M\u0001&=K�g!�u�E��G\u001c\"�\u0004�<,�\t�\u001a�\u0007#�%���?\u0007��y��\u0002����;^�\u001eB�qys�9��:���t��<�9�$W��s���9���r|�������7#�L�Mp�\u001b��K��\u001c�O�<��<mڐ�ˡ7T�j��������J\u00069a/�\u0003�a�jWpd\u001f\u0013T���_�����\u0000L�ɛ���o�<:\u0001�B`-\u0001�e-ٝ�7��&�X�\u000e'�%\u0002L� 8������/M��u���,�\u001c�z7\u0013d���:\"��]CE��s�\u001cq\u001e�ZHK\f!�Ĕ�T�%!,�e�a�\n�6Z\u001bR��z��J��^�\u0013�v�u�]��n_��vk�u�2���\r��\u0002So�m����w�OJ�I�\t��V�I\u0002nz`z�܄�\u0004*\u000b�5\u0004����j�e'\u0010V(�q\u000fL��Sv?�{�ޫޡ%�W����e�+���`�\u000f3�9�7�.�Xl\u0018��2r�\fN�\\��m����0���%�\u001c�\u0007�{����߽{���>}*���\\�o\u0012�3A6sMz-S8�}�ݶ����ڻ\u0001\u0004�\u0000�ɷ\u0019b;\u000e0���\u0013/\u001f=zt��e,�,����;p��o�]_�P��ƻ����w�\u0000g��\u0014`�\u001f~��2\u0007&]��y�%CX=O|=�yk�L���b��*�t�vD��\u001f��F\u001d6^'�-@\u001e\u0007�^sJ�+����}x����\u001bص�H`2������g�h�5���\n$���ʉ&';�6\u0004\u0012~s�ϧ&�����1�\u0010XZ@pYZ��\b\f,0��z��\fLW��\t-=�h��z����и�\u0005\u0004��\t���v\u00042���;��\b�ݓ\\Ҟ!��Q�\u0016���\u0004����\u001e\u00128I �%\u0013r-�\u0015Ȅ�ֽi���{<��3�����\u0012(&���aŊ�ps�ݭ{]��,\\D��\u0012\\\u001c\u0004\u0004\b\u001c��\\���\u0003!�3ղ�%7�4�e\u001f�V��t9t+i�i\"0\rwd<?��ʜL\u0010̽Qri�˴�/C�\u001bcه@z�����\u0006q\t.z��q|��K����m4\u0011��77�:~7��\u0013b��;�W�^\u001d���\u000e��Ho�?\u001e{�.+-�K�<d��B`\t\u0001CEK(ZGw�����ǡ��F�\u001d_������\u001d&�z\u0007��P����ãe��\u0013�[�<��B`)\u0001�e)I��&�wr�Z��%�F��G+'1��\u0004Z�]p����\u001e\u000b.k�Zw\u0013�s/�\u0014`�.O�\u0013X�\u0003�FN\u0012hYwC�'�ċN\u0014\u0010\\N��\u0002\t\u001fw��q�\u0001&!�e\u0017�E\r_��=X\br�մ��I�\u001d\u001cśk�T�\u0002iާ\u0005\u00122\u0012<�X��\u0004�̗�$�ׯ_o�2���-�-q�la\u001d��\u0016���}��Ϻof��\n-� S��$ޭ�����q�������sr��>'��o# ��F�kw%��\u0000�F���A2�ζ�����\u000f�b�7TT� �SO`\n0[\u001cBju�WU-�@��\u000b.��%\u0005\u0004�%5�k�\u0002[\f0�N\\�>0\u0006�9�\u001f�x;n�������\u0004�\u0018`Γ�[\u0004\b\u0010h/ ��7�ō\bL\u0001&���\u0015H{�\ni#��\u001b\u0004\b\f, �\f\\<M�!��3r��\u0000S�\u001eZA���\u0005\u0004�m���5\u00148\u000e0�\u0000��\u000b�e�\r\u000b`S\u0004\b�B@p�E��dK�\u0004�\\�4}\u0002�\u0000�R߶\b\u0010غ���\nۿn\u0002S����\u0004�n��a\u0002\u00046$ �l��v��@&�\u0007F��Y\u001f�\"@`,\u0001�e�zi��\u0002�\u0001f/��4p�4�\u0000��\u0002�K��h�v\u0005�˨�;�f\"�\u001f���\u001d�g\u0004\b\u0010XP@pY\u0010Ӫ\b�F@�����\u0012 @�o\u0001�ő@���\u0000ӹ\u00006O��P\u0002>\u001dz�ri�\u0005�\u0000��ɓ-�}#@��E\u0002��E|~�\u0000\u0001\u0002\u0004\b\u0010h) ��Զ-\u0002\u0004\b\u0010 @�\"\u0001��\">�L�\u0000\u0001\u0002\u0004\b�\u0014\u0010\\Zj�\u0016\u0001\u0002\u0004\b\u0010 p���r\u0011�_&@�\u0000\u0001\u0002\u0004Z\n\b.-�m�\u0000\u0001\u0002\u0004\b\u0010�H@p���/\u0013 @�\u0000\u0001\u0002-\u0005\u0004��ڶE�\u0000\u0001\u0002\u0004\b\\$ �\\��\t\u0010 @�\u0000��\u0002�KKm�\"@�\u0000\u0001\u0002\u0004.\u0012\u0010\\.���\u0004\b\u0010 @�@K\u0001����m\u0011 @�\u0000\u0001\u0002\u0017\t\b.\u0017��e\u0002\u0004\b\u0010 @�����R۶\b\u0010 @�\u0000��\u0004\u0004����2��\u0005~����Wj�\u0004\b\u0010؈�W\u001b�\u000f�A`x�w��]�|��Jp\u0019��v�\u0000�\u0015\u0005\u0004�\u0015q���)\u0002\t,�^�����_Oy��\u0010 @`�\u0002�ˮ�o�{\n$���E`�Y\u0005�&@`4\u0001�e��i��\u0002\t*/^�0$4|%�\u0000\u0001\u0002=\u0004\u0004�\u001e궹K\u0001=,�,��&@`a\u0001�eaP�#�@&ۦ�ŐЇ2�\u0013 @��\u0002�����\u0006��\u0004\u0004�����\u0000\u0001\u0002�\u0012\u0010\\n���\u0004>/���I��Z�B�\u0000\u0001\u0002�\n\b.�zZێ\u0005~���Ð������\u0013 ����:�\rl]@\u000f��+l�\b\u0010�$ �T���\f%���\u001bǽ}�v�vk,\u0001\u0002\u0004F\u0016\u0010\\F���w\u0011ȐP�l!����]\fm�\u0000\u0001\u0002�\n\b.�����\t$�L=,[9�oe?vw0.�����\u0017ZӧW��\u0017_|�\u0005���-\u0004\u0004�[`y�>\u0005�\u0018X�J\n.��>�������k��\u0016\\֒���\u0005����CB���o���\u001dw�����\u000b�nu\\\u000b.���W�. ��n�\u0005\u0005�8��!�L�̾����2���kj�j���/[m�vv ���[��\u0004��N�{\n,��D���ܹs�#��@ u�\u0010\u0018Q@p\u0019�j�<\u0013�\r߾����n�d��e2�e݂ˤ���-?;K��~��\u0016{*��P��U\u0005r��9�%�5���͛7���W�8s�9�ݻw����k�\n����W_9Ռz�Tl���bU��V\u0002�1x�����ǏO�=�eΔ��p�|͞U\u0015�0Q�9.���Rh׀\u0002�ˀE��\u0005�k���\u0007\u000f\u001e�8�4�%�3�_��u\u000fˇzq�t���uz^[���\u0013���>\u001eFk��2ZŴ�F���\u0004����_ݽ{�jz��\u001e��<�Y�����F\u0016����s�ۊ�f}F �n�\b.-���-�e�5��\u001e���ŋ\u0017�Ǯv��pQ\u001e_���k���\u0005\u0012Z�w�jIO�ɹ����\u001d\u0017������g\u0005\u0012�,�\u0016H�c&��\\\\��R{\u001f�\u0012\\�Qg{I�\u0002\u0019Rk=��E\u0005\u0012ZZ����z�\u0016-���% �8\f\b\u0010x/�^\u0017��sl�\\E�znK\u0000\u0005�M\u001dF%vFp)Q\u0006� PC '7CF5j�t+rˀ֡4\u0013�\r\u0015-]I�\u0013\\\u001c\u0003\u0004\b�\u0004�<WhY�#�В�\u0017�-����=�e\u001fun��>��r�����\u0012�̅hyg�˵��&��6\u00017���?�m\t,\u0004�\u0016\u0010\\�\u0016�����r������ɓ��O�^=|���\u0015]�\u0019RȻt\u001f�w\u0001b�_M�l}\u0015Ѵ�\u0019&�\u0015��6��M\u0001�q�f]���r�\u0012$�L7ϛ~{�#�+~Z/��䧟~:|��wέ�/�^n�������Z��;f&\t_�\u0016�㲴��\u001d\u0004�p��\u0003ḇ���{~\u0000b��/��b����,��\u0004�\u001e�q�w��q{�\u000e�oO@���jZb�r��\u001e�\u0004%v��F�j�\f\u0005%�|jIw{��i}���M\u00196��3l��ѣ\u001b?\u000bjz���\u0004R������˱�6�����oYp�z�;���n�?5�LkȰ[���0�#C\u000f�2%\u001fd����N?���@\u0002K�\u0006ˣ�>ߴ�\u0019�\u0010XK@pYKv��u\u000f��\u0006��5�D��Cr��䤘!�� O�-��ֽl;�2��B`�y�������~\n.}�7��\fd�K��J��H/�熄>������#����\fI$��]9Q��Ԯ2\t�\t,9\u001e�]��c�B`M\u0001�eMݝ�;'�=��\u0012���\u0010�\t!���`\u0002L\u001e�\f�����|ͻnW�\u001dW��\u0013T\u0012Prys��b���=r\t�u*~������\u0017Ȼ�=\u0006��\u0003�\u0004�\u001e�\ns]��|�5'���\t-i�����{~�@BI\u001e\t�\u0019\u0002�\u0014Von�U��\u000e}�M�m{\u0002���jZf�\u0012\\�\u000e�����0k\u0005��vg�K�\b��椛6Vo籭�/\u0013Ho��-�\u0019���\u0004���4'�:S`\u000f�rH`����\u000fw���k.���u7�5�˺�\u0016�q�K�-\u0004Z\b�qi���m$�T�Ds�2$�$D���*�j3!6=/\u0016\u0002\u0015\u0004�\u0013��U\u000b�\u0016\u0002z\\Z(�x\u001by'����M\t�K|�ai\u001dZ&ȼ�u\u0015Ϥ�kO��\r���g\u0005��m�e5o�����\u0014X�\u0001��\u0002�T�-\u0006�i�|\u001dG ����\u001b��Z�\t\u0001CE�(c��ȐJ�KyOUK`�;��a���N��}G�\u000f���~\u0004��g�h?�����K�Jl�\u001d�!�;������'��O0H���\u0005\tT��G��a!�R �Z\\E�Rܶ&�/�z\u0017��\u001e�SK|݅@N����7Ϛ\n0B`�ښ���G�b[�\u000e��m���\u0004�7�!S\u000b�\u001e\u0002�K\u000f��o3CF���j�e\u001az�6$t��������ܨ�}�\u0002���В^T\u000b�\u001e\u0002�K\u000fu�<�w�\u0012^�ݝn�\u0011\u0003��\u001e����r����~\f�\f��:�e�zm����V+;�~�D��9\u001a=��\u0004�c�Xf\u001e��r���%\u00042\t7��e�KhZ�%\u0002��%z~w\u0011�\u0017/^\u001cnR�j�h���\u0010\t�\t/n����K\u0004�����S��\u0012D�����\u0018�\u0015]\"���\u0004��C�.Y�u����i\u000eK嫄�k�9?\u0013^�Q�;�\td\b5����u:~�C@p�n�7\n���ի�\u001c�%z`ҭ�\u001e��\u0000o\u000f��\u00186�E�y�5\u0014w�\u0016ߏ)����\u0018\b-c�o��\u0016\\�Z���+'�|�QN�y�f�F��͕\u000f�<�|��|�����}���\u000f������}\u001f��Z��N\u0011\u0010\\NQ��\u0002鉙BLN��A&�$\u0013\u0007�H���W\u0007���^��aw�^�5�g�u\u0004����\u0017Ko��@E\u0001��bU���\n\u0002\t~��+!�B�:��PfhhϽ��Y-\u0001��V=����\u0002���Z}�l�b�\u0004�||�\u0016>\f�b\f+(/ ��/�\u0006\u0012X^ �/�����}\u000bd.X��e��q0��\u000b.#UK[\t,,��_H\u000f�{�,\f;��2\u0017,�%�C\u0016\u0002#\t\b.#UK[\t�$�+�2�W�Y\t��j\u0013T�\u0011\u0017&�\u0016*���J@p�\u0015�\u0017\u0013ض@z`\u0012`\f!m��\t,�Ǣ�e{���\u001e\t.{���%p�@�<J/L����'���\u0014\u0012�-\u00022�%�|o!�\u0005\u0001�e\u000bU�\u000f\u0004V\u0014Hxy����!Ĭ\b�Ъ\u0013P2\f���F\u000b�ZM)\u0001��T94�@m�\f!%ĤG&�+%���W�J������5тu\u0005\u0004�u}����\u0005\u0012\\\u0012f2�wz�gy�.�ǏMC��s��~\u001e�L����\u001dzz��\\Ƽ\u0002�U�\u0016\u0010\\J�G�\b\u0010 @�\u0000�c�/����\u0000\u0001\u0002\u0004\b\u0010 PY@p�\\\u001dm#@�\u0000\u0001\u0002\u0004f\u0002�ˌ�\u0013\u0002\u0004\b\u0010 @����R�:�F�\u0000\u0001\u0002\u0004\b�\u0004\u0004�\u0019�'\u0004\b\u0010 @�@e\u0001��ru��\u0000\u0001\u0002\u0004\b\u0010�\t\b.3\u000eO\b\u0010 @�\u0000��\u0002�K��h\u001b\u0001\u0002\u0004\b\u0010 0\u0013\u0010\\f\u001c�\u0010 @�\u0000\u0001\u0002�\u0005\u0004����6\u0002\u0004\b\u0010 @`& ��8<!@�\u0000\u0001\u0002\u0004*\u000b\b.���m\u0004\b\u0010 @��L@p�qxB�\u0000\u0001\u0002\u0004\bT\u0016\u0010\\*WG�\b\u0010 @�\u0000����2���\u0000\u0001\u0002\u0004\b\u0010�, �T���\u0011 @�\u0000\u0001\u00023\u0001�e��\t\u0001\u0002\u0004\b\u0010 PY@p�\\\u001dm#@�\u0000\u0001\u0002\u0004f\u0002�ˌ�\u0013\u0002\u0004\b\u0010 @����R�:�F�\u0000\u0001\u0002\u0004\b�\u0004\u0004�\u0019�'\u0004\b\u0010 @�@e\u0001��ru��\u0000\u0001\u0002\u0004\b\u0010�\t\b.3\u000eO\b\u0010 @�\u0000��\u0002�K��h\u001b\u0001\u0002\u0004\b\u0010 0\u0013\u0010\\f\u001c�\u0010 @�\u0000\u0001\u0002�\u0005\u0004����6\u0002\u0004\b\u0010 @`& ��8<!@�\u0000\u0001\u0002\u0004*\u000b\b.���m\u0004\b\u0010 @��L@p�qxB�\u0000\u0001\u0002\u0004\bT\u0016\u0010\\*WG�\b\u0010 @�\u0000����2���\u0000\u0001\u0002\u0004\b\u0010�, �T���\u0011 @�\u0000\u0001\u00023\u0001�e��\t\u0001\u0002\u0004\b\u0010 PY@p�\\\u001dm#@�\u0000\u0001\u0002\u0004f\u0002�ˌ�\u0013\u0002\u0004\b\u0010 @����R�:�F�\u0000\u0001\u0002\u0004\b�\u0004\u0004�\u0019�'\u0004\b\u0010 @�@e\u0001��ru��\u0000\u0001\u0002\u0004\b\u0010�\t\b.3\u000eO\b\u0010 @�\u0000��\u0002�K��h\u001b\u0001\u0002\u0004\b\u0010 0\u0013\u0010\\f\u001c�\u0010 @�\u0000\u0001\u0002�\u0005\u0004����6\u0002\u0004\b\u0010 @`& ��8<!@�\u0000\u0001\u0002\u0004*\u000b\b.���m\u0004\b\u0010 @��L@p�qxB�\u0000\u0001\u0002\u0004\bT\u0016\u0010\\*WG�\b\u0010 @�\u0000����2���\u0000\u0001\u0002\u0004\b\u0010�, �T���\u0011 @�\u0000\u0001\u00023\u0001�e��\t\u0001\u0002\u0004\b\u0010 PY@p�\\\u001dm#@�\u0000\u0001\u0002\u0004f\u0002�ˌ�\u0013\u0002\u0004\b\u0010 @����R�:�F�\u0000\u0001\u0002\u0004\b�\u0004\u0004�\u0019�'\u0004\b\u0010 @�@e\u0001��ru��\u0000\u0001\u0002\u0004\b\u0010�\t\b.3\u000eO\b\u0010 @�\u0000��\u0002�K��h\u001b\u0001\u0002\u0004\b\u0010 0\u0013\u0010\\f\u001c�\u0010 @�\u0000\u0001\u0002�\u0005\u0004����6\u0002\u0004\b\u0010 @`& ��8<!@�\u0000\u0001\u0002\u0004*\u000b\b.���m\u0004\b\u0010 @��L@p�qxB�\u0000\u0001\u0002\u0004\bT\u0016\u0010\\*WG�\b\u0010 @�\u0000����2���\u0000\u0001\u0002\u0004\b\u0010�, �T���\u0011 @�\u0000\u0001\u00023\u0001�e��\t\u0001\u0002\u0004\b\u0010 PY@p�\\\u001dm#@�\u0000\u0001\u0002\u0004f\u0002�ˌ�\u0013\u0002\u0004\b\u0010 @����R�:�F�\u0000\u0001\u0002\u0004\b�\u0004\u0004�\u0019�'\u0004\b\u0010 @�@e\u0001��ru��\u0000\u0001\u0002\u0004\b\u0010�\t\b.3\u000eO\b\u0010 @�\u0000��\u0002�K��h\u001b\u0001\u0002\u0004\b\u0010 0\u0013\u0010\\f\u001c�\u0010 @�\u0000\u0001\u0002�\u0005\u0004����6\u0002\u0004\b\u0010 @`& ��8<!@�\u0000\u0001\u0002\u0004*\u000b\b.���m\u0004\b\u0010 @��L@p�qxB�\u0000\u0001\u0002\u0004\bT\u0016\u0010\\*WG�\b\u0010 @�\u0000����2���\u0000\u0001\u0002\u0004\b\u0010�, �T���\u0011 @�\u0000\u0001\u00023\u0001�e��\t\u0001\u0002\u0004\b\u0010 PY@p�\\\u001dm#@�\u0000\u0001\u0002\u0004f\u0002�ˌ�\u0013\u0002\u0004\b\u0010 @����R�:�F�\u0000\u0001\u0002\u0004\b�\u0004\u0004�\u0019�'\u0004\b\u0010 @�@e\u0001��ru��\u0000\u0001\u0002\u0004\b\u0010�\t\b.3\u000eO\b\u0010 @�\u0000��\u0002�K��h\u001b\u0001\u0002\u0004\b\u0010 0\u0013\u0010\\f\u001c�\u0010 @�\u0000\u0001\u0002�\u0005\u0004����6\u0002\u0004\b\u0010 @`& ��8<!@�\u0000\u0001\u0002\u0004*\u000b\b.���m\u0004\b\u0010 @��L@p�qxB�\u0000\u0001\u0002\u0004\bT\u0016\u0010\\*WG�\b\u0010 @�\u0000����2���\u0000\u0001\u0002\u0004\b\u0010�, �T���\u0011 @�\u0000\u0001\u00023\u0001�e��\t\u0001\u0002\u0004\b\u0010 PY@p�\\\u001dm#@�\u0000\u0001\u0002\u0004f\u0002�ˌ�\u0013\u0002\u0004\b\u0010 @����R�:�F�\u0000\u0001\u0002\u0004\b�\u0004\u0004�\u0019�'\u0004\b\u0010 @�@e\u0001��ru��\u0000\u0001\u0002\u0004\b\u0010�\t\b.3\u000eO\b\u0010 @�\u0000��\u0002�K��h\u001b\u0001\u0002\u0004\b\u0010 0\u0013\u0010\\f\u001c�\u0010 @�\u0000\u0001\u0002�\u0005\u0004����6\u0002\u0004\b\u0010 @`& ��8<!@�\u0000\u0001\u0002\u0004*\u000b\b.���m\u0004\b\u0010 @��L@p�qxB�\u0000\u0001\u0002\u0004\bT\u0016\u0010\\*WG�\b\u0010 @�\u0000����2���\u0000\u0001\u0002\u0004\b\u0010�, �T���\u0011 @�\u0000\u0001\u00023\u0001�e��\t\u0001\u0002\u0004\b\u0010 PY@p�\\\u001dm#@�\u0000\u0001\u0002\u0004f\u0002�ˌ�\u0013\u0002\u0004\b\u0010 @����R�:�F�\u0000\u0001\u0002\u0004\b�\u0004\u0004�\u0019�'\u0004\b\u0010 @�@e\u0001��ru��\u0000\u0001\u0002\u0004\b\u0010�\t\b.3\u000eO\b\u0010 @�\u0000��\u0002�K��h\u001b\u0001\u0002\u0004\b\u0010 0\u0013\u0010\\f\u001c�\u0010 @�\u0000\u0001\u0002�\u0005\u0004����6\u0002\u0004\b\u0010 @`& ��8<!@�\u0000\u0001\u0002\u0004*\u000b\b.���m\u0004\b\u0010 @��L@p�qxB�\u0000\u0001\u0002\u0004\bT\u0016\u0010\\*WG�\b\u0010 @�\u0000����2���\u0000\u0001\u0002\u0004\b\u0010�, �T���\u0011 @�\u0000\u0001\u00023\u0001�e��\t\u0001\u0002\u0004\b\u0010 PY@p�\\\u001dm#@�\u0000\u0001\u0002\u0004f\u0002�ˌ�\u0013\u0002\u0004\b\u0010 @����\u0003�㐓�y��\u0000\u0000\u0000\u0000IEND�B`�"
|
|
5933
|
+
},
|
|
5934
|
+
{
|
|
5935
|
+
"path": "src/core/tools/env.ts",
|
|
5936
|
+
"content": "import * as Taro from \"@tarojs/taro\";\n\n/**\n * 环境相关方法\n */\n\n/* 判断是否为 edit 态 */\nexport function isEdit(env): Boolean {\n if (env?.edit) {\n return true;\n } else {\n return false;\n }\n}\n\n/* 判断是否在设计器中运行 */\nexport function isDesigner(env): Boolean {\n if (env?.edit || env?.runtime?.debug) {\n return true;\n } else {\n return !!window?.mybricks;\n }\n}\n\nexport function isH5() {\n return Taro.getEnv() === Taro.ENV_TYPE.WEB || Taro.getEnv() === \"Unknown\";\n}\n"
|
|
5937
|
+
},
|
|
5938
|
+
{
|
|
5939
|
+
"path": "src/core/tools/h5-compress.ts",
|
|
5940
|
+
"content": "export const compressImage = (file: File, quality = 0.7): Promise<File> => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.readAsDataURL(file);\n reader.onload = (event) => {\n const img = new Image();\n img.src = event.target?.result as string;\n img.onload = () => {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n reject(new Error('Cannot get canvas context'));\n return;\n }\n const maxWidth = 1920; // 最大宽度\n const maxHeight = 1080; // 最大高度\n let { width, height } = img;\n\n if (width > maxWidth) {\n height = (maxWidth / width) * height;\n width = maxWidth;\n }\n if (height > maxHeight) {\n width = (maxHeight / height) * width;\n height = maxHeight;\n }\n\n canvas.width = width;\n canvas.height = height;\n ctx.drawImage(img, 0, 0, width, height);\n canvas.toBlob((blob) => {\n if (!blob) {\n reject(new Error('Failed to create blob'));\n return;\n }\n resolve(new File([blob], file.name, { type: file.type, lastModified: file.lastModified }));\n }, file.type, quality);\n };\n };\n reader.onerror = (event) => {\n reject(new Error('Failed to read file'));\n };\n });\n};"
|
|
5941
|
+
},
|
|
5942
|
+
{
|
|
5943
|
+
"path": "src/core/tools/h5-polyfill.ts",
|
|
5944
|
+
"content": "import Taro from \"@tarojs/taro\";\n\n// @ts-ignore\nconst isWeb = Taro.getEnv() === Taro.ENV_TYPE.WEB || Taro.getEnv() === \"Unknown\";\n\n// 判断是否在设计器中,TODO,目前只能这么来判断了\nconst isInDesn = () => isWeb && (!!window.Babel || !!window.antd || !!window.mybricks?.SPADesigner);\n\nif (isInDesn()) {\n if (!document?.body?.appendChild?._is_mybricks_desn_adapt_) {\n const oriAppend = document.body.appendChild;\n document.body.appendChild = (child: any) => {\n if (child?.className === 'weui-picker__overlay') {\n const root = document.getElementById(\"_mybricks-geo-webview_\")?.shadowRoot.querySelector('class^=debugCanvas-')\n return root?.appendChild(child)\n }\n return oriAppend.call(document.body, child)\n }\n document.body.appendChild._is_mybricks_desn_adapt_ = true\n }\n}\n\nconst getDesnRootElement = () => {\n return document.getElementById(\"_mybricks-geo-webview_\")?.shadowRoot\n}\n\nconst getDesnDebugRootElement = () => {\n return getDesnRootElement()?.querySelector?.('[class^=debugCanvas-]')\n}\n\nexport const polyfill_taro_picker = () => {\n if (!isInDesn()) {\n return\n }\n\n if (!(window as any).mybrciks_taro_polyfill_taro_picker) {\n const oriAppend = document.body.appendChild;\n document.body.appendChild = (child: any) => {\n if (child?.className === 'weui-picker__overlay') {\n return getDesnDebugRootElement()?.appendChild(child)\n }\n return oriAppend.call(document.body, child)\n };\n (window as any).mybrciks_taro_polyfill_taro_picker = true;\n }\n}\n\nexport const polyfill_taro_swiper = () => {\n if (!isInDesn()) {\n return\n }\n\n if (!(window as any).mybrciks_taro_polyfill_taro_swiper) {\n // 设计器兼容 https://www.npmjs.com/package/swiper/v/6.8.0?activeTab=code 这个版本的swiper\n const oriQs = document.querySelectorAll;\n document.querySelectorAll = (selector: string) => {\n if (selector.indexOf(\".taro-swiper-\") > -1) {\n return getDesnRootElement()?.querySelectorAll(selector);\n }\n return oriQs.call(document, selector);\n };\n (window as any).mybrciks_taro_polyfill_taro_swiper = true;\n }\n}\n\n\n\n"
|
|
5945
|
+
},
|
|
5946
|
+
{
|
|
5947
|
+
"path": "src/core/tools/image.ts",
|
|
5948
|
+
"content": "import { isNumber, isString } from './core'\nimport * as Taro from \"@tarojs/taro\";\n\nconst pixelRatio = Taro.getSystemInfoSync().pixelRatio;\n\n// const getWidth = (w: number) => Math.round(w / 200) * 200;\nconst dpr = pixelRatio ?? window?.devicePixelRatio;\n// const commonWidth = getWidth((window.screen.availWidth || document.body.clientWidth) * dpr);\n\n// const isSupportWebp = (() => {\n// try {\n// return document.createElement('canvas').toDataURL('image/webp', 0.5).indexOf('data:image/webp') === 0;\n// } catch(err) {\n// return false;\n// }\n// })()\n\n// export function imageWebpProcess(url: string) {\n// return isSupportWebp ? url : ''\n// }\n\n// /**\n// * 给各个云存储的图片增加处理参数\n// */\n// export function imageProcess(url: string, width: number) {\n// width = (width * dpr) | 0;\n// switch (true) {\n// case /https?:\\/\\/js/.test(url):\n// return imageProcessJs(url, width);\n// case /https?:\\/\\/ali/.test(url):\n// return imageProcessAli(url, width);\n// case /https?:\\/\\/tx/.test(url):\n// return imageProcessTx(url, width);\n// case /https?:\\/\\/p[0-9]\\./.test(url): // 其他cdn,按cdn方的人来说是动态的,都支持阿里的参数\n// return imageProcessAli(url, width);\n// default:\n// return url;\n// }\n// }\n\n// /**\n// * 金山云 https://docs.ksyun.com/documents/886\n// * @param url\n// * @param width\n// */\n// function imageProcessJs(url: string, width: number) {\n// width = width || commonWidth;\n// const pos = url.indexOf('@');\n// const base = url.slice(0, pos === -1 ? +Infinity : pos);\n\n// return base + '@base@tag=imgScale&m=1&w=' + width + '&q=85&interlace=1';\n// }\n\n// /**\n// * 阿里云 https://help.aliyun.com/document_detail/44687.html\n// * @param url\n// * @param width\n// */\n// function imageProcessAli(url: string, width: number) {\n// width = width || commonWidth;\n// const pos = url.indexOf('?');\n// const base = url.slice(0, pos === -1 ? +Infinity : pos);\n\n// return base + '?x-oss-process=image/resize,w_' + width + '/format,jpg/interlace,1/quality,q_85';\n// }\n\n// /**\n// * 腾讯云 https://cloud.tencent.com/document/product/460/36540\n// * @param url\n// * @param width\n// */\n// function imageProcessTx(url: string, width: number) {\n// width = width || commonWidth;\n// const pos = url.indexOf('?');\n// const base = url.slice(0, pos === -1 ? +Infinity : pos);\n\n// return base + '?imageView2/2/w/' + width + '/format/jpg/interlace/1/q/85';\n// }\n\nexport enum IMAGE_MODE {\n ASPECTFILL = \"aspectFill\",\n OBJECTFIT = \"objectFit\",\n TOP = \"top\",\n LEFT = \"left\",\n RIGHT = \"right\",\n BOTTOM = \"bottom\",\n ASPECTFIT = \"aspectFit\",\n SCALETOFILL = \"scaleToFill\",\n WIDTHFIX = \"widthFix\",\n HEIGHTFIX = 'heightFix'\n}\n\ninterface CdnCutOptions {\n quality?: number\n}\n\n\ninterface CdnCutMeta {\n url: string\n width?: number\n height?: number\n}\n\nexport function autoCdnCut ({\n url,\n width,\n height,\n}: CdnCutMeta, options: CdnCutOptions) {\n const { quality = 85 } = options ?? {};\n if (!isString(url) || !url) {\n return url;\n }\n\n if (url.indexOf('https') === -1 || url.indexOf('assets.mybricks.world') === -1) {\n return url\n }\n let query = '?x-oss-process=image/resize,';\n\n if (isNumber(width)) {\n query+= `w_${(width * dpr).toFixed(0)}`\n } else if (isNumber(height)) {\n query+= `h_${(height * dpr).toFixed(0)}`\n }\n\n if (isNumber(quality)) {\n query+= `/quality,q_${quality}`\n }\n\n return `${url}${query}`\n}"
|
|
5949
|
+
},
|
|
5950
|
+
{
|
|
5951
|
+
"path": "src/core/tools/index.ts",
|
|
5952
|
+
"content": "import * as Taro from \"@tarojs/taro\";\nimport { useUpdateEffect } from \"./hooks\";\n\nexport function getNavigationLayout(env) {\n if (env?.edit) {\n return {\n // bottom: 56\n // height: 32\n // left: 281\n // right: 368\n // top: 24\n // width: 87\n navigationHeight: 0,\n statusBarHeight: 0,\n titleBarHeight: 0,\n };\n }\n\n let systemInfoSync = Taro.getSystemInfoSync();\n const ratio = systemInfoSync.windowWidth / 375; // 页面 px2rpx 比例\n\n let menuButtonBoundingClientRect = Taro.getMenuButtonBoundingClientRect();\n\n let system = (systemInfoSync.system || \"\").toLocaleLowerCase();\n console.log(\"systemInfoSync\", systemInfoSync);\n\n const isIOS = system.indexOf(\"ios\") > -1; // iOS title 高度 44px\n const isAndroid = system.indexOf(\"android\") > -1; // Android title 高度 48px\n\n const statusBarHeight = systemInfoSync.statusBarHeight; // 状态栏高度\n\n let _statusBarHeight = Math.ceil(statusBarHeight / ratio);\n\n let _titleBarHeight;\n if (isIOS) {\n _titleBarHeight = Math.ceil(44 / ratio);\n } else if (isAndroid) {\n _titleBarHeight = Math.ceil(48 / ratio);\n } else {\n _titleBarHeight = Math.ceil(44 / ratio); // 调试态\n }\n\n return {\n navigationHeight: _statusBarHeight + _titleBarHeight,\n statusBarHeight: _statusBarHeight,\n titleBarHeight: _titleBarHeight,\n };\n}\n\nexport function uuid(pre = \"u_\", len = 6) {\n const seed = \"abcdefhijkmnprstwxyz0123456789\",\n maxPos = seed.length;\n let rtn = \"\";\n for (let i = 0; i < len; i++) {\n rtn += seed.charAt(Math.floor(Math.random() * maxPos));\n }\n return pre + rtn;\n}\n\nexport { useUpdateEffect };\nexport { default as UploadOssHelper } from './oss';\n\nexport function deepCopy(obj: any, cache: any = []) {\n if (obj === null || typeof obj !== \"object\") {\n return obj;\n }\n\n const hit: any = cache.filter((c: any) => c.original === obj)[0];\n if (hit) {\n return hit.copy;\n }\n const copy: any = Array.isArray(obj) ? [] : {};\n\n cache.push({\n original: obj,\n copy,\n });\n\n Object.keys(obj).forEach((key) => {\n copy[key] = deepCopy(obj[key], cache);\n });\n\n return copy;\n}\n\nexport function getUrlFromBg(bgUrl) {\n let picUrl = \"\";\n if (bgUrl) {\n picUrl = bgUrl.replace(/url\\((.*)\\)$/g, \"$1\");\n }\n return picUrl;\n}\n\nexport function throttle(fn: Function, time = 300, ignoreLast = false) {\n let timer: NodeJS.Timeout | null = null;\n let firstTime = true;\n let lastArgs: any[] | null = null;\n\n const throttled = function (this: any, ...args: any[]) {\n if (firstTime) {\n fn.apply(this, args);\n firstTime = false;\n return;\n }\n\n if (timer) {\n if (!ignoreLast) {\n lastArgs = args;\n }\n return;\n }\n\n timer = setTimeout(() => {\n if (lastArgs && !ignoreLast) {\n fn.apply(this, lastArgs);\n }\n timer = null;\n lastArgs = null;\n }, time);\n\n fn.apply(this, args);\n };\n\n throttled.cancel = function () {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n lastArgs = null;\n }\n };\n\n return throttled;\n}\n\n// export function debounce(fn, wait = 300) {\n// let timer;\n// return function (...args) {\n// const context = this;\n// clearTimeout(timer);\n// timer = setTimeout(() => {\n// fn.apply(context, args);\n// }, wait);\n// };\n// }\n\nexport function debounce(fn, delay, immediate = false) {\n let timer;\n let result;\n return function (...args) {\n if (timer) clearTimeout(timer);\n\n if (immediate) {\n // 如果timer存在,说明第二次调用的时候还没到delay时间,因为如果超过delay时间\n // timer会被赋值为null,所以这个时候我们不应该执行fn,应该重新设置一个定时器\n // 但如果是一次的时候,因为还没有设过定时器,所以这里timer会是undefined\n if (timer) {\n timer = setTimeout(() => (timer = null), delay);\n } else {\n result = fn.apply(this, args);\n return result;\n }\n } else {\n timer = setTimeout(() => fn.apply(this, args), delay);\n }\n };\n}\n\n/**\n * 获取url参数\n * @param key key\n * @returns value/undefined\n */\nexport function getUrlParam(key: string): string | undefined {\n const searchAry: string[] = location.search.slice(1).split(\"&\");\n\n for (let i = 0; i < searchAry.length; i++) {\n const kv = searchAry[i].split(\"=\");\n if (kv[0] === key) {\n return kv[1];\n }\n }\n\n return;\n}\n\nconst typeMap = {\n OBJECT: \"[object Object]\",\n ARRAY: \"[object Array]\",\n STRING: \"[object String]\",\n NUMBER: \"[object Number]\",\n FORMDATA: \"[object FormData]\",\n NULL: \"[object Null]\",\n UNDEFINED: \"[object Undefined]\",\n BOOLEAN: \"[object Boolean]\",\n FUNCTION: \"[object Function]\",\n};\n\nexport function typeCheck(variable, type) {\n if (Array.isArray(type)) {\n let bool = false;\n for (let i = 0; i < type.length; i++) {\n if (typeCheck(variable, type[i])) {\n bool = true;\n break;\n }\n }\n return bool;\n } else {\n const checkType = /^\\[.*\\]$/.test(type)\n ? type\n : typeMap[type.toUpperCase()];\n return Object.prototype.toString.call(variable) === checkType;\n }\n}\n\nexport function dateFormate(date: Date | number, fmt: string) {\n const d = new Date(date);\n const o = {\n \"M+\": d.getMonth() + 1, //月份\n \"D+\": d.getDate(), //日\n \"h+\": d.getHours(), //小时\n \"m+\": d.getMinutes(), //分\n \"s+\": d.getSeconds(), //秒\n \"q+\": Math.floor((d.getMonth() + 3) / 3), //季度\n S: d.getMilliseconds(), //毫秒\n };\n if (/(y+)/.test(fmt)) {\n fmt = fmt.replace(\n RegExp.$1,\n (d.getFullYear() + \"\").substr(4 - RegExp.$1.length)\n );\n }\n for (let k in o) {\n if (new RegExp(\"(\" + k + \")\").test(fmt)) {\n fmt = fmt.replace(\n RegExp.$1,\n RegExp.$1.length == 1 ? o[k] : (\"00\" + o[k]).substr((\"\" + o[k]).length)\n );\n }\n }\n return fmt;\n}\n\n// export const getFuncFromEvent = ({ evt, env }) => {\n// if (!evt) {\n// return () => {};\n// }\n\n// if (env.edit) {\n// return;\n// }\n\n// if (evt && evt.type === 'link') {\n// if (env?.yoda?.kwai) {\n// if (/^kwai:\\/\\/.+/.test(evt.value)) {\n// location.href = evt.value;\n// } else {\n// env.yoda.kwai.loadUrlOnNewPage({\n// url: evt.value,\n// type: 'back',\n// });\n// }\n// } else {\n// window.open(evt.value);\n// }\n// }\n// };\nexport function wFormat(value: number) {\n if (typeof value === \"string\") {\n value = +value;\n }\n if (value / 100000000 > 1) {\n const num = parseFloat((value / 100000000).toFixed(1));\n return num + \"亿\";\n } else if (value / 10000 > 1) {\n const num = parseFloat((value / 10000).toFixed(1));\n return num + \"万\";\n } else {\n return value;\n }\n}\n\nexport function padZero(num: number | string, targetLength = 2): string {\n let str = num + \"\";\n while (str.length < targetLength) {\n str = \"0\" + str;\n }\n return str;\n}\n\n// export function share(env, logger) {\n// if(env.kwai && env.kwai.share && typeof env.kwai.share === 'function') {\n// env?.kwai?.share();\n// } else {\n// logger.error(\"无法调起分享\");\n// }\n// }\n\n// export function back(yoda: any) {\n// if ((window as any)._physicalBackCb) {\n// (window as any)._physicalBackCb();\n// } else {\n// if (yoda?.kwai?.popBack) {\n// yoda.kwai.popBack();\n// } else if (yoda?.kwai?.exitWebView) {\n// yoda.kwai.exitWebView();\n// } else {\n// history?.back();\n// }\n// }\n// }\n\n// export function close(yoda: any) {\n// if(yoda?.webview?.backOrClose) {\n// yoda?.webview?.backOrClose().then((res) => {\n// console.log('backOrClose');\n// });\n// } else {\n// back(yoda);\n// }\n// }\n\n// export {\n// event\n// }\n\n/**\n * 暂时只针对白名单 ali2.a.kwimgs.com 域名的图片进行处理\n * todo:提供公共的图片裁剪方法\n */\nexport function resizeImage(url: string, options = {}): string {\n const whitelist = [\"ali2.a.kwimgs.com\"];\n\n let a = parseUrl(url);\n if (whitelist.indexOf(a.hostname) === -1) {\n return url;\n }\n\n if (Object.keys(options).length === 0) {\n return url;\n }\n\n let params = Object.keys(options)\n .map((key) => {\n return `${key}_${options[key]}`;\n })\n .join(\",\");\n\n return `${url}?x-oss-process=image/resize,${params}`;\n\n function parseUrl(url) {\n let a = document.createElement(\"a\");\n a.href = url;\n return a;\n }\n}\n\n/**\n * 将二维数组转为 csv 并下载\n */\nexport function downloadExcel(fileName, fileData) {\n let result = fileData\n .map((row) => {\n return row.join(\",\");\n })\n .join(\"\\r\\n\");\n\n result = \"data:application/csv,\" + encodeURIComponent(result);\n\n let elem = document.createElement(\"A\");\n elem.setAttribute(\"href\", result);\n elem.setAttribute(\"download\", `${fileName}.csv`);\n document.body.appendChild(elem);\n elem.click();\n elem.remove();\n}\n"
|
|
5953
|
+
},
|
|
5954
|
+
{
|
|
5955
|
+
"path": "src/core/tools/InstructionPanel.tsx",
|
|
5956
|
+
"content": "export default function ({ content = \"\", links = [] }) {\n const Markdown = () => {\n return (\n <div style={{ fontSize: 12 }}>\n {content ? <div style={{ opacity: 0.7 }}>{content}</div> : null}\n\n {links.length ? (\n <div className=\"section\">\n <div style={{ fontWeight: 500, marginTop: 6, opacity: 0.7 }}>\n 更多参考链接:\n </div>\n <div className=\"content\">\n <ul>\n {links.map((link) => (\n <li key={link.href}>\n <a href={link.url} target=\"_blank\">\n {link.title}\n </a>\n </li>\n ))}\n </ul>\n </div>\n </div>\n ) : null}\n </div>\n );\n };\n\n return [\n {},\n {\n title: \"\",\n type: \"editorRender\",\n options: {\n render: Markdown,\n },\n },\n ];\n}\n"
|
|
5957
|
+
},
|
|
5958
|
+
{
|
|
5959
|
+
"path": "src/core/tools/oss.ts",
|
|
5960
|
+
"content": "import CryptoJS from 'crypto-js'\nimport * as Taro from '@tarojs/taro'\nimport { isH5 } from './env'\n\ninterface UploadOssHelperOptions {\n accessKeyId: string\n accessKeySecret: string\n timeout?: number\n maxSize?: number\n}\n\ninterface UploadOssParams {\n OSSAccessKeyId: string\n policy: string\n signature: string\n}\n\nclass UploadOssHelper {\n private accessKeyId: string\n private accessKeySecret: string\n private timeout: number\n private maxSize: number\n\n constructor(options: UploadOssHelperOptions) {\n this.accessKeyId = options.accessKeyId\n this.accessKeySecret = options.accessKeySecret\n this.timeout = options.timeout || 1\n this.maxSize = options.maxSize || 10\n }\n\n createUploadParams(): UploadOssParams {\n const policy = this.getPolicyBase64()\n const signature = this.sign(policy)\n return {\n OSSAccessKeyId: this.accessKeyId,\n policy,\n signature,\n }\n }\n\n private getPolicyBase64(): string {\n const date = new Date()\n date.setHours(date.getHours() + this.timeout)\n const policyText = {\n expiration: date.toISOString(),\n conditions: [['content-length-range', 0, this.maxSize * 1024 * 1024]],\n }\n const policy = JSON.stringify(policyText)\n\n if (isH5()) {\n return btoa(unescape(encodeURIComponent(policy)))\n } else {\n const policyBuffer = new Uint8Array(\n policy.split('').map((char) => char.charCodeAt(0))\n ).buffer\n return Taro.arrayBufferToBase64(policyBuffer)\n }\n }\n\n private sign(policy: string): string {\n return CryptoJS.HmacSHA1(policy, this.accessKeySecret).toString(CryptoJS.enc.Base64)\n }\n}\n\nexport default UploadOssHelper\n"
|
|
5961
|
+
},
|
|
5962
|
+
{
|
|
5963
|
+
"path": "src/core/tools/px2rpx.ts",
|
|
5964
|
+
"content": "import * as Taro from \"@tarojs/taro\";\n\nexport const px2rpx = (px: number) => {\n let ratio = Taro.getSystemInfoSync().windowWidth / 375;\n return px / ratio;\n};\n\nexport default px2rpx;\n"
|
|
5965
|
+
},
|
|
5966
|
+
{
|
|
5967
|
+
"path": "src/core/tools/setSlotLayout.ts",
|
|
5968
|
+
"content": "export default function (slot, value) {\n if (!slot) return;\n\n switch (true) {\n case value.position === \"smart\":\n slot.setLayout(\"smart\");\n break;\n\n case value.position === \"absolute\":\n slot.setLayout(value.position);\n break;\n\n case value.display === \"flex\":\n if (value.flexDirection === \"row\") {\n slot.setLayout(\"flex-row\");\n } else if (value.flexDirection === \"column\") {\n slot.setLayout(\"flex-column\");\n } \n\n slot.setAlignItems(value.alignItems);\n slot.setJustifyContent(value.justifyContent);\n break;\n }\n}\n"
|
|
5969
|
+
},
|
|
5970
|
+
{
|
|
5971
|
+
"path": "src/core/tools/transformStyle.ts",
|
|
5972
|
+
"content": "import { isDesigner } from './env'\n\n/**\n * @description \n */\nfunction pxToVw(env, style) {\n if (!style) {\n return {}\n }\n\n if (isDesigner(env)) {\n return style\n }\n\n const cssStyle = {}\n\n const matchKeys = ['marginTop', 'marginBottom', 'marginLeft', 'marginRight', 'paddingLeft', 'paddingRight', 'width', 'height', 'fontSize', 'lineHieght'];\n\n Object.keys(style).forEach(property => {\n const newVal = parseFloat(style[property])\n if (matchKeys.includes(property) && !isNaN(newVal) && style[property] !== '100%') {\n cssStyle[property] = env.pxToVw(`${newVal}px`)\n } else {\n cssStyle[property] = style[property]\n }\n })\n return cssStyle\n}\n\nexport const transformStylePxToVw = pxToVw"
|
|
5973
|
+
},
|
|
5974
|
+
{
|
|
5975
|
+
"path": "src/core/tools/type.ts",
|
|
5976
|
+
"content": "type IsType = (value: any) => boolean\n\nfunction isType(type: string): IsType {\n return value => Object.prototype.toString.call(value) === `[object ${type}]`\n}\n\n/**\n * 判断是否是未定义\n * @param value 入参cd\n * @returns true/false,undefined、null返回true\n */\nexport function isUndef(value: unknown): value is undefined | null {\n return value === undefined || value === null\n}\n\n/**\n * 判断是否为空 undefined、null、空字符串返回true\n * @param value 入参\n */\nexport function isEmpty(value: unknown): value is undefined | null | '' {\n return value === undefined || value === null || value === ''\n}\n\n/**\n * 判断是否为Number类型\n * @param value 入参\n */\nexport function isNumber(value: unknown): value is number {\n return isType('Number')(value)\n}\n\n/**\n * 判断是否为String类型\n * @param value 入参\n */\nexport function isString(value: unknown): value is string {\n return isType('String')(value)\n}\n\n/**\n * 判断是否为Error类型\n * @param value 入参\n */\nexport function isError(value: unknown): value is Error {\n return isType('Error')(value)\n}\n\n/**\n * 判断是否为Array类型\n * @param value 入参\n */\nexport function isArray(value: unknown): value is unknown[] {\n return isType('Array')(value)\n}\n\n/**\n * 判断是否为Function类型,async function为true\n * @param value 入参\n */\nexport function isFunction(value: unknown): value is Function {\n return typeof value === 'function'\n}\n\n/**\n * 判断是否为Date类型\n * @param value 入参\n */\nexport function isDate(value: unknown): value is Date {\n return isType('Date')(value)\n}\n\n/**\n * 判断是否为Boolean 类型\n * @param value 入参\n */\nexport function isBoolean(value: unknown): value is boolean {\n return isType('Boolean')(value)\n}\n\n/**\n * 判断是否为严格Object类型\n * @param value 入参\n */\nexport function isObject(value: unknown): value is Object {\n return isType('Object')(value)\n}\n\n/**\n * 判断是否为泛object,不包括null\n * @param value 入参\n */\nexport function isWideObject(value: unknown): boolean {\n return value !== null && typeof value === 'object'\n}\n\n/**\n * 是否为FormData实例 不支持FormData时返回false\n * @param value - 入参\n */\nexport function isFormData(value: unknown): value is FormData {\n return typeof FormData !== 'undefined' && value instanceof FormData\n}\n\n/**\n * 是否为URLSearchParams实例 不支持URLSearchParams时返回false\n * @param value - 入参\n */\nexport function isURLSearchParams(value: unknown): value is URLSearchParams {\n return (\n typeof URLSearchParams !== 'undefined' &&\n value instanceof URLSearchParams\n )\n}\n"
|
|
5977
|
+
}
|
|
5978
|
+
]
|
|
5979
|
+
},
|
|
5680
5980
|
{
|
|
5681
5981
|
"path": "src/core/utils",
|
|
5682
5982
|
"content": null,
|
|
@@ -5685,17 +5985,25 @@
|
|
|
5685
5985
|
"path": "src/core/utils/ComContext.tsx",
|
|
5686
5986
|
"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"
|
|
5687
5987
|
},
|
|
5988
|
+
{
|
|
5989
|
+
"path": "src/core/utils/comRefResolver.ts",
|
|
5990
|
+
"content": "import { TodoPool } from './pool';\n\n/**\n * 组件引用解析器\n *\n * 职责单一:管理组件引用的查找、创建和注册\n *\n * 核心机制:\n * 1. 查找真实引用时,优先本地,再查父级\n * 2. 未找到时创建影子对象,影子对象调用时会动态查找真实引用\n * 3. 注册真实引用时,向上渗透到父级\n */\nexport class ComRefResolver {\n constructor(\n private registry: Record<string, any>,\n private parent?: ComRefResolver,\n private todoPool?: TodoPool,\n private scopeIndex: number = 0\n ) {}\n\n /**\n * 获取组件引用\n * @returns 真实引用或影子对象\n */\n get(id: string): any {\n // 1. 优先检查本地是否有真实引用\n if (this.registry[id] && !this.registry[id].__isShadow) {\n return this.registry[id];\n }\n\n // 2. 检查父级是否有真实引用\n const parentRef = this.parent?.findRealRef(id);\n if (parentRef) {\n return parentRef;\n }\n\n // 3. 如果已有影子对象,直接返回\n if (this.registry[id]?.__isShadow) {\n return this.registry[id];\n }\n\n // 4. 创建影子对象\n return this.createShadowProxy(id);\n }\n\n /**\n * 注册真实引用\n */\n set(id: string, ref: any): void {\n this.registry[id] = ref;\n // 向上渗透到父级\n this.parent?.set(id, ref);\n }\n\n /**\n * 删除引用\n */\n delete(id: string): void {\n delete this.registry[id];\n this.parent?.delete(id);\n }\n\n /**\n * 查找真实引用(仅用于父级链查找)\n */\n findRealRef(id: string): any | null {\n const local = this.registry[id];\n if (local && !local.__isShadow) {\n return local;\n }\n return this.parent?.findRealRef(id) ?? null;\n }\n\n /**\n * 创建影子对象\n * 关键:影子对象的方法被调用时,会动态查找真实引用\n */\n private createShadowProxy(id: string): any {\n const resolver = this;\n const registry = this.registry;\n const todoPool = this.todoPool;\n const scopeIndex = this.scopeIndex;\n\n const shadow = new Proxy({ __isShadow: true }, {\n get(_, method: string) {\n if (method === '__isShadow') return true;\n\n return (...args: any[]) => {\n // 动态检查是否已有真实引用\n // 注意:这里直接检查 registry[id],因为真实引用注册时会覆盖它\n const realRef = registry[id];\n if (realRef && !realRef.__isShadow) {\n if (typeof realRef[method] === 'function') {\n return realRef[method](...args);\n }\n return;\n }\n\n // 未找到真实引用,缓冲到 TodoPool\n if (todoPool instanceof TodoPool) {\n todoPool.push(id, scopeIndex, method, args);\n }\n };\n }\n });\n\n // 存储影子对象\n this.registry[id] = shadow;\n return shadow;\n }\n}\n"
|
|
5991
|
+
},
|
|
5992
|
+
{
|
|
5993
|
+
"path": "src/core/utils/event.ts",
|
|
5994
|
+
"content": "type EventName = 'rootScroll' | string;\n\nexport class EventEmitter {\n\n private eventsCache = {};\n\n constructor() {\n \n }\n\n addEventListner = (evtName: EventName, listner) => {\n \tif (!this.eventsCache[evtName]) {\n\t\t\tthis.eventsCache[evtName] = new Set([listner])\n \t\treturn;\n \t}\n\t\tthis.eventsCache[evtName].add(listner)\n }\n\n removeEventListner = (evtName: EventName, listner) => {\n \tif (this.eventsCache[evtName]) {\n \t\tthis.eventsCache[evtName].delete(listner);\n \t}\n }\n\n dispatch = (evtName: EventName, detail) => {\n \tif (!this.eventsCache[evtName]) {\n \t\t// console.warn(`no listner on this ${evtName}`);\n \t\treturn;\n \t}\n\n \tlet hasPreventDefault = false;\n\n \t(this.eventsCache[evtName] ?? []).forEach(listner => listner(detail));\n\n \treturn hasPreventDefault;\n }\n}"
|
|
5995
|
+
},
|
|
5688
5996
|
{
|
|
5689
5997
|
"path": "src/core/utils/hooks.ts",
|
|
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
|
|
5998
|
+
"content": "import React from 'react';\nimport { useState, useRef, useMemo, useEffect } from 'react';\nimport { createReactiveInputHandler } from '../mybricks/createReactiveInputHandler';\nimport { useAppContext, useParentSlot } from './ComContext';\nimport { TodoPool } from './pool';\nimport { ComRefResolver } from './comRefResolver';\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 *\n * 使用 ComRefResolver 统一处理引用解析逻辑\n */\nexport function proxyRefs(target: any, parentComRefs?: any, todoPool?: TodoPool): any {\n // 创建解析器,链接父级解析器\n const parentResolver = parentComRefs?.current?.__resolver as ComRefResolver | undefined;\n const scopeIndex = target.$index ?? 0;\n const resolver = new ComRefResolver(target, parentResolver, todoPool, scopeIndex);\n\n // 存储解析器引用,供子级使用\n target.__resolver = resolver;\n\n return new Proxy(target, {\n get(obj, prop) {\n if (prop === '__isProxy') return true;\n if (prop === '__resolver') return resolver;\n if (prop === 'toJSON') return () => obj;\n\n // u_ 开头的组件引用,统一由解析器处理\n if (typeof prop === 'string' && prop.startsWith('u_')) {\n return resolver.get(prop);\n }\n return obj[prop];\n },\n\n set(obj, prop, value) {\n const result = Reflect.set(obj, prop, value);\n\n // 真实引用注册时,同步到解析器\n const isRealRef = typeof prop === 'string'\n && !prop.startsWith('$')\n && value?.__isShadow !== true;\n\n if (isRealRef && typeof prop === 'string' && prop.startsWith('u_')) {\n resolver.set(prop, value);\n } else if (isRealRef && parentComRefs?.current) {\n // 非 u_ 开头的属性,保持原有的父级渗透逻辑\n try { parentComRefs.current[prop] = value; } catch {}\n }\n return result;\n },\n\n deleteProperty(obj, prop) {\n const result = Reflect.deleteProperty(obj, prop);\n\n if (typeof prop === 'string' && prop.startsWith('u_')) {\n resolver.delete(prop);\n } else if (typeof prop === 'string' && !prop.startsWith('$') && 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 === '__isLazyProxy') 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:_setStyle / _setData / show / hide / showOrHide */\nexport function useBuiltinHandlers(opts: {\n data: any;\n setDynamicStyle: React.Dispatch<React.SetStateAction<Record<string, any>>>;\n setShow: React.Dispatch<React.SetStateAction<boolean>>;\n isPopup: boolean;\n}) {\n const { data, setDynamicStyle, setShow, isPopup } = opts;\n return useMemo(() => {\n const handlers: Record<string, any> = {\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 if (!isPopup) {\n Object.assign(handlers, {\n show: () => setShow(true),\n hide: () => setShow(false),\n showOrHide: () => setShow((prev) => !prev),\n });\n }\n return handlers;\n }, [data, setDynamicStyle, setShow, isPopup]);\n}\n\n/**\n * 组件输出绑定 Hook(与 useBindInputs 对称)\n * - 从 props 提取事件函数,创建 eventProxy\n * - 合并 slot outputs,注册到 comRefs.current.$outputs[id]\n */\nexport function useBindOutputs(\n comRefs: any,\n id: string,\n props: any,\n enhancedSlots: any,\n context?: { id: string; name: string; parentSlot?: any }\n) {\n const eventProxy = useMemo(() => {\n const events: Record<string, any> = {};\n Object.keys(props).forEach(key => {\n if (typeof props[key] === 'function') {\n const handler = props[key];\n const wrapped = (original: any) => handler(original);\n wrapped.getConnections = () => [{ id: 'default' }];\n events[key] = wrapped;\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 if (comRefs?.current?.$outputs) {\n const slotOutputsList = Object.values(enhancedSlots || {})\n .map((slot: any) => slot?.outputs)\n .filter(Boolean);\n\n if (slotOutputsList.length > 0) {\n comRefs.current.$outputs[id] = new Proxy({}, {\n get(_, prop: string) {\n for (const outputs of slotOutputsList) {\n const fn = outputs[prop];\n if (fn) return fn;\n }\n return eventProxy[prop];\n }\n });\n } else {\n comRefs.current.$outputs[id] = eventProxy;\n }\n }\n\n return eventProxy;\n}\n"
|
|
5691
5999
|
},
|
|
5692
6000
|
{
|
|
5693
6001
|
"path": "src/core/utils/index.ts",
|
|
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"
|
|
6002
|
+
"content": "export * from './hooks';\nexport { TodoPool } from './pool';\nexport { ComRefResolver } from './comRefResolver';\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"
|
|
5695
6003
|
},
|
|
5696
6004
|
{
|
|
5697
6005
|
"path": "src/core/utils/pageRouter.ts",
|
|
5698
|
-
"content": "// @ts-ignore 运行时由宿主项目提供 @tarojs/taro\nimport Taro from
|
|
6006
|
+
"content": "// @ts-ignore 运行时由宿主项目提供 @tarojs/taro\nimport Taro from \"@tarojs/taro\";\n// @ts-ignore 运行时由宿主项目提供\nimport tabBarConfig from \"@/custom-tab-bar/tabBar.json\";\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 const inputParams: any = instance.router?.params || {};\n\n // 直接页面\"打开\",会有data包裹参数\n // 使用“跳转到”逻辑组件,会直接传递参数\n // TODO: 没有特殊字段和结构可以判断,现只能尽量加条件来判断\n let params =\n Object.keys(inputParams).length === 2 &&\n inputParams.data &&\n typeof inputParams.data === \"string\"\n ? inputParams\n : {\n data:\n Object.keys(inputParams).length > 1\n ? JSON.stringify({ ...inputParams, $taroTimestamp: undefined })\n : undefined,\n $taroTimestamp: inputParams.$taroTimestamp,\n };\n\n // 备份参数,解决某些生命周期下 Taro 获取不到 params 的问题\n if (!params.data && this.paramsBackup[name]) {\n params = { data: this.paramsBackup[name] };\n }\n\n // 解析真实参数\n const paramsDataStr = params.data\n ? decodeURIComponent(params.data)\n : undefined;\n let paramsData;\n try {\n paramsData = paramsDataStr ? JSON.parse(paramsDataStr) : undefined;\n } catch (error) {\n paramsData = paramsDataStr;\n }\n\n return { value: paramsData };\n }\n\n push(name: string, { value }: any) {\n const path = `pages/${name}/index`;\n const navigateType = this.isTabBarPage(path) ? \"switchTab\" : \"navigateTo\";\n this.navigate(navigateType, name, { value });\n }\n\n replace(name: string, { value }: any) {\n const path = `pages/${name}/index`;\n const navigateType = this.isTabBarPage(path) ? \"switchTab\" : \"redirectTo\";\n this.navigate(navigateType, name, { value });\n }\n\n navigate(\n type: \"navigateTo\" | \"redirectTo\" | \"switchTab\",\n name: string,\n { value }: any,\n ) {\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[type]({\n url: `${url}${dataStr ? `?data=${dataStr}` : \"\"}`,\n });\n }\n\n pop() {\n Taro.navigateBack();\n }\n\n /**\n * 判断是否为标签栏页面\n * @param pagePath 页面路径\n * @returns 是否为标签栏页面\n */\n isTabBarPage(pagePath: string) {\n return tabBarConfig?.tabBar?.list?.some(\n (item) => item.pagePath === pagePath,\n );\n }\n}\n\nexport const router = new TaroRouter();\nexport const pageRouter = new Page(router);\n"
|
|
5699
6007
|
},
|
|
5700
6008
|
{
|
|
5701
6009
|
"path": "src/core/utils/pool.ts",
|
|
@@ -5711,15 +6019,19 @@
|
|
|
5711
6019
|
},
|
|
5712
6020
|
{
|
|
5713
6021
|
"path": "src/core/utils/slots.tsx",
|
|
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:
|
|
6022
|
+
"content": "import React, { useMemo, useRef, useState } 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\n/** Channel Proxy 类型 */\ntype ChannelProxy = Record<string, (arg: any) => any>;\n\n/** Slot 渲染函数类型 */\ntype SlotRenderFunction = React.ComponentType<{\n inputValues?: Record<string, any>;\n [key: string]: any;\n}>;\n\ntype SlotState = {\n inputs: ChannelProxy;\n outputs: ChannelProxy;\n _inputs: ChannelProxy;\n /** scopeId -> scoped comRefs(每个 scope 一套,避免列表多实例覆盖) */\n _scopedComRefs: Record<string, any>;\n _render?: SlotRenderFunction;\n /** 存储 inputValues,当 inputs 被调用时更新 */\n _inputValues: Record<string, any>;\n /** 缓存上次合并结果,避免引用变化导致 useEffect 死循环 */\n _lastMergedParams?: any;\n render: (params?: any) => React.ReactNode;\n};\n\n/** 浅比较两个对象的第一层 key-value */\nfunction shallowEqual(a: any, b: any): boolean {\n if (a === b) return true;\n if (!a || !b) return false;\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n return keysA.every(key => a[key] === b[key]);\n}\n\n/**\n * 合并 slot 参数\n * 只有当有实际的 inputValues 时才合并,否则保持 undefined 以便从父级继承\n */\nfunction mergeSlotParams(\n stateInputValues: Record<string, any> | undefined,\n params?: any\n): any {\n const hasStateInputValues = stateInputValues && Object.keys(stateInputValues).length > 0;\n const hasParamsInputValues = params?.inputValues && Object.keys(params.inputValues).length > 0;\n\n if (!hasStateInputValues && !hasParamsInputValues) {\n return params || {};\n }\n\n return {\n ...(params || {}),\n inputValues: {\n ...(stateInputValues || {}),\n ...(params?.inputValues || {}),\n },\n };\n}\n\n/**\n * 生成作用域 ID\n */\nfunction createScopeId(id: string, slotKey: string, rawScope: any): string {\n return `${id}.${slotKey}::${String(rawScope)}`;\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, onInputCall?: (pin: string, value: any) => void) {\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 // 通知外部有输入调用(用于 scope 插槽的 inputValues 更新)\n onInputCall?.(pin, arg);\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 const [, forceUpdate] = useState({});\n\n return useMemo(() => {\n if (!rawSlots) return {};\n const nextSlots: AnyRecord = {};\n\n Object.entries(rawSlots).forEach(([slotKey, slotDef]: any) => {\n // 创建输入回调,当 inputs 被调用时更新 inputValues 并触发重渲染\n const onInputCall = (pin: string, value: any) => {\n const state = slotStoreRef.current[slotKey];\n if (state) {\n if (!state._inputValues) state._inputValues = {};\n state._inputValues[pin] = value;\n // 触发重渲染\n forceUpdate({});\n }\n };\n\n const state =\n slotStoreRef.current[slotKey] ||\n (slotStoreRef.current[slotKey] = {\n inputs: createChannelProxy(`${id}.${slotKey}.inputs`, onInputCall),\n outputs: createChannelProxy(`${id}.${slotKey}.outputs`),\n _inputs: createChannelProxy(`${id}.${slotKey}._inputs`),\n _scopedComRefs: {},\n _inputValues: {},\n _render: undefined,\n render: (params?: any) => {\n const r = state._render;\n const mergedParams = mergeSlotParams(state._inputValues, params);\n\n // 浅比较 inputValues,内容不变时复用上次引用,避免 useEffect 死循环\n if (\n state._lastMergedParams &&\n shallowEqual(mergedParams?.inputValues, state._lastMergedParams?.inputValues)\n ) {\n // 内容没变,复用旧引用\n } else {\n state._lastMergedParams = mergedParams;\n }\n const stableParams = state._lastMergedParams;\n\n // 只有存在 key 或 index 时才认为是\"多实例作用域插槽\",需要实例隔离\n const rawScope = stableParams?.inputValues?.index ?? params?.key;\n if (rawScope === undefined || rawScope === null) {\n return (\n <SlotParamsBridge state={state} params={stableParams} render={r} />\n );\n }\n\n const scopeId = createScopeId(id, slotKey, rawScope);\n const index = stableParams?.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={stableParams} 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"
|
|
6023
|
+
},
|
|
6024
|
+
{
|
|
6025
|
+
"path": "src/core/utils/tabbar.ts",
|
|
6026
|
+
"content": "import { EventEmitter } from './event'\n\nconst isDefine = (val) => val !== undefined && val !== null && val !== ''\n\nclass TabbarInstance {\n list: any = []\n\n eventEmitter = new EventEmitter()\n\n setTabBarBadge = ({ index, text }) => new Promise((resolve, reject) => {\n if (isDefine(index)) {\n this.list[index].active = true\n this.list[index].activeText = text\n\n console.log('change', this.list)\n this.eventEmitter.dispatch('change', this.list)\n }\n \n })\n\n hideTabBarRedDot = ({ index }) => new Promise((resolve, reject) => {\n if (isDefine(index)) {\n this.list[index].active = false\n this.list[index].activeText = 0\n\n this.eventEmitter.dispatch('change', this.list)\n }\n })\n\n removeTabBarBadge = this.hideTabBarRedDot\n\n initWithLength = len => {\n this.list = new Array(len).fill(t => null).map(() => ({ active: false, activeText: '' }))\n }\n}\n\nexport const tabbarIns = new TabbarInstance()"
|
|
5715
6027
|
},
|
|
5716
6028
|
{
|
|
5717
6029
|
"path": "src/core/utils/useContext.ts",
|
|
5718
|
-
"content": "import { useRef, useState, useMemo } from 'react'\nimport
|
|
6030
|
+
"content": "import { useRef, useState, useMemo } from 'react'\n// @ts-ignore\nimport * as Taro from '@tarojs/taro'\n// @ts-ignore\nimport { request } from '@/common/request'\nimport { tabbarIns } from \"@/core/utils/tabbar\"\n// @ts-ignore\nimport rootConfig from '@/common/rootConfig';\nimport { proxyRefs } from './hooks'\nimport { TodoPool } from './pool'\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 tabbar: tabbarIns,\n uploadFile: (params: any) => {\n let header = {};\n let mybricksGlobalHeaders = Taro.getStorageSync(\n \"_MYBRICKS_GLOBAL_HEADERS_\"\n );\n if (mybricksGlobalHeaders) {\n header = {\n ...mybricksGlobalHeaders,\n ...header,\n };\n }\n\n /**\n * 如果 url 不以 http 开头,添加默认域名\n */\n if (\n !/^(http|https):\\/\\/.*/.test(params.url) &&\n rootConfig?.status?.defaultCallServiceHost\n ) {\n params.url = `${rootConfig?.status?.defaultCallServiceHost}${params.url}`;\n }\n \n const { success, fail, ...rest } = params\n Taro.uploadFile({\n ...rest,\n success: (res: any) => success?.(res),\n fail: (err: any) => fail?.(err),\n })\n },\n },\n rootScroll: {},\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"
|
|
5719
6031
|
},
|
|
5720
6032
|
{
|
|
5721
6033
|
"path": "src/core/utils/with.tsx",
|
|
5722
|
-
"content": "import React, { useState, useEffect } from 'react';\n// @ts-ignore 运行时由宿主项目提供 @tarojs/components\nimport { View } from '@tarojs/components';\nimport { useModel, useBindInputs,
|
|
6034
|
+
"content": "import React, { useState, useEffect } from 'react';\n// @ts-ignore 运行时由宿主项目提供 @tarojs/components\nimport { View } from '@tarojs/components';\nimport { useModel, useBindInputs, useBuiltinHandlers, useBindOutputs, 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 [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; //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 const { slots: rawSlots, parentSlot: parentSlotProp, ...restProps } = rest as any;\n const parentSlot = useResolvedParentSlot(parentSlotProp);\n const enhancedSlots = useEnhancedSlots(rawSlots, id);\n\n // ---- inputs ----\n const handlers = useBuiltinHandlers({ data: _data, setDynamicStyle, setShow, isPopup });\n const inputProxy = useBindInputs(comRefs, id, handlers);\n\n // ---- outputs ----\n const outputProxy = useBindOutputs(comRefs, id, restProps, enhancedSlots, {\n id, name: props.name || id, parentSlot\n });\n\n // ---- render ----\n const jsx = (\n <Component\n {...restProps}\n inputs={inputProxy}\n outputs={outputProxy}\n slots={enhancedSlots}\n parentSlot={parentSlot}\n data={_data}\n env={env}\n id={id}\n style={style}\n />\n );\n\n if (parentSlot?.params?.itemWrap) {\n return parentSlot.params.itemWrap({\n id, name: props.name || id, jsx,\n def: (Component as any).def,\n inputs: inputProxy, outputs: outputProxy, style\n });\n }\n\n return (\n show || isPopup ? (\n <View id={id} className={className} style={{ ...style, ...dynamicStyle }}>\n {jsx}\n {props.children}\n </View>\n ) : null\n );\n};\n\nexport const WithWrapper = (id: string, Component: React.ComponentType<any>) => {\n return function WrappedComponent(props: any) {\n const contextStore = useAppCreateContext(id);\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"
|
|
5723
6035
|
}
|
|
5724
6036
|
]
|
|
5725
6037
|
}
|
|
@@ -5739,27 +6051,13 @@
|
|
|
5739
6051
|
}
|
|
5740
6052
|
]
|
|
5741
6053
|
},
|
|
5742
|
-
{
|
|
5743
|
-
"path": "src/custom-tab-bar/utils",
|
|
5744
|
-
"content": null,
|
|
5745
|
-
"children": [
|
|
5746
|
-
{
|
|
5747
|
-
"path": "src/custom-tab-bar/utils/event.ts",
|
|
5748
|
-
"content": "type EventName = 'rootScroll' | string;\n\nexport class EventEmitter {\n\n private eventsCache = {};\n\n constructor() {\n \n }\n\n addEventListner = (evtName: EventName, listner) => {\n \tif (!this.eventsCache[evtName]) {\n\t\t\tthis.eventsCache[evtName] = new Set([listner])\n \t\treturn;\n \t}\n\t\tthis.eventsCache[evtName].add(listner)\n }\n\n removeEventListner = (evtName: EventName, listner) => {\n \tif (this.eventsCache[evtName]) {\n \t\tthis.eventsCache[evtName].delete(listner);\n \t}\n }\n\n dispatch = (evtName: EventName, detail) => {\n \tif (!this.eventsCache[evtName]) {\n \t\t// console.warn(`no listner on this ${evtName}`);\n \t\treturn;\n \t}\n\n \tlet hasPreventDefault = false;\n\n \t(this.eventsCache[evtName] ?? []).forEach(listner => listner(detail));\n\n \treturn hasPreventDefault;\n }\n}"
|
|
5749
|
-
},
|
|
5750
|
-
{
|
|
5751
|
-
"path": "src/custom-tab-bar/utils/tabbar.ts",
|
|
5752
|
-
"content": "import { EventEmitter } from './event'\n\nconst isDefine = (val) => val !== undefined && val !== null && val !== ''\n\nclass TabbarInstance {\n list: any = []\n\n eventEmitter = new EventEmitter()\n\n setTabBarBadge = ({ index, text }) => new Promise((resolve, reject) => {\n if (isDefine(index)) {\n this.list[index].active = true\n this.list[index].activeText = text\n\n console.log('change', this.list)\n this.eventEmitter.dispatch('change', this.list)\n }\n \n })\n\n hideTabBarRedDot = ({ index }) => new Promise((resolve, reject) => {\n if (isDefine(index)) {\n this.list[index].active = false\n this.list[index].activeText = 0\n\n this.eventEmitter.dispatch('change', this.list)\n }\n })\n\n removeTabBarBadge = this.hideTabBarRedDot\n\n initWithLength = len => {\n this.list = new Array(len).fill(t => null).map(() => ({ active: false, activeText: '' }))\n }\n}\n\nexport const tabbarIns = new TabbarInstance()"
|
|
5753
|
-
}
|
|
5754
|
-
]
|
|
5755
|
-
},
|
|
5756
6054
|
{
|
|
5757
6055
|
"path": "src/custom-tab-bar/index.config.ts",
|
|
5758
6056
|
"content": "export default {\n \"component\": true\n}"
|
|
5759
6057
|
},
|
|
5760
6058
|
{
|
|
5761
6059
|
"path": "src/custom-tab-bar/index.tsx",
|
|
5762
|
-
"content": "import React, { useCallback, useMemo, useState, useEffect } from \"react\";\nimport
|
|
6060
|
+
"content": "import React, { useCallback, useMemo, useState, useEffect } from \"react\";\nimport * as Taro from \"@tarojs/taro\";\nimport { View, Image } from \"@tarojs/components\";\nimport DynamicIcon from \"../components/components/dynamic-icon\";\nimport css from \"./style.less\";\nimport tabBarJson from \"./mybricks/tabbar-config\";\nimport { tabbarIns } from \"@/core/utils/tabbar\";\n\ntabbarIns.initWithLength(tabBarJson.length);\n\nfunction CustomTabBar() {\n const [configList, setConfigList] = useState(tabbarIns.list);\n\n const switchTab = useCallback((url) => {\n Taro.switchTab({ url: `/${url}` });\n }, []);\n\n useEffect(() => {\n tabbarIns.eventEmitter.addEventListner(\"change\", (list) => {\n setConfigList(list.map((t) => t));\n });\n }, []);\n\n const tabList = useMemo(() => {\n return tabBarJson.map((item, index) => {\n const config = configList?.[index] ?? {};\n return {\n ...item,\n ...config,\n };\n });\n }, [tabBarJson, configList]);\n\n // 故意的只渲染一次,只在加载的时候渲染,符合预期\n const currentRoute = useMemo(() => {\n let pages = Taro.getCurrentPages();\n return pages[pages.length - 1].route;\n }, []);\n\n const iconRender = (itemData, isSelected) => {\n let useImgIcon = isSelected\n ? itemData.selectedIconUseImg !== false\n : itemData.normalIconUseImg !== false;\n let icon = isSelected ? itemData.selectedIcon : itemData.normalIcon;\n\n let iconStyle = isSelected\n ? itemData.selectedFontIconStyle\n : itemData.normalFontIconStyle;\n\n let imgIcon = isSelected\n ? itemData.selectedIconPath\n : itemData.normalIconPath;\n\n let imgIconStyle = isSelected\n ? itemData.selectedIconStyle\n : itemData.normalIconStyle;\n\n let formatText = \"\";\n if (itemData.active) {\n switch (true) {\n case typeof parseFloat(itemData?.activeText) === \"number\":\n if (itemData?.activeText > 0 && itemData?.activeText < 100) {\n formatText = itemData?.activeText;\n } else if (itemData?.activeText > 100) {\n formatText = \"99+\";\n }\n break;\n case typeof itemData.activeText === \"string\": {\n formatText =\n itemData?.activeText.length > 3\n ? `${itemData?.activeText.slice(0, 2)}...`\n : itemData?.activeText;\n break;\n }\n }\n }\n return (\n <View className={css.iconSlot}>\n {useImgIcon ? (\n <Image\n style={{\n display: \"block\",\n width: \"22px\",\n height: \"22px\",\n ...imgIconStyle,\n }}\n src={imgIcon}\n />\n ) : (\n <DynamicIcon\n className={css.fontIcon}\n name={icon}\n size={iconStyle?.fontSize}\n color={iconStyle?.color}\n />\n )}\n {itemData.active && (\n <View\n className={`${css.badge} ${!formatText ? css.small : css.normal}`}\n >\n {formatText}\n </View>\n )}\n </View>\n );\n };\n\n const $tabBars = useMemo(() => {\n return tabList.map((raw, index) => {\n let pagePath = raw.pagePath;\n\n let isSelected = pagePath === currentRoute;\n\n let textStyle = isSelected ? raw.selectedTextStyle : raw.normalTextStyle;\n let backgroundStyle = isSelected\n ? raw.selectedBackgroundStyle\n : raw.normalBackgroundStyle;\n\n return (\n <View\n className={css.item}\n key={index}\n onClick={() => {\n switchTab(raw.pagePath);\n }}\n style={{ ...backgroundStyle }}\n >\n {iconRender(raw, isSelected)}\n\n {raw.text && (\n <View className={css.textSlot} style={{ ...textStyle }}>\n {raw.text}\n </View>\n )}\n </View>\n );\n });\n }, [tabList, currentRoute]);\n\n return (\n <View className={css.tabBar}>\n <View className={css.items}>{$tabBars}</View>\n <View className={css.safearea}></View>\n </View>\n );\n}\n\nexport default CustomTabBar;\nCustomTabBar.options = {\n addGlobalClass: true,\n};\n"
|
|
5763
6061
|
},
|
|
5764
6062
|
{
|
|
5765
6063
|
"path": "src/custom-tab-bar/style.less",
|
|
@@ -5781,7 +6079,7 @@
|
|
|
5781
6079
|
},
|
|
5782
6080
|
{
|
|
5783
6081
|
"path": "src/app.global.less",
|
|
5784
|
-
"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\n.mybricks_com{\n flex-shrink: 0;\n min-height: 0; /* 防止子元素撑开父元素 */\n}\n\nview {\n box-sizing: border-box;\n}\n"
|
|
6082
|
+
"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\n.mybricks_com{\n flex-shrink: 0;\n min-height: 0; /* 防止子元素撑开父元素 */\n}\n.mybricks_slot{\n width: 100%;\n height: 100%;\n position: relative;\n transform: translateX(0)\n}\n\nview {\n box-sizing: border-box;\n}\n"
|
|
5785
6083
|
},
|
|
5786
6084
|
{
|
|
5787
6085
|
"path": "src/app.ts",
|
|
@@ -5841,11 +6139,11 @@
|
|
|
5841
6139
|
},
|
|
5842
6140
|
{
|
|
5843
6141
|
"path": "package.json",
|
|
5844
|
-
"content": "{\n \"name\": \"checkCom\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"description\": \"\",\n \"templateInfo\": {\n \"name\": \"default\",\n \"typescript\": true,\n \"css\": \"Less\",\n \"framework\": \"React\"\n },\n \"scripts\": {\n \"prepare\": \"husky\",\n \"new\": \"taro new\",\n \"build:weapp\": \"taro build --type weapp\",\n \"build:swan\": \"taro build --type swan\",\n \"build:alipay\": \"taro build --type alipay\",\n \"build:tt\": \"taro build --type tt\",\n \"build:h5\": \"taro build --type h5\",\n \"build:rn\": \"taro build --type rn\",\n \"build:qq\": \"taro build --type qq\",\n \"build:jd\": \"taro build --type jd\",\n \"build:harmony-hybrid\": \"taro build --type harmony-hybrid\",\n \"dev:weapp\": \"npm run build:weapp -- --watch\",\n \"dev:swan\": \"npm run build:swan -- --watch\",\n \"dev:alipay\": \"npm run build:alipay -- --watch\",\n \"dev:tt\": \"npm run build:tt -- --watch\",\n \"dev:h5\": \"npm run build:h5 -- --watch\",\n \"dev:rn\": \"npm run build:rn -- --watch\",\n \"dev:qq\": \"npm run build:qq -- --watch\",\n \"dev:jd\": \"npm run build:jd -- --watch\",\n \"dev:harmony-hybrid\": \"npm run build:harmony-hybrid -- --watch\"\n },\n \"browserslist\": {\n \"development\": [\n \"defaults and fully supports es6-module\",\n \"maintained node versions\"\n ],\n \"production\": [\n \"last 3 versions\",\n \"Android >= 4.1\",\n \"ios >= 8\"\n ]\n },\n \"author\": \"\",\n \"dependencies\": {\n \"@babel/runtime\": \"^7.24.4\",\n \"@tarojs/components\": \"4.1.9\",\n \"@tarojs/helper\": \"4.1.9\",\n \"@tarojs/plugin-platform-weapp\": \"4.1.9\",\n \"@tarojs/plugin-platform-alipay\": \"4.1.9\",\n \"@tarojs/plugin-platform-tt\": \"4.1.9\",\n \"@tarojs/plugin-platform-swan\": \"4.1.9\",\n \"@tarojs/plugin-platform-jd\": \"4.1.9\",\n \"@tarojs/plugin-platform-qq\": \"4.1.9\",\n \"@tarojs/plugin-platform-h5\": \"4.1.9\",\n \"@tarojs/plugin-platform-harmony-hybrid\": \"4.1.9\",\n \"@tarojs/runtime\": \"4.1.9\",\n \"@tarojs/shared\": \"4.1.9\",\n \"@tarojs/taro\": \"4.1.9\",\n \"@tarojs/plugin-framework-react\": \"4.1.9\",\n \"@tarojs/react\": \"4.1.9\",\n \"react-dom\": \"^18.0.0\",\n \"react\": \"^18.0.0\",\n \"brickd-mobile\": \"^0.0.53\",\n \"@taroify/icons\": \"^0.9.0\",\n \"@types/crypto-js\": \"^4.2.2\",\n \"crypto-js\": \"^4.2.0\",\n \"@antv/f2\": \"3.8.12\",\n \"qrcode-generator\": \"^2.0.4\"\n },\n \"devDependencies\": {\n \"@tarojs/plugin-generator\": \"4.1.9\",\n \"@commitlint/cli\": \"^19.8.1\",\n \"@commitlint/config-conventional\": \"^19.8.1\",\n \"lint-staged\": \"^16.1.2\",\n \"husky\": \"^9.1.7\",\n \"stylelint-config-standard\": \"^38.0.0\",\n \"@babel/core\": \"^7.24.4\",\n \"@tarojs/cli\": \"4.1.9\",\n \"@babel/plugin-transform-class-properties\": \"7.25.9\",\n \"@types/webpack-env\": \"^1.13.6\",\n \"@types/react\": \"^18.0.0\",\n \"webpack\": \"5.91.0\",\n \"@tarojs/taro-loader\": \"4.1.9\",\n \"@tarojs/webpack5-runner\": \"4.1.9\",\n \"less\": \"^4.2.0\",\n \"babel-preset-taro\": \"4.1.9\",\n \"eslint-config-taro\": \"4.1.9\",\n \"eslint\": \"^8.57.0\",\n \"@pmmmwh/react-refresh-webpack-plugin\": \"^0.5.5\",\n \"react-refresh\": \"^0.14.0\",\n \"@babel/preset-react\": \"^7.24.1\",\n \"eslint-plugin-react\": \"^7.34.1\",\n \"eslint-plugin-react-hooks\": \"^4.4.0\",\n \"stylelint\": \"^16.4.0\",\n \"typescript\": \"^5.4.5\",\n \"tsconfig-paths-webpack-plugin\": \"^4.1.0\",\n \"postcss\": \"^8.5.6\",\n \"@types/node\": \"^18\",\n \"@types/minimatch\": \"^5\"\n }\n}\n"
|
|
6142
|
+
"content": "{\n \"name\": \"checkCom\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"description\": \"\",\n \"templateInfo\": {\n \"name\": \"default\",\n \"typescript\": true,\n \"css\": \"Less\",\n \"framework\": \"React\"\n },\n \"scripts\": {\n \"prepare\": \"husky\",\n \"new\": \"taro new\",\n \"build:weapp\": \"taro build --type weapp\",\n \"build:swan\": \"taro build --type swan\",\n \"build:alipay\": \"taro build --type alipay\",\n \"build:tt\": \"taro build --type tt\",\n \"build:h5\": \"taro build --type h5\",\n \"build:rn\": \"taro build --type rn\",\n \"build:qq\": \"taro build --type qq\",\n \"build:jd\": \"taro build --type jd\",\n \"build:harmony-hybrid\": \"taro build --type harmony-hybrid\",\n \"dev:weapp\": \"npm run build:weapp -- --watch\",\n \"dev:swan\": \"npm run build:swan -- --watch\",\n \"dev:alipay\": \"npm run build:alipay -- --watch\",\n \"dev:tt\": \"npm run build:tt -- --watch\",\n \"dev:h5\": \"npm run build:h5 -- --watch\",\n \"dev:rn\": \"npm run build:rn -- --watch\",\n \"dev:qq\": \"npm run build:qq -- --watch\",\n \"dev:jd\": \"npm run build:jd -- --watch\",\n \"dev:harmony-hybrid\": \"npm run build:harmony-hybrid -- --watch\"\n },\n \"browserslist\": {\n \"development\": [\n \"defaults and fully supports es6-module\",\n \"maintained node versions\"\n ],\n \"production\": [\n \"last 3 versions\",\n \"Android >= 4.1\",\n \"ios >= 8\"\n ]\n },\n \"author\": \"\",\n \"dependencies\": {\n \"@babel/runtime\": \"^7.24.4\",\n \"@tarojs/components\": \"4.1.9\",\n \"@tarojs/helper\": \"4.1.9\",\n \"@tarojs/plugin-platform-weapp\": \"4.1.9\",\n \"@tarojs/plugin-platform-alipay\": \"4.1.9\",\n \"@tarojs/plugin-platform-tt\": \"4.1.9\",\n \"@tarojs/plugin-platform-swan\": \"4.1.9\",\n \"@tarojs/plugin-platform-jd\": \"4.1.9\",\n \"@tarojs/plugin-platform-qq\": \"4.1.9\",\n \"@tarojs/plugin-platform-h5\": \"4.1.9\",\n \"@tarojs/plugin-platform-harmony-hybrid\": \"4.1.9\",\n \"@tarojs/runtime\": \"4.1.9\",\n \"@tarojs/shared\": \"4.1.9\",\n \"@tarojs/taro\": \"4.1.9\",\n \"@tarojs/plugin-framework-react\": \"4.1.9\",\n \"@tarojs/react\": \"4.1.9\",\n \"react-dom\": \"^18.0.0\",\n \"react\": \"^18.0.0\",\n \"brickd-mobile\": \"^0.0.53\",\n \"@taroify/icons\": \"^0.9.0\",\n \"@types/crypto-js\": \"^4.2.2\",\n \"dayjs\": \"^1.11.19\",\n \"crypto-js\": \"^4.2.0\",\n \"@antv/f2\": \"3.8.12\",\n \"qrcode-generator\": \"^2.0.4\",\n \"lodash\": \"^4.17.21\"\n },\n \"devDependencies\": {\n \"@tarojs/plugin-generator\": \"4.1.9\",\n \"@commitlint/cli\": \"^19.8.1\",\n \"@commitlint/config-conventional\": \"^19.8.1\",\n \"lint-staged\": \"^16.1.2\",\n \"husky\": \"^9.1.7\",\n \"stylelint-config-standard\": \"^38.0.0\",\n \"@babel/core\": \"^7.24.4\",\n \"@tarojs/cli\": \"4.1.9\",\n \"@babel/plugin-transform-class-properties\": \"7.25.9\",\n \"@types/webpack-env\": \"^1.13.6\",\n \"@types/react\": \"^18.0.0\",\n \"webpack\": \"5.91.0\",\n \"@tarojs/taro-loader\": \"4.1.9\",\n \"@tarojs/webpack5-runner\": \"4.1.9\",\n \"less\": \"^4.2.0\",\n \"babel-preset-taro\": \"4.1.9\",\n \"eslint-config-taro\": \"4.1.9\",\n \"eslint\": \"^8.57.0\",\n \"@pmmmwh/react-refresh-webpack-plugin\": \"^0.5.5\",\n \"react-refresh\": \"^0.14.0\",\n \"@babel/preset-react\": \"^7.24.1\",\n \"eslint-plugin-react\": \"^7.34.1\",\n \"eslint-plugin-react-hooks\": \"^4.4.0\",\n \"stylelint\": \"^16.4.0\",\n \"typescript\": \"^5.4.5\",\n \"tsconfig-paths-webpack-plugin\": \"^4.1.0\",\n \"postcss\": \"^8.5.6\",\n \"@types/node\": \"^18\",\n \"@types/minimatch\": \"^5\"\n }\n}\n"
|
|
5845
6143
|
},
|
|
5846
6144
|
{
|
|
5847
6145
|
"path": "project.config.json",
|
|
5848
|
-
"content": "{\n \"miniprogramRoot\": \"./dist\",\n \"projectname\": \"templateTaro\",\n \"description\": \"\",\n \"appid\": \"touristappid\",\n \"setting\": {\n \"urlCheck\":
|
|
6146
|
+
"content": "{\n \"miniprogramRoot\": \"./dist\",\n \"projectname\": \"templateTaro\",\n \"description\": \"\",\n \"appid\": \"touristappid\",\n \"setting\": {\n \"urlCheck\": false,\n \"es6\": false,\n \"enhance\": false,\n \"compileHotReLoad\": false,\n \"postcss\": false,\n \"minified\": false\n },\n \"compileType\": \"miniprogram\"\n}\n"
|
|
5849
6147
|
},
|
|
5850
6148
|
{
|
|
5851
6149
|
"path": "stylelint.config.mjs",
|