# 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

修改表结构的是直接采用 mysql  命令进行操帮我操作


**Development Database**:
```
URL: jdbc:mysql://192.168.10.130:3306/xlcp_dev?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true
Username: xlcp_dev
Password: xlcp_dev
```

**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

