Skip to content

Frontend Development

The frontend project is located under src/web/. It is a Vue 3 + Vite single-page application that provides model management, scenario configuration, pipeline orchestration, live preview, alarm views, and system settings.

Project Structure

src/web/
├── package.json              # Dependencies and scripts
├── vite.config.js            # Build config, aliases, proxy
├── scripts/                  # i18n validation & sync scripts
└── src/
    ├── main.js               # App entry point
    ├── App.vue               # Root component
    ├── api/                  # API modules
    │   └── index.js          # Merges all modules → global $API
    ├── assets/               # Images, icons, audio
    ├── components/           # Shared components
    ├── i18n/                 # vue-i18n setup, locales, short-scopes
    ├── micro/
    │   └── state.js          # Minimal global state
    ├── router/
    │   └── index.js          # Hash-based router
    ├── styles/
    │   └── global.scss       # Global SCSS
    ├── utils/                # Axios wrapper, message, image preview, i18n loader, WebRTC player
    └── views/                # Page components
        ├── main/             # MainLayout (sidebar + header + menu)
        ├── home/             # Dashboard
        ├── box/              # Edge-device views (cameras, events, libraries, system, data-docking)
        └── gam/              # AI-management views (tasks, models, orchestration, image analysis)

Technology Stack

CategoryLibraryVersionPurpose
FrameworkVue 3^3.5.35Composition API + <script setup>
BuildVite6.3.5Dev server, HMR, chunked production builds
RouterVue Router^4.2.0Hash-based client-side routing
UIElement Plus2.13.2Component library (pinned)
HTTPAxios^1.7.0API client with interceptors
ChartsECharts^6.0.0Dashboard and statistics charts
Flow Editor@vue-flow/core^1.48.2Pipeline orchestration editor
@vue-flow/background^1.3.2Flow editor background grid
@vue-flow/controls^1.1.3Flow editor zoom controls
@vue-flow/minimap^1.5.4Flow editor minimap
Tree Transfertree-transfer-vue3^1.2.2Tree-shuttle component for algorithm selection
i18nVue I18n^9.14.5Internationalization
Videoflv.js^1.6.2FLV stream playback
WebRTCnative RTCPeerConnectionWHEP-based playback
Layoutdagre^0.8.5Graph layout for flow diagrams
Utilitieslodash, moment, uuid, js-md5, mittVarious utilities

Getting Started

Environment Variables

Create a .env or .env.development file under src/web/:

VariablePurpose
VITE_APP_BASE_URLApp base path (default /)
VITE_APP_API_URLBackend API target for dev proxy

Dev Server

bash
cd src/web
npm install
npm run dev

The dev server starts on http://localhost:3000. All /gtw, /event, /weblogo, and /web requests are proxied to VITE_APP_API_URL.

Production Build

bash
cd src/web
npm run build

prebuild automatically runs npm run i18n:check before the build. If i18n checks fail, the build is blocked.

Available Scripts

ScriptPurpose
npm run devStart Vite dev server
npm run buildProduction build (via prebuild → i18n check)
npm run previewPreview the production build locally
npm run i18n:checkRun all 5 i18n validation scripts
npm run resource-i18n:checkCheck resource i18n sync status
npm run resource-i18n:syncSync resource i18n keys from the aiboxResource source (review diff before committing)

The i18n validators cover: short-scope correctness, locale key consistency, glossary synchronization, dialog action button labels, and unused-key detection.

Adding a New Page

Step 1: Create the View Component

Create a new .vue file under src/web/src/views/ in the appropriate subdirectory (box/ for device-related views, gam/ for AI-management views).

Step 2: Register a Route

Add a route entry in src/web/src/router/index.js:

js
{
  path: '/myModule/myPage',
  name: 'MyPage',
  component: () => import('@/views/myModule/myPage/index.vue')
}

Pages that need the sidebar + header layout should use the MainLayout parent route. Standalone pages (e.g. login, big-screen) do not require the layout wrapper.

Routes that require login are guarded by the global navigation guard, which checks localStorage.getItem('token').

Step 3: Add a Menu Entry

Edit src/web/src/views/main/menu.js, choose the matching section ("core", "display", "task", "resource", "system"), and add an entry:

js
{
  index: '/myModule/myPage',
  titleKey: 'nav.myPage',
  icon: 'el-icon-xxx',
  section: 'task'
}

Step 4: Add Translations

Add the new i18n keys to both of these files:

  • src/web/src/i18n/locales/zh-CN.js
  • src/web/src/i18n/locales/en-US.js

Menu labels go under nav; create a new top-level key for page-specific strings per module.

API Layer

Pattern

API modules live under src/web/src/api/. Each module default-exports an object of request functions. api/index.js flattens those objects with object spread, and main.js injects the result as global $API.

Usage in components: this.$API.dologin(params) or proxy.$API.dologin(params) (Composition API).

Existing Modules

ModuleFileDomain
Authlogin.jsLogin/logout, captcha, password reset, user info
Devicebox.jsCameras, events, system settings, audio, linkage
AI Managementgam.jsAlgorithms, tasks, models, orchestration, image analysis
Algorithm AdmincountManage.jsAlgorithm CRUD, licenses, hardware info
Base LibrariesbasePic.jsFace library, body library, item library, file imports
Live Streamscreen.jsCamera list, live stream lifecycle, WebSocket
Onboardingonboarding.jsGuide status, completion, and reset

Adding a New Endpoint

Add a function to the relevant module object. When creating a module file, spread its default export into api/index.js:

js
// api/myModule.js
import { request } from '@/utils/request'

export default {
  queryMyData: data => request({
    url: '/gtw/cwai/MyModule/Query',
    method: 'post',
    data
  })
}

// api/index.js
import myModule from './myModule'

export default {
  ...login,
  ...box,
  ...screen,
  ...basePic,
  ...gam,
  ...countManage,
  ...onboarding,
  ...myModule
}

After flattening, components call proxy.$API.queryMyData(data). The current API layer does not use a proxy.$API.myModule.queryMyData(data) namespace.

All API calls share the Axios instance in utils/request.js, which automatically attaches the mtk, token, fileMode, and lang request headers and handles the auth-failure redirect.

Internationalization (i18n)

Setup

  • Default locale: zh-CN
  • Fallback locale: en-US
  • Locale preference is persisted in localStorage under the cosmo.locale key

Translations are managed across three tiers:

TierSourcePurpose
Static locale filesi18n/locales/{zh-CN,en-US}.jsAll built-in UI strings, navigation, validation, status, etc.
Short-form glossaryi18n/glossary.jsCompact labels for constrained layouts
Dynamic resource i18npublic/resource-i18n/resource.{locale}.jsonBackend config items such as algorithm names, parameters, options

Translation API

  • $t('key.path') — Always returns the full translation in the current locale.
  • $tShort('key.path', scope) — Returns the short form only when the glossary permits it for the given scope; otherwise falls back to the full translation.

Short Scopes

Nine UI context scopes control where compact labels are allowed:

Scope IDTypical Component
btn.compactCompact buttons (≤100px)
table.headerTable column headers
sidebar.menuSidebar menu (~180px wide)
flow.nodePipeline orchestration node labels
dashboard.cardDashboard KPI card titles
tag.badgeStatus badges
inline.actionTable row-level action links
tab.compactCompact tab titles
placeholderInput placeholder text

Build Configuration

Vite Config (vite.config.js)

  • Alias: @src/
  • Dev proxy: /gtw, /event, /weblogo, /webVITE_APP_API_URL
  • CSS: SCSS compiled via sass-embedded using the modern-compiler API
  • Build chunks (manual split):
    • vendor-vue — Vue + Router + I18n
    • vendor-element — Element Plus
    • vendor-echarts — ECharts
    • vendor-vue-flow — @vue-flow/*
    • vendor-graph — @antv/x6, @antv/layout (dependencies currently not installed, reserved)
    • vendor-lodash — lodash, dagre
    • vendor-moment — moment
    • vendor-md — highlight.js, markdown-it (dependencies currently not installed, reserved)
    • vendor — remaining dependencies

Environment Variables

The app reads VITE_APP_BASE_URL at build time and uses VITE_APP_API_URL for the dev proxy. .env files are not tracked in the repository; create one locally as needed.

State Management

No Pinia or Vuex stores are used. State is managed through:

  • localStorage: Auth token (mtk), account info, locale preference, run mode.
  • micro/state.js: A minimal global reactive object that manages loading and login state, consumed by the Axios interceptor to control the loading overlay.
  • Component-local state: Most UI state is managed inside each view component via reactive() / ref().

Key Utilities

FilePurpose
utils/request.jsAxios instance; auto-attaches mtk/token/lang headers, handles auth-failure redirects; long-running requests such as uploads and upgrades do not show the loading overlay
utils/message.jsSingleton-deduped ElMessage wrapper
utils/imagePreview.jsFull-screen image preview
utils/resourceLocaleLoader.jsFetches dynamic i18n JSON from the server at app start and merges it into vue-i18n
utils/i18nResource.jsResolves the *I18nKey fields in backend algorithm/parameter config
utils/whepPlayer.jsWHEP WebRTC player based on the native RTCPeerConnection

Released under the Apache 2.0 License.