# Lyzsys 后端开发文档

## 目录

- [项目概述](#项目概述)
- [技术栈](#技术栈)
- [项目架构](#项目架构)
- [模块说明](#模块说明)
- [开发指南](#开发指南)
- [核心功能](#核心功能)
- [部署指南](#部署指南)

---

## 项目概述

Lyzsys 是一个基于 Spring Boot 的企业级后台管理系统，采用模块化单体架构，支持多租户、工作流、权限管理、AI 集成等企业级功能。

### 核心特性

- **模块化架构**: 基于 Maven 多模块的清晰分层设计
- **多租户支持**: 原生支持 SaaS 多租户场景
- **权限管理**: 基于 RBAC 的动态权限和数据权限
- **工作流引擎**: 集成 Flowable 实现业务流程管理
- **AI 集成**: 支持多个 AI 服务提供商集成
- **微服务就绪**: 模块化设计便于未来微服务化改造

---

## 技术栈

### 核心框架

| 技术 | 版本 | 说明 |
|------|------|------|
| Spring Boot | 2.7.18 | 应用开发框架 |
| Spring Security | 5.8.16 | 安全框架 |
| MyBatis Plus | 3.5.15 | ORM 增强框架 |
| Flowable | 6.8.0 | 工作流引擎 |
| Redisson | 3.52.0 | 分布式锁客户端 |

### 数据存储

| 技术 | 版本 | 说明 |
|------|------|------|
| MySQL | 5.7+ | 主数据库 |
| Redis | 5.0+ | 缓存数据库 |
| 支持数据库 | - | MySQL、PostgreSQL、Oracle、SQL Server、H2 等 |

### 工具库

| 技术 | 版本 | 说明 |
|------|------|------|
| Lombok | 1.18.34 | 简化 Java 代码 |
| MapStruct | 1.6.3 | 对象映射 |
| Jackson | 2.13.5 | JSON 处理 |
| Hibernate Validator | 6.2.5 | 参数校验 |
| Knife4j | 3.0.3 | API 文档 |

---

## 项目架构

### 整体架构

Lyzsys 后端采用**模块化单体架构**，基于 **Controller-Service-DAL** 三层架构模式：

```
┌─────────────────────────────────────────────────────────────┐
│                        前端应用                              │
│          (lyzsys-ui-admin / lyzsys-ui-admin-uniapp)         │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                      lyzsys-server                          │
│                   (应用启动入口)                             │
└─────────────────────────────────────────────────────────────┘
                              │
        ┌─────────────────────┼─────────────────────┐
        │                     │                     │
        ▼                     ▼                     ▼
┌──────────────┐    ┌──────────────────┐    ┌──────────────┐
│ lyzsys-framework│    │ lyzsys-module-xxx│    │lyzsys-dependencies│
│  (框架层)      │    │   (业务模块)      │    │  (依赖管理)   │
└──────────────┘    └──────────────────┘    └──────────────┘
```

### 分层架构

每个业务模块都遵循标准的三层架构：

```
controller/        # 控制层 - 接收 HTTP 请求
    ├── admin/     # 管理后台 API
    └── app/       # 用户 App API
        │
        ▼
service/           # 服务层 - 业务逻辑处理
    ├── IxxxService.java      # 服务接口
    └── xxxServiceImpl.java   # 服务实现
        │
        ▼
dal/               # 数据访问层
    ├── dataobject/           # 数据对象 (DO)
    ├── mysql/                # MyBatis Mapper
    └── redis/                # Redis 操作
```

### 架构设计原则

1. **依赖倒置**: Controller 依赖 Service 接口，而非实现
2. **单一职责**: 每层只负责自己的职责
3. **开闭原则**: 通过接口扩展，而非修改
4. **非严格分层**: 允许跨层访问（如 Service 直接调用多个 Mapper）

---

## 模块说明

### Maven 模块分类

项目共有四类 Maven Module：

#### 1. lyzsys-dependencies

**作用**: Maven 依赖版本管理 (BOM)

**说明**: 定义项目中所有 Maven 依赖的版本号，解决依赖冲突问题。

**关键文件**:
- `pom.xml`: 依赖版本定义

#### 2. lyzsys-framework

**作用**: Java 框架拓展

**说明**: 提供项目的基础框架能力，分为技术组件和业务组件。

**技术组件**:

| 模块 | 作用 |
|------|------|
| lyzsys-common | 基础 pojo 类、枚举、工具类 |
| lyzsys-spring-boot-starter-web | Web 封装，全局异常、访问日志 |
| lyzsys-spring-boot-starter-security | 认证授权，基于 Spring Security |
| lyzsys-spring-boot-starter-mybatis | 数据库操作，基于 MyBatis Plus |
| lyzsys-spring-boot-starter-redis | 缓存操作，基于 Spring Data Redis + Redisson |
| lyzsys-spring-boot-starter-mq | 消息队列，基于 Redis 实现 |
| lyzsys-spring-boot-starter-job | 定时任务，基于 Quartz 实现 |
| lyzsys-spring-boot-starter-protection | 服务保障，幂等、分布式锁、限流、熔断 |
| lyzsys-spring-boot-starter-excel | Excel 导入导出，基于 EasyExcel |
| lyzsys-spring-boot-starter-monitor | 服务监控，链路追踪、日志服务 |
| lyzsys-spring-boot-starter-websocket | WebSocket 封装，支持 Token 认证 |

**业务组件**:

| 模块 | 作用 |
|------|------|
| lyzsys-spring-boot-starter-biz-tenant | SaaS 多租户 |
| lyzsys-spring-boot-starter-biz-data-permission | 数据权限 |
| lyzsys-spring-boot-starter-biz-ip | 地区 & IP 库 |

#### 3. lyzsys-module-xxx

**作用**: 业务功能模块

**核心模块**:

| 模块 | 说明 | 是否必须 |
|------|------|----------|
| lyzsys-module-system | 系统功能模块 | √ |
| lyzsys-module-infra | 基础设施模块 | √ |
| lyzsys-module-ai | AI 大模型集成 | × |
| lyzsys-module-bpm | 业务流程管理 | × |
| lyzsys-module-crm | 客户关系管理 | × |
| lyzsys-module-erp | 企业资源规划 | × |
| lyzsys-module-iot | 物联网平台 | × |
| lyzsys-module-mall | 商城系统 | × |
| lyzsys-module-member | 会员中心 | × |
| lyzsys-module-mp | 微信公众号 | × |
| lyzsys-module-pay | 支付系统 | × |
| lyzsys-module-report | 报表系统 | × |

#### 4. lyzsys-server

**作用**: 管理后台 + 用户 App 的服务端

**说明**: 后端 Server 的主项目，通过引入需要的 lyzsys-module-xxx 业务模块，提供 RESTful API。

### 模块标准结构

每个业务模块采用统一的目录结构：

```
lyzsys-module-xxx/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── cn/iocoder/lyzsys/module/xxx/
│   │   │       ├── api/              # 对外 API 接口
│   │   │       │   ├── xxxApi.java
│   │   │       │   └── xxxApiImpl.java
│   │   │       ├── controller/       # 控制层
│   │   │       │   ├── admin/        # 管理后台 Controller
│   │   │       │   │   ├── xxxController.java
│   │   │       │   │   └── vo/       # 视图对象
│   │   │       │   │       ├── xxxReqVO.java
│   │   │       │   │       └── xxxRespVO.java
│   │   │       │   └── app/          # 用户 App Controller
│   │   │       ├── service/          # 服务层
│   │   │       │   ├── xxxService.java
│   │   │       │   └── xxxServiceImpl.java
│   │   │       ├── dal/              # 数据访问层
│   │   │       │   ├── dataobject/   # 数据对象
│   │   │       │   │   └── xxxDO.java
│   │   │       │   ├── mysql/        # MyBatis Mapper
│   │   │       │   │   └── xxxMapper.java
│   │   │       │   └── redis/        # Redis 操作
│   │   │       │       └── xxxRedisDAO.java
│   │   │       ├── convert/          # 对象转换器
│   │   │       │   └── xxxConvert.java
│   │   │       ├── enums/            # 枚举类
│   │   │       │   └── xxxEnum.java
│   │   │       └── framework/        # 模块框架配置
│   │   └── resources/
│   │       └── mapper/               # MyBatis XML
│   └── test/
│       └── java/
└── pom.xml
```

---

## 开发指南

### 环境准备

#### 必需软件

| 软件 | 版本要求 | 下载地址 |
|------|----------|----------|
| JDK | 8+ | https://www.oracle.com/java/technologies/downloads/ |
| MySQL | 5.7+ | https://dev.mysql.com/downloads/mysql/ |
| Redis | 5.0+ | https://redis.io/download |
| Maven | 3.6+ | https://maven.apache.org/download.cgi |
| IDE | IntelliJ IDEA 推荐 | https://www.jetbrains.com/idea/ |

#### 配置数据库

1. 创建数据库：
```sql
CREATE DATABASE lyzsys CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```

2. 导入 SQL 脚本（位置：`sql/` 目录）

3. 修改配置文件 `lyzsys-server/src/main/resources/application.yaml`

### 快速开始

#### 1. 克隆项目

```bash
git clone https://github.com/your-org/lyzsys.git
cd lyzsys/lyzsys_backend
```

#### 2. 导入 IDE

将项目导入 IntelliJ IDEA：

```
File → Open → 选择 lyzsys_backend 目录
```

等待 Maven 依赖下载完成。

#### 3. 启动 Redis

```bash
redis-server
```

#### 4. 运行主类

找到 `lyzsys-server/src/main/java/cn/iocoder/lyzsys/server/LyzsysServerApplication.java`

右键 → Run 'LyzsysServerApplication'

#### 5. 访问应用

- 应用地址: http://localhost:48080
- API 文档: http://localhost:48080/doc.html
- 用户名: admin
- 密码: admin123

### 开发规范

#### 命名规范

**包命名**: 全小写，使用点分隔
```
cn.iocoder.lyzsys.module.system.controller.admin
```

**类命名**: 大驼峰
```
UserController, UserService, UserDO
```

**方法命名**: 小驼峰
```
getUserById(), createUser(), deleteUser()
```

**变量命名**: 小驼峰
```
userName, userAge, isAdmin
```

**常量命名**: 全大写，下划线分隔
```
MAX_SIZE, DEFAULT_PAGE_SIZE, ERROR_CODE
```

#### 注释规范

**类注释**:
```java
/**
 * 用户 Controller
 *
 * @author 芋道源码
 */
@RestController
@RequestMapping("/system/user")
public class UserController {
}
```

**方法注释**:
```java
/**
 * 创建用户
 *
 * @param createReqVO 创建信息
 * @return 用户 ID
 */
@PostMapping("/create")
public CommonResult<Long> createUser(@Valid @RequestBody UserCreateReqVO createReqVO) {
    return success(userService.createUser(createReqVO));
}
```

#### 代码规范

1. **使用 Lombok 简化代码**:
```java
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserDO extends TenantBaseDO {
    private Long id;
    private String username;
}
```

2. **使用 MapStruct 进行对象转换**:
```java
@Mapper
public interface UserConvert {
    UserConvert INSTANCE = Mappers.getMapper(UserConvert.class);

    UserDO convert(UserCreateReqVO bean);

    UserRespVO convert(UserDO bean);
}
```

3. **异常处理**:
```java
// 使用全局异常处理器
throw new ServiceException(USER_USERNAME_EXISTS);

// 或使用工具方法
throw exception(USER_USERNAME_EXISTS);
```

### 接口开发

#### Controller 层

```java
@Tag(name = "管理后台 - 用户")
@RestController
@RequestMapping("/system/user")
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    @PostMapping("/create")
    @Operation(summary = "创建用户")
    @PreAuthorize("@ss.hasPermission('system:user:create')")
    public CommonResult<Long> createUser(@Valid @RequestBody UserCreateReqVO createReqVO) {
        return success(userService.createUser(createReqVO));
    }

    @GetMapping("/get")
    @Operation(summary = "获取用户详情")
    @Parameter(name = "id", description = "用户 ID", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('system:user:query')")
    public CommonResult<UserRespVO> getUser(@RequestParam("id") Long id) {
        return success(userService.getUser(id));
    }
}
```

#### Service 层

```java
public interface UserService {
    Long createUser(UserCreateReqVO createReqVO);
    UserRespVO getUser(Long id);
    void deleteUser(Long id);
}

@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createUser(UserCreateReqVO createReqVO) {
        // 1. 参数校验
        validateUserExists(null, createReqVO.getUsername());

        // 2. 插入用户
        UserDO user = UserConvert.INSTANCE.convert(createReqVO);
        user.setPassword(encodePassword(createReqVO.getPassword()));
        userMapper.insert(user);

        // 3. 返回 ID
        return user.getId();
    }

    @Override
    public UserRespVO getUser(Long id) {
        UserDO user = userMapper.selectById(id);
        return UserConvert.INSTANCE.convert(user);
    }
}
```

#### Mapper 层

```java
@Mapper
public interface UserMapper extends BaseMapperX<UserDO> {

    default UserDO selectByUsername(String username) {
        return selectOne("username", username);
    }

    default List<UserDO> selectListByDeptIds(Collection<Long> deptIds) {
        return selectList(new LambdaQueryWrapperX<UserDO>()
                .in(UserDO::getDeptId, deptIds));
    }

    default PageResult<UserDO> selectPage(UserPageReqVO pageReqVO) {
        return selectPage(pageReqVO, new LambdaQueryWrapperX<UserDO>()
                .likeIfPresent(UserDO::getUsername, pageReqVO.getUsername())
                .likeIfPresent(UserDO::getMobile, pageReqVO.getMobile())
                .betweenIfPresent(UserDO::getCreateTime, pageReqVO.getCreateTime())
                .orderByDesc(UserDO::getId));
    }
}
```

---

## 核心功能

### 认证授权

#### 认证流程

1. **登录认证**:
```
用户输入用户名密码 → 后端验证 → 生成 JWT Token → 返回 Token
```

2. **Token 验证**:
```
请求携带 Token → 后端解析 Token → 验证有效性 → 允许访问
```

3. **Token 刷新**:
```
Token 即将过期 → 使用刷新令牌 → 获取新 Token
```

#### 权限模型

**RBAC (基于角色的访问控制)**:

```
用户 (User)
  ↓
角色 (Role)
  ↓
权限 (Permission)
  ↓
资源 (Resource)
```

**数据权限**:

- 全部数据权限
- 本部门数据权限
- 本部门及以下数据权限
- 仅本人数据权限
- 自定义数据权限

### 多租户

#### 租户隔离

1. **数据库隔离**: 通过 `tenant_id` 字段隔离
2. **自动过滤**: MyBatis Plus 拦截器自动添加租户条件
3. **租户上下文**: `TenantContextHolder` 管理当前租户

#### 使用示例

```java
// 继承租户基类
@TableName("system_user")
public class UserDO extends TenantBaseDO {
    private Long id;
    private String username;
    // tenant_id 由 TenantBaseDO 提供
}

// 查询自动过滤租户
List<UserDO> users = userMapper.selectList();
// SQL: SELECT * FROM system_user WHERE tenant_id = ?
```

### 工作流 (Flowable)

#### 流程定义

```java
@Service
public class ProcessDefinitionService {

    public String createProcessDefinition(ProcessDefinitionCreateReqVO createReqVO) {
        // 1. 校验流程模型
        validateProcessModel(createReqVO.getModelId());

        // 2. 部署流程定义
        Deployment deployment = repositoryService.createDeployment()
                .name(createReqVO.getName())
                .addBytes(createReqVO.getBpmnBytes())
                .deploy();

        // 3. 返回流程定义 ID
        return deployment.getId();
    }
}
```

#### 流程实例

```java
@Service
public class ProcessInstanceService {

    public String startProcessInstance(ProcessInstanceStartReqVO startReqVO) {
        // 1. 启动流程实例
        ProcessInstance instance = runtimeService.startProcessInstanceByKey(
                startReqVO.getProcessDefinitionKey(),
                startReqVO.getBusinessKey()
        );

        // 2. 完成第一个任务
        taskService.complete(instance.getId());

        // 3. 返回实例 ID
        return instance.getId();
    }
}
```

### 缓存管理

#### Redis 缓存

```java
// 使用 RedisTemplate
@Service
@RequiredArgsConstructor
public class UserServiceImpl {

    private final RedisTemplate<String, UserDO> redisTemplate;

    public UserDO getUser(Long id) {
        String key = "user:" + id;
        UserDO user = redisTemplate.opsForValue().get(key);

        if (user == null) {
            user = userMapper.selectById(id);
            redisTemplate.opsForValue().set(key, user, 1, TimeUnit.HOURS);
        }

        return user;
    }
}
```

#### 缓存注解

```java
@Cacheable(value = "user", key = "#id")
public UserDO getUser(Long id) {
    return userMapper.selectById(id);
}

@CachePut(value = "user", key = "#user.id")
public UserDO updateUser(UserDO user) {
    userMapper.updateById(user);
    return user;
}

@CacheEvict(value = "user", key = "#id")
public void deleteUser(Long id) {
    userMapper.deleteById(id);
}
```

### 消息队列

#### Redis 消息队列

```java
@Component
@RequiredArgsConstructor
public class SmsProducer {

    private final RedisTemplate<String, Object> redisTemplate;

    public void sendSmsSendMessage(Long userId, String mobile, String content) {
        SmsSendMessage message = new SmsSendMessage()
                .setUserId(userId)
                .setMobile(mobile)
                .setContent(content);
        redisTemplate.convertAndSend("sms_send", message);
    }
}

@Component
@RequiredArgsConstructor
public class SmsSendConsumer {

    private final SmsService smsService;

    @RedisStreamListener(stream = "sms_send", consumerGroup = "sms_send_group")
    public void consumeSmsSendMessage(SmsSendMessage message) {
        smsService.sendSms(message.getMobile(), message.getContent());
    }
}
```

### 定时任务

#### Quartz 定时任务

```java
@Component
public class DemoJob extends QuartzJobBean {

    @Autowired
    private UserService userService;

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        // 定时清理过期用户
        userService.cleanExpiredUsers();
    }
}
```

### 文件管理

#### 文件上传

```java
@RestController
@RequestMapping("/infra/file")
public class FileController {

    @PostMapping("/upload")
    public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file) {
        // 1. 上传文件
        String url = fileService.uploadFile(file);

        // 2. 返回 URL
        return success(url);
    }
}
```

#### 文件存储

支持多种存储方式：
- 本地存储
- 阿里云 OSS
- 腾讯云 COS
- MinIO
- FTP / SFTP

### Excel 操作

#### 导入

```java
@PostMapping("/import")
public CommonResult<Integer> importUsers(@RequestParam("file") MultipartFile file) {
    List<UserImportExcelVO> list = ExcelUtils.read(file, UserImportExcelVO.class);
    return success(userService.importUsers(list));
}
```

#### 导出

```java
@GetMapping("/export")
public void exportUsers(HttpServletResponse response, UserPageReqVO pageReqVO) {
    List<UserDO> list = userService.getUserList(pageReqVO);
    ExcelUtils.write(response, "用户数据.xls", "用户列表", UserRespVO.class,
            BeanConvertUtils.convertList(list, UserRespVO.class));
}
```

---

## 部署指南

### 本地部署

#### 1. 打包项目

```bash
cd lyzsys_backend
mvn clean package -DskipTests
```

#### 2. 上传文件

将 `lyzsys-server/target/lyzsys-server.jar` 上传到服务器

#### 3. 启动应用

```bash
java -jar lyzsys-server.jar --spring.profiles.active=prod
```

### Docker 部署

#### 1. 构建镜像

```bash
docker build -t lyzsys/lyzsys-server:latest .
```

#### 2. 运行容器

```bash
docker run -d \
  --name lyzsys-server \
  -p 48080:48080 \
  -e SPRING_PROFILES_ACTIVE=prod \
  -e SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/lyzsys \
  -e SPRING_DATASOURCE_USERNAME=root \
  -e SPRING_DATASOURCE_PASSWORD=password \
  -e SPRING_DATA_REDIS_HOST=redis \
  lyzsys/lyzsys-server:latest
```

### 配置说明

#### application.yaml

```yaml
spring:
  # 数据源配置
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/lyzsys?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver

  # Redis 配置
  redis:
    host: 127.0.0.1
    port: 6379
    database: 1
    password:
    timeout: 0

# 项目配置
lyzsys:
  info:
    base-package: cn.iocoder.lyzsys
  web:
    api-prefix: /admin-api
  security:
    mock-enable: true
  upload:
    base-url: http://127.0.0.1:48080
```

---

## Demo 示例模块

### 模块简介

**lyzsys-module-demo** 是一个完整的业务模块示例，展示了如何在 Lyzsys 系统中快速创建一个新的业务模块。该模块实现了项目管理的完整 CRUD 功能，包括增删改查和 Excel 导出。

### 功能特性

- ✅ 完整的 CRUD 接口（增删改查）
- ✅ 分页查询支持
- ✅ 批量删除功能
- ✅ Excel 导出功能
- ✅ 业务字段唯一性校验
- ✅ 权限控制
- ✅ 前后端完整实现

### 模块结构

```
lyzsys-module-demo/
├── pom.xml                                    # Maven 配置
└── src/main/java/cn/iocoder/lyzsys/module/demo/
    ├── controller/admin/project/              # 控制器层
    │   ├── ProjectController.java            # 项目控制器
    │   └── vo/                               # VO 对象
    │       ├── ProjectPageReqVO.java         # 分页查询请求
    │       ├── ProjectRespVO.java            # 响应 VO
    │       └── ProjectSaveReqVO.java         # 保存请求 VO
    ├── service/project/                       # 服务层
    │   ├── ProjectService.java               # 服务接口
    │   └── ProjectServiceImpl.java           # 服务实现
    ├── dal/                                   # 数据访问层
    │   ├── dataobject/project/               # 数据对象
    │   │   └── ProjectDO.java                # 项目实体类
    │   └── mysql/project/                    # Mapper 接口
    │       └── ProjectMapper.java            # 项目 Mapper
    └── enums/                                 # 枚举类
        └── ErrorCodeConstants.java           # 错误码常量
```

### 核心代码示例

#### 实体类（ProjectDO）

```java
@TableName("demo_project")
@Data
@EqualsAndHashCode(callSuper = true)
public class ProjectDO extends BaseDO {
    @TableId
    private Long id;

    // 遵循命名规范：第一个单词不能只有一个字母
    private String projectName;      // ✅ 正确（而非 pName）
    private String projectCode;      // ✅ 正确（而非 pCode）
    private LocalDateTime establishDate;  // ✅ 正确（而非 eDate）
}
```

#### Controller 示例

```java
@Tag(name = "管理后台 - 项目管理")
@RestController
@RequestMapping("/demo/project")
public class ProjectController {

    @PostMapping("/create")
    @Operation(summary = "创建项目")
    @PreAuthorize("@ss.hasPermission('demo:project:create')")
    public CommonResult<Long> createProject(@Valid @RequestBody ProjectSaveReqVO createReqVO) {
        return success(projectService.createProject(createReqVO));
    }

    // 其他 CRUD 方法...
}
```

### 数据库设计

```sql
CREATE TABLE `demo_project` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '项目ID',
  `project_name` varchar(100) NOT NULL COMMENT '项目名称',
  `project_code` varchar(50) NOT NULL COMMENT '项目编号',
  `establish_date` datetime NULL COMMENT '立项时间',
  -- 标准字段
  `creator` varchar(64) DEFAULT '' COMMENT '创建者',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updater` varchar(64) DEFAULT '' COMMENT '更新者',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='项目管理表';
```

### 菜单配置

Demo 模块的菜单结构：

```
项目管理（一级菜单，sort: 1）
  └── 项目列表（二级菜单，sort: 1）
      ├── 项目查询（demo:project:query）
      ├── 项目新增（demo:project:create）
      ├── 项目修改（demo:project:update）
      ├── 项目删除（demo:project:delete）
      └── 项目导出（demo:project:export）
```

### 前端实现

前端代码位置：
- API 接口：`src/api/demo/project/index.ts`
- 列表页面：`src/views/demo/project/index.vue`
- 表单组件：`src/views/demo/project/ProjectForm.vue`

### 作为参考模板

Demo 模块可以作为新业务模块开发的参考模板，包含了：

1. **标准的代码结构** - 遵循项目分层架构
2. **完整的业务逻辑** - 包括校验、异常处理等
3. **规范的命名方式** - 遵循驼峰命名规范
4. **权限控制示例** - 展示如何配置权限
5. **前后端联调** - 完整的前后端交互流程

**详细开发指南请参考**：
- [新模块开发指南](./新模块开发指南.md) - 基于 demo 模块的完整开发教程
- [编码规范](./编码规范.md) - 命名规范、菜单结构规范等

---

## 开发规范

为确保代码质量和团队协作效率，Lyzsys 项目制定了一系列开发规范。

### 核心规范文档

1. **[编码规范](./编码规范.md)** - 必读 ⭐⭐⭐⭐⭐
   - 驼峰命名规范（重要：第一个单词不能只有一个字母）
   - 菜单结构规范
   - 代码结构规范
   - 数据库设计规范
   - API 接口规范
   - 前端开发规范

2. **[新模块开发指南](./新模块开发指南.md)** - 实战教程 ⭐⭐⭐⭐⭐
   - 快速开始
   - 创建后端模块（完整步骤）
   - 创建前端页面
   - 配置菜单权限
   - 以 Demo 模块为参考示例

### 关键规范要点

#### 命名规范核心原则

⚠️ **重要**：所有字段名、类名的驼峰命名中，**第一个单词不能只有一个字母**

```java
// ✅ 正确示例
private String projectId;        // 而非 pId
private String projectName;      // 而非 pName
private String establishDate;    // 而非 eDate

// ❌ 错误示例
private String pId;              // 单字母开头，可能导致 MyBatis Plus 映射问题
private String mType;            // 单字母开头
```

#### 菜单结构规范

业务功能菜单优先展示，系统管理功能放在最后：

```
1-90.  业务菜单（项目管理、客户管理等）
98.    系统管理
99.    基础设施
```

#### 权限标识格式

```
格式：{模块名}:{业务}:{操作}

示例：
demo:project:query      # 查询
demo:project:create     # 新增
demo:project:update     # 修改
demo:project:delete     # 删除
demo:project:export     # 导出
```

### 开发流程建议

1. **阅读规范文档** → 了解编码规范和开发流程
2. **参考 Demo 模块** → 理解标准的实现方式
3. **按照开发指南** → 逐步创建新模块
4. **代码评审** → 确保符合规范要求

---

## 附录

### 常见问题

#### Q1: 如何添加新的业务模块？

**推荐方式**：参考 [新模块开发指南](./新模块开发指南.md)，以 Demo 模块为模板创建新模块。

**快速步骤**：
1. 创建 Maven 模块和目录结构
2. 编写数据库表（遵循命名规范）
3. 按照 Demo 模块的结构创建后端代码
4. 创建前端页面和 API 接口
5. 配置菜单和权限

#### Q2: 如何自定义异常？

1. 在 `module-system/enums/ErrorCodeConstants.java` 中添加错误码
2. 使用 `throw exception(ERROR_CODE)` 抛出异常
3. 全局异常处理器会自动处理并返回统一格式

#### Q3: 如何实现数据权限？

1. 在 `@Table` 注解中配置 `dataPermission` 属性
2. 使用 `@DataPermission` 注解标记需要数据权限的方法
3. 框架会自动添加数据权限过滤条件

### 参考资源

- [Spring Boot 官方文档](https://spring.io/projects/spring-boot)
- [MyBatis Plus 官方文档](https://baomidou.com/)
- [Flowable 官方文档](https://www.flowable.com/open-source/docs)
- [Redis 官方文档](https://redis.io/documentation)
- [芋道源码文档](https://doc.iocoder.cn/)

---

**文档版本**: v1.0.0
**最后更新**: 2025-01-19
**维护团队**: Lyzsys 开发团队
