6.5 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
This is the RuoYi-Vue-Plus frontend — a multi-tenant enterprise management system (Vue 3 + TypeScript + Element Plus + Vite). It is the UI for a Java Spring Boot backend and follows a standard admin panel architecture with RBAC, dynamic routing, and multi-tenant support.
Commands
# Development (uses pnpm)
pnpm dev # Start dev server (port from VITE_APP_PORT, default 80)
pnpm build:prod # Production build
pnpm build:dev # Development build
pnpm preview # Preview production build locally
# Code quality
pnpm lint:eslint # Run ESLint
pnpm lint:eslint:fix # Auto-fix ESLint issues
pnpm prettier # Format all files with Prettier
# No test runner configured yet (vitest is installed but no vitest.config.ts exists)
Architecture
Entry & Bootstrap (src/main.ts)
- Creates Vue app → mounts Pinia → Vue Router → vue-i18n → plugins → custom directives → VXE Table
- Loads UnoCSS, Element Plus styles, Highlight.js, SVG icons
- Imports
src/permission.tsfor route guards
Routing (src/router/index.ts)
Two-tier route system:
constantRoutes— always loaded (login, register, 401, 404, index, redirect, profile)dynamicRoutes— initially empty array; populated by frontend-defined routes checked against user permissions
Actual menus come from the backend API (/getRouters). permission.ts store fetches these, converts backend route configs to Vue Router routes via filterAsyncRouter(), and dynamically adds them. Component strings from backend (e.g., "system/user/index") are resolved against import.meta.glob('./../../views/**/*.vue').
Permission Guard (src/permission.ts)
Router beforeEach:
- No token → redirect to
/login(unless whitelisted) - Has token + no roles loaded → fetch user info (
useUserStore().getInfo()) then generate routes (usePermissionStore().generateRoutes()) → dynamically add routes → redirect to target - Has token + roles loaded → allow navigation
State Management (Pinia)
| Store | File | Purpose |
|---|---|---|
user |
src/store/modules/user.ts |
Auth token, user info, roles, permissions |
permission |
src/store/modules/permission.ts |
Dynamic routes generation, sidebar/topbar route trees |
app |
src/store/modules/app.ts |
Sidebar state, device type, language, size |
settings |
src/store/modules/settings.ts |
Layout config (theme, navType, tagsView, etc.) persisted to localStorage |
dict |
src/store/modules/dict.ts |
Dictionary data cache |
tagsView |
src/store/modules/tagsView.ts |
Multi-tab page management |
notice |
src/store/modules/notice.ts |
Notification/announcement state |
HTTP Layer (src/utils/request.ts)
Axios instance with:
- Request interceptor: injects Bearer token +
Content-Languageheader, GET params serialization, duplicate submit detection (500ms window via sessionStorage), optional AES body encryption (ECB mode, key encrypted with RSA public key) - Response interceptor: AES decryption, 401 → re-login prompt, 500 → error message, 601 → warning
download()helper for file downloads with loading state
Encryption is toggleable via VITE_APP_ENCRYPT env var — must match backend config.
Permission System (src/plugins/auth.ts)
hasPermi(permission)— exact permission match (admin*:*:*wildcard supported)hasPermiOr(permissions)— any matchhasPermiAnd(permissions)— all matchhasRole(role)/hasRoleOr(roles)/hasRoleAnd(roles)— role-based equivalents- Used in route filtering and button-level UI control via custom directives
Layout (src/layout/index.vue)
Classic admin layout: Sidebar + Navbar + TagsView + AppMain + Settings drawer. Supports:
NavTypeEnum.LEFT— left sidebarNavTypeEnum.TOP— top navigationNavTypeEnum.MIX— mixed mode- Responsive: mobile detection at 992px breakpoint
API Layer (src/api/)
Organized by backend module:
src/api/login.ts— auth (login, logout, register, tenant list)src/api/menu.ts— menu/routingsrc/api/system/— user, role, menu, dept, post, dict, config, notice, tenant, oss, client, socialsrc/api/monitor/— online users, operlog, loginInfo, cachesrc/api/tool/gen/— code generationsrc/api/workflow/— workflow (category, definition, instance, task, leave)src/api/demo/— demo/demo, demo/tree
Directory Quick Reference
| Directory | Purpose |
|---|---|
src/views/ |
Page components, mirrors src/api/ module structure |
src/components/ |
Shared components (Breadcrumb, DictTag, FileUpload, ImageUpload, Editor, Pagination, etc.) |
src/plugins/ |
Global Vue plugins installed via app.use() — auth, cache, modal, tab, download, svgicon |
src/directive/ |
Custom directives (permission checks, common utilities) |
src/utils/ |
Utilities — request, auth (token storage), crypto (AES+RSA), validate, websocket, sse, ruoyi (helper fns), dict, theme, scroll-to |
src/lang/ |
vue-i18n language packs (zh_CN, en_US) |
src/enums/ |
TypeScript enums (HttpStatus, NavTypeEnum, LanguageEnum, SideThemeEnum, MenuTypeEnum) |
src/types/ |
Global type declarations (env.d.ts, router.d.ts, global.d.ts, etc.) |
vite/plugins/ |
Vite plugin configs — auto-import, auto-components, UnoCSS, SVG icons, compression, setup-extend |
Key Conventions
- Auto-imported:
vue,vue-router,@vueuse/core,pinia(viaunplugin-auto-import) - Auto-registered: Element Plus components +
icon-parkicons (viaunplugin-vue-components) - Path alias:
@/→src/ - Uses UnoCSS with
presetAttributify(attribute-based utilities) andpresetIcons - SCSS variables in
src/assets/styles/variables.module.scss - Backend API prefix:
/dev-api(dev), configurable viaVITE_APP_BASE_API - Token stored in localStorage under key
Admin-Token, managed via@vueuse/core'suseStorage - SSR/SSE:
src/utils/sse.tsfor Server-Sent Events,src/utils/websocket.tsfor WebSocket
Important: Backend-Driven Nature
Many UI aspects are controlled by backend API responses:
- Menus/routes come from backend (not frontend route definitions)
- Dictionaries (
dictstore) provide dynamic dropdown options throughout the app - Tenant info is fetched on auth and drives data isolation
- Always check the backend API contract when modifying UI modules