11 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
antdv-next-admin is a modern Vue 3 + TypeScript admin scaffold built on:
- antdv-next (Ant Design Vue) - UI component library
- Pinia - State management
- Vue Router - Routing with dynamic route generation
- vue-i18n - Internationalization (Chinese/English)
- Vite - Build tool
- Full RBAC permission system with dynamic routes
- Mock data system for development
Environment Requirements
- Node.js >= 16
- npm >= 8
Common Commands
# Development
npm run dev # Start dev server on http://localhost:3000
# Building
npm run build # Production build
npm run build:check # Type check before build
npm run preview # Preview production build
# Type Checking
npm run type-check # TypeScript type checking
Note: This project currently has no test or lint scripts configured.
Architecture
State Management (Pinia Stores)
All stores use the setup syntax pattern. Located in src/stores/:
- auth - Authentication, user info, roles, permissions. Includes demo mode for development.
- permission - Dynamic route generation based on user roles/permissions
- theme - Theme mode (light/dark/auto), primary color (6 presets), CSS variable management
- layout - Layout mode (vertical/horizontal), sidebar state, mobile detection
- tabs - Multi-tab system with KeepAlive caching, affix tabs, right-click menu
- settings - User preferences (animations, gray mode, menu theme, etc.)
- notification - Notification panel state
Key Pattern: Store initialization happens in router guards. Auth store includes both demo mode (mock) and production mode (real API) login flows.
Routing System
Routes are organized in three categories (src/router/routes.ts):
- staticRoutes - No auth required (login, error pages)
- basicRoutes - Require auth (dashboard, profile)
- asyncRoutes - Require specific permissions (system management, etc.)
Dynamic Route Generation:
- Routes are generated in
src/router/guards.tsduring navigation - Permission store (
generateRoutes) filters async routes based on user roles/permissions - Routes are added dynamically with
router.addRoute()after successful login - First navigation to dynamic route may redirect to 404, then recover by regenerating routes
Route Meta Fields:
{
title: string // i18n key for page title
icon?: string // Icon component name (e.g., 'DashboardOutlined')
requiresAuth?: boolean // Default true
requiredPermissions?: string[] // Permission codes required
requiredRoles?: string[] // Role codes required
hidden?: boolean // Hide from menu
affix?: boolean // Pin tab (can't be closed)
order?: number // Menu sort order
}
Permission System
Three ways to check permissions:
-
Directive (
src/directives/permission.ts):<a-button v-permission="'user.create'">Create</a-button> <a-button v-permission="['user.edit', 'user.delete']">Actions</a-button> <a-button v-permission.all="['user.edit', 'user.approve']">Approve</a-button> -
Composable (
src/composables/usePermission.ts):const { can, canAll } = usePermission() if (can('user.create')) { /* ... */ } if (canAll(['user.edit', 'user.approve'])) { /* ... */ } -
Component (
src/components/Permission/PermissionButton.vue):<PermissionButton permission="user.create"> <a-button>Create User</a-button> </PermissionButton>
API & Request Handling
Base Service: src/utils/request.ts - Axios instance with interceptors
- Auto-adds Bearer token from auth store
- Handles 401 (logout + redirect to login), 403 (forbidden), 404, 500
- Response interceptor checks
res.codefield (expects 200) - All API calls use the
requesthelper with typed responses
Mock System (mock/ directory):
- Enabled via
VITE_USE_MOCK=truein.env.development - Two-layer structure:
data/(mock data sources) +handlers/(request handlers) - Available mock APIs: auth, users, roles, permissions, dashboard
- Supports pagination, search, CRUD operations
Pro Components
ProTable (src/components/Pro/ProTable/):
- Configuration-based table with search form, toolbar, pagination
- Column types defined via
ProTableColumninterface (seesrc/types/pro.ts) - Supports value types: text, date, dateTime, tag, badge, money, percent, avatar, etc.
- Search types: input, select, dateRange, datePicker, etc.
- Built-in features: column resizing, fixed headers, sorting, actions column
- Important: Uses CSS variables for scrollbar width alignment (see scrollbar.ts utility)
- Two rendering modes:
scroll-mode: Table handles its own scrollingfill-mode: Parent container scrolls, table fills height withfixedHeader
ProForm (src/components/Pro/ProForm/):
- Configuration-based form with validation
- Form item types: input, password, textarea, number, select, radio, checkbox, switch, datePicker, etc.
- Grid layout support with
colSpanand responsivecols - Dynamic options via
requestfunction - Custom rendering via
renderprop
Type Definitions: Always reference src/types/pro.ts for column/form configurations.
Icons
Two icon systems are available:
-
Ant Design Icons (
@antdv-next/icons):import { UserOutlined } from '@antdv-next/icons' -
Iconify (
@iconify/vue):- Component:
src/components/Icon/index.vue - Picker:
src/components/IconPicker/index.vue - Supports online/offline modes with local icon sets (ion, mdi, ri)
- Use
<Icon icon="mdi:home" />syntax
- Component:
Theme System
Themes use CSS variables defined in src/assets/styles/variables.css:
- 6 preset primary colors: blue (default), green, purple, red, orange, cyan
- Dark/light/auto modes
- CSS variables follow pattern:
--ant-primary-color,--bg-color,--text-color, etc. - Theme store dynamically updates CSS variables on document root
- Sidebar supports independent dark/light theme (via
--sidebar-bg-colorvariables)
Internationalization
System: vue-i18n with locale files in src/locales/
zh-CN.ts- Chinese (default)en-US.ts- English- Access via
$t('key')in templates ort('key')fromuseI18n() - Helper:
src/utils/i18n.ts-resolveLocaleText()for dynamic text resolution
Charts & Visualization
ECharts Integration: The project includes echarts and vue-echarts for data visualization in the dashboard. Use the <v-chart> component from vue-echarts for rendering charts.
Keyboard Shortcuts
Ctrl/Cmd + K- Open global menu search
Development Guidelines
File Naming & Structure
- Components: PascalCase (e.g.,
AdminLayout.vue) - Files: kebab-case (e.g.,
use-permission.ts) - Path alias: Use
@/forsrc/(configured in vite.config.ts and tsconfig.json)
TypeScript
- Strict mode enabled - All code must be type-safe
- Types organized in
src/types/: api.ts, auth.ts, router.ts, layout.ts, pro.ts - Use
typefor object shapes,interfacefor extensible contracts - Route type:
AppRouteRecordRaw(extends Vue Router'sRouteRecordRaw) - API responses:
ApiResponse<T>pattern
Adding New Pages
- Create view in
src/views/[module]/ - Add route to appropriate category in
src/router/routes.ts - Add i18n keys to
src/locales/zh-CN.tsanden-US.ts - If requires permissions, set
meta.requiredPermissionsormeta.requiredRoles - Router guards will handle dynamic route injection
Adding New Stores
Follow the setup syntax pattern:
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useMyStore = defineStore('my-store', () => {
// State
const data = ref<MyType | null>(null)
// Getters
const processedData = computed(() => /* ... */)
// Actions
const fetchData = async () => { /* ... */ }
return { data, processedData, fetchData }
})
Export from src/stores/index.ts for centralized access.
Working with ProTable
Always define columns using the ProTableColumn type:
import type { ProTableColumn } from '@/types/pro'
const columns: ProTableColumn[] = [
{
title: 'Name',
dataIndex: 'name',
search: true, // Enable search
searchType: 'input', // Search field type
valueType: 'text' // Display type
},
{
title: 'Status',
dataIndex: 'status',
valueType: 'tag',
valueEnum: {
active: { text: 'Active', status: 'success' },
inactive: { text: 'Inactive', status: 'default' }
}
}
]
Known Issue: ProTable had scrollbar alignment bugs that were fixed by:
- Using CSS variables for dynamic scrollbar width (
--actual-scrollbar-width) - Scrollbar detection utility in
src/utils/scrollbar.ts - When modifying table layout, verify scrollbar placeholder alignment
Authentication Flow
Demo Mode (development):
- Credentials:
admin/123456oruser/123456 - No real backend, uses mock data from auth store
- Token stored in localStorage
Production Mode:
- Set
VITE_USE_MOCK=falseandVITE_API_BASE_URLin.env.production - Uses real API calls via
src/api/auth.ts
Mock Data Development
To add new mock endpoints:
- Create data source in
mock/data/[entity].data.ts - Create handler in
mock/handlers/[entity].mock.ts - Mock server auto-reloads, accessible at
/api/*prefix
Common Patterns
Conditional Rendering by Permission
import { useAuthStore } from '@/stores/auth'
const authStore = useAuthStore()
if (authStore.hasAnyPermission(['user.edit', 'user.delete'])) {
// Show actions
}
Accessing Current Route in Components
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.meta.title)
Multi-Tab Operations
import { useTabsStore } from '@/stores/tabs'
const tabsStore = useTabsStore()
tabsStore.closeTab(path) // Close specific tab
tabsStore.closeOtherTabs(path) // Close all except this
tabsStore.closeAllTabs() // Close all closeable tabs
tabsStore.refreshTab(path) // Refresh tab content
Theme Changes
import { useThemeStore } from '@/stores/theme'
const themeStore = useThemeStore()
themeStore.setThemeMode('dark') // 'light' | 'dark' | 'auto'
themeStore.setPrimaryColor('#1890ff') // Any valid color
Important Notes
- Never commit environment-specific values to
.envfiles - Router guards handle most auth/permission logic - avoid duplicating checks
- CSS variables are the preferred method for theming - avoid hardcoded colors
- ProTable fixedHeader mode requires parent container with fixed height
- Dynamic routes are regenerated on each login - changes to
asyncRoutesrequire re-login - Tabs state persists in localStorage via settings store
- Mock mode is determined by
VITE_USE_MOCKenv variable, checked at runtime
Default Accounts
Development mode credentials:
- Admin:
admin / 123456 - User:
user / 123456