Skip to content

多平台广告管理系统架构文档:登录 / 权限 / 路由 / 账号 / 平台

目录

  1. 系统总览
  2. 登录系统
  3. 权限系统
  4. 路由系统
  5. 账号系统
  6. 平台系统
  7. 模块间关系图

1. 系统总览

本应用是一个多平台广告管理系统,基于 Vue 2 + Vuex + Vue Router 构建。系统支持 Amazon、Walmart、Criteo、Instacart、CitrusAd 等多个广告平台,采用多租户架构,支持主/子账号体系。

核心技术栈

层级技术
框架Vue 2 (Options API + Composition API 混用)
状态管理Vuex (模块化) + Composition API reactive store (OmniCenter)
路由Vue Router 3 (history mode)
HTTPAxios (带拦截器)
Token 存储localStorage ([app-token])
SSOCookie ([sso_token_key] @ .[company-domain].com)

系统总体架构图


2. 登录系统

2.1 登录流程概览

2.2 登录方式

系统支持以下登录方式:

方式说明文件
账号密码登录用户名 + Base64 编码密码views/login/login.vue
手机验证码登录仅中文用户可用views/login/login.vue
URL Token 免登录URL 带 ?token=xxx 自动登录permission.js + api/login.js
二次验证 (2FA)短信/邮件验证码views/login/login.vue

2.3 Token 管理

Token 存储在 localStorage 中,key 为 [app-token],结构如下:

javascript
// utils/auth.js
{
  xToken: string,      // X-Token,用于请求头
  jwt: string,         // JWT,用于 Authorization Bearer
  chatJwt: string,     // 第三方客服聊天 JWT
  expireTime: number   // 过期时间戳 (Date.now() + expires_in * 1000)
}

关键方法:

  • getTokenInfo() — 从 localStorage 读取 token
  • setTokenInfo(tokenInfo) — 写入 token
  • removeTokenInfo() — 清除 token
  • isTokenValid() — 判断 token 是否过期
  • getXToken() — 获取 X-Token
  • getJwt() — 获取 JWT

2.4 SSO 机制

登录成功后,系统会将 token 和用户信息写入 .[company-domain].com 域的 Cookie,实现跨子域 SSO:

javascript
// utils/sso.js
setSsoCookie(token, expires)       // Cookie: [sso_token_key]
setSsoUserInfo(userInfo, expires)  // Cookie: [sso_user_info_key]

2.5 登录后首页路由决策

2.6 登出流程


3. 权限系统

3.1 权限模型

系统采用基于权限码 (Permission Code) 的扁平权限模型,不使用传统的 RBAC 角色树。

3.2 权限存储

权限码在两个地方存储,互为备份:

  1. Vuex Store (store.state.user.permission) — 运行时主要来源
  2. localStorage (access_action) — 页面刷新后的恢复来源

权限恢复逻辑(在 permission.js 路由守卫中):

javascript
// 无权限时尝试从 localStorage 恢复
let permissions = store.getters.permission || []
if (permissions.length === 0) {
  const localPermissions = localStorage.getItem('access_action')
  if (localPermissions) {
    permissions = JSON.parse(localPermissions)
    store.commit('user/SET_PERMISSION', JSON.parse(localPermissions))
  }
}

3.3 权限检查工具

utils/permission.js 提供两个核心方法:

javascript
// 单个权限码检查
isPermission(permissionCode)  // 返回 boolean

// 多个权限码检查(任一匹配即通过)
hasPermission(codes)          // codes: string | string[],返回 boolean

白名单路径(无需权限):/custom-board/share

3.4 权限检查层级

3.5 路由级权限 (meta.key)

每个路由可通过 meta.key 声明所需权限码:

javascript
// 单个权限码
{ path: '/home', meta: { key: 'Overview' } }

// 多个权限码(任一匹配即可)
{ path: '/home_new', meta: { key: 'HomePageV2' } }

// 数组形式
{ path: '/some-page', meta: { key: ['Permission1', 'Permission2'] } }

3.6 菜单级权限

Navbar 组件中,每个菜单项都有 permission 字段,通过 $hasPermission 过滤:

javascript
// 菜单定义示例
{
  permission: ['Sponsored_Ads_New_View', 'Portfolios_New_View'],
  icon: 'icon-ads-optimization',
  url: '/allCampaigns/index',
  text: 'route.adOptimize.title',
  submenus: [
    { permission: ['Sponsored_Ads_New_View'], url: '/allCampaigns/index', text: 'route.allCampaigns' },
    { permission: 'Portfolios_New_View', url: '/portfolio_new/index', text: 'route.allPortfolios' }
  ]
}

3.7 关键权限码一览

权限码用途
HomePageV2新版首页访问
Overview旧版首页访问
Authorize / Authorize_Amazon / Authorize_Walmart授权管理页面
Sponsored_Ads_New_View搜索广告查看
AutomationView自动化规则
WalmartAdManager_ViewWalmart 广告管理
GoogleAdsGoogle 广告
AmazonDSPAmazon DSP
AMC_ModelGalleryAMC 模型库
CNPLGExplore中国 PLG 探索版
[chat_service]第三方客服
data_sync数据同步

4. 路由系统

4.1 路由架构

4.2 路由白名单

以下路径不需要认证即可访问:

javascript
const whiteList = [
  '', '/', '/login', '/auth-redirect', '/register',
  '/cn/register', '/register-finish', '/forgetPassword',
  '/website', '/website-consult', '/custom-board/share'
]

4.3 路由守卫流程 (beforeEach)

4.4 路由守卫流程 (afterEach)

afterEach 负责以下工作:

  1. GA 埋点gtag('event', 'page_view', ...)
  2. 进度条结束NProgress.done()
  3. 面包屑更新store.commit('router/SET_BREADCRUMBS', ...)
  4. DSP 页面检测store.commit('global/detectDspPage', to)
  5. 平台自动切换 — 根据 URL 路径前缀自动切换当前平台
  6. 公告消息 — 特定路由显示下线/升级提示
  7. URL token 清理 — 移除 URL 中的 token 参数

4.5 平台路由自动检测

跨平台页面列表:

javascript
const crossPlatformPages = ['/profileHome', '/subAccount', '/settings/index']

4.6 路由结构

平台路由前缀注册方式路由文件
Amazon/ (根路径)静态注册router/modules/*.js
Walmart/walmart静态注册router/walmart/index.js
Criteo/criteo静态注册router/criteo/index.js
Instacart/instacart动态注册 (router.addRoute)omni/instacart/route/index.js
CitrusAd/citrusAd动态注册 (router.addRoute)omni/citrusAd/route/index.js

4.7 Layout 结构

所有需要认证的页面都使用 Layout (layout/main/index.vue) 作为父组件:


5. 账号系统

5.1 账号层级模型

5.2 用户属性

用户信息存储在 Vuex store.state.user 中:

字段类型说明
idnumber用户 ID
uidstring用户唯一标识
namestring用户名
emailstring邮箱
isAdminnumber是否管理员 (0/1)
isMainnumber是否主账号 (0/1)
mainUserIdnumber对应主账号 ID
userTypestring用户类型
businessTypestring业务类型 (1=国内, 2=海外)
businessVersionstring版本 ([version_tier_1]/[version_tier_2]/[version_tier_3]/[version_tier_4]/[version_tier_5])
sourceChannelstring来源渠道 (4=[partner_name])
rolesarray角色 ID 列表 (mainRoleIds)
permissionarray权限码列表
isAsinSkipboolean是否走 ASIN 分权限逻辑
asinAuthModenumberASIN 分权限模式 (-1主账号, 0宽松, 1不隔离, 2严格)
isGroupLeadernumber是否组长
isAgencystring是否代理商

5.3 多租户 (Multi-Tenant) 机制

租户 ID 在不同平台有独立存储:

平台Vuex 字段URL 参数缓存方式
Amazonglobal.tenantIdtenantIdsessionStorage
Walmartglobal.walmartTenantIdwalmartTenantIdlocalStorage
Criteoglobal.criteoTenantIdcriteoTenantIdsessionStorage
Omni (Instacart/CitrusAd)OmniCenter.curTenantIdtenantIdsessionStorage

5.4 子账号管理

子账号管理页面 (/subAccount) 的功能:

  • 主账号视角:可查看/创建/编辑/删除子账号,分配资源权限
  • 组长视角:可管理组内子账号
  • 子账号视角:只能查看自己的资源权限

相关 API:

API方法说明
/v1/usersGET获取账号列表
/v1/usersPOST创建子账号
/v1/users/:idPUT更新子账号
/v1/users/:idDELETE删除子账号
/v3/resource/assign-allPOST分配资源权限

5.5 ASIN 分权限

系统支持基于 ASIN 的细粒度权限控制:

ASIN 分权限标志通过 HTTP 请求头 isAsinSkip 传递给后端。


6. 平台系统

6.1 平台架构总览

6.2 平台状态管理对比

特性遗留平台 (Amazon/Walmart/Criteo)OmniCenter 平台 (Instacart/CitrusAd)
状态管理Vuex modulesComposition API reactive
路由注册静态 (router/index.js)动态 (router.addRoute)
初始化global.initPlatform dispatchOmniCenter.switchPlatform()
租户管理各平台独立字段统一 curTenantId
店铺管理各平台独立 store统一 curProfileIds
菜单定义Navbar.vue 内联platformConfig.menus 函数
Header各平台独立组件platformConfig.renderHeader

6.3 OmniCenter 架构

OmniCenter 是新一代平台管理框架,使用 Composition API 构建:

6.4 平台配置 (platformConfig)

每个 OmniCenter 平台需要提供一个配置对象:

javascript
// omni/instacart/platformConfig.js 示例
export default {
  id: 'instacart',              // 平台 ID,也是路由前缀
  name: 'Instacart',            // 显示名称
  icon: svgIcon,                // 图标
  permission: undefined,        // 访问权限码 (undefined = 无限制)
  menus: getInstacartMenus,     // 菜单生成函数
  profiles: {
    list: getInstacartStore,    // 获取店铺列表 API
    getById: getInstacartStoreById  // 根据 ID 获取店铺 API
  },
  renderHeader: h => h(InstacartHeader),  // Header 渲染函数
  supportLanguages: ['en'],     // 支持的语言
  supportCurrencies: ['USD'],   // 支持的货币
  install() {                   // 安装钩子
    router.addRoute(instacartRoute)  // 动态注册路由
    eventBus.$on('loginSuccess', () => {
      checkInstacartAuth()      // 登录后检查授权
    })
  }
}

6.5 平台切换流程

6.6 HTTP 请求拦截器中的平台处理

utils/request.js 的请求拦截器会根据当前平台自动设置请求头:

6.7 各平台 Vuex Store 模块


7. 模块间关系图

7.1 五大模块完整交互图

7.2 用户完整生命周期

7.3 数据流向图


8. 关键文件索引

模块文件职责
登录views/login/login.vue登录页面 UI 和逻辑
登录api/login.js登录/免登录 API
登录api/user.js用户注册/登出/密码/验证码 API
登录utils/auth.jsToken 读写和校验
登录utils/sso.jsSSO Cookie 管理
权限utils/permission.js权限检查工具函数
权限store/modules/user.js用户状态和权限存储
路由router/index.js路由配置和注册
路由permission.js路由守卫 (beforeEach/afterEach)
路由router/modules/*.jsAmazon 各模块路由
路由router/walmart/index.jsWalmart 路由
路由router/criteo/index.jsCriteo 路由
账号api/account.js账号 CRUD API
账号views/subAccount/index.vue子账号管理页面
账号views/profile/index.vue授权管理页面 (店铺绑定)
账号api/profile.js店铺/授权 API
平台store/modules/global.js全局状态 (平台/租户/店铺/时间)
平台omniCenter/store.jsOmniCenter 状态管理
平台omniCenter/index.jsOmniCenter 入口和平台匹配
平台omniCenter/utils.jsURL 参数同步工具
平台omni/instacart/platformConfig.jsInstacart 平台配置
平台omni/citrusAd/platformConfig.jsCitrusAd 平台配置
平台layout/main/index.vue主布局 (初始化入口)
平台layout/main/components/Navbar.vue导航菜单
平台utils/request.jsHTTP 请求拦截器
平台store/getters/index.jsVuex 全局 getters