Vue 3TypeScript架构SaaS
Vue 3 + TS 在多租户 SaaS 后台的实践:分层、权限与可维护性
把 vue3-admin-ts 沉淀一篇文章出来,聊聊在多租户 + 多角色权限场景下,前端架构是怎么演进的。
背景
过去一年多在做一个装修行业 SaaS 平台,营销、交付、商户、集团四个子系统并行,前端主仓库是 vue3-admin-ts。这里把几个关键决策整理一下。
1. 分层:API 层 vs Service 层
早期所有请求都堆在 src/api/,文件多了之后业务逻辑和 HTTP 调用耦合死。重构后:
src/api/—— 只负责 HTTP 调用,返回原始响应。src/service/—— 业务逻辑层:组合多个 API、缓存策略、字段归一化。src/store// Composable —— 状态层,只通过 service 拿数据。
好处:换请求库(axios → fetch)、换字段命名、加埋点,都只动单层。
2. 权限:路由级 + 按钮级双轨
vue3-admin-ts 用了 roles 模式(见 src/settings.ts 的 permissionMode):
- 路由级:
router.beforeEach+ 动态addRoute,按角色裁剪可见菜单。 - 按钮级:自定义
v-permission指令,避免在每个组件里写v-if="user.roles.includes('admin')"。
权限点用后端下发的二维数组,前端不做硬编码兜底——这能避免”前后端权限对不上”的经典 bug。
3. 可维护性:几个小约定
- 常量集中:路由名、权限点、字典值全部进
src/consts/或专门的dict/目录,不允许在组件里写魔法字符串。 - 组件目录按业务域划分,不按组件类型(
components/Button/❌,views/marketing/coupon/✅)。 - Vuex 模块自动注册:
require.context扫描,避免每次加 store 都要改入口。 - Patch 机制:Element Plus 有过几次回归 bug,直接打 patch 进
patches/,比等官方修快。
4. 一些踩过的坑
- 多租户的数据隔离:前端不要相信 URL 里的
tenantId,永远从用户上下文取。 - 路由缓存:keep-alive + 动态路由时,include 名字要稳定,否则会反复重新渲染。
- 类型生成:openapi-typescript 自动生成类型后,DTO 改字段不会让你编译报错——CI 一定要跑
tsc-check。
收尾
架构没什么银弹,关键是让下一次改需求的人(可能是三个月后的自己)能快速看懂。这个仓库在这一年多的迭代里基本没大改过结构,主要就是新加模块,说明方向是对的。