跳到主要内容

整体架构

· 阅读需 4 分钟
Quany
软件工程师
  1. 整体架构示意 ┌─────────────────────────────────────────────────────────────────────────────────┐│ 云帆 CRM 技术架构 │├─────────────────────────────────────────────────────────────────────────────────┤│ ││ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││ │ Web (Vite) │ │ App (RN) │ │ 后端 (SB) │ ││ │ React 19 │ ──ajax─▶│ axios │ ──▶ │ context │ ││ │ Ant Design │ │ Jotai │ │ /api │ ││ └─────────────┘ └─────────────┘ └──────┬──────┘ ││ │ │ │ ││ │ baseUrl: /api │ │ ││ └────────────────────────┴────────────────────────┘ ││ │ ││ ┌─────────────┼─────────────┐ ││ ▼ ▼ ▼ ││ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ││ │ MySQL │ │ Redis │ │ RabbitMQ │ │ 存储/CDN │ ││ │ 8.0 │ │ 7 │ │ (可选?) │ │ 本地/OSS │ ││ └──────────┘ └──────────┘ └──────────┘ └──────────┘ ││ │└─────────────────────────────────────────────────────────────────────────────────┘
  2. 后端架构(Java + Spring Boot) 2.1 分层与职责 层 位置 职责 Controller controller/ REST 接口,参数校验,调用 Service Service service/ + impl/ 业务逻辑,事务边界 Mapper mapper/ MyBatis-Plus,单表/批量 Entity entity/ 表映射;DTO 在 dto/、common/ 下 Common common/ 缓存、安全、审计、消息、通知、存储、调度等 统一响应:Result(code / message / data / timestamp)。全局异常:GlobalExceptionHandler。 2.2 已做得不错的地方 分层清晰:Controller → Service → Mapper,DTO 与 Entity 分离。 统一出口:Result、全局异常、Knife4j 文档。 基础设施:Redis 缓存(枚举/国家/配置)、Druid 连接池与监控、MyBatis-Plus 分页与逻辑删除。 扩展模块:审计、GDPR、数据隔离(按国家)、消息(RabbitMQ)、通知(邮件/企微)、定时任务、存储抽象(本地/OSS)。 部署:docker-compose 含 MySQL、Redis、应用,环境变量清晰。 2.3 可优化点(架构层面) 点 现状 建议 API 版本与路径 大部分接口无版本(如 /api/lead-pool),仅 AiCrawlerSourceController 用 /api/v1/ai-crawler-sources 统一约定:要么全加 /api/v1/ 前缀,要么全不加,并文档化,便于以后做 v2 不破坏现有前端。 安全 SecurityConfig 当前 anyRequest().permitAll(),仅靠请求头 auth-token 若已上生产,建议在 Security 里显式配置需认证的路径、放行文档/健康检查等,避免“默认全放行”的误用。 RabbitMQ 与部署 代码里有 RabbitMQ 配置与消费者,但 docker-compose 未包含 RabbitMQ 要么在 docker-compose 中增加 RabbitMQ 服务,要么用 @ConditionalOnProperty 等让消息模块在未配置时不可用,避免本地/测试环境因连不上 MQ 启动失败。 MyBatis 二级缓存 application.yml 里 cache-enabled: false 保持关闭是稳妥的;若以后要开,需考虑多实例与 Redis 等集中缓存,避免本地缓存不一致。
  3. 前端 Web 架构(React + Vite) 3.1 结构 入口:AppRouter 用 ~pages-config 生成路由,根级 Suspense + useRoutes。 请求:统一 axios 实例,baseUrl /api,请求头带 auth-token,拦截器处理 loading/成功/错误/取消。 页面:pages/ 下按业务分目录(lead-pool、personal-leads、todos、users 等),列表页多为「Form 筛 + Table 分页」。 配置:config-hoc(权限、标题、抽屉、弹窗)、menus、多环境 config。 3.2 可优化点 点 说明 路由懒加载 需确认 @ts-max/vite-plugin-pages-config 生成的路由是否按页面 React.lazy;若否,首屏会包含所有页面 chunk,可考虑按路由懒加载以减小首包。 请求缓存 未使用 React Query/SWR 等,重复进入同一列表会重复请求;可对只读列表/详情做短时缓存或 stale-while-revalidate,减轻后端压力、提升体验。 类型与接口 列表/详情类型多在各自 pages/xxx/types.ts;若后端有 OpenAPI/Knife4j 生成类型,可考虑统一生成前端类型,减少手写不一致。
  4. App 架构(React Native) 4.1 结构 API:api/ 下按领域拆模块(todo、customer、clue、brand 等),client 统一请求。 状态:Jotai + Zustand,MMKV 持久化。 列表:FlashList;图片:fast-image。 导航:React Navigation v7 静态导航;大量 screens/ 与业务组件。 4.2 可优化点 点 说明 与后端对齐 App 的 api 模块(如 approval、contract、invoice)若与当前后端 controller 不完全对应,需确认是历史模块、多后端,还是待收敛;对齐后可减少重复与歧义。 共享类型 若 Web 与 App 共用同一套后端 API,可考虑把通用类型/接口定义放到 monorepo 公共包或从 OpenAPI 生成双端类型,避免两套定义漂移。
  5. 跨端与一致性 维度 现状 可优化 认证 Web:auth-token 头;App:需看 authService 是否同一套 统一 token 存储、刷新、过期处理与错误码,便于双端体验一致。 API 契约 后端 Knife4j/OpenAPI,前端手写类型 用 OpenAPI 生成 TS 类型或 SDK,减少手写、保证与文档一致。 错误与多语言 后端统一异常、前端拦截器处理;i18n 各端自有 错误码与 key 统一约定,便于前端做统一错误文案与多语言映射。