FORMA

企业微信与小程序工单问题

背景

工单相关业务同时服务两类使用者:企业微信师傅端(内部/外部人员在企业微信内处理工单)与小程序商家端(商家在微信小程序内查看、跟进工单)。历史实现为节省初期开发成本,长期采用「一套代码、按运行环境做条件分支」的方式承载两端页面,随着工单流程不断迭代,该方式的维护成本逐渐显现。

早期这种“一套代码走两端”的选择并非没有理由:初期功能简单、两端差异小,共用代码确实能节省一部分重复开发时间。但随着工单流程新增「二次上门」「多级审批」「小程序订阅消息提醒」等两端专属能力,条件分支数量呈增长趋势,公共模块中夹杂端侧判断的比例也随之上升,团队在规划下一阶段迭代时,需要重新评估这套代码结构是否还能支撑后续需求。

主要痛点

痛点具体表现影响
页面/组件边界不清晰企微师傅端与商家端页面、组件互相嵌套引用,同一组件内部混杂两端分支逻辑改一端逻辑容易误改到另一端;代码审查成本高
引入规范缺失组件模块引入方式不统一(相对路径、别名、按端条件引入并存)新人上手成本高,容易引入循环依赖或重复打包
公共代码与端侧代码耦合工具函数、状态管理、路由守卫中夹杂端侧判断(如 isWecomisMiniProgram修改公共逻辑需要同时验证两端,回归成本高
加载性能一般两端能力打包在同一产物中,实际只需要其中一端的代码也会被下载首屏体积偏大,弱网环境下体验下降

为何建议拆分为两套代码 / 两个项目

企业微信与小程序在运行环境、组件体系、鉴权与跳转方式上存在本质差异,勉强用一套代码覆盖两端,长期看维护收益低于拆分成本。

对比项企业微信师傅端小程序商家端
运行容器企业微信内嵌 H5 / 企微 JS-SDK微信小程序原生运行时
组件体系Web 组件库(如 Vant / Element 等)小程序原生组件 + 小程序组件库
鉴权方式企业微信免登 + 内部账号体系小程序 login 态 + 商家账号体系
跳转能力location.href / 企微 JS-SDK 跳转、wx.agentConfig 相关能力wx.navigateTo / 小程序路由栈
主题与设计规范偏内部工具风格偏商家 C 端体验风格
能力依赖企业微信会话、消息、审批等强相关 API小程序支付、分享、订阅消息等 API

若强行合并为一套代码,通常会出现以下问题:

  • 能力不可迁移:企微端无法直接调用小程序专属能力(如小程序支付、订阅消息),小程序端也无法使用企微专属能力(会话存档、企微消息卡片等),条件分支只能越堆越多;
  • 鉴权链路冲突:小程序页面依赖独立登录态与 session_key 体系,企微页面依赖企业身份免登,二者混在一套路由与状态管理中,容易出现登录态互相污染或刷新后态丢失;
  • 构建与发布耦合:任一端发版都需要重新构建、验证整个产物,无法独立发布节奏。

边界划分建议

  1. 按运行环境彻底拆分为两个独立项目/仓库,各自维护构建配置、依赖版本与发布节奏;
  2. 企业微信端优先使用企业微信原生能力与组件体系,涉及「二次上门」「工单会话」「审批流」等场景直接对接企微 JS-SDK,不做小程序兼容层;
  3. 小程序端优先使用小程序原生组件与能力(如 wx.navigateTo、订阅消息、原生支付),不引入企微专属依赖;
  4. 若确有业务口径一致的部分(如工单状态枚举、金额计算规则、文案),可下沉为纯逻辑的公共包(不含 UI、不含端侧判断),通过 npm 私有包或 monorepo 子包方式复用,避免把 UI 层也强行合并。

拆分后目录结构建议

两个仓库各自维护独立的目录结构,公共逻辑包以子包或私有 npm 包形式被两端引用:

text
wecom-worker/            # 企业微信师傅端仓库
  src/
    pages/
    components/
    sdk/                 # 企微 JS-SDK 封装
  vite.config.ts

merchant-miniapp/        # 小程序商家端仓库
  src/
    pages/
    components/
  project.config.json

@org/work-order-shared/  # 纯逻辑公共包(工单状态枚举、金额计算等)
  src/
    enums.ts
    calc.ts
  package.json

公共包只做纯逻辑导出,不引入任何 UI 组件或端侧 SDK,两端各自按需 import 后在本端 UI 中使用。

迁移注意事项

  • 接口层面:确认后端接口是否已按「渠道来源」区分返回字段(如工单来源标记企微/小程序),迁移过程中避免两端同时读写导致状态覆盖;
  • 鉴权迁移:企微免登与小程序登录分别独立改造,迁移期建议保留双写日志,便于定位登录态错乱问题;
  • 灰度节奏:建议先拆分低风险的展示型页面(列表、详情),再迁移涉及下单/审批等高风险交互页面,降低整体风险;
  • 历史链接兼容:企业微信历史消息卡片、小程序历史分享路径中可能固化了旧路由,拆分后需保留一段时间的路由重定向;
  • 组件库对齐:拆分后两端设计规范可能出现差异,建议提前与产品/设计确认,避免用户感知到「同一功能两套体验」的割裂感。

性能优化建议

  • 拆分后各端产物只包含自身依赖,天然减少无关代码的下载与解析;
  • 企微端可结合 企业微信群工具打开缓慢原因分析 中的构建体积、资源预加载、SDK 初始化链路优化经验,缩短首次进入耗时;
  • 小程序端建议关注分包加载、按需注入组件,避免主包体积超限;
  • 公共逻辑包应保持轻量、无副作用,避免因公共包体积增长间接拖慢两端首屏。

实施排期建议

拆分不建议“一刀切”式停机重构,按风险从低到高分阶段推进:

阶段内容周期参考风险
第一阶段新建两个独立仓库,搭建各自构建配置与基础依赖,公共逻辑包先以最小集合(枚举、金额计算)落地1-2 周低,不影响存量线上功能
第二阶段迁移展示型页面(列表、详情),两端并行验证2-3 周低-中,回退成本低
第三阶段迁移交互型页面(下单、审批、状态变更)2-4 周中-高,需重点验证鉴权与状态一致性
第四阶段下线旧路由与旧代码,清理条件分支1 周低,但需确认历史链接兼容期已过

常见疑问

  1. 两套代码会不会增加维护成本?
    短期看确实需要维护两个仓库,但长期看两端条件分支消失后,单侧改动不再需要担心「误改另一端」,整体回归成本反而下降。
  2. 公共逻辑包要不要包含请求层?
    不建议。企微端与小程序端的网络请求封装(尤其是鉴权头、baseURL、错误处理)差异较大,强行合并容易引入隐藏的端侧判断,违背拆分初衷;公共包应只保留纯函数逻辑。
  3. 拆分后两端设计不一致怎么办?
    属于预期内的短期现象,建议提前与产品/设计同步拆分计划,必要时给出统一的视觉规范作为两端后续迭代的共同基线,而不是强行在代码层维持一致。

回归检查清单

  • 企业微信端所有工单相关页面(列表、详情、审批)在拆分后可正常访问,无残留小程序端专属依赖报错;
  • 小程序端所有工单相关页面在拆分后可正常访问,无残留企微 JS-SDK 相关报错;
  • 公共逻辑包(状态枚举、金额计算规则)在两端引用后计算结果一致,重点覆盖边界值(如金额为 0、状态为空);
  • 企业微信历史消息卡片与小程序历史分享路径可正确重定向到新页面,不出现 404 或白屏;
  • 两端鉴权链路(企微免登 / 小程序登录态)互不影响,切换账号或重新登录后状态不串号;
  • 两端各自的构建产物体积较拆分前下降,且不包含另一端专属依赖(可通过构建分析工具核实);
  • 灰度期间新老入口并存时,同一工单在两个入口查看的数据一致,无因渠道字段处理不一致导致的展示差异。

总结

企微师傅端与小程序商家端在运行环境、组件体系、鉴权链路上差异明显,是否拆分不应仅从“短期是否好维护”判断,而应从长期迭代成本与两端独立发布能力综合评估。建议尽快完成边界拆分,公共逻辑通过纯逻辑包复用,两端 UI 与端侧能力各自独立演进。

相关链接

相关文章