@mybricks/to-code-taro 1.0.8 → 1.1.0
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/comlib/_Modal.js +68 -0
- package/dist/cjs/core/comlib/_TimerDelay.js +55 -30
- package/dist/cjs/core/comlib/index.js +3 -0
- package/dist/cjs/core/mybricks/log.js +0 -1
- package/dist/cjs/core/utils/hooks.js +3 -2
- package/dist/cjs/core/utils/slots.js +11 -5
- package/dist/cjs/core/utils/useContext.js +5 -3
- package/dist/cjs/core/utils/with.js +5 -6
- package/dist/cjs/generate/generateTaroProjectJson.js +18 -1
- package/dist/cjs/handleCom.js +47 -73
- package/dist/cjs/handleSlot.js +5 -3
- package/dist/cjs/processors/processComEvents.js +2 -3
- package/dist/cjs/processors/processModule.js +23 -0
- package/dist/cjs/processors/processScene.js +23 -0
- package/dist/cjs/processors/processSceneLogic.d.ts +4 -1
- package/dist/cjs/processors/processSceneLogic.js +72 -12
- package/dist/cjs/taro-template.json +68 -42
- package/dist/cjs/toCodeTaro.d.ts +14 -1
- package/dist/cjs/toCodeTaro.js +1 -0
- package/dist/cjs/utils/builder/buildResult.d.ts +1 -0
- package/dist/cjs/utils/builder/buildResult.js +8 -1
- package/dist/cjs/utils/common/helper.d.ts +10 -0
- package/dist/cjs/utils/common/helper.js +21 -0
- package/dist/cjs/utils/common/string.d.ts +10 -0
- package/dist/cjs/utils/common/string.js +13 -0
- package/dist/cjs/utils/config/content/converter.js +1 -0
- package/dist/cjs/utils/config/content/tabBarConfig.d.ts +19 -4
- package/dist/cjs/utils/config/content/tabBarConfig.js +18 -1
- package/dist/cjs/utils/config/content/types.d.ts +15 -10
- package/dist/cjs/utils/config/handlePageConfig.d.ts +6 -0
- package/dist/cjs/utils/config/handlePageConfig.js +13 -1
- package/dist/cjs/utils/logic/handleProcess.js +50 -33
- package/dist/cjs/utils/style/converter.js +1 -6
- package/dist/cjs/utils/templates/index.d.ts +1 -0
- package/dist/cjs/utils/templates/index.js +11 -4
- package/dist/cjs/utils/templates/renderManager.js +4 -2
- package/dist/cjs/utils/templates/scene.d.ts +2 -1
- package/dist/cjs/utils/templates/scene.js +4 -3
- package/dist/esm/abstractEventTypeDef.d.ts.map +1 -0
- package/dist/esm/core/comlib/_Modal.js +51 -0
- package/dist/esm/core/comlib/_TimerDelay.js +46 -14
- package/dist/esm/core/comlib/index.js +2 -0
- package/dist/esm/core/mybricks/log.js +1 -5
- package/dist/esm/core/utils/hooks.js +7 -2
- package/dist/esm/core/utils/slots.js +28 -10
- package/dist/esm/core/utils/useContext.js +9 -3
- package/dist/esm/core/utils/with.js +5 -9
- package/dist/esm/generate/generateTaroProjectJson.d.ts.map +1 -0
- package/dist/esm/generate/generateTaroProjectJson.js +22 -0
- package/dist/esm/generate/generateTaroTempalteJson.d.ts.map +1 -0
- package/dist/esm/generate/utils/appConfig.d.ts.map +1 -0
- package/dist/esm/generate/utils/commonDir.d.ts.map +1 -0
- package/dist/esm/generate/utils/fileNode.d.ts.map +1 -0
- package/dist/esm/generate/utils/index.d.ts.map +1 -0
- package/dist/esm/generate/utils/tabBarImages.d.ts.map +1 -0
- package/dist/esm/handleCom.js +60 -95
- package/dist/esm/handleDom.d.ts.map +1 -0
- package/dist/esm/handleExtension.d.ts.map +1 -0
- package/dist/esm/handleGlobal.d.ts.map +1 -0
- package/dist/esm/handleModule.d.ts.map +1 -0
- package/dist/esm/handleSlot.js +9 -4
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/processors/processComEvents.js +6 -3
- package/dist/esm/processors/processModule.d.ts.map +1 -0
- package/dist/esm/processors/processModule.js +35 -0
- package/dist/esm/processors/processScene.d.ts.map +1 -0
- package/dist/esm/processors/processScene.js +35 -0
- package/dist/esm/processors/processSceneLogic.d.ts +4 -1
- package/dist/esm/processors/processSceneLogic.js +90 -15
- package/dist/esm/taro-template.json +68 -42
- package/dist/esm/toCodeTaro.d.ts +14 -1
- package/dist/esm/toCodeTaro.d.ts.map +1 -0
- package/dist/esm/toCodeTaro.js +1 -0
- package/dist/esm/utils/builder/buildResult.d.ts +1 -0
- package/dist/esm/utils/builder/buildResult.d.ts.map +1 -0
- package/dist/esm/utils/builder/buildResult.js +8 -1
- package/dist/esm/utils/common/ImportManager.d.ts.map +1 -0
- package/dist/esm/utils/common/helper.d.ts +10 -0
- package/dist/esm/utils/common/helper.js +29 -0
- package/dist/esm/utils/common/object.d.ts.map +1 -0
- package/dist/esm/utils/common/string.d.ts +10 -0
- package/dist/esm/utils/common/string.d.ts.map +1 -0
- package/dist/esm/utils/common/string.js +16 -0
- package/dist/esm/utils/config/content/converter.d.ts.map +1 -0
- package/dist/esm/utils/config/content/converter.js +1 -0
- package/dist/esm/utils/config/content/index.d.ts.map +1 -0
- package/dist/esm/utils/config/content/pageConfig.d.ts.map +1 -0
- package/dist/esm/utils/config/content/saveBase64Image.d.ts.map +1 -0
- package/dist/esm/utils/config/content/tabBarConfig.d.ts +19 -4
- package/dist/esm/utils/config/content/tabBarConfig.d.ts.map +1 -0
- package/dist/esm/utils/config/content/tabBarConfig.js +28 -4
- package/dist/esm/utils/config/content/types.d.ts +15 -10
- package/dist/esm/utils/config/content/types.d.ts.map +1 -0
- package/dist/esm/utils/config/content/validator.d.ts.map +1 -0
- package/dist/esm/utils/config/handlePageConfig.d.ts +6 -0
- package/dist/esm/utils/config/handlePageConfig.d.ts.map +1 -0
- package/dist/esm/utils/config/handlePageConfig.js +17 -2
- package/dist/esm/utils/context/buildContext.d.ts.map +1 -0
- package/dist/esm/utils/context/buildFrameMap.d.ts.map +1 -0
- package/dist/esm/utils/context/buildGlobalData.d.ts.map +1 -0
- package/dist/esm/utils/context/collectJSModules.d.ts.map +1 -0
- package/dist/esm/utils/context/createEventQueries.d.ts.map +1 -0
- package/dist/esm/utils/context/createProvider.d.ts.map +1 -0
- package/dist/esm/utils/index.d.ts.map +1 -0
- package/dist/esm/utils/logic/convertNamespace.d.ts.map +1 -0
- package/dist/esm/utils/logic/genJSModules.d.ts.map +1 -0
- package/dist/esm/utils/logic/handleProcess.js +66 -40
- package/dist/esm/utils/logic/processChildren.d.ts.map +1 -0
- package/dist/esm/utils/style/color.d.ts.map +1 -0
- package/dist/esm/utils/style/converter.js +11 -8
- package/dist/esm/utils/style/getComponentClassName.d.ts.map +1 -0
- package/dist/esm/utils/style/pxtransform.d.ts.map +1 -0
- package/dist/esm/utils/style/types.d.ts.map +1 -0
- package/dist/esm/utils/templates/component.d.ts.map +1 -0
- package/dist/esm/utils/templates/index.d.ts +1 -0
- package/dist/esm/utils/templates/index.js +20 -10
- package/dist/esm/utils/templates/renderManager.js +5 -2
- package/dist/esm/utils/templates/scene.d.ts +2 -1
- package/dist/esm/utils/templates/scene.js +7 -6
- package/package.json +1 -1
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"path": "config/index.ts",
|
|
12
|
-
"content": "import { defineConfig, type UserConfigExport } from '@tarojs/cli'\nimport TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin'\nimport devConfig from './dev'\nimport prodConfig from './prod'\n\n// https://taro-docs.jd.com/docs/next/config#defineconfig-辅助函数\nexport default defineConfig<'webpack5'>(async (merge, { command, mode }) => {\n const baseConfig: UserConfigExport<'webpack5'> = {\n projectName: 'checkCom',\n date: '2025-12-24',\n designWidth: 375,\n deviceRatio: {\n 640: 2.34 / 2,\n 750: 1,\n 375: 2,\n 828: 1.81 / 2\n },\n sourceRoot: 'src',\n outputRoot: 'dist',\n plugins: [\n \"@tarojs/plugin-generator\"\n ],\n defineConstants: {\n },\n copy: {\n patterns: [\n ],\n options: {\n }\n },\n framework: 'react',\n compiler: {\n type: 'webpack5',\n prebundle: {\n exclude: ['brickd-mobile']\n }\n },\n cache: {\n enable: false // Webpack 持久化缓存配置,建议开启。默认配置请参考:https://docs.taro.zone/docs/config-detail#cache\n },\n mini: {\n postcss: {\n pxtransform: {\n enable: true,\n config: {\n\n }\n },\n cssModules: {\n enable: true, // 默认为 false,如需使用 css modules 功能,则设为 true\n config: {\n namingPattern: 'global', // 转换模式,取值为 global/module\n generateScopedName: '[name]__[local]___[hash:base64:5]'\n }\n }\n },\n webpackChain(chain) {\n chain.resolve.plugin('tsconfig-paths').use(TsconfigPathsPlugin)\n }\n },\n h5: {\n publicPath: '/',\n staticDirectory: 'static',\n output: {\n filename: 'js/[name].[hash:8].js',\n chunkFilename: 'js/[name].[chunkhash:8].js'\n },\n miniCssExtractPluginOption: {\n ignoreOrder: true,\n filename: 'css/[name].[hash].css',\n chunkFilename: 'css/[name].[chunkhash].css'\n },\n postcss: {\n autoprefixer: {\n enable: true,\n config: {}\n },\n cssModules: {\n enable: true, // 默认为 false,如需使用 css modules 功能,则设为 true\n config: {\n namingPattern: 'module', // 转换模式,取值为 global/module\n generateScopedName: '[name]__[local]___[hash:base64:5]'\n }\n }\n },\n webpackChain(chain) {\n chain.resolve.plugin('tsconfig-paths').use(TsconfigPathsPlugin)\n }\n },\n rn: {\n appName: 'taroDemo',\n postcss: {\n cssModules: {\n enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true\n }\n }\n }\n }\n\n process.env.BROWSERSLIST_ENV = process.env.NODE_ENV\n\n if (process.env.NODE_ENV === 'development') {\n // 本地开发构建配置(不混淆压缩)\n return merge({}, baseConfig, devConfig)\n }\n // 生产构建配置(默认开启压缩混淆等)\n return merge({}, baseConfig, prodConfig)\n})\n"
|
|
12
|
+
"content": "import { defineConfig, type UserConfigExport } from '@tarojs/cli'\nimport TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin'\nimport devConfig from './dev'\nimport prodConfig from './prod'\n\n// https://taro-docs.jd.com/docs/next/config#defineconfig-辅助函数\nexport default defineConfig<'webpack5'>(async (merge, { command, mode }) => {\n const baseConfig: UserConfigExport<'webpack5'> = {\n projectName: 'checkCom',\n date: '2025-12-24',\n designWidth: 375,\n deviceRatio: {\n 640: 2.34 / 2,\n 750: 1,\n 375: 2,\n 828: 1.81 / 2\n },\n sourceRoot: 'src',\n outputRoot: 'dist',\n plugins: [\n \"@tarojs/plugin-generator\"\n ],\n defineConstants: {\n },\n copy: {\n patterns: [\n ],\n options: {\n }\n },\n framework: 'react',\n compiler: {\n type: 'webpack5',\n prebundle: {\n exclude: ['brickd-mobile', '@taroify/icons']\n }\n },\n cache: {\n enable: false // Webpack 持久化缓存配置,建议开启。默认配置请参考:https://docs.taro.zone/docs/config-detail#cache\n },\n mini: {\n postcss: {\n pxtransform: {\n enable: true,\n config: {\n\n }\n },\n cssModules: {\n enable: true, // 默认为 false,如需使用 css modules 功能,则设为 true\n config: {\n namingPattern: 'global', // 转换模式,取值为 global/module\n generateScopedName: '[name]__[local]___[hash:base64:5]'\n }\n }\n },\n webpackChain(chain) {\n chain.resolve.plugin('tsconfig-paths').use(TsconfigPathsPlugin)\n }\n },\n h5: {\n publicPath: '/',\n staticDirectory: 'static',\n output: {\n filename: 'js/[name].[hash:8].js',\n chunkFilename: 'js/[name].[chunkhash:8].js'\n },\n miniCssExtractPluginOption: {\n ignoreOrder: true,\n filename: 'css/[name].[hash].css',\n chunkFilename: 'css/[name].[chunkhash].css'\n },\n postcss: {\n autoprefixer: {\n enable: true,\n config: {}\n },\n cssModules: {\n enable: true, // 默认为 false,如需使用 css modules 功能,则设为 true\n config: {\n namingPattern: 'module', // 转换模式,取值为 global/module\n generateScopedName: '[name]__[local]___[hash:base64:5]'\n }\n }\n },\n webpackChain(chain) {\n chain.resolve.plugin('tsconfig-paths').use(TsconfigPathsPlugin)\n }\n },\n rn: {\n appName: 'taroDemo',\n postcss: {\n cssModules: {\n enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true\n }\n }\n }\n }\n\n process.env.BROWSERSLIST_ENV = process.env.NODE_ENV\n\n if (process.env.NODE_ENV === 'development') {\n // 本地开发构建配置(不混淆压缩)\n return merge({}, baseConfig, devConfig)\n }\n // 生产构建配置(默认开启压缩混淆等)\n return merge({}, baseConfig, prodConfig)\n})\n"
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
"path": "config/prod.ts",
|
|
@@ -450,40 +450,16 @@
|
|
|
450
450
|
"content": null,
|
|
451
451
|
"children": [
|
|
452
452
|
{
|
|
453
|
-
"path": "src/components/components/dynamic-icon/
|
|
454
|
-
"content": null,
|
|
455
|
-
"children": [
|
|
456
|
-
{
|
|
457
|
-
"path": "src/components/components/dynamic-icon/harmony-icons/icons.tsx",
|
|
458
|
-
"content": "export const HarmonyIcons = [\n {\n title: \"系统UI\",\n icons: {\n HM_airplane_fill: \"\",\n HM_arrow_clockwise: \"\",\n HM_arrow_counterclockwise: \"\",\n HM_arrow_counterclockwise_clock: \"\",\n HM_arrow_down_right_and_arrow_up_left: \"\",\n HM_arrow_right_up_and_square: \"\",\n HM_arrow_up_left_and_arrow_down_right: \"\",\n HM_arrowshape_turn_up_right_fill: \"\",\n HM_battery: \"\",\n HM_battery_75percent: \"\",\n HM_bell_fill: \"\",\n HM_bell_slash: \"\",\n HM_bell_slash_fill: \"\",\n HM_bluetooth: \"\",\n HM_bluetooth_slash: \"\",\n HM_bookmark: \"\",\n HM_bookmark_filled_on_bookmark: \"\",\n HM_brush: \"\",\n HM_brush_fill: \"\",\n HM_checkmark: \"\",\n HM_checkmark_circle: \"\",\n HM_checkmark_circle_fill: \"\",\n HM_checkmark_square: \"\",\n HM_checkmark_square_fill: \"\",\n HM_checkmark_square_on_square: \"\",\n HM_checkmark_square_on_square_fill: \"\",\n HM_circle_viewfinder: \"\",\n HM_clean: \"\",\n HM_clean_fill: \"\",\n HM_dot_grid_1x2: \"\",\n HM_dot_grid_2x2: \"\",\n HM_externaldrive: \"\",\n HM_externaldrive_fill: \"\",\n HM_externaldrive_fill_3: \"\",\n HM_eye: \"\",\n HM_eye_slash: \"\",\n HM_flag: \"\",\n HM_flashlight_off_fill: \"\",\n HM_flashlight_on_fill: \"\",\n HM_full_screen_fill: \"\",\n HM_gearshape: \"\",\n HM_hand_point_up_tap_fill: \"\",\n HM_hand_point_up_tap_fill_1: \"\",\n HM_hand_point_up_tap_fill_slash: \"\",\n HM_hand_tap: \"\",\n HM_hand_thumbsup_fill: \"\",\n HM_heart: \"\",\n HM_heart_fill: \"\",\n HM_heart_slash: \"\",\n HM_house: \"\",\n HM_house_fill: \"\",\n HM_label: \"\",\n HM_line_viewfinder: \"\",\n HM_lock: \"\",\n HM_lock_fill: \"\",\n HM_lock_filled_arrow_counterclockwise: \"\",\n HM_lock_open: \"\",\n HM_lock_open_fill: \"\",\n HM_magnifyingglass: \"\",\n HM_mic: \"\",\n HM_mic_fill: \"\",\n HM_minus: \"\",\n HM_minus_circle: \"\",\n HM_minus_magnifyingglass: \"\",\n HM_moon_circle_fill: \"\",\n HM_moon_fill: \"\",\n HM_moon_slash_circle: \"\",\n HM_more: \"\",\n HM_nfc: \"\",\n HM_nfc_fill: \"\",\n HM_paperplane: \"\",\n HM_paperplane_right_fill: \"\",\n HM_pin: \"\",\n HM_pin_fill_1: \"\",\n HM_plus: \"\",\n HM_plus_magnifyingglass: \"\",\n HM_plus_square: \"\",\n HM_plus_square_on_square_fill: \"\",\n HM_power: \"\",\n HM_qrcode: \"\",\n HM_rays: \"\",\n HM_rectangle_and_arrowshape_turn_up_right: \"\",\n HM_rectangle_portrait_rotate: \"\",\n HM_rectangle_rotate: \"\",\n HM_redo: \"\",\n HM_save: \"\",\n HM_share: \"\",\n HM_slider_horizontal_2: \"\",\n HM_slider_vertical_3: \"\",\n HM_speaker: \"\",\n HM_speaker_slash: \"\",\n HM_speaker_wave_3: \"\",\n HM_speaker_wave_3_slash: \"\",\n HM_square_fill_grid_2x2: \"\",\n HM_square_grid_2x2: \"\",\n HM_star: \"\",\n HM_star_fill: \"\",\n HM_sun_max: \"\",\n HM_sun_max_fill: \"\",\n HM_sun_min: \"\",\n HM_trash: \"\",\n HM_trash_fill: \"\",\n HM_undo: \"\",\n HM_wifi: \"\",\n HM_wifi_slash: \"\",\n HM_xmark: \"\",\n HM_xmark_circle: \"\",\n HM_xmark_circle_fill: \"\",\n },\n },\n {\n title: \"时间\",\n icons: {\n HM_alarm_fill_1: \"\",\n HM_calendar: \"\",\n HM_calendar_badge_clock: \"\",\n HM_calendar_fill: \"\",\n HM_clock: \"\",\n HM_clock_fill: \"\",\n HM_stopwatch_2: \"\",\n HM_timer: \"\",\n HM_timer_circle_fill: \"\",\n HM_worldclock: \"\",\n HM_worldclock_fill: \"\",\n HM_worldclock_fill_2: \"\",\n },\n },\n {\n title: \"箭头\",\n icons: {\n HM_arrow_clockwise: \"\",\n HM_arrow_counterclockwise: \"\",\n HM_arrow_counterclockwise_clock: \"\",\n HM_arrow_down_circle: \"\",\n HM_arrow_down_right_and_arrow_up_left: \"\",\n HM_arrow_left: \"\",\n HM_arrow_left_circle: \"\",\n HM_arrow_right: \"\",\n HM_arrow_right_circle: \"\",\n HM_arrow_right_up_and_square: \"\",\n HM_arrow_up_circle: \"\",\n HM_arrow_up_circle_fill: \"\",\n HM_arrow_up_left: \"\",\n HM_arrow_up_left_and_arrow_down_right: \"\",\n HM_arrow_up_to_line: \"\",\n HM_arrowshape_3_triangle_path: \"\",\n HM_arrowshape_down_to_line_fill: \"\",\n HM_arrowshape_turn_up_right_fill: \"\",\n HM_arrowshape_up: \"\",\n HM_arrowshape_up_fill: \"\",\n HM_arrowshape_up_frame_fill: \"\",\n HM_arrowshape_up_left_and_arrowshape_down_right: \"\",\n HM_arrowshape_up_to_line_fill: \"\",\n HM_arrowtriangle_down_fill: \"\",\n HM_arrowtriangle_up_fill: \"\",\n HM_chevron_down: \"\",\n HM_chevron_down_2_circle: \"\",\n HM_chevron_down_circle: \"\",\n HM_chevron_left: \"\",\n HM_chevron_left_2: \"\",\n HM_chevron_left_circle: \"\",\n HM_chevron_right: \"\",\n HM_chevron_right_circle: \"\",\n HM_chevron_up: \"\",\n HM_chevron_up_2: \"\",\n HM_chevron_up_2_circle: \"\",\n HM_chevron_up_circle: \"\",\n HM_line_below_arrowtriangle_up_circle_fill: \"\",\n HM_line_below_arrowtriangle_up_fill: \"\",\n HM_paperplane: \"\",\n HM_rectangle_and_arrowshape_turn_up_right: \"\",\n HM_redo: \"\",\n HM_transfer_station: \"\",\n HM_undo: \"\",\n },\n },\n {\n title: \"相机与照片\",\n icons: {\n HM_arrow_down_and_rectangle_on_rectangle: \"\",\n HM_arrow_up_and_rectangle_on_rectangle: \"\",\n HM_camera: \"\",\n HM_camera_fill: \"\",\n HM_camera_filters_fill: \"\",\n HM_capture_smiles: \"\",\n HM_circle_lefthalf_inset_filled: \"\",\n HM_circle_righthalf_inset_filled: \"\",\n HM_dot_video_fill: \"\",\n HM_drop: \"\",\n HM_drop_bottomrighthalf_inset_filled: \"\",\n HM_flower: \"\",\n HM_hand_draw: \"\",\n HM_heart_square_stack_fill: \"\",\n HM_lightbulb: \"\",\n HM_lightbulb_slash: \"\",\n HM_line_arrowtriangle_2_inward: \"\",\n HM_livephoto: \"\",\n HM_movie_fill: \"\",\n HM_paintpalette: \"\",\n HM_picture: \"\",\n HM_picture_2: \"\",\n HM_picture_damage: \"\",\n HM_picture_fill: \"\",\n HM_play_video: \"\",\n HM_play_video_fill: \"\",\n HM_puzzle: \"\",\n HM_puzzle_fill: \"\",\n HM_rectangle_on_rectangle: \"\",\n HM_rectangle_on_rectangle_fill: \"\",\n HM_resolution_video: \"\",\n HM_scope: \"\",\n HM_scope_slash: \"\",\n HM_shutter_photo: \"\",\n HM_square_slash: \"\",\n HM_template: \"\",\n HM_template_fill: \"\",\n HM_video_fill: \"\",\n HM_video_slasj_fill: \"\",\n HM_xmark_picture: \"\",\n HM_xmark_picture_fill: \"\",\n },\n },\n {\n title: \"办公文件\",\n icons: {\n HM_arrow_right_folder_circle: \"\",\n HM_arrow_right_folder_fill: \"\",\n HM_book_open_fill: \"\",\n HM_book_pages_fill_1: \"\",\n HM_briefcase: \"\",\n HM_case_fill: \"\",\n HM_checkmark_clipboard_fill: \"\",\n HM_doc: \"\",\n HM_doc_plaintext: \"\",\n HM_doc_plaintext_and_pencil: \"\",\n HM_doc_plaintext_and_pencil_fill: \"\",\n HM_doc_plaintext_fill: \"\",\n HM_doc_text: \"\",\n HM_doc_text_badge_arrow_up: \"\",\n HM_doc_text_badge_checkmark: \"\",\n HM_doc_text_badge_magnifyingglass: \"\",\n HM_doc_text_fill: \"\",\n HM_folder: \"\",\n HM_folder_badge_eye: \"\",\n HM_folder_badge_plus: \"\",\n HM_folder_fill: \"\",\n HM_form: \"\",\n HM_grid: \"\",\n HM_list_square_bill: \"\",\n HM_paperclip: \"\",\n HM_text_clipboard: \"\",\n },\n },\n {\n title: \"键盘\",\n icons: {\n HM_asterisk_rectangle_badge_handwritten: \"\",\n HM_celiakeyboard_elevate: \"\",\n HM_celiakeyboard_mechanical: \"\",\n HM_celiakeyboard_menu_icon_size: \"\",\n HM_delete_left: \"\",\n HM_delete_left_fill: \"\",\n HM_input_mode: \"\",\n HM_keyboard_badge_bihua: \"\",\n HM_keyboard_badge_cangjie: \"\",\n HM_keyboard_badge_handwritten: \"\",\n HM_keyboard_badge_spell: \"\",\n HM_keyboard_badge_wubi: \"\",\n HM_keyboard_badge_zhuyin: \"\",\n HM_keyboard_circle: \"\",\n HM_keyboard_onehanded_left: \"\",\n HM_keyboard_onehanded_right: \"\",\n HM_keyboard_square: \"\",\n HM_keyboard_thumbmode: \"\",\n HM_onehand: \"\",\n HM_selector: \"\",\n HM_space_1: \"\",\n HM_swipeup_input: \"\",\n HM_traditional_square: \"\",\n HM_translate: \"\",\n HM_translate_c2e: \"\",\n HM_translate_e2c: \"\",\n },\n },\n {\n title: \"媒体\",\n icons: {\n HM_backward_end_fill: \"\",\n HM_discover_fill: \"\",\n HM_fast_forward: \"\",\n HM_forward_end_fill: \"\",\n HM_gobackward_15: \"\",\n HM_gobackward_30: \"\",\n HM_goforward_10: \"\",\n HM_goforward_15: \"\",\n HM_goforward_30: \"\",\n HM_headphones_fill: \"\",\n HM_identify_song: \"\",\n HM_list_interrupt: \"\",\n HM_media_center: \"\",\n HM_music: \"\",\n HM_music_fill: \"\",\n HM_music_note_list: \"\",\n HM_order_play: \"\",\n HM_pause: \"\",\n HM_pause_round_triangle_fill: \"\",\n HM_play_circle_fill: \"\",\n HM_play_fill: \"\",\n HM_play_hexagon_fill: \"\",\n HM_play_round_rectangle_fill: \"\",\n HM_record_circle: \"\",\n HM_remove_songlist: \"\",\n HM_repeat: \"\",\n HM_repeat_1: \"\",\n HM_reverse_order: \"\",\n HM_service: \"\",\n HM_shuffle: \"\",\n HM_skip_silence: \"\",\n },\n },\n {\n title: \"通信\",\n icons: {\n HM_beidou_satellite_circle_fill: \"\",\n HM_beidou_satellite_fill: \"\",\n HM_dial: \"\",\n HM_ellipsis_bubble: \"\",\n HM_ellipsis_message: \"\",\n HM_ellipsis_message_fill: \"\",\n HM_envelope: \"\",\n HM_envelope_fill: \"\",\n HM_envelope_open_fill: \"\",\n HM_hd_square_fill: \"\",\n HM_message: \"\",\n HM_message_badge_gearshape_1: \"\",\n HM_message_on_message: \"\",\n HM_message_on_message_fill: \"\",\n HM_mic: \"\",\n HM_mic_circle: \"\",\n HM_mic_fill: \"\",\n HM_mic_slash: \"\",\n HM_mic_slash_fill: \"\",\n HM_phone_down_fill: \"\",\n HM_phone_fill: \"\",\n HM_recordingtape: \"\",\n HM_recordingtape_rectangle: \"\",\n HM_recordingtape_rectangle_fill: \"\",\n HM_satellite: \"\",\n },\n },\n {\n title: \"连接\",\n icons: {\n HM_bluetooth: \"\",\n HM_bluetooth_slash: \"\",\n HM_dot_radiowaves_left_and_right: \"\",\n HM_hotspot: \"\",\n HM_icloud: \"\",\n HM_icloud_slash: \"\",\n HM_icloud_slash_fill: \"\",\n HM_link_slash: \"\",\n HM_mobiledata: \"\",\n HM_nfc: \"\",\n HM_nfc_fill: \"\",\n HM_wifi: \"\",\n HM_wifi_slash: \"\",\n },\n },\n {\n title: \"符号标识\",\n icons: {\n HM_bolt: \"\",\n HM_bolt_filled_on_circle: \"\",\n HM_bolt_shield_fill: \"\",\n HM_exclamationmark: \"\",\n HM_exclamationmark_circle: \"\",\n HM_exclamationmark_shield_fill: \"\",\n HM_exclamationmark_triangle_fill: \"\",\n HM_info_circle: \"\",\n HM_info_shield: \"\",\n HM_nosign: \"\",\n HM_questionmark_circle: \"\",\n },\n },\n {\n title: \"编辑\",\n icons: {\n HM_calculator_1: \"\",\n HM_character_arrow_clockwise: \"\",\n HM_character_viewfinder: \"\",\n HM_circle_dashed: \"\",\n HM_close_sidebar: \"\",\n HM_crop_rotate: \"\",\n HM_cut: \"\",\n HM_eraser_line: \"\",\n HM_indent_right: \"\",\n HM_indentation_left: \"\",\n HM_list_bullet: \"\",\n HM_list_bullet_circle: \"\",\n HM_list_bullet_square_fill: \"\",\n HM_list_checkmask: \"\",\n HM_list_letter: \"\",\n HM_list_number: \"\",\n HM_list_square: \"\",\n HM_open_sidebar: \"\",\n HM_paintbrush: \"\",\n HM_paintbrush_fill: \"\",\n HM_paintpalette_fill: \"\",\n HM_pencil_line_1: \"\",\n HM_pencil_waveform: \"\",\n HM_pencil_waveform_fill: \"\",\n HM_rectangle_and_cut: \"\",\n HM_rename: \"\",\n HM_sort: \"\",\n HM_square_and_pencil: \"\",\n HM_square_and_pencil_fill: \"\",\n HM_swap: \"\",\n HM_text_aligncenter: \"\",\n HM_text_alignleft: \"\",\n HM_text_alignright: \"\",\n HM_text_and_arrow_down: \"\",\n HM_text_and_arrow_up: \"\",\n HM_textformat_size_square: \"\",\n HM_transparency_lock: \"\",\n HM_trapezoid_and_line_horizontal: \"\",\n HM_trapezoid_and_line_vertical: \"\",\n HM_triangleshape_fill: \"\",\n HM_vertical_flip: \"\",\n },\n },\n {\n title: \"隐私&安全\",\n icons: {\n HM_checkmark_shield: \"\",\n HM_checkmark_shield_fill: \"\",\n HM_eye: \"\",\n HM_eye_slash: \"\",\n HM_hand_raised_hexagon: \"\",\n HM_hand_raised_hexagon_fill: \"\",\n HM_key_horizontal: \"\",\n HM_key_shield: \"\",\n HM_key_shield_fill: \"\",\n HM_lock: \"\",\n HM_lock_fill: \"\",\n HM_lock_open: \"\",\n HM_lock_open_fill: \"\",\n HM_nearlink: \"\",\n HM_person_shield: \"\",\n HM_person_shield_fill: \"\",\n HM_staroflife_rectangle: \"\",\n HM_touchid: \"\",\n HM_vpn_key: \"\",\n },\n },\n {\n title: \"人物\",\n icons: {\n HM_children: \"\",\n HM_ear: \"\",\n HM_face: \"\",\n HM_face_smiling: \"\",\n HM_figure_arms_open: \"\",\n HM_figure_running: \"\",\n HM_hand_point_up_tap_fill: \"\",\n HM_hand_point_up_tap_fill_1: \"\",\n HM_hand_point_up_tap_fill_slash: \"\",\n HM_hand_tap: \"\",\n HM_person: \"\",\n HM_person_2: \"\",\n HM_person_2_fill: \"\",\n HM_person_badge_plus: \"\",\n HM_person_crop_circle_fill_1: \"\",\n HM_person_filled_badge_plus: \"\",\n HM_person_filled_viewfinder: \"\",\n HM_person_square_fill: \"\",\n HM_portrait: \"\",\n },\n },\n {\n title: \"形状\",\n icons: {\n HM_circle: \"\",\n HM_oval: \"\",\n HM_rectangle: \"\",\n HM_rectangle_split_3x1: \"\",\n HM_rotate_left: \"\",\n HM_smallcircle_filled_circle: \"\",\n HM_square: \"\",\n },\n },\n {\n title: \"交通出行\",\n icons: {\n HM_local_fill: \"\",\n HM_location_north_up_right_circle_fill: \"\",\n HM_map: \"\",\n HM_map_badge_local: \"\",\n HM_map_slash: \"\",\n HM_navigation: \"\",\n HM_position: \"\",\n HM_route_plan: \"\",\n HM_satellite_map: \"\",\n HM_satellite_map_fill: \"\",\n },\n },\n];\n\nexport const AllHarmonyIconsKey = HarmonyIcons.flatMap((item) =>\n Object.keys(item.icons)\n);\n\nexport default HarmonyIcons.reduce((acc, cur) => {\n const icons = cur.icons;\n Object.keys(icons).forEach((iconName) => {\n acc[iconName] = icons[iconName];\n });\n return acc;\n}, {});\n"
|
|
459
|
-
},
|
|
460
|
-
{
|
|
461
|
-
"path": "src/components/components/dynamic-icon/harmony-icons/index.less",
|
|
462
|
-
"content": "@font-face {\n font-family: \"HMSymbol\";\n src: url(\"https://f2.eckwai.com/kos/nlav11092/test/HMSymbol.ttf\")\n format(\"truetype\");\n font-weight: normal;\n font-style: normal;\n}\n\n.hmIcon {\n font-family: \"HMSymbol\" !important;\n font-style: normal;\n font-weight: normal;\n font-variant: normal;\n text-transform: none;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n display: inline-block;\n}\n"
|
|
463
|
-
},
|
|
464
|
-
{
|
|
465
|
-
"path": "src/components/components/dynamic-icon/harmony-icons/index.tsx",
|
|
466
|
-
"content": "import SystemIcons from \"./icons\";\nimport React from \"react\";\nimport { View } from \"@tarojs/components\";\nimport css from \"./index.less\";\n\nexport default function ({ size = 24, color = \"#000\", name, className = \"\" }) {\n return (\n <View\n class={`${css.hmIcon} ${className}`}\n style={{ fontSize: size, color }}\n >\n {SystemIcons[name] || SystemIcons[\"HM_plus\"]}\n </View>\n );\n}\n"
|
|
467
|
-
}
|
|
468
|
-
]
|
|
453
|
+
"path": "src/components/components/dynamic-icon/icons.tsx",
|
|
454
|
+
"content": "export const HarmonyIcons = [\n {\n title: \"系统UI\",\n icons: {\n HM_airplane_fill: \"\",\n HM_arrow_clockwise: \"\",\n HM_arrow_counterclockwise: \"\",\n HM_arrow_counterclockwise_clock: \"\",\n HM_arrow_down_right_and_arrow_up_left: \"\",\n HM_arrow_right_up_and_square: \"\",\n HM_arrow_up_left_and_arrow_down_right: \"\",\n HM_arrowshape_turn_up_right_fill: \"\",\n HM_battery: \"\",\n HM_battery_75percent: \"\",\n HM_bell_fill: \"\",\n HM_bell_slash: \"\",\n HM_bell_slash_fill: \"\",\n HM_bluetooth: \"\",\n HM_bluetooth_slash: \"\",\n HM_bookmark: \"\",\n HM_bookmark_filled_on_bookmark: \"\",\n HM_brush: \"\",\n HM_brush_fill: \"\",\n HM_checkmark: \"\",\n HM_checkmark_circle: \"\",\n HM_checkmark_circle_fill: \"\",\n HM_checkmark_square: \"\",\n HM_checkmark_square_fill: \"\",\n HM_checkmark_square_on_square: \"\",\n HM_checkmark_square_on_square_fill: \"\",\n HM_circle_viewfinder: \"\",\n HM_clean: \"\",\n HM_clean_fill: \"\",\n HM_dot_grid_1x2: \"\",\n HM_dot_grid_2x2: \"\",\n HM_externaldrive: \"\",\n HM_externaldrive_fill: \"\",\n HM_externaldrive_fill_3: \"\",\n HM_eye: \"\",\n HM_eye_slash: \"\",\n HM_flag: \"\",\n HM_flashlight_off_fill: \"\",\n HM_flashlight_on_fill: \"\",\n HM_full_screen_fill: \"\",\n HM_gearshape: \"\",\n HM_hand_point_up_tap_fill: \"\",\n HM_hand_point_up_tap_fill_1: \"\",\n HM_hand_point_up_tap_fill_slash: \"\",\n HM_hand_tap: \"\",\n HM_hand_thumbsup_fill: \"\",\n HM_heart: \"\",\n HM_heart_fill: \"\",\n HM_heart_slash: \"\",\n HM_house: \"\",\n HM_house_fill: \"\",\n HM_label: \"\",\n HM_line_viewfinder: \"\",\n HM_lock: \"\",\n HM_lock_fill: \"\",\n HM_lock_filled_arrow_counterclockwise: \"\",\n HM_lock_open: \"\",\n HM_lock_open_fill: \"\",\n HM_magnifyingglass: \"\",\n HM_mic: \"\",\n HM_mic_fill: \"\",\n HM_minus: \"\",\n HM_minus_circle: \"\",\n HM_minus_magnifyingglass: \"\",\n HM_moon_circle_fill: \"\",\n HM_moon_fill: \"\",\n HM_moon_slash_circle: \"\",\n HM_more: \"\",\n HM_nfc: \"\",\n HM_nfc_fill: \"\",\n HM_paperplane: \"\",\n HM_paperplane_right_fill: \"\",\n HM_pin: \"\",\n HM_pin_fill_1: \"\",\n HM_plus: \"\",\n HM_plus_magnifyingglass: \"\",\n HM_plus_square: \"\",\n HM_plus_square_on_square_fill: \"\",\n HM_power: \"\",\n HM_qrcode: \"\",\n HM_rays: \"\",\n HM_rectangle_and_arrowshape_turn_up_right: \"\",\n HM_rectangle_portrait_rotate: \"\",\n HM_rectangle_rotate: \"\",\n HM_redo: \"\",\n HM_save: \"\",\n HM_share: \"\",\n HM_slider_horizontal_2: \"\",\n HM_slider_vertical_3: \"\",\n HM_speaker: \"\",\n HM_speaker_slash: \"\",\n HM_speaker_wave_3: \"\",\n HM_speaker_wave_3_slash: \"\",\n HM_square_fill_grid_2x2: \"\",\n HM_square_grid_2x2: \"\",\n HM_star: \"\",\n HM_star_fill: \"\",\n HM_sun_max: \"\",\n HM_sun_max_fill: \"\",\n HM_sun_min: \"\",\n HM_trash: \"\",\n HM_trash_fill: \"\",\n HM_undo: \"\",\n HM_wifi: \"\",\n HM_wifi_slash: \"\",\n HM_xmark: \"\",\n HM_xmark_circle: \"\",\n HM_xmark_circle_fill: \"\",\n },\n },\n {\n title: \"时间\",\n icons: {\n HM_alarm_fill_1: \"\",\n HM_calendar: \"\",\n HM_calendar_badge_clock: \"\",\n HM_calendar_fill: \"\",\n HM_clock: \"\",\n HM_clock_fill: \"\",\n HM_stopwatch_2: \"\",\n HM_timer: \"\",\n HM_timer_circle_fill: \"\",\n HM_worldclock: \"\",\n HM_worldclock_fill: \"\",\n HM_worldclock_fill_2: \"\",\n },\n },\n {\n title: \"箭头\",\n icons: {\n HM_arrow_clockwise: \"\",\n HM_arrow_counterclockwise: \"\",\n HM_arrow_counterclockwise_clock: \"\",\n HM_arrow_down_circle: \"\",\n HM_arrow_down_right_and_arrow_up_left: \"\",\n HM_arrow_left: \"\",\n HM_arrow_left_circle: \"\",\n HM_arrow_right: \"\",\n HM_arrow_right_circle: \"\",\n HM_arrow_right_up_and_square: \"\",\n HM_arrow_up_circle: \"\",\n HM_arrow_up_circle_fill: \"\",\n HM_arrow_up_left: \"\",\n HM_arrow_up_left_and_arrow_down_right: \"\",\n HM_arrow_up_to_line: \"\",\n HM_arrowshape_3_triangle_path: \"\",\n HM_arrowshape_down_to_line_fill: \"\",\n HM_arrowshape_turn_up_right_fill: \"\",\n HM_arrowshape_up: \"\",\n HM_arrowshape_up_fill: \"\",\n HM_arrowshape_up_frame_fill: \"\",\n HM_arrowshape_up_left_and_arrowshape_down_right: \"\",\n HM_arrowshape_up_to_line_fill: \"\",\n HM_arrowtriangle_down_fill: \"\",\n HM_arrowtriangle_up_fill: \"\",\n HM_chevron_down: \"\",\n HM_chevron_down_2_circle: \"\",\n HM_chevron_down_circle: \"\",\n HM_chevron_left: \"\",\n HM_chevron_left_2: \"\",\n HM_chevron_left_circle: \"\",\n HM_chevron_right: \"\",\n HM_chevron_right_circle: \"\",\n HM_chevron_up: \"\",\n HM_chevron_up_2: \"\",\n HM_chevron_up_2_circle: \"\",\n HM_chevron_up_circle: \"\",\n HM_line_below_arrowtriangle_up_circle_fill: \"\",\n HM_line_below_arrowtriangle_up_fill: \"\",\n HM_paperplane: \"\",\n HM_rectangle_and_arrowshape_turn_up_right: \"\",\n HM_redo: \"\",\n HM_transfer_station: \"\",\n HM_undo: \"\",\n },\n },\n {\n title: \"相机与照片\",\n icons: {\n HM_arrow_down_and_rectangle_on_rectangle: \"\",\n HM_arrow_up_and_rectangle_on_rectangle: \"\",\n HM_camera: \"\",\n HM_camera_fill: \"\",\n HM_camera_filters_fill: \"\",\n HM_capture_smiles: \"\",\n HM_circle_lefthalf_inset_filled: \"\",\n HM_circle_righthalf_inset_filled: \"\",\n HM_dot_video_fill: \"\",\n HM_drop: \"\",\n HM_drop_bottomrighthalf_inset_filled: \"\",\n HM_flower: \"\",\n HM_hand_draw: \"\",\n HM_heart_square_stack_fill: \"\",\n HM_lightbulb: \"\",\n HM_lightbulb_slash: \"\",\n HM_line_arrowtriangle_2_inward: \"\",\n HM_livephoto: \"\",\n HM_movie_fill: \"\",\n HM_paintpalette: \"\",\n HM_picture: \"\",\n HM_picture_2: \"\",\n HM_picture_damage: \"\",\n HM_picture_fill: \"\",\n HM_play_video: \"\",\n HM_play_video_fill: \"\",\n HM_puzzle: \"\",\n HM_puzzle_fill: \"\",\n HM_rectangle_on_rectangle: \"\",\n HM_rectangle_on_rectangle_fill: \"\",\n HM_resolution_video: \"\",\n HM_scope: \"\",\n HM_scope_slash: \"\",\n HM_shutter_photo: \"\",\n HM_square_slash: \"\",\n HM_template: \"\",\n HM_template_fill: \"\",\n HM_video_fill: \"\",\n HM_video_slasj_fill: \"\",\n HM_xmark_picture: \"\",\n HM_xmark_picture_fill: \"\",\n },\n },\n {\n title: \"办公文件\",\n icons: {\n HM_arrow_right_folder_circle: \"\",\n HM_arrow_right_folder_fill: \"\",\n HM_book_open_fill: \"\",\n HM_book_pages_fill_1: \"\",\n HM_briefcase: \"\",\n HM_case_fill: \"\",\n HM_checkmark_clipboard_fill: \"\",\n HM_doc: \"\",\n HM_doc_plaintext: \"\",\n HM_doc_plaintext_and_pencil: \"\",\n HM_doc_plaintext_and_pencil_fill: \"\",\n HM_doc_plaintext_fill: \"\",\n HM_doc_text: \"\",\n HM_doc_text_badge_arrow_up: \"\",\n HM_doc_text_badge_checkmark: \"\",\n HM_doc_text_badge_magnifyingglass: \"\",\n HM_doc_text_fill: \"\",\n HM_folder: \"\",\n HM_folder_badge_eye: \"\",\n HM_folder_badge_plus: \"\",\n HM_folder_fill: \"\",\n HM_form: \"\",\n HM_grid: \"\",\n HM_list_square_bill: \"\",\n HM_paperclip: \"\",\n HM_text_clipboard: \"\",\n },\n },\n {\n title: \"键盘\",\n icons: {\n HM_asterisk_rectangle_badge_handwritten: \"\",\n HM_celiakeyboard_elevate: \"\",\n HM_celiakeyboard_mechanical: \"\",\n HM_celiakeyboard_menu_icon_size: \"\",\n HM_delete_left: \"\",\n HM_delete_left_fill: \"\",\n HM_input_mode: \"\",\n HM_keyboard_badge_bihua: \"\",\n HM_keyboard_badge_cangjie: \"\",\n HM_keyboard_badge_handwritten: \"\",\n HM_keyboard_badge_spell: \"\",\n HM_keyboard_badge_wubi: \"\",\n HM_keyboard_badge_zhuyin: \"\",\n HM_keyboard_circle: \"\",\n HM_keyboard_onehanded_left: \"\",\n HM_keyboard_onehanded_right: \"\",\n HM_keyboard_square: \"\",\n HM_keyboard_thumbmode: \"\",\n HM_onehand: \"\",\n HM_selector: \"\",\n HM_space_1: \"\",\n HM_swipeup_input: \"\",\n HM_traditional_square: \"\",\n HM_translate: \"\",\n HM_translate_c2e: \"\",\n HM_translate_e2c: \"\",\n },\n },\n {\n title: \"媒体\",\n icons: {\n HM_backward_end_fill: \"\",\n HM_discover_fill: \"\",\n HM_fast_forward: \"\",\n HM_forward_end_fill: \"\",\n HM_gobackward_15: \"\",\n HM_gobackward_30: \"\",\n HM_goforward_10: \"\",\n HM_goforward_15: \"\",\n HM_goforward_30: \"\",\n HM_headphones_fill: \"\",\n HM_identify_song: \"\",\n HM_list_interrupt: \"\",\n HM_media_center: \"\",\n HM_music: \"\",\n HM_music_fill: \"\",\n HM_music_note_list: \"\",\n HM_order_play: \"\",\n HM_pause: \"\",\n HM_pause_round_triangle_fill: \"\",\n HM_play_circle_fill: \"\",\n HM_play_fill: \"\",\n HM_play_hexagon_fill: \"\",\n HM_play_round_rectangle_fill: \"\",\n HM_record_circle: \"\",\n HM_remove_songlist: \"\",\n HM_repeat: \"\",\n HM_repeat_1: \"\",\n HM_reverse_order: \"\",\n HM_service: \"\",\n HM_shuffle: \"\",\n HM_skip_silence: \"\",\n },\n },\n {\n title: \"通信\",\n icons: {\n HM_beidou_satellite_circle_fill: \"\",\n HM_beidou_satellite_fill: \"\",\n HM_dial: \"\",\n HM_ellipsis_bubble: \"\",\n HM_ellipsis_message: \"\",\n HM_ellipsis_message_fill: \"\",\n HM_envelope: \"\",\n HM_envelope_fill: \"\",\n HM_envelope_open_fill: \"\",\n HM_hd_square_fill: \"\",\n HM_message: \"\",\n HM_message_badge_gearshape_1: \"\",\n HM_message_on_message: \"\",\n HM_message_on_message_fill: \"\",\n HM_mic: \"\",\n HM_mic_circle: \"\",\n HM_mic_fill: \"\",\n HM_mic_slash: \"\",\n HM_mic_slash_fill: \"\",\n HM_phone_down_fill: \"\",\n HM_phone_fill: \"\",\n HM_recordingtape: \"\",\n HM_recordingtape_rectangle: \"\",\n HM_recordingtape_rectangle_fill: \"\",\n HM_satellite: \"\",\n },\n },\n {\n title: \"连接\",\n icons: {\n HM_bluetooth: \"\",\n HM_bluetooth_slash: \"\",\n HM_dot_radiowaves_left_and_right: \"\",\n HM_hotspot: \"\",\n HM_icloud: \"\",\n HM_icloud_slash: \"\",\n HM_icloud_slash_fill: \"\",\n HM_link_slash: \"\",\n HM_mobiledata: \"\",\n HM_nfc: \"\",\n HM_nfc_fill: \"\",\n HM_wifi: \"\",\n HM_wifi_slash: \"\",\n },\n },\n {\n title: \"符号标识\",\n icons: {\n HM_bolt: \"\",\n HM_bolt_filled_on_circle: \"\",\n HM_bolt_shield_fill: \"\",\n HM_exclamationmark: \"\",\n HM_exclamationmark_circle: \"\",\n HM_exclamationmark_shield_fill: \"\",\n HM_exclamationmark_triangle_fill: \"\",\n HM_info_circle: \"\",\n HM_info_shield: \"\",\n HM_nosign: \"\",\n HM_questionmark_circle: \"\",\n },\n },\n {\n title: \"编辑\",\n icons: {\n HM_calculator_1: \"\",\n HM_character_arrow_clockwise: \"\",\n HM_character_viewfinder: \"\",\n HM_circle_dashed: \"\",\n HM_close_sidebar: \"\",\n HM_crop_rotate: \"\",\n HM_cut: \"\",\n HM_eraser_line: \"\",\n HM_indent_right: \"\",\n HM_indentation_left: \"\",\n HM_list_bullet: \"\",\n HM_list_bullet_circle: \"\",\n HM_list_bullet_square_fill: \"\",\n HM_list_checkmask: \"\",\n HM_list_letter: \"\",\n HM_list_number: \"\",\n HM_list_square: \"\",\n HM_open_sidebar: \"\",\n HM_paintbrush: \"\",\n HM_paintbrush_fill: \"\",\n HM_paintpalette_fill: \"\",\n HM_pencil_line_1: \"\",\n HM_pencil_waveform: \"\",\n HM_pencil_waveform_fill: \"\",\n HM_rectangle_and_cut: \"\",\n HM_rename: \"\",\n HM_sort: \"\",\n HM_square_and_pencil: \"\",\n HM_square_and_pencil_fill: \"\",\n HM_swap: \"\",\n HM_text_aligncenter: \"\",\n HM_text_alignleft: \"\",\n HM_text_alignright: \"\",\n HM_text_and_arrow_down: \"\",\n HM_text_and_arrow_up: \"\",\n HM_textformat_size_square: \"\",\n HM_transparency_lock: \"\",\n HM_trapezoid_and_line_horizontal: \"\",\n HM_trapezoid_and_line_vertical: \"\",\n HM_triangleshape_fill: \"\",\n HM_vertical_flip: \"\",\n },\n },\n {\n title: \"隐私&安全\",\n icons: {\n HM_checkmark_shield: \"\",\n HM_checkmark_shield_fill: \"\",\n HM_eye: \"\",\n HM_eye_slash: \"\",\n HM_hand_raised_hexagon: \"\",\n HM_hand_raised_hexagon_fill: \"\",\n HM_key_horizontal: \"\",\n HM_key_shield: \"\",\n HM_key_shield_fill: \"\",\n HM_lock: \"\",\n HM_lock_fill: \"\",\n HM_lock_open: \"\",\n HM_lock_open_fill: \"\",\n HM_nearlink: \"\",\n HM_person_shield: \"\",\n HM_person_shield_fill: \"\",\n HM_staroflife_rectangle: \"\",\n HM_touchid: \"\",\n HM_vpn_key: \"\",\n },\n },\n {\n title: \"人物\",\n icons: {\n HM_children: \"\",\n HM_ear: \"\",\n HM_face: \"\",\n HM_face_smiling: \"\",\n HM_figure_arms_open: \"\",\n HM_figure_running: \"\",\n HM_hand_point_up_tap_fill: \"\",\n HM_hand_point_up_tap_fill_1: \"\",\n HM_hand_point_up_tap_fill_slash: \"\",\n HM_hand_tap: \"\",\n HM_person: \"\",\n HM_person_2: \"\",\n HM_person_2_fill: \"\",\n HM_person_badge_plus: \"\",\n HM_person_crop_circle_fill_1: \"\",\n HM_person_filled_badge_plus: \"\",\n HM_person_filled_viewfinder: \"\",\n HM_person_square_fill: \"\",\n HM_portrait: \"\",\n },\n },\n {\n title: \"形状\",\n icons: {\n HM_circle: \"\",\n HM_oval: \"\",\n HM_rectangle: \"\",\n HM_rectangle_split_3x1: \"\",\n HM_rotate_left: \"\",\n HM_smallcircle_filled_circle: \"\",\n HM_square: \"\",\n },\n },\n {\n title: \"交通出行\",\n icons: {\n HM_local_fill: \"\",\n HM_location_north_up_right_circle_fill: \"\",\n HM_map: \"\",\n HM_map_badge_local: \"\",\n HM_map_slash: \"\",\n HM_navigation: \"\",\n HM_position: \"\",\n HM_route_plan: \"\",\n HM_satellite_map: \"\",\n HM_satellite_map_fill: \"\",\n },\n },\n];\n\nexport const AllHarmonyIconsKey = HarmonyIcons.flatMap((item) =>\n Object.keys(item.icons)\n);\n\nexport default HarmonyIcons.reduce((acc, cur) => {\n const icons = cur.icons;\n Object.keys(icons).forEach((iconName) => {\n acc[iconName] = icons[iconName];\n });\n return acc;\n}, {});\n"
|
|
469
455
|
},
|
|
470
456
|
{
|
|
471
|
-
"path": "src/components/components/dynamic-icon/
|
|
472
|
-
"content":
|
|
473
|
-
"children": [
|
|
474
|
-
{
|
|
475
|
-
"path": "src/components/components/dynamic-icon/taroify-icons/icons.ts",
|
|
476
|
-
"content": "export const TaroifyIcons = [\n {\n title: \"基础图标\",\n icons: {\n Arrow: \"Arrow\",\n ArrowLeft: \"ArrowLeft\",\n ArrowUp: \"ArrowUp\",\n ArrowDown: \"ArrowDown\",\n Success: \"Success\",\n Cross: \"Cross\",\n Plus: \"Plus\",\n Minus: \"Minus\",\n Fail: \"Fail\",\n Circle: \"Circle\",\n },\n },\n {\n title: \"线框风格\",\n icons: {\n LocationOutlined: \"LocationOutlined\",\n LikeOutlined: \"LikeOutlined\",\n StarOutlined: \"StarOutlined\",\n PhoneOutlined: \"PhoneOutlined\",\n SettingOutlined: \"SettingOutlined\",\n FireOutlined: \"FireOutlined\",\n CouponOutlined: \"CouponOutlined\",\n CartOutlined: \"CartOutlined\",\n ShoppingCartOutlined: \"ShoppingCartOutlined\",\n CartCircleOutlined: \"CartCircleOutlined\",\n FriendsOutlined: \"FriendsOutlined\",\n CommentOutlined: \"CommentOutlined\",\n GemOutlined: \"GemOutlined\",\n GiftOutlined: \"GiftOutlined\",\n PointGiftOutlined: \"PointGiftOutlined\",\n SendGiftOutlined: \"SendGiftOutlined\",\n ServiceOutlined: \"ServiceOutlined\",\n BagOutlined: \"BagOutlined\",\n TodoListOutlined: \"TodoListOutlined\",\n BalanceListOutlined: \"BalanceListOutlined\",\n Close: \"Close\",\n ClockOutlined: \"ClockOutlined\",\n QuestionOutlined: \"QuestionOutlined\",\n Passed: \"Passed\",\n AddOutlined: \"AddOutlined\",\n GoldCoinOutlined: \"GoldCoinOutlined\",\n InfoOutlined: \"InfoOutlined\",\n PlayCircleOutlined: \"PlayCircleOutlined\",\n PauseCircleOutlined: \"PauseCircleOutlined\",\n StopCircleOutlined: \"StopCircleOutlined\",\n WarningOutlined: \"WarningOutlined\",\n PhoneCircleOutlined: \"PhoneCircleOutlined\",\n MusicOutlined: \"MusicOutlined\",\n SmileOutlined: \"SmileOutlined\",\n ThumbCircleOutlined: \"ThumbCircleOutlined\",\n CommentCircleOutlined: \"CommentCircleOutlined\",\n BrowsingHistoryOutlined: \"BrowsingHistoryOutlined\",\n UnderwayOutlined: \"UnderwayOutlined\",\n MoreOutlined: \"MoreOutlined\",\n VideoOutlined: \"VideoOutlined\",\n ShopOutlined: \"ShopOutlined\",\n ShopCollectOutlined: \"ShopCollectOutlined\",\n ShareOutlined: \"ShareOutlined\",\n ChatOutlined: \"ChatOutlined\",\n SmileCommentOutlined: \"SmileCommentOutlined\",\n VipCardOutlined: \"VipCardOutlined\",\n AwardOutlined: \"AwardOutlined\",\n DiamondOutlined: \"DiamondOutlined\",\n VolumeOutlined: \"VolumeOutlined\",\n ClusterOutlined: \"ClusterOutlined\",\n WapHomeOutlined: \"WapHomeOutlined\",\n PhotoOutlined: \"PhotoOutlined\",\n GiftCardOutlined: \"GiftCardOutlined\",\n ExpandOutlined: \"ExpandOutlined\",\n MedalOutlined: \"MedalOutlined\",\n GoodJobOutlined: \"GoodJobOutlined\",\n ManagerOutlined: \"ManagerOutlined\",\n LabelOutlined: \"LabelOutlined\",\n BookmarkOutlined: \"BookmarkOutlined\",\n BillOutlined: \"BillOutlined\",\n HotOutlined: \"HotOutlined\",\n HotSaleOutlined: \"HotSaleOutlined\",\n NewOutlined: \"NewOutlined\",\n NewArrivalOutlined: \"NewArrivalOutlined\",\n GoodsCollectOutlined: \"GoodsCollectOutlined\",\n EyeOutlined: \"EyeOutlined\",\n },\n },\n {\n title: \"实底风格\",\n icons: {\n Location: \"Location\",\n Like: \"Like\",\n Star: \"Star\",\n Phone: \"Phone\",\n Setting: \"Setting\",\n Fire: \"Fire\",\n Coupon: \"Coupon\",\n Cart: \"Cart\",\n ShoppingCart: \"ShoppingCart\",\n CartCircle: \"CartCircle\",\n Friends: \"Friends\",\n Comment: \"Comment\",\n Gem: \"Gem\",\n Gift: \"Gift\",\n PointGift: \"PointGift\",\n SendGift: \"SendGift\",\n Service: \"Service\",\n Bag: \"Bag\",\n TodoList: \"TodoList\",\n BalanceList: \"BalanceList\",\n Clear: \"Clear\",\n Clock: \"Clock\",\n Question: \"Question\",\n Checked: \"Checked\",\n Add: \"Add\",\n GoldCoin: \"GoldCoin\",\n Info: \"Info\",\n PlayCircle: \"PlayCircle\",\n PauseCircle: \"PauseCircle\",\n StopCircle: \"StopCircle\",\n Warning: \"Warning\",\n PhoneCircle: \"PhoneCircle\",\n Music: \"Music\",\n Smile: \"Smile\",\n ThumbCircle: \"ThumbCircle\",\n CommentCircle: \"CommentCircle\",\n BrowsingHistory: \"BrowsingHistory\",\n Underway: \"Underway\",\n More: \"More\",\n Video: \"Video\",\n Shop: \"Shop\",\n ShopCollect: \"ShopCollect\",\n Share: \"Share\",\n Chat: \"Chat\",\n SmileComment: \"SmileComment\",\n VipCard: \"VipCard\",\n Award: \"Award\",\n Diamond: \"Diamond\",\n Volume: \"Volume\",\n Cluster: \"Cluster\",\n WapHome: \"WapHome\",\n Photo: \"Photo\",\n GiftCard: \"GiftCard\",\n Expand: \"Expand\",\n Medal: \"Medal\",\n GoodJob: \"GoodJob\",\n Manager: \"Manager\",\n Label: \"Label\",\n Bookmark: \"Bookmark\",\n Bill: \"Bill\",\n Hot: \"Hot\",\n HotSale: \"HotSale\",\n New: \"New\",\n NewArrival: \"NewArrival\",\n GoodsCollect: \"GoodsCollect\",\n },\n },\n];\n\nexport const AllTaroifyIconsKey = TaroifyIcons.flatMap((item) =>\n Object.keys(item.icons)\n);\n\nexport default TaroifyIcons.reduce((acc, cur) => {\n const icons = cur.icons;\n Object.keys(icons).forEach((iconName) => {\n acc[iconName] = icons[iconName];\n });\n return acc;\n}, {});\n"
|
|
477
|
-
},
|
|
478
|
-
{
|
|
479
|
-
"path": "src/components/components/dynamic-icon/taroify-icons/index.tsx",
|
|
480
|
-
"content": "import { Icon } from \"@taroify/icons\";\nimport allIcons from \"./icons\";\n\nexport default function ({ name, ...props }) {\n if (!name || !allIcons[name]) {\n return <Icon name={'Plus'} {...props} />;\n }\n\n return <Icon name={name} {...props} />;\n}\n"
|
|
481
|
-
}
|
|
482
|
-
]
|
|
457
|
+
"path": "src/components/components/dynamic-icon/index.less",
|
|
458
|
+
"content": "@font-face {\n font-family: \"HMSymbol\";\n src: url(\"https://f2.eckwai.com/kos/nlav11092/test/HMSymbol.ttf\")\n format(\"truetype\");\n font-weight: normal;\n font-style: normal;\n}\n\n.hmIcon {\n font-family: \"HMSymbol\" !important;\n font-style: normal;\n font-weight: normal;\n font-variant: normal;\n text-transform: none;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n display: inline-block;\n}\n"
|
|
483
459
|
},
|
|
484
460
|
{
|
|
485
461
|
"path": "src/components/components/dynamic-icon/index.tsx",
|
|
486
|
-
"content": "import
|
|
462
|
+
"content": "import SystemIcons from \"./icons\";\nimport { View } from \"@tarojs/components\";\nimport css from \"./index.less\";\n\ntype DynamicIconProps = {\n name: string;\n size?: number;\n color?: string;\n className?: string;\n};\n\nexport default function (props: DynamicIconProps) {\n const { size = 24, color = \"#000\", name = \"HM_plus\", className = \"\" } = props;\n return (\n <View\n className={`${css.hmIcon} ${className}`}\n style={{ fontSize: size, color }}\n >\n {SystemIcons[name] || SystemIcons[\"HM_plus\"]}\n </View>\n );\n}\n"
|
|
487
463
|
}
|
|
488
464
|
]
|
|
489
465
|
},
|
|
@@ -1519,7 +1495,7 @@
|
|
|
1519
1495
|
},
|
|
1520
1496
|
{
|
|
1521
1497
|
"path": "src/components/containerList/runtime.tsx",
|
|
1522
|
-
"content": "import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { View } from \"@tarojs/components\";\nimport css from \"./style.less\";\nimport { uuid, debounce, throttle } from \"../utils\";\nimport { List, Loading } from \"brickd-mobile\";\nimport { Direction } from \"./constant\";\nimport cx from \"classnames\";\n\nconst rowKey = \"_itemKey\";\n\nconst mockData: DsItem[] = [\n { [rowKey]: 1, index: 1 },\n { [rowKey]: 2, index: 2 },\n { [rowKey]: 3, index: 3 },\n] as DsItem[];\n\ninterface DsItem {\n item: any;\n [rowKey]: string | number;\n index: number;\n}\n\nenum ListStatus {\n IDLE = \"idle\",\n LOADING = \"loading\",\n ERROR = \"error\",\n NOMORE = \"noMore\",\n EMPTY = \"empty\",\n}\n\nconst useReachBottom = (callback, { env, enable = false }) => {\n const scrollMeta = useRef({ clientHeight: 0 });\n\n const cbRef = useRef(callback);\n\n const updateScrollRect = useCallback(\n debounce(\n () => {\n env?.rootScroll.getBoundingClientRect?.().then(({ height }) => {\n scrollMeta.current.clientHeight = height;\n });\n },\n 300,\n true\n ),\n []\n );\n\n const callbackThrottle = useCallback(\n throttle(\n () => {\n cbRef.current?.();\n },\n 300,\n true\n ),\n []\n );\n\n useEffect(() => {\n if (!enable) {\n return;\n }\n\n const offset = 100;\n\n env?.rootScroll?.onScroll?.((e) => {\n const { scrollTop, scrollHeight } = e.detail ?? {};\n updateScrollRect();\n //支付宝 scrollMeta.current.clientHeight 会取不到,先直接设置为750兼容一下\n const clientHeight =\n scrollMeta.current.clientHeight == 0\n ? 750\n : scrollMeta.current.clientHeight;\n const isReachEdge = scrollTop + clientHeight + offset > scrollHeight;\n if (isReachEdge) {\n callbackThrottle();\n }\n // }\n });\n }, [enable]);\n};\n\nexport const ContainerList = ({ env, data, inputs, outputs, slots }) => {\n const [dataSource, setDataSource] = useState<DsItem[]>(\n env.edit || env?.runtime?.debug?.prototype ? mockData : []\n );\n const [status, setStatus] = useState<ListStatus>(ListStatus.IDLE);\n const statusRef = useRef(false);\n\n useReachBottom(\n () => {\n if (statusRef.current === ListStatus.IDLE && status === ListStatus.IDLE) {\n setStatus(ListStatus.LOADING);\n statusRef.current = ListStatus.LOADING;\n outputs[\"onScrollLoad\"]?.();\n }\n },\n { env, enable: !!data.scrollRefresh && data.direction !== Direction.Row }\n );\n\n //默认是否显示加载中\n useEffect(() => {\n if (data.defaultActive == \"loading\" && !env.edit) {\n setStatus(ListStatus.LOADING);\n statusRef.current = ListStatus.LOADING;\n }\n }, [data.defaultActive]);\n\n /** 注意!!!,inputs loading 必须在设置数据源之前,否则时序上会导致有可能设置数据源比loading快的情况,会导致onScrollLoad无法触发 */\n useMemo(() => {\n inputs[\"loading\"]?.((bool) => {\n setStatus(ListStatus.LOADING);\n statusRef.current = ListStatus.LOADING;\n });\n\n inputs[\"noMore\"]?.((bool) => {\n setStatus(ListStatus.NOMORE);\n statusRef.current = ListStatus.NOMORE;\n });\n\n inputs[\"error\"]?.((bool) => {\n setStatus(ListStatus.ERROR);\n statusRef.current = ListStatus.ERROR;\n });\n\n inputs[\"empty\"]?.((bool) => {\n setStatus(ListStatus.EMPTY);\n statusRef.current = ListStatus.EMPTY;\n });\n\n inputs[\"addDataSource\"]((val) => {\n if (Array.isArray(val)) {\n const ds = val.map((item, index) => ({\n item,\n [rowKey]: data.rowKey === \"\" ? uuid() : item[data.rowKey] || uuid(),\n index: index,\n }));\n setDataSource((c) => c.concat(ds));\n setTimeout(() => {\n setStatus(ListStatus.IDLE);\n statusRef.current = ListStatus.IDLE;\n }, 0);\n }\n });\n\n inputs[\"refreshDataSource\"]((val) => {\n if (Array.isArray(val)) {\n const ds = val.map((item, index) => ({\n item,\n [rowKey]: data.rowKey === \"\" ? uuid() : item[data.rowKey] || uuid(),\n index: index,\n }));\n //覆盖数据前先清空,放置输入重复内容时,列表项不会触发\n setDataSource([]);\n setTimeout(() => {\n setDataSource(ds);\n }, 0);\n if (data.autoEmptyCondition && val.length === 0) {\n setStatus(ListStatus.EMPTY);\n statusRef.current = ListStatus.EMPTY;\n } else {\n setStatus(ListStatus.IDLE);\n statusRef.current = ListStatus.IDLE;\n }\n }\n });\n }, []);\n\n useEffect(() => {\n /* 获取值 */\n inputs[\"getDataSource\"]?.((val, outputRels) => {\n outputRels[\"getDataSourceSuccess\"](\n dataSource.map((item, index) => ({ ...item.item }))\n );\n });\n }, [dataSource]);\n\n // const $placeholder = useMemo(() => {\n // if (env.edit && !slots[\"item\"].size) {\n // return null\n // return (\n // <View\n // className={css.placeholder}\n // style={{\n // [data.direction === Direction.Row\n // ? \"marginRight\"\n // : \"marginBottom\"]: `${data.spacing}px`,\n // }}\n // >\n // {slots[\"item\"].render({\n // style: {\n // height: \"120px\",\n // },\n // })}\n // </View>\n // );\n // } else {\n // return null;\n // }\n // }, [\n // env.edit,\n // dataSource,\n // slots[\"item\"],\n // slots[\"item\"].size,\n // data.direction,\n // data.spacing,\n // ]);\n\n const empty = useMemo(() => {\n return ListStatus.EMPTY === status;\n }, [status]);\n\n const hasMore = useMemo(() => {\n return ListStatus.NOMORE !== status;\n }, [status]);\n\n const loading = useMemo(() => {\n return ListStatus.LOADING === status;\n }, [status]);\n\n const error = useMemo(() => {\n return ListStatus.ERROR === status;\n }, [status]);\n\n const wrapperCls = useMemo(() => {\n if (data.direction === Direction.Row) {\n //显示加载中和错误的时候,居中对齐\n if (loading || error) {\n return `${css.list} ${css.row} ${css.scroll_x} ${css.justify_content_center} `;\n } else if (data.wrap) {\n return `${css.list} ${css.row} ${css.scroll_x} ${css.flex_wrap}`;\n } else {\n return `${css.list} ${css.row} ${css.scroll_x}`;\n }\n }\n\n return data.scrollRefresh\n ? `${css.list} ${css.scroll}`\n : `${css.list} ${css.normal}`;\n }, [data.scrollRefresh, data.direction, loading, error, data.wrap]);\n\n const didMount = useRef(false);\n useEffect(() => {\n // if (!didMount.current) {\n // // 不管上次配置的如何,第一次渲染必须配置成默认\n // data._edit_status_ = \"默认\";\n // didMount.current = true;\n // }\n if (env.edit) {\n switch (true) {\n case data._edit_status_ === \"加载中\": {\n setStatus(ListStatus.LOADING);\n statusRef.current = ListStatus.LOADING;\n break;\n }\n case data._edit_status_ === \"加载失败\": {\n setStatus(ListStatus.ERROR);\n statusRef.current = ListStatus.ERROR;\n break;\n }\n case data._edit_status_ === \"没有更多\": {\n setStatus(ListStatus.NOMORE);\n statusRef.current = ListStatus.NOMORE;\n break;\n }\n case data._edit_status_ === \"无内容\": {\n setStatus(ListStatus.EMPTY);\n statusRef.current = ListStatus.EMPTY;\n break;\n }\n default: {\n setStatus(ListStatus.IDLE);\n statusRef.current = ListStatus.IDLE;\n break;\n }\n }\n }\n }, [data._edit_status_]);\n\n // const showDataSource = useMemo(() => {\n // if (env.edit && status !== ListStatus.IDLE && !data.scrollRefresh) {\n // return false;\n // }\n // return true;\n // }, [status]);\n\n const $list = dataSource.map(\n ({ [rowKey]: key, index: index, item: item }, _idx) => {\n const isLastItem = _idx === dataSource.length - 1;\n return (\n <View\n className={cx({\n [css.item]: true,\n [\"disabled-area\"]: env.edit && _idx > 0,\n [css.item]: !env.edit || _idx === 0,\n // env.edit && _idx > 0 ? \"disabled-area\" : css.item\n })}\n key={key}\n //如果是最后一项,则不加margin\n style={{\n [data.direction === Direction.Row ? \"marginRight\" : \"marginBottom\"]:\n isLastItem ? `0px` : `${data.spacing}px`,\n }}\n >\n {/* 当前项数据和索引 */}\n {slots[\"item\"].render({\n inputValues: {\n itemData: item,\n index: index,\n },\n key: key,\n cache:{\n for: 0,\n index: _idx,\n },\n style: {\n width:\n slots[\"item\"].size || data.direction === Direction.Column\n ? \"\"\n : \"72px\",\n height: slots[\"item\"].size ? \"unset\" : \"60px\",\n },\n })}\n </View>\n );\n }\n );\n\n return (\n <View className={css.listWrapper}>\n <View\n className={wrapperCls}\n // style={{\n // [data.direction === Direction.Row\n // ? \"marginRight\"\n // : \"marginBottom\"]: `-${data.spacing}px`,\n // }}\n >\n {/* {$placeholder || ( */}\n <>\n {!!data?.scrollRefresh ? (\n <>\n {!empty && $list}\n {status !== ListStatus.IDLE && (\n <List.Placeholder>\n {loading && <Loading>{data.loadingTip ?? \"...\"}</Loading>}\n {error && (data.errorTip ?? \"加载失败,请重试\")}\n {!hasMore && (data.emptyTip ?? \"没有更多了\")}\n {empty && data.showEmptySlot ? (\n <View>\n {\" \"}\n {slots[\"emptySlot\"].render({\n style: {\n minHeight: 130,\n minWidth: 200,\n },\n })}\n </View>\n ) : (\n empty && data.initialEmptyTip\n )}\n </List.Placeholder>\n )}\n </>\n ) : (\n <>\n {status !== ListStatus.IDLE ? (\n <List.Placeholder>\n {loading && <Loading>{data.loadingTip ?? \"...\"}</Loading>}\n {error && (data.errorTip ?? \"加载失败,请重试\")}\n {empty && data.showEmptySlot ? (\n <View className={css.empty_slot}>\n {\" \"}\n {slots[\"emptySlot\"].render({\n style: {\n minHeight: 130,\n minWidth: 200,\n },\n })}\n </View>\n ) : (\n empty && data.initialEmptyTip\n )}\n </List.Placeholder>\n ) : (\n $list\n )}\n </>\n )}\n </>\n {/* )} */}\n </View>\n </View>\n );\n};\n\nexport default ContainerList;\n"
|
|
1498
|
+
"content": "import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { View } from \"@tarojs/components\";\nimport css from \"./style.less\";\nimport { uuid, debounce, throttle } from \"../utils\";\nimport { List, Loading } from \"brickd-mobile\";\nimport { Direction } from \"./constant\";\nimport cx from \"classnames\";\n\nconst rowKey = \"_itemKey\";\n\nconst mockData: DsItem[] = [\n { [rowKey]: 1, index: 1 },\n { [rowKey]: 2, index: 2 },\n { [rowKey]: 3, index: 3 },\n] as DsItem[];\n\ninterface DsItem {\n item: any;\n [rowKey]: string | number;\n index: number;\n}\n\nenum ListStatus {\n IDLE = \"idle\",\n LOADING = \"loading\",\n ERROR = \"error\",\n NOMORE = \"noMore\",\n EMPTY = \"empty\",\n}\n\nconst useReachBottom = (callback, { env, enable = false }) => {\n const scrollMeta = useRef({ clientHeight: 0 });\n\n const cbRef = useRef(callback);\n\n const updateScrollRect = useCallback(\n debounce(\n () => {\n env?.rootScroll.getBoundingClientRect?.().then(({ height }) => {\n scrollMeta.current.clientHeight = height;\n });\n },\n 300,\n true\n ),\n []\n );\n\n const callbackThrottle = useCallback(\n throttle(\n () => {\n cbRef.current?.();\n },\n 300,\n true\n ),\n []\n );\n\n useEffect(() => {\n if (!enable) {\n return;\n }\n\n const offset = 100;\n\n env?.rootScroll?.onScroll?.((e) => {\n const { scrollTop, scrollHeight } = e.detail ?? {};\n updateScrollRect();\n //支付宝 scrollMeta.current.clientHeight 会取不到,先直接设置为750兼容一下\n const clientHeight =\n scrollMeta.current.clientHeight == 0\n ? 750\n : scrollMeta.current.clientHeight;\n const isReachEdge = scrollTop + clientHeight + offset > scrollHeight;\n if (isReachEdge) {\n callbackThrottle();\n }\n // }\n });\n }, [enable]);\n};\n\nexport const ContainerList = ({ env, data, inputs, outputs, slots }) => {\n const [dataSource, setDataSource] = useState<DsItem[]>(\n env.edit || env?.runtime?.debug?.prototype ? mockData : []\n );\n const [status, setStatus] = useState<ListStatus>(ListStatus.IDLE);\n const statusRef = useRef(false);\n\n useReachBottom(\n () => {\n if (statusRef.current === ListStatus.IDLE && status === ListStatus.IDLE) {\n setStatus(ListStatus.LOADING);\n statusRef.current = ListStatus.LOADING;\n outputs[\"onScrollLoad\"]?.();\n }\n },\n { env, enable: !!data.scrollRefresh && data.direction !== Direction.Row }\n );\n\n //默认是否显示加载中\n useEffect(() => {\n if (data.defaultActive == \"loading\" && !env.edit) {\n setStatus(ListStatus.LOADING);\n statusRef.current = ListStatus.LOADING;\n }\n }, [data.defaultActive]);\n\n /** 注意!!!,inputs loading 必须在设置数据源之前,否则时序上会导致有可能设置数据源比loading快的情况,会导致onScrollLoad无法触发 */\n useMemo(() => {\n inputs[\"loading\"]?.((bool) => {\n setStatus(ListStatus.LOADING);\n statusRef.current = ListStatus.LOADING;\n });\n\n inputs[\"noMore\"]?.((bool) => {\n setStatus(ListStatus.NOMORE);\n statusRef.current = ListStatus.NOMORE;\n });\n\n inputs[\"error\"]?.((bool) => {\n setStatus(ListStatus.ERROR);\n statusRef.current = ListStatus.ERROR;\n });\n\n inputs[\"empty\"]?.((bool) => {\n setStatus(ListStatus.EMPTY);\n statusRef.current = ListStatus.EMPTY;\n });\n\n inputs[\"addDataSource\"]((val) => {\n if (Array.isArray(val)) {\n const ds = val.map((item, index) => ({\n item,\n [rowKey]: data.rowKey === \"\" ? uuid() : item[data.rowKey] || uuid(),\n index: index,\n }));\n setDataSource((c) => c.concat(ds));\n setTimeout(() => {\n setStatus(ListStatus.IDLE);\n statusRef.current = ListStatus.IDLE;\n }, 0);\n }\n });\n\n inputs[\"refreshDataSource\"]((val) => {\n console.log(\"refreshDataSource==\", val);\n if (Array.isArray(val)) {\n const ds = val.map((item, index) => ({\n item,\n [rowKey]: data.rowKey === \"\" ? uuid() : item[data.rowKey] || uuid(),\n index: index,\n }));\n //覆盖数据前先清空,放置输入重复内容时,列表项不会触发\n setDataSource([]);\n setTimeout(() => {\n setDataSource(ds);\n }, 0);\n if (data.autoEmptyCondition && val.length === 0) {\n setStatus(ListStatus.EMPTY);\n statusRef.current = ListStatus.EMPTY;\n } else {\n setStatus(ListStatus.IDLE);\n statusRef.current = ListStatus.IDLE;\n }\n }\n });\n }, []);\n\n useEffect(() => {\n /* 获取值 */\n inputs[\"getDataSource\"]?.((val, outputRels) => {\n outputRels[\"getDataSourceSuccess\"](\n dataSource.map((item, index) => ({ ...item.item }))\n );\n });\n }, [dataSource]);\n\n // const $placeholder = useMemo(() => {\n // if (env.edit && !slots[\"item\"].size) {\n // return null\n // return (\n // <View\n // className={css.placeholder}\n // style={{\n // [data.direction === Direction.Row\n // ? \"marginRight\"\n // : \"marginBottom\"]: `${data.spacing}px`,\n // }}\n // >\n // {slots[\"item\"].render({\n // style: {\n // height: \"120px\",\n // },\n // })}\n // </View>\n // );\n // } else {\n // return null;\n // }\n // }, [\n // env.edit,\n // dataSource,\n // slots[\"item\"],\n // slots[\"item\"].size,\n // data.direction,\n // data.spacing,\n // ]);\n\n const empty = useMemo(() => {\n return ListStatus.EMPTY === status;\n }, [status]);\n\n const hasMore = useMemo(() => {\n return ListStatus.NOMORE !== status;\n }, [status]);\n\n const loading = useMemo(() => {\n return ListStatus.LOADING === status;\n }, [status]);\n\n const error = useMemo(() => {\n return ListStatus.ERROR === status;\n }, [status]);\n\n const wrapperCls = useMemo(() => {\n if (data.direction === Direction.Row) {\n //显示加载中和错误的时候,居中对齐\n if (loading || error) {\n return `${css.list} ${css.row} ${css.scroll_x} ${css.justify_content_center} `;\n } else if (data.wrap) {\n return `${css.list} ${css.row} ${css.scroll_x} ${css.flex_wrap}`;\n } else {\n return `${css.list} ${css.row} ${css.scroll_x}`;\n }\n }\n\n return data.scrollRefresh\n ? `${css.list} ${css.scroll}`\n : `${css.list} ${css.normal}`;\n }, [data.scrollRefresh, data.direction, loading, error, data.wrap]);\n\n const didMount = useRef(false);\n useEffect(() => {\n // if (!didMount.current) {\n // // 不管上次配置的如何,第一次渲染必须配置成默认\n // data._edit_status_ = \"默认\";\n // didMount.current = true;\n // }\n if (env.edit) {\n switch (true) {\n case data._edit_status_ === \"加载中\": {\n setStatus(ListStatus.LOADING);\n statusRef.current = ListStatus.LOADING;\n break;\n }\n case data._edit_status_ === \"加载失败\": {\n setStatus(ListStatus.ERROR);\n statusRef.current = ListStatus.ERROR;\n break;\n }\n case data._edit_status_ === \"没有更多\": {\n setStatus(ListStatus.NOMORE);\n statusRef.current = ListStatus.NOMORE;\n break;\n }\n case data._edit_status_ === \"无内容\": {\n setStatus(ListStatus.EMPTY);\n statusRef.current = ListStatus.EMPTY;\n break;\n }\n default: {\n setStatus(ListStatus.IDLE);\n statusRef.current = ListStatus.IDLE;\n break;\n }\n }\n }\n }, [data._edit_status_]);\n\n // const showDataSource = useMemo(() => {\n // if (env.edit && status !== ListStatus.IDLE && !data.scrollRefresh) {\n // return false;\n // }\n // return true;\n // }, [status]);\n\n const $list = dataSource.map(\n ({ [rowKey]: key, index: index, item: item }, _idx) => {\n const isLastItem = _idx === dataSource.length - 1;\n return (\n <View\n className={cx({\n [css.item]: true,\n [\"disabled-area\"]: env.edit && _idx > 0,\n [css.item]: !env.edit || _idx === 0,\n // env.edit && _idx > 0 ? \"disabled-area\" : css.item\n })}\n key={key}\n //如果是最后一项,则不加margin\n style={{\n [data.direction === Direction.Row ? \"marginRight\" : \"marginBottom\"]:\n isLastItem ? `0px` : `${data.spacing}px`,\n }}\n >\n {/* 当前项数据和索引 */}\n {slots[\"item\"].render({\n inputValues: {\n itemData: item,\n index: index,\n },\n key: key,\n cache:{\n for: 0,\n index: _idx,\n },\n style: {\n width:\n slots[\"item\"].size || data.direction === Direction.Column\n ? \"\"\n : \"72px\",\n height: slots[\"item\"].size ? \"unset\" : \"60px\",\n },\n })}\n </View>\n );\n }\n );\n\n return (\n <View className={css.listWrapper}>\n <View\n className={wrapperCls}\n // style={{\n // [data.direction === Direction.Row\n // ? \"marginRight\"\n // : \"marginBottom\"]: `-${data.spacing}px`,\n // }}\n >\n {/* {$placeholder || ( */}\n <>\n {!!data?.scrollRefresh ? (\n <>\n {!empty && $list}\n {status !== ListStatus.IDLE && (\n <List.Placeholder>\n {loading && <Loading>{data.loadingTip ?? \"...\"}</Loading>}\n {error && (data.errorTip ?? \"加载失败,请重试\")}\n {!hasMore && (data.emptyTip ?? \"没有更多了\")}\n {empty && data.showEmptySlot ? (\n <View>\n {\" \"}\n {slots[\"emptySlot\"].render({\n style: {\n minHeight: 130,\n minWidth: 200,\n },\n })}\n </View>\n ) : (\n empty && data.initialEmptyTip\n )}\n </List.Placeholder>\n )}\n </>\n ) : (\n <>\n {status !== ListStatus.IDLE ? (\n <List.Placeholder>\n {loading && <Loading>{data.loadingTip ?? \"...\"}</Loading>}\n {error && (data.errorTip ?? \"加载失败,请重试\")}\n {empty && data.showEmptySlot ? (\n <View className={css.empty_slot}>\n {\" \"}\n {slots[\"emptySlot\"].render({\n style: {\n minHeight: 130,\n minWidth: 200,\n },\n })}\n </View>\n ) : (\n empty && data.initialEmptyTip\n )}\n </List.Placeholder>\n ) : (\n $list\n )}\n </>\n )}\n </>\n {/* )} */}\n </View>\n </View>\n );\n};\n\nexport default ContainerList;\n"
|
|
1523
1499
|
},
|
|
1524
1500
|
{
|
|
1525
1501
|
"path": "src/components/containerList/style.less",
|
|
@@ -3955,7 +3931,7 @@
|
|
|
3955
3931
|
},
|
|
3956
3932
|
{
|
|
3957
3933
|
"path": "src/components/system/systemPage/runtime.tsx",
|
|
3958
|
-
"content": "import React, {\n useCallback,\n useRef,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport { View, ScrollView, Image } from \"@tarojs/components\";\nimport { useShareAppMessage } from \"@tarojs/taro\";\nimport * as Taro from \"@tarojs/taro\";\nimport css from \"./style.less\";\nimport cx from \"classnames\";\nimport DefaultNavigation from \"../modules/defaultNavigation\";\nimport CustomNavigation from \"../modules/customNavigation\";\nimport NoneNavigation from \"../modules/noneNavigation\";\nimport CustomTabBar from \"../modules/customTabBar\";\nimport { isH5, isDesigner } from \"../../utils/env\";\n\nconst isIOS = Taro.getSystemInfoSync().platform === \"ios\";\n\nconst defaultMenuButtonBoundingClientRect = {\n width: 87,\n height: 32,\n top: 48,\n right: 368,\n bottom: 80,\n left: 281,\n};\n\nconst usePullDownRefresh = ({\n enabled = false,\n onLoad,\n setDisableScrollWhenPulling,\n}) => {\n const [state, setState] = useState({\n refresherTriggered: false,\n });\n\n const onLoadRef = useRef(() => Promise.resolve());\n const loading = useRef(false);\n\n useEffect(() => {\n onLoadRef.current = onLoad;\n }, [onLoad]);\n\n const onRefresh = useCallback(() => {\n if (loading.current) {\n return;\n }\n\n setState({ refresherTriggered: true });\n\n loading.current = true;\n onLoadRef.current?.();\n }, []);\n\n const cancelPullRefresh = useCallback(() => {\n loading.current = false;\n setState({ refresherTriggered: false });\n }, []);\n\n // const onRestore = useCallback(() => {\n // setState({ refresherTriggered: false })\n // }, [])\n\n if (!enabled) {\n return {\n cancelPullRefresh,\n refresherEnabled: false,\n };\n }\n\n return {\n cancelPullRefresh,\n refresherEnabled: true,\n refresherThreshold: 100,\n refresherDefaultStyle: \"black\",\n refresherBackground: \"transparent\",\n refresherTriggered: state.refresherTriggered,\n onRefresherRefresh: onRefresh,\n onRefresherPulling: (e) => {\n // 下拉时,禁止 scroll-view 滚动\n setDisableScrollWhenPulling(true);\n },\n onRefresherStatusChange: (e) => {\n console.log(\"onRefresherStatusChange\", e.detail);\n if (e.detail === \"releasing\") {\n Taro.vibrateShort();\n }\n },\n onRefresherRestore: (e) => {\n console.log(\"onRefresherRestore\", e.detail);\n setDisableScrollWhenPulling(false);\n },\n onRefresherAbort: (e) => {\n console.log(\"onRefresherAbort\", e.detail);\n setDisableScrollWhenPulling(false);\n },\n // onRefresherRestore: onRestore,\n };\n};\n\nexport default function (props) {\n const { id, env, data, inputs, outputs, slots } = props;\n const [ready, setReady] = useState(false);\n\n const [footerHeight, setFooterHeight] = useState(0);\n const footerRef = useRef(null);\n\n const scrollRef = useRef(null);\n const [scrollTop, setScrollTop] = useState(0);\n\n const [disableScrollWhenPulling, setDisableScrollWhenPulling] =\n useState(false);\n\n /**\n * 监听页面重新显示、隐藏\n */\n useEffect(() => {\n Taro.eventCenter.on(\"pageDidShow\", ({ path, query }) => {\n if (path.indexOf(env.canvas.id) === -1) {\n return;\n }\n outputs[\"pageDidShow\"]?.({ ...query });\n });\n\n Taro.eventCenter.on(\"pageDidHide\", ({ path, query }) => {\n if (path.indexOf(env.canvas.id) === -1) {\n return;\n }\n outputs[\"pageDidHide\"]?.({ ...query });\n });\n }, []);\n\n useEffect(() => {\n if (isDesigner(env)) {\n return;\n }\n\n if (!footerRef.current) {\n return;\n }\n\n const query = Taro.createSelectorQuery();\n query.select(`#${id} .mybricks-footer`).boundingClientRect();\n query.exec((res) => {\n if (res[0]) {\n let windowWidth = isDesigner(env)\n ? 315\n : Taro.getSystemInfoSync().windowWidth;\n let height = (res[0].height / windowWidth) * 375;\n console.log(\"footerHeight\", height);\n setFooterHeight(height);\n }\n });\n }, [footerRef.current]);\n\n // 获取菜单按钮的布局位置信息\n const relativeRect = useMemo(() => {\n if (isDesigner(env)) {\n return defaultMenuButtonBoundingClientRect;\n } else {\n let boundingClientRect = Taro.getMenuButtonBoundingClientRect();\n let ratio = Taro.getSystemInfoSync().windowWidth / 375;\n\n return {\n width: boundingClientRect.width / ratio,\n height: boundingClientRect.height / ratio,\n top: boundingClientRect.top / ratio,\n right: boundingClientRect.right / ratio,\n bottom: boundingClientRect.bottom / ratio,\n left: boundingClientRect.left / ratio,\n };\n }\n }, []);\n\n const useTabBar = useMemo(() => {\n if (!data.useTabBar) {\n return false;\n }\n if (data.tabBar.length < 2 || data.tabBar.length > 5) {\n return false;\n }\n\n let isContain = data.tabBar.find((item) => {\n return item.scene.id == env.canvas.id;\n });\n if (!isContain) {\n return false;\n }\n return true;\n }, [data.useTabBar, data.tabBar, env.canvas.id, data.id]);\n\n useEffect(() => {\n env.useTabBar = useTabBar;\n }, [useTabBar]);\n\n const onLoad = useCallback(() => {\n outputs[\"pulldown\"]?.(true);\n }, []);\n\n const [scrollToProps, setScrollToProps] = useState<any>({\n scrollWithAnimation: false,\n scrollAnimationDuration: 0,\n scrollIntoView: \"u_000none\",\n scrollTop: 0,\n });\n\n const { cancelPullRefresh, ...pulldownProps } = usePullDownRefresh({\n enabled: data.enabledPulldown,\n onLoad,\n setDisableScrollWhenPulling,\n });\n\n useEffect(() => {\n inputs[\"cancelPulldown\"]?.(() => {\n cancelPullRefresh?.();\n });\n }, [cancelPullRefresh]);\n\n useEffect(() => {\n inputs[\"setShare\"]?.((val) => {\n let msgConfig = {};\n let timelineConfig = {};\n if (val?.title || val?.imageUrl) {\n msgConfig = { title: val.title, imageUrl: val.imageUrl };\n\n // 分享给好友支持 path\n if (val?.path) {\n msgConfig[\"path\"] = val.path;\n }\n\n timelineConfig = { title: val.title }; // 分享到朋友圈暂时不加图片\n } else {\n if (val.message) {\n msgConfig = val.message;\n }\n if (val.timeline) {\n timelineConfig = val.timeline;\n }\n }\n env?.setShareConfig?.(\"message\", msgConfig);\n env?.setShareConfig?.(\"timeline\", timelineConfig);\n });\n }, []);\n\n useMemo(() => {\n if (env?.rootScroll && !isDesigner(env)) {\n env.rootScroll.scrollTo = ({ scrollTop, id, duration = 0 }) => {\n /** 这里务必注意,scrollTop的优先级比scrollIntoView高,且这两个值只会在变化时生效,所以每次setScrollToProps务必只设置变化的字段,保证之前字段不变 */\n const isAnimte = duration > 0;\n if (id) {\n // H5\n if (isH5()) {\n let anchor = document.querySelector(id);\n if (anchor) {\n document.querySelector(\"#root_scroll\").scrollTo({\n top: anchor.offsetTop,\n behavior: isAnimte ? \"smooth\" : \"auto\",\n });\n return;\n }\n }\n\n setScrollToProps((c) => ({\n ...c,\n scrollIntoView: id,\n scrollTop: Math.random() + 20,\n scrollAnimationDuration: duration,\n scrollWithAnimation: isAnimte,\n }));\n } else {\n setScrollToProps((c) => ({\n ...c,\n scrollTop,\n scrollAnimationDuration: duration,\n scrollWithAnimation: isAnimte,\n }));\n\n // hack 设置当前滚动位置\n scrollRef.current = scrollTop;\n }\n };\n\n env.rootScroll.getBoundingClientRect = () =>\n new Promise((resolve, reject) => {\n Taro.createSelectorQuery()\n .select(\"#root_scroll\")\n .boundingClientRect(function (rect) {\n resolve(rect);\n })\n .exec();\n });\n }\n }, []);\n\n const handleScroll = useCallback(\n (e) => {\n scrollRef.current = e.detail.scrollTop;\n env?.rootScroll?.emitScrollEvent?.(e);\n },\n [scrollRef.current]\n );\n\n // useEffect(() => {\n // if (!data?.enabledShareMessage) {\n // Taro.hideShareMenu({\n // menus: [\"shareAppMessage\", \"shareTimeline\"],\n // });\n // }\n // }, [data?.enabledShareMessage]);\n\n useEffect(() => {\n if (!data?.enabledShareAppMessage) {\n Taro.hideShareMenu({\n menus: [\"shareAppMessage\"],\n });\n }\n }, [data?.enabledShareAppMessage])\n\n useEffect(() => {\n if (!data?.enabledShareTimeline) {\n Taro.hideShareMenu({\n menus: [\"shareTimeline\"],\n });\n }\n }, [data?.enabledShareTimeline])\n\n /**\n * 骨架屏\n */\n useEffect(() => {\n inputs?.[\"ready\"](() => {\n setReady(true);\n });\n }, []);\n\n const slotStyle = useMemo(() => {\n if (data?.layout?.position === \"smart\") {\n return {\n overflow: \"visible\", // overflow 必须是visible,用于覆盖render-web给的overflow: hidden,否则子元素的sticky不生效\n // overflow: \"hidden auto\", // auto 会导致页面出现滚动条\n display: \"inline-block\", // 防止margin重叠用,触发BFC,不可以删除\n // height: \"fit-content !important\", // 说加了这个会导致页面不能铺满\n // paddingBottom: `${data.bottomSpace}px`,\n };\n }\n return {\n height: \"fit-content !important\", // 防止margin重叠用,触发BFC,不可以删除\n // display: \"inline-block\", // 防止margin重叠用,触发BFC,不可以删除\n // paddingBottom: `${data.bottomSpace}px`,\n ...data?.layout,\n };\n }, [data?.layout, data.bottomSpace]);\n\n let background = useMemo(() => {\n let result = {};\n\n if (data.backgroundImage) {\n result[\"backgroundImage\"] = `${data.backgroundImage}`;\n }\n\n if (data.backgroundSize) {\n result[\"backgroundSize\"] = data.backgroundSize;\n }\n\n if (data.backgroundRepeat) {\n result[\"backgroundRepeat\"] = data.backgroundRepeat;\n }\n\n if (data.backgroundPosition) {\n result[\"backgroundPosition\"] = data.backgroundPosition;\n }\n\n if (data.background) {\n result[\"backgroundColor\"] = data.background;\n }\n\n return result;\n }, [\n data.backgroundImage,\n data.backgroundSize,\n data.backgroundRepeat,\n data.backgroundPosition,\n data.background,\n ]);\n\n if (data.useLoading && !ready) {\n return (\n <View className={css.loading}>\n <View className={css.icon}></View>\n </View>\n );\n }\n\n const enhanced = useMemo(() => {\n const systemInfo = Taro.getSystemInfoSync();\n if (isIOS) {\n if (data.enabledPulldown) {\n return false\n } else {\n //判断下是否是iOS26,需要返回false(兼容该系统版本下 enhanced true 导致的 ScrollView高度塌陷问题)\n if (systemInfo.system == \"iOS 26.0\") {\n return false\n } else {\n return true\n }\n }\n } else {\n return true\n }\n }, [data.enabledPulldown, isIOS])\n\n const iOS26scrollViewStyle = useMemo(() => {\n //iOS26版本,scrollView必须给定一个具体的值,否则会塌陷\n const systemInfo = Taro.getSystemInfoSync();\n if (isIOS && systemInfo.system == \"iOS 26.0\") {\n return {\n height: systemInfo.windowHeight\n }\n } else {\n return {}\n }\n\n }, [])\n\n\n return (\n <View\n className={cx({\n [css.page]: true,\n [css.h5page]: isH5(),\n [css.debug]: isDesigner(env)\n })}\n style={{ ...background }}\n >\n {/* Header ⬇️⬇️⬇️ */}\n {/* Header ⬇️⬇️⬇️ */}\n {/* Header ⬇️⬇️⬇️ */}\n\n {/* 默认样式 */}\n {data.useNavigationStyle === \"default\" ? (\n <>\n {/* debug 时渲染 fixedTop */}\n {/* runtime 时不渲染*/}\n {env.runtime.debug ? (\n <>\n <View style={{ width: 375, height: 84 }}></View>\n <View className={css.fixedTop}>\n <DefaultNavigation env={env} data={data} />\n </View>\n </>\n ) : null}\n </>\n ) : null}\n\n {/* 自定义导航栏 */}\n {data.useNavigationStyle === \"custom\" ? (\n <>\n {env.runtime?.debug ? (\n <>\n <View style={{ width: 375, height: 84 }}></View>\n <View className={css.fixedTop}>\n <CustomNavigation env={env} data={data} slots={slots} />\n </View>\n </>\n ) : (\n <>\n <View id=\"custom_navigation\">\n <View\n style={{\n width: 375,\n height: relativeRect.top - (40 - relativeRect.height) / 2,\n }}\n ></View>\n <View style={{ width: 375, height: 40 }}></View>\n </View>\n <View className={css.fixedTop}>\n <CustomNavigation env={env} data={data} slots={slots} />\n </View>\n </>\n )}\n </>\n ) : null}\n\n {/* 隐藏导航栏 */}\n {data.useNavigationStyle === \"none\" ? (\n <NoneNavigation env={env} data={data} />\n ) : null}\n\n {/* content ⬇️⬇️⬇️ */}\n {/* content ⬇️⬇️⬇️ */}\n {/* content ⬇️⬇️⬇️ */}\n\n {/* {contentPlaceholder ? (\n <View className={cx(css.contentPlaceholder, \"mybricks-contentPlaceholder\")}></View>\n ) : ( */}\n <View id=\"root\" className={css.fixedContainer}>\n <ScrollView\n key={\"page\"}\n id=\"root_scroll\"\n scrollY={!data.disableScroll && !disableScrollWhenPulling}\n // scrollY={!data.disableScroll}\n enhanced={enhanced}\n // enhanced={true}\n // enhancedBounce={false}\n bounce={false}\n enablePassive={true}\n showScrollbar={false}\n onScroll={handleScroll}\n enableBackToTop={true}\n {...scrollToProps}\n scrollTop={scrollRef.current}\n {...pulldownProps}\n className={css.contentScrollView}\n style={iOS26scrollViewStyle}\n >\n {slots[\"content\"]?.render?.({\n style: {\n ...slotStyle,\n },\n })}\n </ScrollView>\n </View>\n\n {/* )} */}\n\n {/* Footer ⬇️⬇️⬇️ */}\n {/* Footer ⬇️⬇️⬇️ */}\n {/* Footer ⬇️⬇️⬇️ */}\n\n {/* debug 时渲染 tabbar */}\n {useTabBar && env.runtime.debug ? (\n <>\n <View style={{ width: 375, height: 60 }}></View>\n <View className={css.fixedBottom}>\n <CustomTabBar {...props} />\n </View>\n </>\n ) : null}\n\n {/* runtime 时渲染 tabbar placeholder */}\n {useTabBar && !env.runtime.debug && !isH5() ? (\n <View className={cx(css.tabBarPlaceholder)}></View>\n ) : null}\n\n {/* 开启了页脚插槽 */}\n {!useTabBar && data.useFooter ? (\n <>\n <View\n className={css.footerPlaceholder}\n style={{ height: footerHeight }}\n ></View>\n <View className={cx(css.footer, \"mybricks-footer\")} ref={footerRef}>\n {slots[\"footerBar\"]?.render?.()}\n <View className={css.safearea}></View>\n </View>\n </>\n ) : null}\n </View>\n );\n}\n"
|
|
3934
|
+
"content": "import React, {\n useCallback,\n useRef,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport { View, ScrollView, Image } from \"@tarojs/components\";\nimport { useShareAppMessage } from \"@tarojs/taro\";\nimport * as Taro from \"@tarojs/taro\";\nimport css from \"./style.less\";\nimport cx from \"classnames\";\nimport DefaultNavigation from \"../modules/defaultNavigation\";\nimport CustomNavigation from \"../modules/customNavigation\";\nimport NoneNavigation from \"../modules/noneNavigation\";\nimport CustomTabBar from \"../modules/customTabBar\";\nimport { isH5, isDesigner } from \"../../utils/env\";\nimport tabBarJson from \"@/custom-tab-bar/mybricks/tabbar-config\";\n\nconst isIOS = Taro.getSystemInfoSync().platform === \"ios\";\n\nconst defaultMenuButtonBoundingClientRect = {\n width: 87,\n height: 32,\n top: 48,\n right: 368,\n bottom: 80,\n left: 281,\n};\n\nconst usePullDownRefresh = ({\n enabled = false,\n onLoad,\n setDisableScrollWhenPulling,\n}) => {\n const [state, setState] = useState({\n refresherTriggered: false,\n });\n\n const onLoadRef = useRef(() => Promise.resolve());\n const loading = useRef(false);\n\n useEffect(() => {\n onLoadRef.current = onLoad;\n }, [onLoad]);\n\n const onRefresh = useCallback(() => {\n if (loading.current) {\n return;\n }\n\n setState({ refresherTriggered: true });\n\n loading.current = true;\n onLoadRef.current?.();\n }, []);\n\n const cancelPullRefresh = useCallback(() => {\n loading.current = false;\n setState({ refresherTriggered: false });\n }, []);\n\n // const onRestore = useCallback(() => {\n // setState({ refresherTriggered: false })\n // }, [])\n\n if (!enabled) {\n return {\n cancelPullRefresh,\n refresherEnabled: false,\n };\n }\n\n return {\n cancelPullRefresh,\n refresherEnabled: true,\n refresherThreshold: 100,\n refresherDefaultStyle: \"black\",\n refresherBackground: \"transparent\",\n refresherTriggered: state.refresherTriggered,\n onRefresherRefresh: onRefresh,\n onRefresherPulling: (e) => {\n // 下拉时,禁止 scroll-view 滚动\n setDisableScrollWhenPulling(true);\n },\n onRefresherStatusChange: (e) => {\n console.log(\"onRefresherStatusChange\", e.detail);\n if (e.detail === \"releasing\") {\n Taro.vibrateShort();\n }\n },\n onRefresherRestore: (e) => {\n console.log(\"onRefresherRestore\", e.detail);\n setDisableScrollWhenPulling(false);\n },\n onRefresherAbort: (e) => {\n console.log(\"onRefresherAbort\", e.detail);\n setDisableScrollWhenPulling(false);\n },\n // onRefresherRestore: onRestore,\n };\n};\n\nexport default function (props) {\n const { id, env, data, inputs, outputs, slots } = props;\n const [ready, setReady] = useState(false);\n\n const [footerHeight, setFooterHeight] = useState(0);\n const footerRef = useRef(null);\n\n const scrollRef = useRef(null);\n const [scrollTop, setScrollTop] = useState(0);\n\n const [disableScrollWhenPulling, setDisableScrollWhenPulling] =\n useState(false);\n\n /**\n * 监听页面重新显示、隐藏\n */\n useEffect(() => {\n Taro.eventCenter.on(\"pageDidShow\", ({ path, query }) => {\n if (path.indexOf(env.canvas.id) === -1) {\n return;\n }\n outputs[\"pageDidShow\"]?.({ ...query });\n });\n\n Taro.eventCenter.on(\"pageDidHide\", ({ path, query }) => {\n if (path.indexOf(env.canvas.id) === -1) {\n return;\n }\n outputs[\"pageDidHide\"]?.({ ...query });\n });\n }, []);\n\n useEffect(() => {\n if (isDesigner(env)) {\n return;\n }\n\n if (!footerRef.current) {\n return;\n }\n\n const query = Taro.createSelectorQuery();\n query.select(`#${id} .mybricks-footer`).boundingClientRect();\n query.exec((res) => {\n if (res[0]) {\n let windowWidth = isDesigner(env)\n ? 315\n : Taro.getSystemInfoSync().windowWidth;\n let height = (res[0].height / windowWidth) * 375;\n console.log(\"footerHeight\", height);\n setFooterHeight(height);\n }\n });\n }, [footerRef.current]);\n\n // 获取菜单按钮的布局位置信息\n const relativeRect = useMemo(() => {\n if (isDesigner(env)) {\n return defaultMenuButtonBoundingClientRect;\n } else {\n let boundingClientRect = Taro.getMenuButtonBoundingClientRect();\n let ratio = Taro.getSystemInfoSync().windowWidth / 375;\n\n return {\n width: boundingClientRect.width / ratio,\n height: boundingClientRect.height / ratio,\n top: boundingClientRect.top / ratio,\n right: boundingClientRect.right / ratio,\n bottom: boundingClientRect.bottom / ratio,\n left: boundingClientRect.left / ratio,\n };\n }\n }, []);\n\n const useTabBar = useMemo(() => {\n if (!data.useTabBar) {\n return false;\n }\n if (tabBarJson?.length < 2 || tabBarJson?.length > 5) {\n return false;\n }\n\n let isContain = tabBarJson.find((item) => {\n return item.scene.id == env.canvas.id;\n });\n if (!isContain) {\n return false;\n }\n return true;\n }, [data.useTabBar, tabBarJson, env.canvas.id, data.id]);\n\n useEffect(() => {\n env.useTabBar = useTabBar;\n }, [useTabBar]);\n\n const onLoad = useCallback(() => {\n outputs[\"pulldown\"]?.(true);\n }, []);\n\n const [scrollToProps, setScrollToProps] = useState<any>({\n scrollWithAnimation: false,\n scrollAnimationDuration: 0,\n scrollIntoView: \"u_000none\",\n scrollTop: 0,\n });\n\n const { cancelPullRefresh, ...pulldownProps } = usePullDownRefresh({\n enabled: data.enabledPulldown,\n onLoad,\n setDisableScrollWhenPulling,\n });\n\n useEffect(() => {\n inputs[\"cancelPulldown\"]?.(() => {\n cancelPullRefresh?.();\n });\n }, [cancelPullRefresh]);\n\n useEffect(() => {\n inputs[\"setShare\"]?.((val) => {\n let msgConfig = {};\n let timelineConfig = {};\n if (val?.title || val?.imageUrl) {\n msgConfig = { title: val.title, imageUrl: val.imageUrl };\n\n // 分享给好友支持 path\n if (val?.path) {\n msgConfig[\"path\"] = val.path;\n }\n\n timelineConfig = { title: val.title }; // 分享到朋友圈暂时不加图片\n } else {\n if (val.message) {\n msgConfig = val.message;\n }\n if (val.timeline) {\n timelineConfig = val.timeline;\n }\n }\n env?.setShareConfig?.(\"message\", msgConfig);\n env?.setShareConfig?.(\"timeline\", timelineConfig);\n });\n }, []);\n\n useMemo(() => {\n if (env?.rootScroll && !isDesigner(env)) {\n env.rootScroll.scrollTo = ({ scrollTop, id, duration = 0 }) => {\n /** 这里务必注意,scrollTop的优先级比scrollIntoView高,且这两个值只会在变化时生效,所以每次setScrollToProps务必只设置变化的字段,保证之前字段不变 */\n const isAnimte = duration > 0;\n if (id) {\n // H5\n if (isH5()) {\n let anchor = document.querySelector(id);\n if (anchor) {\n document.querySelector(\"#root_scroll\").scrollTo({\n top: anchor.offsetTop,\n behavior: isAnimte ? \"smooth\" : \"auto\",\n });\n return;\n }\n }\n\n setScrollToProps((c) => ({\n ...c,\n scrollIntoView: id,\n scrollTop: Math.random() + 20,\n scrollAnimationDuration: duration,\n scrollWithAnimation: isAnimte,\n }));\n } else {\n setScrollToProps((c) => ({\n ...c,\n scrollTop,\n scrollAnimationDuration: duration,\n scrollWithAnimation: isAnimte,\n }));\n\n // hack 设置当前滚动位置\n scrollRef.current = scrollTop;\n }\n };\n\n env.rootScroll.getBoundingClientRect = () =>\n new Promise((resolve, reject) => {\n Taro.createSelectorQuery()\n .select(\"#root_scroll\")\n .boundingClientRect(function (rect) {\n resolve(rect);\n })\n .exec();\n });\n }\n }, []);\n\n const handleScroll = useCallback(\n (e) => {\n scrollRef.current = e.detail.scrollTop;\n env?.rootScroll?.emitScrollEvent?.(e);\n },\n [scrollRef.current]\n );\n\n // useEffect(() => {\n // if (!data?.enabledShareMessage) {\n // Taro.hideShareMenu({\n // menus: [\"shareAppMessage\", \"shareTimeline\"],\n // });\n // }\n // }, [data?.enabledShareMessage]);\n\n useEffect(() => {\n if (!data?.enabledShareAppMessage) {\n Taro.hideShareMenu({\n menus: [\"shareAppMessage\"],\n });\n }\n }, [data?.enabledShareAppMessage])\n\n useEffect(() => {\n if (!data?.enabledShareTimeline) {\n Taro.hideShareMenu({\n menus: [\"shareTimeline\"],\n });\n }\n }, [data?.enabledShareTimeline])\n\n /**\n * 骨架屏\n */\n useEffect(() => {\n inputs?.[\"ready\"](() => {\n setReady(true);\n });\n }, []);\n\n const slotStyle = useMemo(() => {\n if (data?.layout?.position === \"smart\") {\n return {\n overflow: \"visible\", // overflow 必须是visible,用于覆盖render-web给的overflow: hidden,否则子元素的sticky不生效\n // overflow: \"hidden auto\", // auto 会导致页面出现滚动条\n display: \"inline-block\", // 防止margin重叠用,触发BFC,不可以删除\n // height: \"fit-content !important\", // 说加了这个会导致页面不能铺满\n // paddingBottom: `${data.bottomSpace}px`,\n };\n }\n return {\n height: \"fit-content !important\", // 防止margin重叠用,触发BFC,不可以删除\n // display: \"inline-block\", // 防止margin重叠用,触发BFC,不可以删除\n // paddingBottom: `${data.bottomSpace}px`,\n ...data?.layout,\n };\n }, [data?.layout, data.bottomSpace]);\n\n let background = useMemo(() => {\n let result = {};\n\n if (data.backgroundImage) {\n result[\"backgroundImage\"] = `${data.backgroundImage}`;\n }\n\n if (data.backgroundSize) {\n result[\"backgroundSize\"] = data.backgroundSize;\n }\n\n if (data.backgroundRepeat) {\n result[\"backgroundRepeat\"] = data.backgroundRepeat;\n }\n\n if (data.backgroundPosition) {\n result[\"backgroundPosition\"] = data.backgroundPosition;\n }\n\n if (data.background) {\n result[\"backgroundColor\"] = data.background;\n }\n\n return result;\n }, [\n data.backgroundImage,\n data.backgroundSize,\n data.backgroundRepeat,\n data.backgroundPosition,\n data.background,\n ]);\n\n if (data.useLoading && !ready) {\n return (\n <View className={css.loading}>\n <View className={css.icon}></View>\n </View>\n );\n }\n\n const enhanced = useMemo(() => {\n const systemInfo = Taro.getSystemInfoSync();\n if (isIOS) {\n if (data.enabledPulldown) {\n return false\n } else {\n //判断下是否是iOS26,需要返回false(兼容该系统版本下 enhanced true 导致的 ScrollView高度塌陷问题)\n if (systemInfo.system == \"iOS 26.0\") {\n return false\n } else {\n return true\n }\n }\n } else {\n return true\n }\n }, [data.enabledPulldown, isIOS])\n\n const iOS26scrollViewStyle = useMemo(() => {\n //iOS26版本,scrollView必须给定一个具体的值,否则会塌陷\n const systemInfo = Taro.getSystemInfoSync();\n if (isIOS && systemInfo.system == \"iOS 26.0\") {\n return {\n height: systemInfo.windowHeight\n }\n } else {\n return {}\n }\n\n }, [])\n\n\n return (\n <View\n className={cx({\n [css.page]: true,\n [css.h5page]: isH5(),\n [css.debug]: isDesigner(env)\n })}\n style={{ ...background }}\n >\n {/* Header ⬇️⬇️⬇️ */}\n {/* Header ⬇️⬇️⬇️ */}\n {/* Header ⬇️⬇️⬇️ */}\n\n {/* 默认样式 */}\n {data.useNavigationStyle === \"default\" ? (\n <>\n {/* debug 时渲染 fixedTop */}\n {/* runtime 时不渲染*/}\n {env.runtime.debug ? (\n <>\n <View style={{ width: 375, height: 84 }}></View>\n <View className={css.fixedTop}>\n <DefaultNavigation env={env} data={data} />\n </View>\n </>\n ) : null}\n </>\n ) : null}\n\n {/* 自定义导航栏 */}\n {data.useNavigationStyle === \"custom\" ? (\n <>\n {env.runtime?.debug ? (\n <>\n <View style={{ width: 375, height: 84 }}></View>\n <View className={css.fixedTop}>\n <CustomNavigation env={env} data={data} slots={slots} />\n </View>\n </>\n ) : (\n <>\n <View id=\"custom_navigation\">\n <View\n style={{\n width: 375,\n height: relativeRect.top - (40 - relativeRect.height) / 2,\n }}\n ></View>\n <View style={{ width: 375, height: 40 }}></View>\n </View>\n <View className={css.fixedTop}>\n <CustomNavigation env={env} data={data} slots={slots} />\n </View>\n </>\n )}\n </>\n ) : null}\n\n {/* 隐藏导航栏 */}\n {data.useNavigationStyle === \"none\" ? (\n <NoneNavigation env={env} data={data} />\n ) : null}\n\n {/* content ⬇️⬇️⬇️ */}\n {/* content ⬇️⬇️⬇️ */}\n {/* content ⬇️⬇️⬇️ */}\n\n {/* {contentPlaceholder ? (\n <View className={cx(css.contentPlaceholder, \"mybricks-contentPlaceholder\")}></View>\n ) : ( */}\n <View id=\"root\" className={css.fixedContainer}>\n <ScrollView\n key={\"page\"}\n id=\"root_scroll\"\n scrollY={!data.disableScroll && !disableScrollWhenPulling}\n // scrollY={!data.disableScroll}\n enhanced={enhanced}\n // enhanced={true}\n // enhancedBounce={false}\n bounce={false}\n enablePassive={true}\n showScrollbar={false}\n onScroll={handleScroll}\n enableBackToTop={true}\n {...scrollToProps}\n scrollTop={scrollRef.current}\n {...pulldownProps}\n className={css.contentScrollView}\n style={iOS26scrollViewStyle}\n >\n {slots[\"content\"]?.render?.({\n style: {\n ...slotStyle,\n },\n })}\n </ScrollView>\n </View>\n\n {/* )} */}\n\n {/* Footer ⬇️⬇️⬇️ */}\n {/* Footer ⬇️⬇️⬇️ */}\n {/* Footer ⬇️⬇️⬇️ */}\n\n {/* debug 时渲染 tabbar */}\n {useTabBar && env.runtime.debug ? (\n <>\n <View style={{ width: 375, height: 60 }}></View>\n <View className={css.fixedBottom}>\n <CustomTabBar {...props} />\n </View>\n </>\n ) : null}\n\n {/* runtime 时渲染 tabbar placeholder */}\n {useTabBar && !env.runtime.debug && !isH5() ? (\n <View className={cx(css.tabBarPlaceholder)}></View>\n ) : null}\n\n {/* 开启了页脚插槽 */}\n {!useTabBar && data.useFooter ? (\n <>\n <View\n className={css.footerPlaceholder}\n style={{ height: footerHeight }}\n ></View>\n <View className={cx(css.footer, \"mybricks-footer\")} ref={footerRef}>\n {slots[\"footerBar\"]?.render?.()}\n <View className={css.safearea}></View>\n </View>\n </>\n ) : null}\n </View>\n );\n}\n"
|
|
3959
3935
|
},
|
|
3960
3936
|
{
|
|
3961
3937
|
"path": "src/components/system/systemPage/runtimeEdit.tsx",
|
|
@@ -5149,7 +5125,7 @@
|
|
|
5149
5125
|
},
|
|
5150
5126
|
{
|
|
5151
5127
|
"path": "src/components/utils/image.ts",
|
|
5152
|
-
"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
|
|
5128
|
+
"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';\n\n // 尺寸\n const numWidth = isNumber(width) ? width : parseFloat(width ?? '0');\n const numHeight = isNumber(height) ? height : parseFloat(height ?? '0');\n\n if (numWidth) {\n query+= `/resize,w_${(numWidth * dpr).toFixed(0)}`\n } else if (numHeight) {\n query+= `/resize,h_${(numHeight * dpr).toFixed(0)}`\n }\n\n if (isNumber(quality)) {\n query+= `/quality,q_${quality}`\n }\n\n return `${url}${query}`\n}"
|
|
5153
5129
|
},
|
|
5154
5130
|
{
|
|
5155
5131
|
"path": "src/components/utils/index.ts",
|
|
@@ -5273,6 +5249,10 @@
|
|
|
5273
5249
|
"path": "src/core/comlib/_GetSystemInfo.ts",
|
|
5274
5250
|
"content": "import Taro from '@tarojs/taro';\n\nexport type DataType = {\n sync?: boolean;\n};\n\nexport interface Inputs {\n getSystemInfo?: (fn: (config: DataType, relOutputs?: any) => void) => void;\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void;\n onFail: (value?: any) => void;\n}\n\ninterface IOContext {\n data: DataType;\n inputs: Inputs;\n outputs: Outputs;\n}\n\nexport default (context: IOContext) => {\n const data: DataType = context.data;\n const inputs: Inputs = context.inputs;\n const outputs: Outputs = context.outputs;\n\n inputs.getSystemInfo?.((val: DataType) => {\n try {\n const useSync = val?.sync !== undefined ? val.sync : data.sync || false;\n\n if (useSync) {\n try {\n const systemInfo = Taro.getSystemInfoSync();\n outputs.onSuccess(systemInfo);\n } catch (error: any) {\n outputs.onFail(error?.message || '获取系统信息失败');\n }\n } else {\n Taro.getSystemInfo({\n success: (res) => outputs.onSuccess(res),\n fail: (err) => outputs.onFail(err.errMsg || '获取系统信息失败'),\n });\n }\n } catch (error: any) {\n console.error('获取系统信息失败:', error);\n outputs.onFail(error?.message || '获取系统信息失败');\n }\n });\n};\n"
|
|
5275
5251
|
},
|
|
5252
|
+
{
|
|
5253
|
+
"path": "src/core/comlib/_Modal.ts",
|
|
5254
|
+
"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 | string, 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?: DataType | string) => {\n try {\n const cfg: DataType =\n typeof val === 'string'\n ? { content: val }\n : (val || {});\n\n const modalConfig: any = {\n title: cfg.title ?? data.title ?? '',\n content: cfg.content ?? data.content ?? '',\n showCancel: cfg.showCancel ?? data.showCancel ?? true,\n cancelText: cfg.cancelText ?? data.cancelText ?? '取消',\n cancelColor: cfg.cancelColor ?? data.cancelColor,\n confirmText: cfg.confirmText ?? data.confirmText ?? '确认',\n confirmColor: cfg.confirmColor ?? data.confirmColor,\n };\n\n // editable 不是所有端都支持,按存在即传\n if (cfg.editable !== undefined) modalConfig.editable = cfg.editable;\n else if (data.editable !== undefined) modalConfig.editable = data.editable;\n\n const res: any = await (Taro as any).showModal(modalConfig);\n if (res?.confirm) outputs.onConfirm?.(res);\n else outputs.onCancel?.(res);\n } catch (error: any) {\n console.error('显示 Modal 失败:', error);\n outputs.onCancel?.(error);\n }\n });\n};\n\n\n"
|
|
5255
|
+
},
|
|
5276
5256
|
{
|
|
5277
5257
|
"path": "src/core/comlib/_OpenCamera.ts",
|
|
5278
5258
|
"content": "import Taro from '@tarojs/taro';\n\nexport type DataType = {\n camera?: 'back' | 'front';\n flash?: 'auto' | 'on' | 'off';\n quality?: 'high' | 'normal' | 'low';\n};\n\nexport interface Inputs {\n openCamera?: (fn: (config: DataType, relOutputs?: any) => void) => void;\n}\n\nexport interface Outputs {\n onSuccess: (value?: any) => void;\n onFail: (value?: any) => void;\n}\n\ninterface IOContext {\n data: DataType;\n inputs: Inputs;\n outputs: Outputs;\n}\n\nexport default (context: IOContext) => {\n const data: DataType = context.data;\n const inputs: Inputs = context.inputs;\n const outputs: Outputs = context.outputs;\n\n inputs.openCamera?.((val: DataType) => {\n try {\n const config = {\n camera: val?.camera || data.camera || 'back',\n flash: val?.flash || data.flash || 'auto',\n quality: val?.quality || data.quality || 'normal',\n };\n\n // Taro没有直接的打开相机API,我们可以:\n // 1. 使用chooseImage并设置sourceType为camera\n // 2. 或者提示用户使用系统相机\n\n Taro.chooseImage({\n count: 1,\n sourceType: ['camera'],\n success: (res) => {\n outputs.onSuccess({\n type: 'camera',\n tempFilePath: res.tempFilePaths[0],\n tempFile: res.tempFiles[0],\n config,\n });\n },\n fail: (err) => {\n if (err.errMsg?.includes('cancel')) {\n outputs.onFail('用户取消拍照');\n } else {\n outputs.onFail(err.errMsg || '打开相机失败');\n }\n },\n });\n } catch (error: any) {\n console.error('打开相机失败:', error);\n outputs.onFail(error?.message || '打开相机失败');\n }\n });\n};\n"
|
|
@@ -5319,7 +5299,7 @@
|
|
|
5319
5299
|
},
|
|
5320
5300
|
{
|
|
5321
5301
|
"path": "src/core/comlib/_TimerDelay.ts",
|
|
5322
|
-
"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\nexport interface Outputs {\n onStart: (value?: any) => void;\n onExecute: (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 let timeoutId:
|
|
5302
|
+
"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\nexport default (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"
|
|
5323
5303
|
},
|
|
5324
5304
|
{
|
|
5325
5305
|
"path": "src/core/comlib/_TimerThrottle.ts",
|
|
@@ -5331,7 +5311,7 @@
|
|
|
5331
5311
|
},
|
|
5332
5312
|
{
|
|
5333
5313
|
"path": "src/core/comlib/index.ts",
|
|
5334
|
-
"content": "// 显示提示消息\nexport { default as mybricks_taro_showToast } from './_ShowToast';\nexport type { DataType as mybricks_taro_showToast_DataType } from './_ShowToast';\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_setStorage } from './_SetStorage';\nexport type { DataType as mybricks_taro_setStorage_DataType } from './_SetStorage';\n\nexport { default as mybricks_taro_getStorage } from './_GetStorage';\nexport type { DataType as mybricks_taro_getStorage_DataType } from './_GetStorage';\n\nexport { default as mybricks_taro_removeStorage } from './_RemoveStorage';\nexport type { DataType as mybricks_taro_removeStorage_DataType } from './_RemoveStorage';\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_vibrate } from './_Vibrate';\nexport type { DataType as mybricks_taro_vibrate_DataType } from './_Vibrate';\n\nexport { default as mybricks_taro_callPhone } from './_CallPhone';\nexport type { DataType as mybricks_taro_callPhone_DataType } from './_CallPhone';\n\nexport { default as mybricks_taro_openCamera } from './_OpenCamera';\nexport type { DataType as mybricks_taro_openCamera_DataType } from './_OpenCamera';\n\n// 系统功能\nexport { default as mybricks_taro_openUrl } from './_OpenUrl';\nexport type { DataType as mybricks_taro_openUrl_DataType } from './_OpenUrl';\n\nexport { default as mybricks_taro_share } from './_Share';\nexport type { DataType as mybricks_taro_share_DataType } from './_Share';\n\nexport { default as mybricks_taro_getSystemInfo } from './_GetSystemInfo';\nexport type { DataType as mybricks_taro_getSystemInfo_DataType } from './_GetSystemInfo';\n\n// 数据处理\nexport { default as mybricks_taro_aesEncode } from './_AesEncode';\nexport type { DataType as mybricks_taro_aesEncode_DataType } from './_AesEncode';\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_chooseFile } from './_ChooseFile';\nexport type { DataType as mybricks_taro_chooseFile_DataType } from './_ChooseFile';\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_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_backTo } from './_BackTo';\nexport type { DataType as mybricks_taro_backTo_DataType } from './_BackTo';\n\nexport { default as mybricks_taro_router } from './_Router';\nexport type { DataType as mybricks_taro_router_DataType } from './_Router';\n\nexport { default as mybricks_taro_openPetalMap } from './_OpenPetalMap';\nexport type { DataType as mybricks_taro_openPetalMap_DataType } from './_OpenPetalMap';\n\n// 语音和多媒体\nexport { default as mybricks_taro_textToSpeech } from './_TextToSpeech';\nexport type { DataType as mybricks_taro_textToSpeech_DataType } from './_TextToSpeech';\n\n// 定时器\nexport { default as mybricks_taro_timerDebounce } from './_TimerDebounce';\nexport type { DataType as mybricks_taro_timerDebounce_DataType } from './_TimerDebounce';\n\nexport { default as mybricks_taro_timerDelay } from './_TimerDelay';\nexport type { DataType as mybricks_taro_timerDelay_DataType } from './_TimerDelay';\n\nexport { default as mybricks_taro_timerThrottle } from './_TimerThrottle';\nexport type { DataType as mybricks_taro_timerThrottle_DataType } from './_TimerThrottle';\n\n"
|
|
5314
|
+
"content": "// 显示提示消息\nexport { default as mybricks_taro_showToast } from './_ShowToast';\nexport type { DataType as mybricks_taro_showToast_DataType } from './_ShowToast';\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_setStorage } from './_SetStorage';\nexport type { DataType as mybricks_taro_setStorage_DataType } from './_SetStorage';\n\nexport { default as mybricks_taro_getStorage } from './_GetStorage';\nexport type { DataType as mybricks_taro_getStorage_DataType } from './_GetStorage';\n\nexport { default as mybricks_taro_removeStorage } from './_RemoveStorage';\nexport type { DataType as mybricks_taro_removeStorage_DataType } from './_RemoveStorage';\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_vibrate } from './_Vibrate';\nexport type { DataType as mybricks_taro_vibrate_DataType } from './_Vibrate';\n\nexport { default as mybricks_taro_callPhone } from './_CallPhone';\nexport type { DataType as mybricks_taro_callPhone_DataType } from './_CallPhone';\n\nexport { default as mybricks_taro_openCamera } from './_OpenCamera';\nexport type { DataType as mybricks_taro_openCamera_DataType } from './_OpenCamera';\n\n// 系统功能\nexport { default as mybricks_taro_openUrl } from './_OpenUrl';\nexport type { DataType as mybricks_taro_openUrl_DataType } from './_OpenUrl';\n\nexport { default as mybricks_taro_share } from './_Share';\nexport type { DataType as mybricks_taro_share_DataType } from './_Share';\n\nexport { default as mybricks_taro_getSystemInfo } from './_GetSystemInfo';\nexport type { DataType as mybricks_taro_getSystemInfo_DataType } from './_GetSystemInfo';\n\n// 数据处理\nexport { default as mybricks_taro_aesEncode } from './_AesEncode';\nexport type { DataType as mybricks_taro_aesEncode_DataType } from './_AesEncode';\n\n// 模态对话框\nexport { default as mybricks_taro_modal } from './_Modal';\nexport type { DataType as mybricks_taro_modal_DataType } from './_Modal';\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_chooseFile } from './_ChooseFile';\nexport type { DataType as mybricks_taro_chooseFile_DataType } from './_ChooseFile';\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_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_backTo } from './_BackTo';\nexport type { DataType as mybricks_taro_backTo_DataType } from './_BackTo';\n\nexport { default as mybricks_taro_router } from './_Router';\nexport type { DataType as mybricks_taro_router_DataType } from './_Router';\n\nexport { default as mybricks_taro_openPetalMap } from './_OpenPetalMap';\nexport type { DataType as mybricks_taro_openPetalMap_DataType } from './_OpenPetalMap';\n\n// 语音和多媒体\nexport { default as mybricks_taro_textToSpeech } from './_TextToSpeech';\nexport type { DataType as mybricks_taro_textToSpeech_DataType } from './_TextToSpeech';\n\n// 定时器\nexport { default as mybricks_taro_timerDebounce } from './_TimerDebounce';\nexport type { DataType as mybricks_taro_timerDebounce_DataType } from './_TimerDebounce';\n\nexport { default as mybricks_taro_timerDelay } from './_TimerDelay';\nexport type { DataType as mybricks_taro_timerDelay_DataType } from './_TimerDelay';\n\nexport { default as mybricks_taro_timerThrottle } from './_TimerThrottle';\nexport type { DataType as mybricks_taro_timerThrottle_DataType } from './_TimerThrottle';\n\n"
|
|
5335
5315
|
}
|
|
5336
5316
|
]
|
|
5337
5317
|
},
|
|
@@ -5403,7 +5383,7 @@
|
|
|
5403
5383
|
},
|
|
5404
5384
|
{
|
|
5405
5385
|
"path": "src/core/utils/hooks.ts",
|
|
5406
|
-
"content": "import { useState, useRef, useMemo } from 'react';\nimport {
|
|
5386
|
+
"content": "import { useState, useRef, useMemo } from 'react';\nimport { createReactiveInputHandler } from '../mybricks/createReactiveInputHandler';\n\n/**\n * 深度代理,支持自动路径初始化和响应式更新(鸿蒙化处理方案)\n */\nexport function deepProxy(target: any, onSet?: () => void): any {\n if (target === null || typeof target !== 'object' || target.__isProxy) {\n return target;\n }\n\n return new Proxy(target, {\n get(obj, prop) {\n if (prop === '__isProxy') return true;\n if (prop === 'toJSON') return () => obj;\n\n let value = (obj as any)[prop];\n\n // 只代理已存在的对象属性,不自动创建空对象\n // 避免访问不存在的属性(如 disabled)时污染原始数据\n if (typeof value === 'object' && value !== null && !value.__isProxy) {\n (obj as any)[prop] = deepProxy(value, onSet);\n }\n\n return (obj as any)[prop];\n },\n set(obj, prop, value) {\n const result = Reflect.set(obj, prop, value);\n if (onSet) onSet();\n return result;\n }\n });\n}\n\nexport function useModel(rawData: any) {\n const [, forceUpdate] = useState({});\n const dataRef = useRef(rawData || {});\n\n return useMemo(() => {\n return deepProxy(dataRef.current, () => forceUpdate({}));\n }, []);\n}\n\nexport function useBindInputs(scope: any, id: string, initialHandlers?: Record<string, any>) {\n const handlersRef = useRef<Record<string, any>>({ ...initialHandlers });\n\n // 同步最新的 initialHandlers\n if (initialHandlers) {\n Object.assign(handlersRef.current, initialHandlers);\n }\n\n return useMemo(() => {\n const proxy = new Proxy({}, {\n get: (_target, pin: string) => {\n return (arg: any, ...args: any[]) => {\n if (typeof arg === 'function') {\n // 组件注册回调\n handlersRef.current[pin] = arg;\n } else {\n // 逻辑流触发输入\n const handler = handlersRef.current[pin];\n\n if (typeof handler === 'function') {\n if (pin === '_setData') {\n return handler(arg, ...args);\n }\n // 构造 createReactiveInputHandler 需要的参数\n return createReactiveInputHandler({\n input: handler,\n value: arg,\n rels: {}, // 这里可以扩展 output 关联\n title: id\n });\n }\n }\n };\n }\n });\n\n // 将代理对象挂载到作用域,供外部 comRefs.current.id.pin() 调用\n if (scope && scope.current) {\n scope.current[id] = proxy;\n }\n return proxy;\n }, [scope, id]);\n}\n\nexport function useBindEvents(props: any, context?: { id: string, name: string, parentSlot?: any }) {\n return useMemo(() => {\n const _events: Record<string, any> = {};\n\n // 预处理已存在的事件\n Object.keys(props).forEach(key => {\n // 兼容:MyBricks 输出 pin 既可能是 onChange,也可能是 changeTab 这种非 on 前缀\n if (typeof props[key] === 'function') {\n const handler = props[key];\n const wrapped = (originalValue: any) => {\n // 鸿蒙/render-web 规范:如果是在插槽中触发事件,且存在父级协议,则自动封装元数据\n // 这解决了 FormContainer 等组件识别子项的需求\n // 注意:不要仅凭 parentSlot 存在就封装,否则会影响 Tabs2/changeTab 这类事件直接给 JS 计算组件传参\n // 仅在父级 slot 使用 itemWrap 协议时才需要这层元数据\n const value = context?.parentSlot?.params?.itemWrap ? {\n id: context.id,\n name: context.name,\n value: originalValue\n } : originalValue;\n \n return handler(value);\n };\n wrapped.getConnections = () => [{ id: 'default' }];\n _events[key] = wrapped;\n }\n });\n\n return new Proxy(_events, {\n get(target, key: string) {\n // 对 onXXX 事件(不少组件 runtime 直接 outputs[\"onChange\"](...))提供兜底函数,避免未连线时报错\n if (typeof key === 'string' && key.startsWith('on')) {\n if ((target as any)[key]) {\n return (target as any)[key];\n }\n // 对未连接的事件返回兜底函数\n const emptyFn: any = () => { };\n emptyFn.getConnections = () => [];\n return emptyFn;\n }\n return (target as any)[key];\n }\n });\n }, [props, context]);\n}\n\n\n"
|
|
5407
5387
|
},
|
|
5408
5388
|
{
|
|
5409
5389
|
"path": "src/core/utils/index.ts",
|
|
@@ -5415,7 +5395,7 @@
|
|
|
5415
5395
|
},
|
|
5416
5396
|
{
|
|
5417
5397
|
"path": "src/core/utils/PopupRenderer.tsx",
|
|
5418
|
-
"content": "import React from 'react';\nimport { View } from '@tarojs/components';\nimport { useAppContext } from './ComContext';\n\ninterface PopupRendererProps {\n popupMap: Record<string, any>;\n}\n\nexport const PopupRenderer: React.FC<PopupRendererProps> = ({ popupMap }) => {\n const { popupState } = useAppContext();\n\n const ActivePopup = popupState.visible && popupMap[popupState.name] \n ? popupMap[popupState.name] \n : null;\n\n if (!ActivePopup) return
|
|
5398
|
+
"content": "import React from 'react';\nimport { View } from '@tarojs/components';\nimport { useAppContext } from './ComContext';\n\ninterface PopupRendererProps {\n popupMap: Record<string, any>;\n}\n\nexport const PopupRenderer: React.FC<PopupRendererProps> = ({ popupMap }) => {\n const { popupState } = useAppContext();\n\n const ActivePopup = popupState.visible && popupMap[popupState.name] \n ? popupMap[popupState.name] \n : null;\n\n if (!ActivePopup) return <View></View>;\n\n return (\n <View \n className=\"global-popup-container\" \n style={{ \n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 999999,\n pointerEvents: 'auto',\n }}\n >\n <View style={{ width: '100%', height: '100%' }}>\n <ActivePopup />\n </View>\n </View>\n );\n};\n\n"
|
|
5419
5399
|
},
|
|
5420
5400
|
{
|
|
5421
5401
|
"path": "src/core/utils/popupRouter.ts",
|
|
@@ -5423,20 +5403,66 @@
|
|
|
5423
5403
|
},
|
|
5424
5404
|
{
|
|
5425
5405
|
"path": "src/core/utils/slots.tsx",
|
|
5426
|
-
"content": "import React, { useMemo, useRef
|
|
5406
|
+
"content": "import React, { useMemo, useRef } from \"react\";\nimport ComContext, { SlotProvider, useAppContext, useParentSlot } from \"./ComContext\";\nimport { createReactiveInputHandler } from \"../mybricks/createReactiveInputHandler\";\n\ntype AnyRecord = Record<string, any>;\n\ntype SlotState = {\n inputs: any;\n outputs: any;\n _inputs: any;\n /** scopeId -> scoped comRefs(每个 scope 一套,避免列表多实例覆盖) */\n _scopedComRefs?: Record<string, any>;\n _render?: any;\n render: (params?: any) => any;\n};\n\nfunction SlotParamsBridge(props: {\n state: SlotState;\n params: any;\n render?: any;\n children?: React.ReactNode;\n}) {\n const parentSlot = useParentSlot<any>();\n const mergedParams =\n props.params?.inputValues === undefined && parentSlot?.params?.inputValues\n ? { ...(props.params || {}), inputValues: parentSlot.params.inputValues }\n : props.params;\n\n const SlotComp = props.render;\n const content = SlotComp ? <SlotComp {...(mergedParams || {})} /> : props.children ?? null;\n\n return <SlotProvider value={{ ...props.state, params: mergedParams }}>{content}</SlotProvider>;\n}\n\nfunction createChannelProxy(title: string) {\n const handlersMap: Record<string, any> = {};\n return new Proxy(\n {},\n {\n get: (_t, pin: string) => {\n return (arg: any) => {\n if (typeof arg === \"function\") {\n handlersMap[pin] = arg;\n return;\n }\n const handler = handlersMap[pin];\n if (typeof handler === \"function\") {\n return createReactiveInputHandler({\n input: handler,\n value: arg,\n rels: {},\n title,\n });\n }\n };\n },\n },\n );\n}\n\n/**\n * 参考鸿蒙的 createSlotsIO:\n * - 确保每个 slot 都具备 inputs / outputs / _inputs 三套通道,避免 runtime 访问时报 undefined\n * - render 时通过 SlotProvider 注入 parentSlot(slot 内子组件可 useParentSlot 获取)\n */\nexport function useEnhancedSlots(rawSlots: any, id: string) {\n const slotStoreRef = useRef<Record<string, SlotState>>({});\n\n return useMemo(() => {\n if (!rawSlots) return {};\n const nextSlots: AnyRecord = {};\n\n Object.entries(rawSlots).forEach(([slotKey, slotDef]: any) => {\n const state =\n slotStoreRef.current[slotKey] ||\n (slotStoreRef.current[slotKey] = {\n inputs: createChannelProxy(`${id}.${slotKey}.inputs`),\n outputs: createChannelProxy(`${id}.${slotKey}.outputs`),\n _inputs: createChannelProxy(`${id}.${slotKey}._inputs`),\n _scopedComRefs: {},\n _render: undefined,\n render: (params?: any) => {\n const r = state._render;\n // 只有存在 key 或 index 时才认为是“多实例作用域插槽”,需要实例隔离\n const rawScope = params?.key ?? params?.inputValues?.index ?? params?.inputValues?.itemData?.id;\n \n if (rawScope === undefined || rawScope === null) {\n return (\n <SlotParamsBridge state={state} params={params} render={r} />\n );\n }\n\n const scopeId = `${id}.${slotKey}::${String(rawScope)}`;\n const scopedComRefs =\n (state._scopedComRefs![scopeId] ||= { current: { $inputs: {}, $outputs: {} } });\n return (\n <SlotProvider value={{ ...state, params }}>\n <ScopedComContextProvider comRefs={scopedComRefs} scopeId={scopeId}>\n <SlotParamsBridge state={state} params={params} render={r} />\n </ScopedComContextProvider>\n </SlotProvider>\n );\n },\n });\n\n state._render = slotDef?.render;\n nextSlots[slotKey] = {\n ...(slotDef || {}),\n render: state.render,\n inputs: state.inputs,\n outputs: state.outputs,\n _inputs: state._inputs,\n };\n });\n\n return nextSlots;\n }, [rawSlots, id]);\n}\n\nexport function ScopedComContextProvider(props: {\n comRefs?: any;\n scopeId: string;\n children: React.ReactNode;\n}) {\n const parent = useAppContext();\n const value = useMemo(() => {\n // $outputs 与 $inputs 一样:在 scoped 下应当隔离(由 scopedComRefs.current.$outputs 提供)\n // 如果没有显式传 comRefs,则沿用父级的,但依然带上新的 scopeId\n return {\n ...parent,\n comRefs: props.comRefs || parent.comRefs,\n $scopeId: props.scopeId,\n } as any;\n }, [parent, props.comRefs, props.scopeId]);\n\n return <ComContext.Provider value={value}>{props.children}</ComContext.Provider>;\n}\n\n/** parentSlot 解析:props 优先,其次用 SlotProvider 注入的 context */\nexport function useResolvedParentSlot(parentSlotProp: any) {\n const parentSlotFromCtx = useParentSlot();\n return parentSlotProp ?? parentSlotFromCtx;\n}\n"
|
|
5427
5407
|
},
|
|
5428
5408
|
{
|
|
5429
5409
|
"path": "src/core/utils/useContext.ts",
|
|
5430
|
-
"content": "import { useRef, useState, useMemo } from 'react'\nimport { deepProxy } from './hooks'\n\nexport interface ComContextStore {\n comRefs: any;\n
|
|
5410
|
+
"content": "import { useRef, useState, useMemo } from 'react'\nimport { deepProxy } from './hooks'\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}\n\nexport function useAppCreateContext(id: string): ComContextStore {\n // 约定:场景级 inputs 统一挂载到 $inputs,避免与组件 runtime 的 inputs 命名冲突\n // 同时可避免 `Cannot set property 'open' of undefined`\n // 注册表拆分:\n // - comRefs: 组件实例/inputs/outputs 注册表(可 scoped)\n // - $vars/$fxs: 逻辑能力注册表(仅页面级,全作用域共享)\n const comRefs = useRef<any>(deepProxy({ $inputs: {}, $outputs: {} }));\n const $vars = useRef<any>({});\n const $fxs = useRef<any>({});\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, // 使用 data 中的 id\n },\n runtime: {\n debug: false,\n },\n edit: false,\n isH5: false,\n isDesigner: false,\n isPreview: false,\n isRelease: false,\n isDebug: false,\n isLocal: false,\n isTest: false,\n tabBar: [],\n useTabBar: false,\n }).current;\n\n return useMemo(() => ({\n comRefs,\n $vars,\n $fxs,\n appContext,\n popupState,\n setPopupState\n }), [popupState]);\n}\n"
|
|
5431
5411
|
},
|
|
5432
5412
|
{
|
|
5433
5413
|
"path": "src/core/utils/with.tsx",
|
|
5434
|
-
"content": "import React, { useState, useEffect } from 'react';\n// @ts-ignore 运行时由宿主项目提供 @tarojs/components\nimport { View } from '@tarojs/components';\nimport { useModel, useBindInputs, useBindEvents, subscribePopupRouter, closeActivePopupRouter } from './index';\nimport { useAppCreateContext } from './useContext';\nimport ComContext, { useAppContext } from './ComContext';\nimport { useEnhancedSlots, useResolvedParentSlot } from './slots';\n// @ts-ignore 运行时由宿主项目提供 @tarojs/taro\nimport { useTabItemTap } from '@tarojs/taro';\n\ninterface WithComProps {\n component: React.ComponentType<any>;\n intputRef?: any;\n id?: string;\n data?: any;\n className?: string;\n style?: any;\n
|
|
5414
|
+
"content": "import React, { useState, useEffect } from 'react';\n// @ts-ignore 运行时由宿主项目提供 @tarojs/components\nimport { View } from '@tarojs/components';\nimport { useModel, useBindInputs, useBindEvents, subscribePopupRouter, closeActivePopupRouter } from './index';\nimport { useAppCreateContext } from './useContext';\nimport ComContext, { useAppContext } from './ComContext';\nimport { useEnhancedSlots, useResolvedParentSlot } from './slots';\n// @ts-ignore 运行时由宿主项目提供 @tarojs/taro\nimport { useTabItemTap } from '@tarojs/taro';\n\ninterface WithComProps {\n component: React.ComponentType<any>;\n intputRef?: any;\n id?: string;\n data?: any;\n className?: string;\n style?: any;\n [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 // 内置通用能力\n const handlers = {\n _setStyle: (style: any) => {\n setDynamicStyle((prev) => ({ ...prev, ...style }));\n },\n _setData: (path: string, value: any) => {\n const paths = path.split('.');\n let current = _data;\n for (let i = 0; i < paths.length - 1; i++) {\n if (!current[paths[i]]) current[paths[i]] = {};\n current = current[paths[i]];\n }\n current[paths[paths.length - 1]] = value;\n }\n };\n\n if (!isPopup) {\n Object.assign(handlers, {\n show: () => setShow(true),\n hide: () => setShow(false),\n showOrHide: () => setShow((prev) => !prev),\n });\n }\n\n // 绑定输入,传入初始 handlers\n const inputProxy = useBindInputs(comRefs, id, handlers);\n\n const { slots: rawSlots, parentSlot: parentSlotProp, ...restProps } = rest as any;\n const parentSlot = useResolvedParentSlot(parentSlotProp);\n\n // 绑定事件,带上上下文(用于事件流自动封装 id/name)\n const eventProxy = useBindEvents(restProps, { \n id, \n name: props.name || id, \n parentSlot \n });\n\n // 注册 outputs 到注册表(按组件 id)\n if (comRefs?.current?.$outputs) {\n comRefs.current.$outputs[id] = eventProxy;\n }\n\n // 鸿蒙规范:确保 comRefs 中挂载的是最新的 inputProxy\n comRefs.current[id] = inputProxy;\n\n const enhancedSlots = useEnhancedSlots(rawSlots, id);\n\n const jsx = (\n <Component\n {...restProps}\n inputs={inputProxy}\n outputs={eventProxy}\n slots={enhancedSlots}\n parentSlot={parentSlot}\n data={_data}\n env={env}\n id={id}\n style={style}\n />\n );\n\n // 鸿蒙化处理:支持 itemWrap 协议\n if (parentSlot?.params?.itemWrap) {\n return parentSlot.params.itemWrap({\n id,\n name: props.name || id,\n jsx,\n def: (Component as any).def,\n inputs: inputProxy,\n outputs: eventProxy,\n style\n });\n }\n\n return (\n show || isPopup ? (\n <View className={className} style={{ ...style, ...dynamicStyle }} >\n {jsx}\n </View>\n ) : null\n );\n};\n\nexport const WithWrapper = (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"
|
|
5435
5415
|
}
|
|
5436
5416
|
]
|
|
5437
5417
|
}
|
|
5438
5418
|
]
|
|
5439
5419
|
},
|
|
5420
|
+
{
|
|
5421
|
+
"path": "src/custom-tab-bar",
|
|
5422
|
+
"content": null,
|
|
5423
|
+
"children": [
|
|
5424
|
+
{
|
|
5425
|
+
"path": "src/custom-tab-bar/mybricks",
|
|
5426
|
+
"content": null,
|
|
5427
|
+
"children": [
|
|
5428
|
+
{
|
|
5429
|
+
"path": "src/custom-tab-bar/mybricks/tabbar-config.ts",
|
|
5430
|
+
"content": "export default [\n {\n \"scene\": { \"id\": \"u_SdZVq\" },\n \"text\": \"111\",\n \"selectedIconPath\": \"data:image/png;base64,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\",\n \"selectedIconUseImg\": false,\n \"selectedIcon\": \"HM_plus\",\n \"selectedFontIconStyle\": { \"fontSize\": \"22px\", \"color\": \"#FD6A00\" },\n \"selectedIconStyle\": { \"width\": \"22px\", \"height\": \"22px\" },\n \"selectedTextStyle\": {\n \"marginTop\": \"6px\",\n \"fontSize\": \"12px\",\n \"color\": \"#FD6A00\"\n },\n \"normalIconUseImg\": false,\n \"normalIconPath\": \"data:image/png;base64,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\",\n \"normalIcon\": \"HM_plus\",\n \"normalFontIconStyle\": { \"fontSize\": \"22px\", \"color\": \"#909093\" },\n \"normalIconStyle\": { \"width\": \"22px\", \"height\": \"22px\" },\n \"normalTextStyle\": {\n \"marginTop\": \"6px\",\n \"fontSize\": \"12px\",\n \"color\": \"#909093\"\n }\n },\n {\n \"scene\": { \"id\": \"u_RrrgT\" },\n \"text\": \"333\",\n \"selectedIconPath\": \"data:image/png;base64,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\",\n \"selectedIconUseImg\": false,\n \"selectedIcon\": \"HM_plus\",\n \"selectedFontIconStyle\": { \"fontSize\": \"22px\", \"color\": \"#FD6A00\" },\n \"selectedIconStyle\": { \"width\": \"22px\", \"height\": \"22px\" },\n \"selectedTextStyle\": {\n \"marginTop\": \"6px\",\n \"fontSize\": \"12px\",\n \"color\": \"#FD6A00\"\n },\n \"normalIconUseImg\": false,\n \"normalIconPath\": \"data:image/png;base64,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\",\n \"normalIcon\": \"HM_plus\",\n \"normalFontIconStyle\": { \"fontSize\": \"22px\", \"color\": \"#909093\" },\n \"normalIconStyle\": { \"width\": \"22px\", \"height\": \"22px\" },\n \"normalTextStyle\": {\n \"marginTop\": \"6px\",\n \"fontSize\": \"12px\",\n \"color\": \"#909093\"\n }\n }\n ] as any\n"
|
|
5431
|
+
}
|
|
5432
|
+
]
|
|
5433
|
+
},
|
|
5434
|
+
{
|
|
5435
|
+
"path": "src/custom-tab-bar/utils",
|
|
5436
|
+
"content": null,
|
|
5437
|
+
"children": [
|
|
5438
|
+
{
|
|
5439
|
+
"path": "src/custom-tab-bar/utils/event.ts",
|
|
5440
|
+
"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}"
|
|
5441
|
+
},
|
|
5442
|
+
{
|
|
5443
|
+
"path": "src/custom-tab-bar/utils/tabbar.ts",
|
|
5444
|
+
"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()"
|
|
5445
|
+
}
|
|
5446
|
+
]
|
|
5447
|
+
},
|
|
5448
|
+
{
|
|
5449
|
+
"path": "src/custom-tab-bar/index.config.ts",
|
|
5450
|
+
"content": "export default {\n \"component\": true\n}"
|
|
5451
|
+
},
|
|
5452
|
+
{
|
|
5453
|
+
"path": "src/custom-tab-bar/index.tsx",
|
|
5454
|
+
"content": "import React, { useCallback, useMemo, useState, useEffect } from \"react\";\nimport cx from \"classnames\";\nimport * as Taro from \"@tarojs/taro\";\nimport { View, Image } from \"@tarojs/components\";\nimport DynamicIcon from \"../components/components/dynamic-icon\";\nimport css from \"./style.less\";\n\nimport tabBarJson from \"./mybricks/tabbar-config\";\nimport { tabbarIns } from \"./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 iconSlotCx = cx({\n [\"iconSlot\"]: true,\n });\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={iconSlotCx}>\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 className={`badge ${!formatText ? \"small\" : \"normal\"}`}>\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"
|
|
5455
|
+
},
|
|
5456
|
+
{
|
|
5457
|
+
"path": "src/custom-tab-bar/style.less",
|
|
5458
|
+
"content": ".tabBar {\n width: 375px;\n background: #ffffff;\n box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.1);\n z-index: 9999;\n\n .items {\n width: 375px;\n height: 54px;\n display: flex;\n }\n\n .safearea {\n width: 375px;\n height: constant(safe-area-inset-bottom);\n height: env(safe-area-inset-bottom);\n }\n\n .item {\n position: relative;\n flex: 1;\n height: 100%;\n padding-top: 6px;\n padding-bottom: 6px;\n\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n\n .iconSlot {\n position: relative;\n .fontIcon {\n display: block;\n }\n\n .badge {\n position: absolute;\n\n transform-origin: 100% 0%;\n transform: translate(50%, -40%);\n\n top: 0px;\n right: 0px;\n\n background-color: #ff4d4f;\n }\n .badge.normal {\n padding: 0px 3px;\n min-width: 14px;\n height: 14px;\n border-radius: 100px;\n font-size: 10px;\n\n display: flex;\n align-items: center;\n justify-content: center;\n color: #fff;\n }\n .badge.small {\n width: 9px;\n height: 9px;\n border-radius: 50%;\n }\n }\n\n .textSlot {\n margin-top: 6px;\n height: 14px;\n }\n }\n}\n"
|
|
5459
|
+
},
|
|
5460
|
+
{
|
|
5461
|
+
"path": "src/custom-tab-bar/tabBar.json",
|
|
5462
|
+
"content": "{}"
|
|
5463
|
+
}
|
|
5464
|
+
]
|
|
5465
|
+
},
|
|
5440
5466
|
{
|
|
5441
5467
|
"path": "src/pages",
|
|
5442
5468
|
"content": null
|
|
@@ -5446,12 +5472,12 @@
|
|
|
5446
5472
|
"content": "export default defineAppConfig({\n pages: [],\n window: {\n backgroundTextStyle: 'light',\n navigationBarBackgroundColor: '#fff',\n navigationBarTitleText: 'WeChat',\n navigationBarTextStyle: 'black'\n }\n})\n"
|
|
5447
5473
|
},
|
|
5448
5474
|
{
|
|
5449
|
-
"path": "src/app.less",
|
|
5475
|
+
"path": "src/app.global.less",
|
|
5450
5476
|
"content": "/* 隐藏 React Refresh 的全屏错误遮罩 */\n#react-refresh-overlay, \niframe[id=\"react-refresh-overlay\"] {\n display: none !important;\n}\n\n.mybricks_taro_systemPage {\n height: 100vh !important;\n}\n\nview {\n box-sizing: border-box;\n}\n"
|
|
5451
5477
|
},
|
|
5452
5478
|
{
|
|
5453
5479
|
"path": "src/app.ts",
|
|
5454
|
-
"content": "import { PropsWithChildren } from 'react'\nimport { useLaunch } from '@tarojs/taro'\nimport 'brickd-mobile/lib/index.css' \nimport \"@taroify/icons/style\"\nimport './app.less'\n\nfunction App({ children }: PropsWithChildren<any>) {\n useLaunch(() => {\n console.log('App launched.')\n })\n\n // children 是将要会渲染的页面\n return children\n}\n \n\n\nexport default App\n"
|
|
5480
|
+
"content": "import { PropsWithChildren } from 'react'\nimport { useLaunch } from '@tarojs/taro'\nimport 'brickd-mobile/lib/index.css' \nimport \"@taroify/icons/style\"\nimport './app.global.less'\n\nfunction App({ children }: PropsWithChildren<any>) {\n useLaunch(() => {\n console.log('App launched.')\n })\n\n // children 是将要会渲染的页面\n return children\n}\n \n\n\nexport default App\n"
|
|
5455
5481
|
},
|
|
5456
5482
|
{
|
|
5457
5483
|
"path": "src/index.html",
|