7.2 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
RuoYi-Vue-Plus is a multi-tenant management system frontend built with Vue 3, TypeScript, Element Plus, and Vite. This is the official UI for the RuoYi-Vue-Plus backend framework (distributed/microservices architecture).
Tech Stack: Vue 3.5+ | TypeScript 5.9+ | Element Plus 2.11+ | Vite 6+ | Pinia 3+ | Vue Router 4.6+
Development Commands
# Install dependencies (using npm mirror for China)
npm install --registry=https://registry.npmmirror.com
# Start development server (runs on http://localhost:80)
npm run dev
# Build for production
npm run build:prod
# Build for development environment
npm run build:dev
# Lint code
npm run lint:eslint
# Fix linting issues automatically
npm run lint:eslint:fix
# Format code with Prettier
npm run prettier
Engine Requirements: Node.js >= 18.18.0 | npm >= 8.9.0
Architecture
Project Structure
src/
├── api/ # API modules organized by domain (system, monitor, workflow, net, demo)
├── assets/ # Static assets (images, styles, icons)
├── components/ # Reusable components (UI + business components)
├── directive/ # Custom Vue directives (v-auth, v-copy, etc.)
├── enums/ # TypeScript enums and constants
├── hooks/ # Vue 3 Composition API hooks
├── lang/ # i18n language files (Chinese/English)
├── layout/ # Layout components (Sidebar, Navbar, TagsView)
├── plugins/ # Global plugins ($tab, $modal, $cache, $auth)
├── router/ # Vue Router configuration
├── store/ # Pinia state management
├── types/ # TypeScript type definitions
├── utils/ # Utility functions (request, crypto, validation)
├── views/ # Page components (mirrors api structure)
├── App.vue # Root component
├── main.ts # Application entry point
├── permission.ts # Route permission control
└── settings.ts # Global settings
Dynamic Routing & Permissions
The application uses backend-driven routing with permission-based access control:
-
Route Loading Flow (
src/permission.ts):- User authentication check via
getToken() - If authenticated but no user info: fetch user info → generate routes → add routes dynamically
- Routes are fetched from backend via
getRouters()API - Components are lazy-loaded using
import.meta.glob('./../../views/**/*.vue')
- User authentication check via
-
Route Types:
constantRoutes: Always accessible (login, 404, etc.)dynamicRoutes: Permission-based routes added dynamically- Special components:
Layout,ParentView,InnerLink(handled specially insrc/store/modules/permission.ts:76-99)
-
Permission Checking: Uses custom directives and plugins for fine-grained control
State Management (Pinia)
Located in src/store/modules/:
- user.ts: Authentication, user info, logout logic
- permission.ts: Dynamic route generation and management
- app.ts: Application settings (sidebar, language, size) - persisted with
@vueuse/core - settings.ts: Theme and UI preferences
- tagsView.ts: Visited page tabs management
- dict.ts: Dictionary data caching
- notice.ts: Notification state
API Layer
- Base configuration:
src/utils/request.ts- Axios instance with interceptors - Features:
- JWT token management (
Authorization: Bearer <token>) - Request/response encryption support (RSA + AES)
- Duplicate submission prevention (500ms interval)
- Internationalized error messages
- Download progress loading
- JWT token management (
- API modules: Organized by domain in
src/api/mirroring backend structure
Global Plugins
Available in all components via this.$pluginName or composables:
$tab: Tab/page operations (openPage, closePage, refreshPage)$modal: Modal/dialog management (msg, alert, confirm, loading)$cache: Session/local storage wrapper$auth: Permission checking (hasPermi, hasRole, hasPermiOr)
Code Style & Configuration
- Prettier: 150 char line width, single quotes, 2 spaces, no trailing commas
- ESLint: Vue + TypeScript + Prettier integration
- TypeScript: Path alias
@/*→./src/*, strict mode with some relaxations (noImplicitAny: false,strictNullChecks: false) - Import: Auto-import for Vue APIs via
unplugin-auto-import
Environment Variables
Defined in .env.development and .env.production:
VITE_APP_TITLE: Application titleVITE_APP_BASE_API: API base URL (e.g.,/dev-api)VITE_APP_CONTEXT_PATH: Application context pathVITE_APP_CLIENT_ID: OAuth client IDVITE_APP_ENCRYPT: Enable request/response encryptionVITE_APP_RSA_PUBLIC_KEY: Request encryption public keyVITE_APP_RSA_PRIVATE_KEY: Response decryption private keyVITE_APP_WEBSOCKET: WebSocket toggle (defaults to SSE)VITE_APP_SSE: Server-Sent Events toggle
Component Patterns
- Composition API: Use
<script setup lang="ts">syntax - Props: Use
vue-typesfor runtime type validation - Auto-import: Vue APIs (
ref,reactive,computed, etc.) are auto-imported - Component naming: Use
defineOptionswithnameproperty for keep-alive compatibility
Key Features
- Multi-tenancy: Full tenant isolation support
- Workflow Engine: Business process management integration
- Real-time: WebSocket and SSE support for push notifications
- Code Generation: Scaffolding tools for CRUD operations
- File Management: Upload/download with configurable storage
- Monitoring: Cache, logs, server metrics, online users
- i18n: Chinese/English with Element Plus locale integration
- Theme: Light/dark mode with CSS variables
Module Organization
- system: Core system management (users, roles, menus, departments, tenants)
- monitor: System monitoring (logs, cache, online users, server metrics)
- workflow: Workflow process management
- net: Networking/communication features
- demo: Example features and use cases
- tool: Development tools (code generation, form builder)
Backend Integration
This frontend pairs with:
- RuoYi-Vue-Plus: Distributed cluster framework
- RuoYi-Cloud-Plus: Microservices framework
Both available on Gitee/GitHub under dromara organization.
Common Patterns
Adding a New Feature
- Create API module in
src/api/<domain>/ - Create views in
src/views/<domain>/ - Add types in
src/types/if needed - Routes will be loaded dynamically from backend
Permission Checking
// In template
<v-auth="'system:user:add'">Button</v-auth>
// In code
import { useAuth } from '@/hooks/useAuth';
const { hasPermi } = useAuth();
if (hasPermi('system:user:add')) { ... }
API Call Pattern
import { getUserList } from '@/api/system/user';
const { proxy } = getCurrentInstance()!;
const loading = ref(true);
const getList = async () => {
loading.value = true;
try {
const res = await getUserList(queryParams.value);
// Handle response
} finally {
loading.value = false;
}
};