全球 HR 与合规管理系统的前端复杂度往往被低估:它既要支持几十个国家、十几种语言的员工自助服务,又要满足不同法域下的数据展示规范和审批流转规则。类似 Deel 这样的全球化用工平台,其前端工程必须解决多租户、多语言、多币种、多时区以及权限隔离五大问题。Vue 3 的组合式 API、Vite 的按需编译能力,加上成熟的生态插件,恰好能为这类系统提供一套清晰的工程化路径。本文将从项目搭建、国际化、权限控制、性能优化和数据合规五个维度,完整讲解实现方案。

一、项目初始化与工程结构设计
工程化的第一步是建立可维护的目录结构。全球 HR 系统的业务模块通常包括员工管理、薪酬发放、合规文档、签证与工作许可等,每个模块都有独立的页面、状态和类型定义。推荐采用「按业务域分组」的目录组织方式,而不是简单的 pages/components 平铺结构,这样当团队按业务线分工时,各小组的代码边界清晰,冲突更少。
使用 Vite 创建项目并配置多环境变量是基础操作。首先初始化项目:
npm create vite@latest hr-compliance-platform -- --template vue-ts cd hr-compliance-platform npm install pinia vue-router axios
接着配置环境变量。在项目根目录创建 .env.development、.env.staging 和 .env.production 三个文件,分别对应开发、预发和生产环境。Vite 会根据启动命令自动加载对应的文件,通过 import.meta.env 访问变量:
// .env.production VITE_API_BASE_URL=https://api.hr-platform.ippipp.com VITE_I18N_LOCALE=en-US VITE_ENABLE_SENTRY=true // 在代码中读取 const apiBaseUrl = import.meta.env.VITE_API_BASE_URL;
推荐的目录结构如下,核心思想是 modules 目录下按业务域垂直切分,每个模块自带自己的路由、状态与组件:
src/ ├── modules/ │ ├── employee/ # 员工管理域 │ ├── payroll/ # 薪酬域 │ ├── compliance/ # 合规文档域 │ └── visa/ # 签证与工作许可域 ├── shared/ # 跨模块复用的组件、工具、组合式函数 ├── locales/ # 国际化语言包 ├── router/ # 路由入口与守卫 ├── stores/ # 全局状态 └── main.ts
这种结构的好处在于团队协作与构建优化两方面:按域分组使得代码评审和权限分配可以精确到目录级别;同时配合 Vite 的动态 import,每个模块可以自然形成独立的异步 chunk,为首屏性能优化打下基础。
二、国际化方案:不止是翻译文本
国际化是全球 HR 系统的重中之重,但它远不止文本翻译。真正完整的 i18n 方案需要处理日期格式、货币显示、数字分隔符、姓名顺序以及复数规则等文化差异。vue-i18n 是 Vue 3 生态的标准选择,建议使用 Composition API 模式并在构建时做语言包按需加载。
import { createI18n } from 'vue-i18n';
import type { I18n } from 'vue-i18n';
// 只同步加载默认语言,其他语言按需异步获取
import enUS from './locales/en-US.json';
export const i18n: I18n = createI18n({
legacy: false,
locale: 'en-US',
fallbackLocale: 'en-US',
messages: {
'en-US': enUS
}
});
// 异步切换语言,减小首包体积
export async function switchLocale(locale: string) {
const messages = await import(`./locales/${locale}.json`);
i18n.global.setLocaleMessage(locale, messages.default);
i18n.global.locale.value = locale;
document.documentElement.setAttribute('lang', locale);
}
需要注意的细节有三个。第一,货币与数字格式不要手写格式化逻辑,直接使用 Intl.NumberFormat,它原生支持按地区显示货币符号和千分位规则,例如德国员工看到的是 1.234,56 而美国员工看到的是 1,234.56。第二,日期与时区必须统一在后端存储 UTC 时间戳,前端展示时按用户所在时区转换,否则跨国团队的薪酬周期必然出现偏差。第三,姓名展示顺序在部分语言环境需要反转(如匈牙利语习惯姓在前),语言包中应预留格式化占位符而不是简单拼接字符串。
三、权限控制与多租户隔离
合规系统的权限设计通常是 RBAC(基于角色的访问控制)叠加数据范围限制:同样是「薪酬详情」页面,HR 管理员可以看全公司数据,团队经理只能看自己团队,普通员工只能看自己的工资单。前端层面的实现分两步:路由级守卫控制页面可达性,组件级指令控制按钮和字段的可见性。
// 权限指令:无权限时直接移除元素
import type { Directive } from 'vue';
const permissionDirective: Directive = {
mounted(el, binding) {
const { userStore } = useStores();
const required = binding.value; // 例如 'payroll:approve'
if (!userStore.permissions.includes(required)) {
el.parentNode?.removeChild(el);
}
}
};
export default permissionDirective;
// 模板中使用:<button v-permission="'payroll:approve'">审批</button>
路由守卫的实现要点是区分「静态路由」和「动态路由」。登录页、错误页等静态路由直接注册;业务路由则根据后端返回的菜单权限数据动态生成,通过 router.addRoute 注入。这样权限变更时前端无需发版,只需后端调整权限配置即可生效。多租户场景下,还要在请求拦截器中统一注入租户标识头,避免每个请求手动传递:
axios.interceptors.request.use(config => {
const tenantId = useTenantStore().currentTenantId;
if (tenantId) {
config.headers['X-Tenant-Id'] = tenantId;
}
return config;
});
四、性能优化与数据合规的工程细节
性能层面,全球 HR 系统的典型瓶颈是巨大的表单和数据表格。员工信息表单可能有上百个字段,建议用 Vue 3 的 defineAsyncComponent 拆分表单分区组件,配合 shallowRef 存储大列表数据,避免深层响应式带来的开销。表格组件优先选用支持虚拟滚动的方案,只渲染可视区域内的行,万级数据也能保持流畅。
数据合规层面,前端能做且必须做的事情不少。首先是敏感数据的落盘控制:薪酬、身份证号等字段的日志上报必须脱敏,禁止将原始值写入 console 或前端监控平台。其次是 GDPR 要求的「被遗忘权」与数据可携权,前端应提供数据导出入口,并在用户删除账户后清理所有本地存储:
// 退出登录或账户删除时清理本地痕迹
export function purgeLocalUserData() {
localStorage.clear();
sessionStorage.clear();
// 清理IndexedDB中缓存的文档副本
indexedDB.databases().then(dbs => {
dbs.forEach(db => indexedDB.deleteDatabase(db.name));
});
}
最后是文档预览的合规处理。劳动合同、合规证明等文件建议使用带时效的签名 URL 直接从对象存储加载,前端只做展示不落盘,下载行为记录审计日志。这样既满足不同法域的数据驻留要求,也降低了敏感文件泄露的风险。综合来看,Vue 3 工程化不是单纯的工具链配置,而是一套围绕业务复杂度展开的系统设计,把国际化、权限、性能与合规这四条线在工程层面提前铺好,后续的多国业务扩展才能平稳落地。