457 lines
16 KiB
Markdown
457 lines
16 KiB
Markdown
# CLAUDE.md
|
||
|
||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
||
## Project Overview
|
||
|
||
XL Prison Management System (XL监狱综合管理平台) - A prison management platform built on the Yudao (芋道) project framework. Currently in active development phase integrating 8 prison-related modules.
|
||
|
||
## Tech Stack
|
||
|
||
**Backend**: Java 17, Spring Boot 3.5.9, MyBatis-Plus, Maven multi-module, Spring Security, Swagger/OpenAPI 3
|
||
**Frontend**: Vue 3.5.12, Vite 5.1.4, TypeScript 5.3.3, Element Plus, Pinia, Vue Router, Axios
|
||
**Database**: MySQL 8.0+, Redis
|
||
**Build Tools**: Maven 3.9+, pnpm 8.6+
|
||
|
||
## Commands
|
||
|
||
### Backend (Java/Maven)
|
||
```bash
|
||
# Build all modules (from backend directory)
|
||
cd backend && mvn clean install -DskipTests
|
||
|
||
# Build specific prison module
|
||
cd backend/yudao-module-prison && mvn clean package
|
||
|
||
# Run development server (from backend directory)
|
||
cd backend/yudao-server && mvn spring-boot:run
|
||
|
||
# Run tests for prison module
|
||
cd backend/yudao-module-prison && mvn test
|
||
|
||
# Run single test class
|
||
mvn test -Dtest=GenderEnumTest
|
||
```
|
||
|
||
### Frontend (Vue/Vite)
|
||
```bash
|
||
cd frontend
|
||
|
||
# Install dependencies
|
||
pnpm install
|
||
|
||
# Dev server (local mode - uses .env.local)
|
||
pnpm dev
|
||
|
||
# Dev server (development mode - uses .env.dev)
|
||
pnpm dev-server
|
||
|
||
# TypeScript type checking
|
||
pnpm ts:check
|
||
|
||
# Build for different environments
|
||
pnpm build:local # Local build (uses .env.local)
|
||
pnpm build:dev # Development build (uses .env.dev)
|
||
pnpm build:test # Testing build (uses .env.test)
|
||
pnpm build:prod # Production build (uses .env.prod)
|
||
|
||
# Linting and formatting
|
||
pnpm lint:eslint # ESLint check and fix
|
||
pnpm lint:format # Prettier format
|
||
pnpm lint:style # Stylelint check and fix
|
||
```
|
||
|
||
## Architecture
|
||
|
||
### Backend Structure
|
||
```
|
||
backend/
|
||
├── yudao-server/ # Main application entry (Spring Boot)
|
||
├── yudao-framework/ # Core framework modules
|
||
│ ├── yudao-spring-boot-starter-web
|
||
│ ├── yudao-spring-boot-starter-security
|
||
│ ├── yudao-spring-boot-starter-mybatis
|
||
│ ├── yudao-spring-boot-starter-redis
|
||
│ └── ...
|
||
├── yudao-module-system/ # User/permission system module
|
||
├── yudao-module-infra/ # Infrastructure (code generation, config)
|
||
├── yudao-module-prison/ # Prison management module (active development)
|
||
└── yudao-module-temp/ # Temporary/template module
|
||
```
|
||
|
||
**Prison Module Structure** (`yudao-module-prison/`):
|
||
```
|
||
src/main/java/cn/iocoder/yudao/module/prison/
|
||
├── controller/admin/{module}/ # REST API controllers
|
||
│ ├── {Module}Controller.java # CRUD endpoints
|
||
│ └── vo/ # Request/Response VO objects
|
||
│ ├── {Module}SaveReqVO.java # Create/Update request
|
||
│ ├── {Module}PageReqVO.java # Page query request
|
||
│ ├── {Module}RespVO.java # Response object
|
||
│ └── ...
|
||
├── service/{module}/ # Service layer
|
||
│ ├── {Module}Service.java # Service interface
|
||
│ └── impl/
|
||
│ └── {Module}ServiceImpl.java # Service implementation
|
||
├── dal/ # Data access layer
|
||
│ ├── dataobject/{module}/ # MyBatis-Plus DO objects
|
||
│ │ └── {Module}DO.java
|
||
│ ├── mysql/{module}/ # MyBatis mappers
|
||
│ │ └── {Module}Mapper.java
|
||
│ └── dal/ # Data access helpers
|
||
├── convert/{module}/ # MapStruct converters
|
||
│ └── {Module}Convert.java
|
||
├── enums/ # Enum definitions
|
||
│ └── {Module}Enum.java
|
||
└── util/ # Utility classes
|
||
```
|
||
|
||
**Database Schema Convention**:
|
||
- Table prefix: `prison_{module}`
|
||
- Common fields: `id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`
|
||
- Soft delete: `deleted` bit(1) field
|
||
- Tenant support: `tenant_id` bigint field
|
||
|
||
### Frontend Structure
|
||
```
|
||
frontend/src/
|
||
├── views/prison/{module}/ # Page components
|
||
│ ├── index.vue # List page with table/search
|
||
│ └── {Module}Form.vue # Create/Edit form dialog
|
||
├── api/prison/{module}/ # API definitions
|
||
│ └── index.ts # Axios API calls + TypeScript types
|
||
├── components/ # Shared components
|
||
├── store/ # Pinia stores (state management)
|
||
├── router/ # Vue Router config
|
||
├── hooks/ # Composable hooks
|
||
├── types/ # TypeScript type definitions
|
||
├── utils/ # Utility functions
|
||
└── config/ # Configuration files
|
||
```
|
||
|
||
**Frontend API Pattern** (`api/prison/{module}/index.ts`):
|
||
```typescript
|
||
// Interface definitions
|
||
export interface Area {
|
||
id: number;
|
||
name?: string;
|
||
code: string;
|
||
type: number;
|
||
// ...
|
||
}
|
||
|
||
// API object with methods
|
||
export const AreaApi = {
|
||
getAreaPage: async (params: any) => { ... },
|
||
getArea: async (id: number) => { ... },
|
||
createArea: async (data: Area) => { ... },
|
||
updateArea: async (data: Area) => { ... },
|
||
deleteArea: async (id: number) => { ... },
|
||
deleteAreaList: async (ids: number[]) => { ... },
|
||
exportArea: async (params) => { ... }
|
||
}
|
||
```
|
||
|
||
**Frontend View Pattern** (`views/prison/{module}/index.vue`):
|
||
- Uses Element Plus table with pagination
|
||
- Search form with filters
|
||
- CRUD operations with dialog forms
|
||
- Export functionality
|
||
- Batch delete support
|
||
|
||
### Data Flow Pattern
|
||
```
|
||
Frontend (Vue Component)
|
||
↓
|
||
API Layer (TypeScript + Axios)
|
||
↓
|
||
Backend Controller (REST API)
|
||
↓
|
||
Service Layer (Business Logic)
|
||
↓
|
||
Data Access (MyBatis-Plus)
|
||
↓
|
||
MySQL Database
|
||
```
|
||
|
||
## Current Integration Status
|
||
|
||
**8 Modules integrated into prison module**:
|
||
| Module | Chinese | Backend Path | Frontend Path | Status |
|
||
|--------|---------|--------------|---------------|--------|
|
||
| Area | 监区管理 | `controller/admin/area/` | `views/prison/area/` | ✅ Complete |
|
||
| Cell | 监室管理 | `controller/admin/cell/` | `views/prison/cell/` | ✅ Complete |
|
||
| Consumption | 消费记录 | `controller/admin/consumption/` | `views/prison/consumption/` | ✅ Complete |
|
||
| Question | 问卷问题 | `controller/admin/question/` | `views/prison/question/` | ✅ Complete |
|
||
| Questionnaire | 问卷模板 | `controller/admin/questionnaire/` | `views/prison/questionnaire/` | ✅ Complete |
|
||
| QuestionnaireRecord | 问卷答题记录 | `controller/admin/questionnairerecord/` | `views/prison/questionnairerecord/` | ✅ Complete |
|
||
| RiskAssessment | 危险评估 | `controller/admin/riskassessment/` | `views/prison/riskassessment/` | ✅ Complete |
|
||
| Score | 计分考核 | `controller/admin/score/` | `views/prison/score/` | ✅ Complete |
|
||
|
||
**Core Features per Module**:
|
||
- ✅ RESTful CRUD API endpoints
|
||
- ✅ MyBatis-Plus data access layer
|
||
- ✅ Request/Response VO objects
|
||
- ✅ MapStruct type conversion
|
||
- ✅ Frontend list page with pagination
|
||
- ✅ Frontend form dialogs for create/edit
|
||
- ✅ Export to Excel functionality
|
||
- ✅ Batch delete operations
|
||
- ✅ Menu permissions SQL scripts
|
||
|
||
**Recent Updates (2026-01-15)**:
|
||
- Code review completed for questionnaire modules (Question, Questionnaire, QuestionnaireRecord)
|
||
- Backend fixes: VO field synchronization, batch update optimization, empty validation
|
||
- Frontend fixes: TypeScript type definitions, date formatting standardization
|
||
- Added enum classes: QuestionnaireStatusEnum, QuestionnaireRecordStatusEnum, QuestionnaireRecordPassStatusEnum
|
||
- Added database migration scripts for new columns
|
||
|
||
## Database Configuration
|
||
|
||
**Development Database**:
|
||
```
|
||
URL: jdbc:mysql://192.168.10.130:3306/xlcp_dev?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true
|
||
Username: (configured in application-local.yaml)
|
||
Password: (configured in application-local.yaml)
|
||
```
|
||
|
||
**SQL Scripts Location**:
|
||
- Module tables and permissions: `backend/yudao-module-prison/src/main/resources/sql/prison_module.sql`
|
||
- Execute this script to create all prison module tables and menu permissions
|
||
|
||
## Configuration Files
|
||
|
||
### Backend Configuration
|
||
**Location**: `backend/yudao-server/src/main/resources/`
|
||
|
||
**Key Files**:
|
||
- `application.yaml` - Base configuration
|
||
- `application-local.yaml` - Local development (port 48080)
|
||
- `application-dev.yaml` - Development environment
|
||
|
||
**Mock Settings** (application-local.yaml):
|
||
```yaml
|
||
yudao:
|
||
security:
|
||
mock-enable: true # 是否开启 Token 的模拟机制(生产环境必须关闭)
|
||
mock-secret: emsoft # Token 模拟机制的 Token 前缀
|
||
```
|
||
|
||
**使用场景**:方便使用 Postman、Swagger 调试接口时模拟 Token 认证,无需真实登录。
|
||
|
||
**多租户调用方式**:
|
||
```bash
|
||
# 格式:Authorization: Bearer {mockSecret}{用户ID}
|
||
# 必须传递 tenant-id 请求头
|
||
|
||
curl -X GET "{{url}}" \
|
||
-H "Authorization: Bearer emsoft1" \
|
||
-H "tenant-id: 1"
|
||
```
|
||
|
||
**说明**:
|
||
| 参数 | 说明 | 示例值 |
|
||
|------|------|--------|
|
||
| `Authorization` | mock token,格式 `{mockSecret}{userId}` | `Bearer emsoft1` 表示用户 ID 为 1 |
|
||
| `tenant-id` | 租户 ID(多租户场景必传) | `1` |
|
||
|
||
**示例**:
|
||
- 模拟用户 ID=1,租户 ID=1:`Authorization: Bearer emsoft1` + `tenant-id: 1`
|
||
- 模拟用户 ID=2,租户 ID=1:`Authorization: Bearer emsoft2` + `tenant-id: 1`
|
||
|
||
### Frontend Configuration
|
||
**Location**: `frontend/`
|
||
|
||
**Key Files**:
|
||
- `.env.local` - Local development environment
|
||
- `.env.dev` - Development environment
|
||
- `.env.test` - Testing environment
|
||
- `.env.prod` - Production environment
|
||
|
||
**Local Environment** (.env.local):
|
||
```
|
||
VITE_BASE_URL='http://localhost:48080'
|
||
VITE_API_URL='/admin-api'
|
||
VITE_DEV=true
|
||
```
|
||
|
||
## Development Workflow
|
||
|
||
### Adding a New Module
|
||
1. **Backend**:
|
||
- Create package: `controller/admin/{module}/`, `service/{module}/`, `dal/dataobject/{module}/`, etc.
|
||
- Define DO in `dal/dataobject/{module}/{Module}DO.java`
|
||
- Create Mapper in `dal/mysql/{module}/{Module}Mapper.java`
|
||
- Implement Service in `service/{module}/impl/{Module}ServiceImpl.java`
|
||
- Create Controller in `controller/admin/{module}/{Module}Controller.java`
|
||
- Define VOs in `controller/admin/{module}/vo/`
|
||
- Add MapStruct converter in `convert/{module}/{Module}Convert.java`
|
||
- Add enum if needed in `enums/`
|
||
|
||
2. **Frontend**:
|
||
- Create API: `api/prison/{module}/index.ts`
|
||
- Create views: `views/prison/{module}/index.vue` and `{Module}Form.vue`
|
||
- Define TypeScript interfaces
|
||
- Implement CRUD operations
|
||
|
||
3. **Database**:
|
||
- Add table creation SQL to `backend/yudao-module-prison/src/main/resources/sql/prison_module.sql`
|
||
- Add menu permission SQL
|
||
|
||
### Testing a Module
|
||
**Backend**:
|
||
```bash
|
||
# Test all prison module
|
||
cd backend/yudao-module-prison && mvn test
|
||
|
||
# Test specific class
|
||
mvn test -Dtest=PrisonAreaControllerTest
|
||
```
|
||
|
||
**Frontend**:
|
||
```bash
|
||
# Type check only
|
||
cd frontend && pnpm ts:check
|
||
|
||
# Dev server with hot reload
|
||
pnpm dev
|
||
```
|
||
|
||
## Common Patterns
|
||
|
||
### Backend Controller Pattern
|
||
```java
|
||
@RestController
|
||
@RequestMapping("/prison/{module}")
|
||
@Tag(name = "管理后台 - {中文名称}")
|
||
public class {Module}Controller {
|
||
|
||
@Resource
|
||
private {Module}Service {module}Service;
|
||
|
||
@PostMapping("/create")
|
||
@Operation(summary = "创建{中文名称}")
|
||
@PreAuthorize("@ss.hasPermission('prison:{module}:create')")
|
||
public CommonResult<Long> create(@Valid @RequestBody {Module}SaveReqVO vo) {
|
||
return success({module}Service.create(vo));
|
||
}
|
||
|
||
@PutMapping("/update")
|
||
@Operation(summary = "更新{中文名称}")
|
||
@PreAuthorize("@ss.hasPermission('prison:{module}:update')")
|
||
public CommonResult<Boolean> update(@Valid @RequestBody {Module}SaveReqVO vo) {
|
||
return success({module}Service.update(vo));
|
||
}
|
||
|
||
@DeleteMapping("/delete")
|
||
@Operation(summary = "删除{中文名称}")
|
||
@PreAuthorize("@ss.hasPermission('prison:{module}:delete')")
|
||
public CommonResult<Boolean> delete(@RequestParam("id") Long id) {
|
||
return success({module}Service.delete(id));
|
||
}
|
||
|
||
@GetMapping("/page")
|
||
@Operation(summary = "分页查询{中文名称}")
|
||
@PreAuthorize("@ss.hasPermission('prison:{module}:query')")
|
||
public CommonResult<PageResult<{Module}RespVO>> page(@Valid {Module}PageReqVO vo) {
|
||
return success({module}Service.page(vo));
|
||
}
|
||
|
||
@GetMapping("/get")
|
||
@Operation(summary = "查询{中文名称}详情")
|
||
@PreAuthorize("@ss.hasPermission('prison:{module}:query')")
|
||
public CommonResult<{Module}RespVO> get(@RequestParam("id") Long id) {
|
||
return success({module}Service.get(id));
|
||
}
|
||
|
||
@GetMapping("/export-excel")
|
||
@Operation(summary = "导出{中文名称} Excel")
|
||
@PreAuthorize("@ss.hasPermission('prison:{module}:export')")
|
||
public void exportExcel(@Valid {Module}PageReqVO vo, HttpServletResponse response) {
|
||
{module}Service.exportExcel(vo, response);
|
||
}
|
||
}
|
||
```
|
||
|
||
### Service Layer Pattern
|
||
```java
|
||
public interface {Module}Service {
|
||
Long create({Module}SaveReqVO vo);
|
||
Boolean update({Module}SaveReqVO vo);
|
||
Boolean delete(Long id);
|
||
{Module}RespVO get(Long id);
|
||
PageResult<{Module}RespVO> page({Module}PageReqVO vo);
|
||
void exportExcel({Module}PageReqVO vo, HttpServletResponse response);
|
||
}
|
||
```
|
||
|
||
### Frontend API Pattern
|
||
```typescript
|
||
export interface {Module} {
|
||
id: number;
|
||
// ... other fields
|
||
}
|
||
|
||
export const {Module}Api = {
|
||
getPage: async (params: any) => {
|
||
return await request.get({ url: `/{module}/page`, params })
|
||
},
|
||
get: async (id: number) => {
|
||
return await request.get({ url: `/{module}/get?id=${id}` })
|
||
},
|
||
create: async (data: {Module}) => {
|
||
return await request.post({ url: `/{module}/create`, data })
|
||
},
|
||
update: async (data: {Module}) => {
|
||
return await request.put({ url: `/{module}/update`, data })
|
||
},
|
||
delete: async (id: number) => {
|
||
return await request.delete({ url: `/{module}/delete?id=${id}` })
|
||
},
|
||
deleteList: async (ids: number[]) => {
|
||
return await request.delete({ url: `/{module}/delete-list?ids=${ids.join(',')}` })
|
||
},
|
||
export: async (params) => {
|
||
return await request.download({ url: `/{module}/export-excel`, params })
|
||
}
|
||
}
|
||
```
|
||
|
||
## Important Notes
|
||
|
||
- **Package Prefix**: All prison module classes use `cn.iocoder.yudao.module.prison`
|
||
- **API Base Path**: `/admin-api/prison/{module}`
|
||
- **Permission Codes**: Follow pattern `prison:{module}:{action}` (e.g., `prison:area:create`)
|
||
- **Frontend Paths**: Use `views/prison/` and `api/prison/` directories
|
||
- **Database Tables**: Use `prison_` prefix and soft delete (`deleted` field)
|
||
- **Error Codes**: Defined in `ErrorCodeConstants.java` (shared across modules)
|
||
- **Enum Types**: Defined in `enums/` directory with `Enum` suffix
|
||
- **VO Naming**: `SaveReqVO`, `PageReqVO`, `RespVO` suffixes
|
||
- **DO Naming**: `{Module}DO` with table mapping via `@TableName`
|
||
- **Mapper Naming**: `{Module}Mapper` extending `BaseMapper<{Module}DO>`
|
||
- **Service Impl**: Located in `service/{module}/impl/` directory
|
||
|
||
## Code Generation
|
||
|
||
**Source**: `codegen/` directory contains template files for generating new modules
|
||
**Usage**: Copy and adapt these templates when adding new prison modules
|
||
|
||
## Build & Deployment
|
||
|
||
**Backend JAR**: `backend/yudao-server/target/yudao-server-{version}.jar`
|
||
**Frontend Dist**: `frontend/dist/` (static files for nginx)
|
||
|
||
## Troubleshooting
|
||
|
||
**Common Issues**:
|
||
1. **Maven dependency issues**: Run `mvn clean install -U` to force update
|
||
2. **Frontend type errors**: Run `pnpm ts:check` to identify issues
|
||
3. **Database connection**: Verify MySQL is running and credentials in `application-local.yaml`
|
||
4. **Mock mode**: Check `yudao.mock.enable` setting in configuration
|
||
5. **Port conflicts**: Default backend port is 48080
|
||
|
||
**Debug Mode**:
|
||
- Backend: Add `--debug` to mvn command for remote debugging on port 5005
|
||
- Frontend: Browser dev tools + Vue DevTools browser extension
|
||
|