找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1615

积分

1

好友

227

主题
发表于 4 天前 | 查看: 15| 回复: 0

背 景

在外卖平台的运营中,我们致力于通过灵活的补贴策略激励商家,与商家共同打造良好的合作关系,也会提供多样化的营销活动,帮助商家吸引更多用户下单。通过这些活动,不仅能够提高商家的销量,还能让用户感受到实际的优惠,从而增强他们对平台的粘性。

前端技术特点

业务特点:营销场景玩法多、活动类型多、活动链路长、活动规则复杂。
中后台技术特点:活动配置表单规则多、联动复杂。
前台技术特点:终端类型多(PC/EXE/PAD/PHONE)、代码重复度高、用户输入校验规则复杂。

业务技术架构

图片

活动链路

图片

商家营销相关项目迭代时间较长,积累的历史技术债务越来越多,结合业务背景和以上的技术特点,之前对历史项目进行过一波代码治理,比如:多端代码复用、后台复杂度治理等。

2023年的治理更多解决的是代码重复及腐化相关的问题,而外卖商家营销活动的配置能力还处于非常基础的阶段。2024年,我们结合业务新诉求的契机,从系统架构治理维度,对商家营销前端项目做了一个全面的升级。

现状

外卖商家营销活动,按活动来源区分主要有四大类:平台招商、代运营、品牌代建、商户自营销,按类型区分主要有四大类:特价菜、买赠、免配、满减。前后端底层区分这些活动渠道及类型都是case by case的形式。

以招商活动创建为例,不同活动类型,优惠信息都放在不同的字段里:特价菜是specialItemRule,免配是freeDeliveryRule,满减是reductionRule,买赠是buyGiftsRule,且规则rules字段层级嵌套冗余,字段属性没有规律可循。以下列举了两类活动的部分字段。

特价菜活动规则字段示例

"specialItemRule": [{
    "rulePurposeType": 0,
    "rules": [{
      "type": 3,
      "content": {
        "discountValueRange": null,
        "discountValueList": [10, 11, 20],
        "discountType": 1
      }
    }],
    "selectItemNumRange": {
      "min": 1,
      "max": 10
    },
    "itemPromoRangeValue": {
      "min": 1,
      "max": 50
    },
    "picLimit": 1,
    "priceLimit": null,
    "itemType": 0,
    "checkItemPriceDay": 7
  }]

满减规则字段示例

"reductionRule": [{
    "rulePurposeType": 0,
    "rules": [{
      "type": 1,
      "content": {
        "threshold": 10,
        "discount": 5
      }
    }, {
      "type": 1,
      "content": {
        "threshold": 20,
        "discount": 8
      }
    }]
  }]

面临的挑战

2024年随着国际化外卖营销业务需求明显增长,例如需要从0到1搭建连锁品牌商家自运营能力、拓展新的营销活动类型(商家券)。按照现有的架构及配置能力来看,存在以下几个问题:

  • 产品需求迭代支撑效率低:涉及通用字段,需要重复修改。特价菜、免配、满减、买赠,4种活动类型改4次,如果再算上活动渠道修改,需要再翻倍,即4种渠道 × 4类活动 = 16 次。
  • 开发遗漏:活动链路长,以当前最为复杂的招商活动为例,从运营后台配置招商计划到商户前台报名招商活动,是一个较长的链路。由于系统数据模型不够灵活,导致修改字段及UI展示时无规律可循,经常需要梳理遗漏点。
  • 可拓展性差:当前架构下,如果新增活动类型,则涉及全链路所有接口改动,可复用性低。

由于业务发展的契机,国际化外卖商家侧需要新增一个连锁品牌管理端,借助这个项目,我们进行了商家营销架构的升级。

解决方案

问题分析

商家营销配置能力薄弱主要体现在底层数据结构缺乏通用性和扩展性。

从全局配置维度来看:

图片

从数据结构现状来看:

图片

  • 同一类活动,在不同平台(端、后台)数据结构不一致。
  • 同一类活动,在不同活动来源场景下(自营销、招商、代运营、品牌),数据结构不一致。
  • 四类活动,活动规则数据结构不一致,创建需要case by case拼装,详情需要case by case渲染。
  • 差异化分支众多:自营销创建4 + 招商报名4 + 招商计划4 + 代运营1 + 品牌4 = 17。

整体思路

架构治理最重要的一环就是设计出一个统一的活动数据模型,涵盖所有平台和活动来源场景。

图片

  1. 抽象活动实体信息
  2. 统一差异化配置
    • 按活动信息维度拆分组织字段,而不是按业务维度拆分(收敛类型、来源)。
    • 按通用字段概括优惠类型,而不是按业务概念枚举(收敛规则)。
  3. 支持灵活拓展

项目成果

在抽象出活动配置模型后,为保证后续需求或者人员变更能够按照规范持续迭代,我们配套了前端JSON Schema校验工具,并生成相应的API文档,以此约束后续的拓展行为。

底层数据结构完成治理后,在新项目中,我们也对配置表单方案进行了优化,使得项目的数据流转更加清晰,确保数据的一致性和可靠性。而在前后端交互层面,通过引入运行时的接口字段校验机制,加强了对接口安全的约束,有效避免了因数据缺陷而导致的前端错误。

数据结构对比

新版活动数据结构采用了一种面向对象的设计架构,借鉴了组合式领域模型的思想,并通过策略模式来实现业务规则的动态装配。

基础活动模型(ActInfoModel)可以被视为一个父类,定义了通用的属性和行为。而其子类(如自营销活动模型selfOpsModel)则继承了这些基础特性,并可以实现或重写特定的功能,以满足不同渠道的具体需求。

当出现新的渠道或者活动类型时,只需要创建新的子类,并遵循父类定义的结构即可。而基础模型的修改,只要确保子类能够适应其接口变化,就不会影响到所有子类,这大大提升了系统的灵活性和可维护性。

图片

配置表单方案优化

在之前的项目中,表单组件间的通信采用传统的多层组件数据传递形式,即通过父子组件层层传递。

图片

  • 数据流:自上而下,每个组件都需要通过props接收和传递数据。
  • 缺点:增加了代码复杂性,每个组件都需要显式传递数据,容易出现冗余代码和数据同步问题。

这种形式对于简单的表单场景来说比较直观,但对于商家营销活动配置这类复杂场景,在过往需求迭代中暴露出了维护困难和数据同步异常的问题。在新项目中,我们采用了配置模型+依赖注入的表单方案。

图片

  • 数据流:数据通过依赖注入在组件树的各层之间传递,子组件可以直接获取所需数据。
  • 优点:降低了组件之间的耦合性,减少了多层传递的冗余,数据更加集中且易于管理。

数据流转对比

图片

使用配置模型 + 依赖注入的方式不仅可以简化数据流转,还能实现集中管理,减少代码冗余,提高数据一致性,并使得维护和调试更加容易,在需要动态配置或处理复杂业务逻辑的场景下优势尤为明显。在现代Vue或React应用中,这种模式常通过Context或Provide/Inject等特性实现。

接口安全保障

当前数据安全问题

为了避免接口数据异常导致前端页面白屏,我们通常会在代码中加入一些字段兜底逻辑,但这带来了新的问题:

  • 冗余的兜底逻辑:在组件中,频繁使用“||”操作符、可选链和解构默认值等方式进行兜底处理,导致同样的逻辑在多个地方反复出现。
  • 复杂的数据结构处理:对于复杂的数据结构,为了某个字段兜底往往需要编写一大段繁琐的代码,影响代码可读性与执行效率。
  • 数据类型安全问题:常规兜底形式无法保证数据类型安全,可能造成不符合预期的类型错误,进而引发应用程序中的逻辑错误或页面崩溃。

在抽象出活动配置模型后,活动配置的定义由标准的JSON Schema描述。基于此,我们定义了校验及默认填充规则,并引入集中式的兜底机制。在接口数据返回时,调用一个统一的校验工具函数,实现统一的兜底策略。这个校验工具函数是借助Zod这个工具库实现的。

招商活动配置描述示例

// 招商活动规则
export const SignUpActRuleSchema = ActRuleSchema.extend({
  selectNumRange: z
    .object({
      min: z.number().default(0),
      max: z.number().default(0),
    })
    .default({ min: 0, max: 0 }),
  actType: z.union([z.number(), z.string()]).default(0),
  rule: z.array(SignUpRuleSchema).default([]),
})
export type SignUpActRule = z.infer<typeof SignUpActRuleSchema>

// 招商活动详情页接口信息
export const SignUpDetailSchema = z.object({
  actRule: SignUpActRuleSchema.default({}),
  actInfo: SignUpInfoSchema.default({}),
  shopJoinInfo: z.array(ShopJoinInfoSchema).default([]),
})

接口返回处理示例

// 招商活动详情接口
// useApiSchema是统一的返回数据校验工具函数
export async function getSignUpDetail(params: object = {}): Promise<SignUpDetail> {
  const response = await post(GET_SIGN_UP_DETAIL, params, { returnData: false })
  return useApiSchema<SignUpDetail>(SignUpDetailSchema, response.data, response.traceId)
}

useApiSchema函数功能包含:数据校验、兜底数据填充、埋点上报。当接口返回字段中出现数据类型错误字段缺失的情况时,函数将返回预先定义好的安全默认值,从而保障页面正常展示。同时,对于识别的错误数据会进行埋点上报,当错误量达到一定阈值时会触发报警,方便后端和Node.js服务端同学及时定位问题。

效率提升

日常迭代

活动配置模型通过字段的抽象和整合,大幅提升了字段扩展的效率。原本因各活动类型和场景的数据结构差异,需要在多处修改数据结构和组件逻辑的场景,现在只需在一处进行修改即可,大大提高了开发效率。

以前台项目活动规则相关迭代为例:

图片

开发实例

以近期需求为例,我们需要新增一种券活动类型。通过采用活动配置模型和集中式状态管理的开发形式,使得开发过程中对于数据相关的处理逻辑与状态管理要比之前简易很多,开发效率提升约40%

后续规划

以上架构治理实践都是在新项目中进行的。对于国际化外卖商家营销前端的其他存量项目,同样需要进行架构升级改造。后续我们计划收敛运营后台的活动配置,将最为复杂的招商活动链路进行标准化,使得后台配置和前台应用能够引用同一套数据模型。

国际化外卖商家营销前端架构预期

图片




上一篇:技术债务治理实战:企业级系统持续演进与Flutter代码质量优化方案
下一篇:技术债务治理实战:滴滴国际化外卖骑手侧H5项目代码重构与优化经验
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-24 20:53 , Processed in 0.162072 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表