全部项目

Case Study

POS 机支付云系统

面向多品牌收单场景的支付云管理台:设备、交易、结算数据的统一视图与离线可用能力。

-60%

类型错误率

3 端

统一组件与主题

离线可用

IndexedDB 本地缓存

背景

支付云管理台要同时承载三类使用者:运营看交易大盘,风控查异常流水,运维管设备状态。旧系统由多个时期的技术栈拼接而成,同一个「交易详情」在不同模块有三套实现,字段口径也不一致。项目的第一优先级不是加功能,而是建立统一的类型与组件边界。

我的角色

  • 负责管理台核心模块的前端架构与开发:交易查询、设备管理、结算对账、权限体系对接。
  • 主导 JavaScript → TypeScript 的渐进式迁移与 Vue2 → Vue3 的架构升级。
  • 搭建图表与大数据量表格的通用方案,抽象出可复用的业务组件。

关键设计

1. 用类型定义统一「口径」

迁移不是给变量补 : string,而是先把领域模型抽出来:

export type TransactionStatus = 'pending' | 'success' | 'failed' | 'reversed';

export interface Transaction {
  id: string;
  merchantId: string;
  amount: number;        // 单位:分,避免浮点误差
  currency: 'CNY';
  status: TransactionStatus;
  paidAt: string | null; // ISO 8601
  deviceSn: string;
}

金额统一用「分」存储与计算,展示层再做格式化;时间统一 ISO 字符串,避免 Date 在序列化时丢失时区。仅这两条约定,就消掉了对账页面长期存在的「差一分钱」争议。

2. 编译期就拦住跨模块误用

配合 vue-tsc 与 GitLab CI,类型检查成为合并前的硬性门禁;同时开启 strict、noUncheckedIndexedAccess,把「可能为空」显式化。最终类型相关缺陷下降约 60%,评审时也不再需要靠人工核对字段。

3. 大数据量表格与图表的性能取舍

  • 交易列表采用虚拟滚动 + 分页缓存,单页 5000 行仍保持滚动流畅。
  • 图表只渲染视口内的系列,切换筛选时复用实例而不是重建。
  • 高频查询结果写入 IndexedDB,弱网或后端抖动时优先展示本地快照,并标注数据时间。

支付类系统的体验底线是「不误导」。宁可显示「数据截至 10:32」的旧快照,也不要因为请求失败展示一片空白。

结果

  • TypeScript 覆盖率从不足 20% 提升到核心模块 100%,类型错误率下降约 60%。
  • 交易、设备、结算三个模块共用一套表格与图表能力,新页面开发时间显著缩短。
  • 弱网环境下管理台仍可查看最近一次交易快照,客服排障不再依赖「刷新试试」。

复盘

前端重构最容易陷入「为了新而新」。这次迁移真正产生价值的,是借 TypeScript 强制团队对金额单位、时间格式、状态枚举达成一致的约定。技术升级只是手段,口径统一才是收益。