Skip to content

自定义装修配置模块

自定义装修配置模块是一个用于在商城中实现自定义装修功能的模块。它提供了可视化的拖拽配置界面,用户可以通过拖拽模块来定制商城的页面布局和样式。

1. 架构设计

1.1 系统分层架构

1.2 模块间交互关系

1.3 技术选型说明

层级技术栈说明
后管配置端React@18 + Umi4 + Ant Design提供可视化拖拽配置界面
小程序渲染端Taro + React跨端渲染组件,支持微信小程序等
共用数据模块TypeScript类型定义和业务逻辑
构建工具pnpm + monorepo统一依赖管理和构建流程
样式方案Less + CSS Modules组件样式隔离

2. 模块说明

2.1 后管配置端 (decoration-backend)

功能描述

  • 提供可视化拖拽界面,支持模块的添加、删除、排序

  • 为每个模块提供专门的配置表单

  • 实时预览配置效果

  • 生成标准化的JSON配置数据

核心类/接口定义

typescript
// 模块信息接口
interface IModuleInfo {
  type: BasicModuleSignEnum;
  cname: string;
  icon: string;
  category?: EModuleCategory;
  getDefaultProps: () => any;
  settingComponet: React.ComponentType;
}

// 存储上下文接口
interface IStoreContextValue {
  modules: IModule[];
  logo: string;
  name: string;
  form: FormInstance<any>;
  upload?(fileList: File[], options?: any): Promise<string[]>;
}

关键实现逻辑

  1. 模块自动注册机制
typescript
function creatInitContext() {
  const modules: IModule[] = []
  const $require = require['context']('./decorationModules', true, /^\.\/\w+\/index.[tj]sx?$/)
  
  function generateModules(request, rmodules) {
    const module = rmodules(request) as IModule
    const { moduleInfo } = module
    if (moduleInfo) {
      const { category = EModuleCategory.Basic } = moduleInfo
      modules.push({ ...module, moduleInfo: { ...moduleInfo, category } })
    }
  }
  $require.keys().forEach((request) => generateModules(request, $require))
  
  return { modules }
}
  1. 模块配置表单 每个模块都有对应的 settingComponet 配置组件,提供:
  • 内容配置:业务数据设置

  • 样式配置:外观样式调整

  • 组件样式:边距、背景等通用样式

2.2 小程序渲染端 (decoration-taro)

功能描述

  • 提供跨端渲染组件,支持各种装修模块的展示

  • 处理用户交互事件(点击、跳转等)

  • 适配不同端的样式和行为差异

  • 支持热区点击、图片懒加载等高级功能

核心组件

typescript
// 图片模块组件
interface IBasicModuleImageProps extends BasicModuleImageDTO {
  onLinkJump?(item: IJumpLink, index: number): void;
}

// 热区组件
interface IHotZoneProps {
  data?: IHotZoneValue[];
  mode?: EJumpLinkMode;
  onClick(data: IHotZoneValue): void;
}

关键实现逻辑

  1. 样式适配处理
typescript
const { style, css } = useComponentStyle(componentStyle)

let imageStyle: CSSProperties = {}
if (arrangeType === EArrangeType.Orientation) {
  imageStyle = {
    borderRadius: contentStyle.borderRadius + 'px',
    marginRight: contentStyle.imageMargin + 'px'
  }
}
  1. 事件处理机制
typescript
const handleClick = (item: ImageLinkDataDTO, index: number) => {
  if (item.jumpMode === EJumpLinkMode.Link) {
    props.onLinkJump?.(item.link, index)
  }
}

2.3 共用数据模块 (decoration-data)

功能描述

  • 定义所有模块的TypeScript类型

  • 提供枚举常量和默认配置

  • 统一数据结构和业务逻辑

  • 确保前后端数据一致性

核心类型定义

typescript
// 基础模块标识枚举
enum BasicModuleSignEnum {
  Search = 'Search',
  Slider = 'Slider',
  Navigation = 'Navigation',
  Product = 'Product',
  Image = 'Image',
  // ... 更多模块类型
}

// 组件样式接口
interface IComponentStyle {
  pagePadding: number;
  paddingTop: number;
  paddingBottom: number;
}

// 图片链接数据
interface ImageLinkDataDTO {
  name: string;
  key: string;
  url: string;
  jumpMode: EJumpLinkMode;
  link: IJumpLink;
  hotZones?: IHotZoneValue[];
}

2.4 前端渲染组件 (taro-shop-component)

功能描述

  • 作为最终的页面渲染器,整合所有装修模块

  • 提供页面上下文管理

  • 处理模块间的数据传递和事件通信

  • 支持不同页面类型的渲染

核心实现

typescript
const Component: FC<IPageModulesProps> = (props) => {
  const { data = [], pageType = EPageType.Default, pageParams = {}, flag = 0 } = props

  const contextValue = useMemo(() => ({ pageType, pageParams }), [props.pageType, props.pageParams, flag])
  
  return (
    <PageContext.Provider value={contextValue}>
      <View className={styles.pageModulesStyle}>
        {data.map((item, index) => {
          return (
            <View key={item.id + index}>
              {
                {
                  [BasicModuleSignEnum.Search]: <BasicModuleSearch {...item.data} />,
                  [BasicModuleSignEnum.Image]: <BasicModuleImage {...item.data} />,
                  // ... 更多模块映射
                }[item.type]
              }
            </View>
          )
        })}
      </View>
    </PageContext.Provider>
  )
}

3. 配置说明

3.1 JSON配置结构定义

json
{
  "pageId": "string",
  "pageName": "string",
  "pageType": "Default | Shop | Custom",
  "modules": [
    {
      "id": "string",
      "type": "BasicModuleSignEnum",
      "data": {
        // 模块特定的配置数据
        "componentStyle": {
          "pagePadding": 15,
          "paddingTop": 0,
          "paddingBottom": 0
        },
        "contentStyle": {
          // 内容样式配置
        },
        // 其他业务数据
      }
    }
  ]
}

3.2 可配置参数说明

通用组件样式 (IComponentStyle)

  • pagePadding: 页面边距 (0-50px)

  • paddingTop: 上边距 (0-100px)

  • paddingBottom: 下边距 (0-100px)

图片模块配置 (BasicModuleImageDTO)

  • arrangeType: 排列方式 (纵向/横向/滚动)

  • data: 图片数据数组

  • contentStyle.borderRadius: 图片圆角 (0-20px)

  • contentStyle.imageMargin: 图片间距 (0-20px)

标题栏模块配置 (BasicModuleTitleDTO)

  • name: 标题名称 (最大10字符)

  • left.show: 是否显示左侧图标

  • left.icon: 图标选择

  • left.image: 自定义图片

  • right.showArrow: 是否显示箭头

  • right.content: 右侧文本 (最大4字符)

  • link: 跳转链接配置

3.3 配置约束条件

  1. 数据验证规则

    • 标题名称不超过10个字符

    • 右侧文本不超过4个字符

    • 图片圆角范围0-20px

    • 边距范围0-100px

  2. 业务约束

    • 每个页面最多支持50个模块

    • 图片模块最多支持20张图片

    • 商品模块最多显示100个商品

  3. 平台限制

    • 直播模块仅支持小程序端

    • 某些跳转类型在H5端有限制

4. 使用方式

4.1 后管配置操作指南

添加模块

  1. 从左侧模块库拖拽模块到画布
  2. 点击模块进入配置面板
  3. 配置内容数据和样式参数
  4. 实时预览配置效果

配置模块

  1. 内容配置:设置业务相关数据

    • 图片上传和链接设置

    • 文本内容编辑

    • 商品选择和活动配置

  2. 样式配置:调整外观样式

    • 颜色、字体、大小设置

    • 布局和对齐方式

    • 边距和间距调整

  3. 组件样式:通用样式设置

    • 页面边距

    • 上下边距

    • 背景色等

保存发布

  1. 点击保存按钮生成配置JSON
  2. 通过API接口保存到后端
  3. 配置文件存储到OSS
  4. 小程序端可实时获取最新配置

4.2 小程序接入流程

安装依赖

bash
pnpm add @wmeimob-modules/decoration-data
pnpm add @wmeimob-modules/decoration-taro
pnpm add @wmeimob/taro-shop-component

页面集成

typescript
import PageModules from '@wmeimob/taro-shop-component/src/components/pageModules'

function CustomPage() {
  const [pageData, setPageData] = useState([])
  
  useEffect(() => {
    // 获取页面配置数据
    fetchPageConfig().then(setPageData)
  }, [])
  
  return (
    <PageModules 
      data={pageData}
      pageType={EPageType.Custom}
      pageParams={{ pageId: 'xxx' }}
    />
  )
}

自定义模块

typescript
// 1. 在 decoration-data 中定义类型
interface ICustomModuleData {
  title: string;
  componentStyle: IComponentStyle;
}

// 2. 在 decoration-backend 中实现配置组件
const CustomModuleConfig = () => {
  return (
    <Form>
      <ProFormInput name="title" label="标题" />
      <ComponentStyle />
    </Form>
  )
}

// 3. 在 decoration-taro 中实现渲染组件
const CustomModule: FC<ICustomModuleData> = (props) => {
  const { style } = useComponentStyle(props.componentStyle)
  return <View style={style}>{props.title}</View>
}

4.3 API调用规范

保存页面配置

typescript
POST /api/decoration/pages
Content-Type: application/json

{
  "pageId": "string",
  "pageName": "string", 
  "pageType": "Custom",
  "config": {
    // 完整的页面配置JSON
  }
}

获取页面配置

typescript
GET /api/decoration/pages/{pageId}

Response:
{
  "code": 200,
  "data": {
    "pageId": "string",
    "config": {
      // 页面配置JSON
    }
  }
}

上传图片资源

typescript
POST /api/decoration/upload
Content-Type: multipart/form-data

FormData: {
  files: File[]
}

Response: {
  "code": 200,
  "data": ["https://oss.example.com/image1.jpg"]
}

5. 数据流转

5.1 配置数据生成流程

5.2 存储与读取机制

存储机制

  1. 配置数据序列化:将表单数据转换为标准JSON格式
  2. 数据压缩:对大型配置进行压缩存储
  3. 版本管理:支持配置的版本控制和回滚
  4. 缓存策略:热点配置数据缓存到Redis

读取机制

  1. 按需加载:根据页面ID获取对应配置
  2. 缓存优先:优先从缓存读取,缓存失效时从OSS读取
  3. 增量更新:支持配置的增量更新和推送
  4. 容错处理:配置解析失败时使用默认配置

5.3 渲染数据传递过程

6. 注意事项

6.1 性能优化建议

前端优化

  1. 组件懒加载

    typescript
    const BasicModuleImage = lazy(() => import('./basicModuleImage'))
  2. 图片优化

    typescript
    // 使用阿里云图片处理服务
    const optimizedUrl = getImage(originalUrl, 400) // 限制宽度400px
  3. 虚拟滚动

    • 对于长列表页面,使用虚拟滚动减少DOM节点

    • 图片懒加载,进入可视区域才加载

  4. 缓存策略

    typescript
    // 页面配置缓存
    const pageConfig = useMemo(() => processConfig(rawConfig), [rawConfig])

后端优化

  1. 配置缓存:热点页面配置缓存到Redis
  2. CDN加速:静态资源使用CDN分发
  3. 数据压缩:大型配置使用gzip压缩
  4. 接口优化:批量接口减少请求次数

6.2 常见问题处理

配置丢失问题

问题:用户配置的数据突然丢失 解决方案

  1. 实现自动保存机制,每30秒保存一次草稿
  2. 添加配置版本管理,支持历史版本恢复
  3. 本地存储备份,防止网络异常导致的数据丢失

渲染异常问题

问题:某些模块在特定环境下渲染异常 解决方案

  1. 添加错误边界组件,捕获渲染错误
  2. 提供降级方案,渲染失败时显示占位组件
  3. 完善类型检查,避免数据类型不匹配

跨端兼容问题

问题:同一配置在不同端表现不一致 解决方案

  1. 使用Taro的跨端API,避免平台特定代码
  2. 针对不同平台提供样式适配
  3. 功能降级处理,不支持的功能隐藏或替换

6.3 扩展性说明

新增模块类型

  1. 定义数据类型

    typescript
    // decoration-data/src/modules.ts
    interface INewModuleData {
      title: string;
      componentStyle: IComponentStyle;
    }
  2. 添加模块标识

    typescript
    // decoration-data/src/enums/BasicModuleSignEnum.ts
    export enum BasicModuleSignEnum {
      // ... 现有模块
      NewModule = 'NewModule'
    }
  3. 实现后管配置组件

    typescript
    // decoration-backend/src/components/decorationModules/newModule/
    ├── index.tsx          // 预览组件
    ├── const.ts           // 类型定义和默认值
    └── settingComponet/   // 配置表单
        └── index.tsx
  4. 实现渲染组件

    typescript
    // decoration-taro/src/components/newModule/
    ├── index.tsx          // 渲染组件
    └── index.module.less  // 样式文件
  5. 注册到渲染器

    typescript
    // taro-shop-component/src/components/pageModules/index.tsx
    {
      [BasicModuleSignEnum.NewModule]: <NewModule {...item.data} />
    }[item.type]

扩展配置能力

  1. 添加新的样式配置

    typescript
    interface IComponentStyle {
      pagePadding: number;
      paddingTop: number;
      paddingBottom: number;
      // 新增配置
      borderRadius?: number;
      boxShadow?: string;
    }
  2. 扩展跳转类型

    typescript
    enum EJumpType {
      // ... 现有类型
      CustomAction = 'CustomAction'
    }
  3. 添加新的排列方式

    typescript
    enum EArrangeType {
      Vertical = 1,
      Orientation = 2,
      Scroll = 3,
      // 新增
      Grid = 4
    }

国际化支持

  1. 多语言配置

    typescript
    interface IModuleInfo {
      type: BasicModuleSignEnum;
      cname: string;
      // 新增多语言支持
      i18n?: {
        'zh-CN': string;
        'en-US': string;
      };
    }

通过以上架构设计,自定义装修配置模块具备了良好的可扩展性、可维护性和性能表现,能够满足复杂的业务需求和未来的功能扩展。