Files
lyzsys_backend/doc/后端开发文档.md

1075 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 开发团队