# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview 福安德综合办公系统 (FAD OA) — 基于 RuoYi-Flowable-Plus 二次开发,面向工程项目的投标管理、进度控制、成本核算及日常 OA 办公。 **Tech Stack**: Spring Boot 2.7 + MyBatis-Plus 3.5 + Flowable 6.8 + Vue 2 + Element UI + MySQL 8.0 + Redis ## Build & Run ```bash # Backend build (dev profile, skip tests) mvn clean package -D maven.test.skip=true -P dev # Backend build (prod) mvn clean package -D maven.test.skip=true -P prod # Frontend dev server (port 80) cd ruoyi-ui && npm run dev # Frontend lint cd ruoyi-ui && npm run lint # Frontend prod build cd ruoyi-ui && npm run build:prod ``` Active Maven profile defaults to `dev` (`pom.xml` line 72). Backend entry point: `ruoyi-admin/`. ## Database Init script: `script/sql/mysql/ry-vue-flowable-xg.sql`. Module-specific migrations live in `sql/` (e.g. `oa_approval.sql`, `warehouse_*.sql`, `hrm_*.sql`). Dev DB: `fad_oa_dev` @ 49.232.154.205:13306 Prod DB: `fad_oa` @ 49.232.154.205:13306 Redis: 49.232.154.205:6379 (password: WANGyu11!) **Menu SQL pattern**: When adding menus to `sys_menu`, use fixed snowflake IDs (not RAND()). Reference `sql/warehouse_phase0_menu.sql` for the correct pattern. Menu changes require COMMIT + restart backend to flush Redis cache — clearing Redis is not enough on its own. ## Module Architecture | Module | Purpose | |--------|---------| | `ruoyi-admin/` | Spring Boot entry point, YAML configs | | `ruoyi-framework/` | Security (Sa-Token), interceptors, global config | | `ruoyi-system/` | Users, roles, menus, depts, dicts, posts | | `ruoyi-flowable/` | Flowable workflow engine integration | | `ruoyi-oa/` | Core OA: projects, contracts, bidding, finance, warehouse, approval | | `ruoyi-ui/` | Vue 2 frontend (Element UI) | | `fad-hrm/` | HRM: employees, attendance, leave, travel, seal, payroll, flow tasks | | `fad-app/` | Mobile app API endpoints | | `fad-export/` | Foreign trade public web pages | | `fad-rolling-mill/` | Rolling mill business module | | `klp-wms/` | Warehouse management module | ## Dynamic Menu System (Critical) Menus are **not hardcoded in Vue Router**. They are stored in `sys_menu` DB table and delivered by `GET /getRouters`. The frontend flow: 1. `ruoyi-ui/src/store/modules/permission.js` → `GenerateRoutes` action 2. Calls `getRouters()` → `@/api/menu.js` → `GET /getRouters` 3. Backend returns JSON with `component` paths (e.g. `"hrm/employee/index"`) 4. `filterAsyncRouter()` resolves strings to actual Vue components via dynamic `import()` 5. Routes are added at runtime via `router.addRoutes()` **Implication**: Adding a new page requires both a `sys_menu` INSERT (with correct `component` path) AND the actual `.vue` file at `ruoyi-ui/src/views/`. No changes to `router/index.js` are needed for C-type page menus — only hidden/detail routes go there. F-type menus (buttons) use `perms` field for permission checks (e.g. `system:user:add`). M-type menus are directory containers with no component. ## HRM Module Structure The HRM module (`fad-hrm/` backend, `ruoyi-ui/src/views/hrm/` frontend) is a self-contained HR system built on a custom flow engine (NOT Flowable — uses its own `hrm_flow_*` tables). **Two separate approval systems exist**: - **HRM flow engine**: `hrm_flow_task`, `hrm_flow_instance` etc. — handles leave/travel/seal/reimburse/appropriation workflows. Pages: `hrm/requests/` - **OA approval center**: `oa_approval_instance` table — lightweight generic approval for purchase/contract. Pages: `oa/approval/` Both have items named "我的审批" in the menu. They serve different data sources and must NOT be conflated. ## Key Auth Patterns - Uses **Sa-Token** (not Spring Security), configured in `application.yml` - `@SaCheckPermission` for API-level permission checks - Frontend permission checks: `v-hasPermi` directive and `auth.hasPermiOr()` in `@/plugins/auth` - Menu visibility is controlled by `sys_role_menu` table — role-to-menu many-to-many ## API Response Conventions The backend uses two response wrappers: - `TableDataInfo`: `{ total, rows, code, msg }` — paginated lists → frontend accesses `res.rows` - `R`: `{ data, code, msg }` — single entities → frontend accesses `res.data` Frontend API modules are in `ruoyi-ui/src/api/`. The axios interceptor in `@/utils/request` unwraps the HTTP response, so `.then(res => ...)` receives the JSON body directly (not the full axios response).