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

29 KiB
Raw Blame History

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. 创建数据库:
CREATE DATABASE lyzsys CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  1. 导入 SQL 脚本(位置:sql/ 目录)

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

快速开始

1. 克隆项目

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

2. 导入 IDE

将项目导入 IntelliJ IDEA

File → Open → 选择 lyzsys_backend 目录

等待 Maven 依赖下载完成。

3. 启动 Redis

redis-server

4. 运行主类

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

右键 → Run 'LyzsysServerApplication'

5. 访问应用

开发规范

命名规范

包命名: 全小写,使用点分隔

cn.iocoder.lyzsys.module.system.controller.admin

类命名: 大驼峰

UserController, UserService, UserDO

方法命名: 小驼峰

getUserById(), createUser(), deleteUser()

变量命名: 小驼峰

userName, userAge, isAdmin

常量命名: 全大写,下划线分隔

MAX_SIZE, DEFAULT_PAGE_SIZE, ERROR_CODE

注释规范

类注释:

/**
 * 用户 Controller
 *
 * @author 芋道源码
 */
@RestController
@RequestMapping("/system/user")
public class UserController {
}

方法注释:

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

代码规范

  1. 使用 Lombok 简化代码:
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserDO extends TenantBaseDO {
    private Long id;
    private String username;
}
  1. 使用 MapStruct 进行对象转换:
@Mapper
public interface UserConvert {
    UserConvert INSTANCE = Mappers.getMapper(UserConvert.class);

    UserDO convert(UserCreateReqVO bean);

    UserRespVO convert(UserDO bean);
}
  1. 异常处理:
// 使用全局异常处理器
throw new ServiceException(USER_USERNAME_EXISTS);

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

接口开发

Controller 层

@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 层

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 层

@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
  1. Token 验证:
请求携带 Token → 后端解析 Token → 验证有效性 → 允许访问
  1. Token 刷新:
Token 即将过期 → 使用刷新令牌 → 获取新 Token

权限模型

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

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

数据权限:

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

多租户

租户隔离

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

使用示例

// 继承租户基类
@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)

流程定义

@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();
    }
}

流程实例

@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 缓存

// 使用 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;
    }
}

缓存注解

@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 消息队列

@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 定时任务

@Component
public class DemoJob extends QuartzJobBean {

    @Autowired
    private UserService userService;

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

文件管理

文件上传

@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 操作

导入

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

导出

@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. 打包项目

cd lyzsys_backend
mvn clean package -DskipTests

2. 上传文件

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

3. 启动应用

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

Docker 部署

1. 构建镜像

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

2. 运行容器

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

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

@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 示例

@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 方法...
}

数据库设计

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. 前后端联调 - 完整的前后端交互流程

详细开发指南请参考


开发规范

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

核心规范文档

  1. 编码规范 - 必读

    • 驼峰命名规范(重要:第一个单词不能只有一个字母)
    • 菜单结构规范
    • 代码结构规范
    • 数据库设计规范
    • API 接口规范
    • 前端开发规范
  2. 新模块开发指南 - 实战教程

    • 快速开始
    • 创建后端模块(完整步骤)
    • 创建前端页面
    • 配置菜单权限
    • 以 Demo 模块为参考示例

关键规范要点

命名规范核心原则

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

// ✅ 正确示例
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: 如何添加新的业务模块?

推荐方式:参考 新模块开发指南,以 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. 框架会自动添加数据权限过滤条件

参考资源


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