# EasyExample **Repository Path**: qoder/easy-example ## Basic Information - **Project Name**: EasyExample - **Description**: EasyBoot示例项目 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-23 - **Last Updated**: 2026-03-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Easy-Demo 示例项目 ## 介绍 easy-demo 是基于 EasyBoot 框架的示例项目,演示了如何使用 EasyBoot 开发完整的前后端分离应用。本项目实现了一个简单的**成员管理系统**,包含成员的增删改查功能。 本项目同时提供了独立前端示例,可用于开发移动端 H5、小程序、App 等不依赖 EasyBoot 内置前端框架的应用。 ## 技术栈 - **后端**: SpringBoot + Sqltoy + MapStruct - **内置前端**: Vue3 + HeyUI - **独立前端**: TypeScript + Vite + React JSX(可选) - **框架**: EasyBoot 1.1-SNAPSHOT ## 项目结构 ``` easy-demo ├── pom.xml # Maven 配置 ├── doc │ └── sql │ └── m_member.sql # 成员表初始化 SQL ├── frontend # 独立前端项目(可选) │ ├── src │ │ └── api │ │ └── client.ts # 后端 API 客户端封装 │ └── README.md # 前端独立项目说明 ├── src/main/java/com/rankeiot/easy │ ├── Main.java # 启动类 │ └── member │ ├── MemberMenu.java # 菜单与权限定义 │ ├── config │ │ └── MemberConfig.java # 模块配置项 │ ├── api │ │ └── MemberApiController.java # API 接口(供独立前端调用) │ ├── controller │ │ └── MemberController.java # 成员管理控制器 │ ├── dao │ │ └── MemberDao.java # 数据访问层 │ ├── dict │ │ ├── MemberStatus.java # 成员状态字典 │ │ └── MemberType.java # 成员类型字典 │ ├── domain │ │ └── Member.java # 成员实体类 │ ├── dto │ │ └── MemberVo.java # 成员值对象 │ └── service │ ├── MemberService.java # 服务层(实现IMemberLoader) │ └── MemberMapper.java # MapStruct 映射接口 └── src/main/resources ├── application.yml # 应用配置 ├── application-dev.yml # 开发环境配置 ├── models/member/m_member.json # 代码生成器模型定义 └── static ├── css │ └── global.css # 全局样式(隐藏首页面包屑) ├── js │ └── init.js # 全局初始化脚本 ├── home.vue # 首页 └── member ├── member.vue # 成员列表页面 └── memberDialog.vue # 成员编辑对话框 ``` ## 功能说明 ### 1. 成员管理(CRUD) | 功能 | 说明 | | ------ | ------------------------ | | 新增 | 添加新成员信息 | | 修改 | 编辑已有成员信息 | | 删除 | 批量删除成员 | | 查询 | 按手机号、姓名、状态查询 | | 详情 | 查看成员详细信息 | | 注册 | 会员自主注册 | | 重置密码 | 生成新随机密码 | ### 2. 会员登录 本模块实现了 `IMemberLoader` 接口,支持会员登录功能。登录时使用手机号作为账号。 ```java public class MemberService implements IMemberLoader { /** * 用于系统加载用户信息(会员登录验证) */ @Override public UserInfo loadMember(String username, String password) { Member member = memberDao.getByPhone(username); if (member == null) return null; // 验证密码 String encodedPassword = PasswordUtil.encodePassword(password, username); if (!Objects.equals(member.getPasswordHash(), encodedPassword)) { return null; } // 构建用户信息 UserInfo userInfo = new UserInfo(); userInfo.setId(member.getId().toString()); userInfo.setUserType(Current.TYPE_MEMBER); // 会员类型 userInfo.setUsername(member.getPhone()); userInfo.setName(member.getName()); userInfo.setSubType(member.getMemberType()); // 会员子类型 return userInfo; } } ``` ### 3. 密码管理 | 方法 | 说明 | | ----------------- | ------------------------ | | `register()` | 会员注册,设置自定义密码 | | `addMember()` | 后台添加会员,生成8位随机密码 | | `resetPassword()` | 重置密码,返回新随机密码 | | `getMemberByPhone()` | 根据手机号获取会员信息 | 密码加密使用 `PasswordUtil.encodePassword()`,采用盐值加密方式。 ### 4. 数据字典 **成员状态 (MemberStatus)** | 值 | 描述 | | ---- | ---- | | 0 | 正常 | | 1 | 锁定 | | 2 | 删除 | **成员类型 (MemberType)** | 值 | 描述 | | ------ | -------- | | COMMON | 普通会员 | | TEMP | 临时会员 | | VIP | VIP会员 | ### 5. 权限控制 | 权限Key | 说明 | | ----------------- | ------ | | Member.member | 查看 | | Member.member.add | 新增 | | Member.member.edit| 修改 | | Member.member.delete | 删除 | ## 后端指南 ### 实体类 (Member) ```java @Data @Entity(tableName="m_member") public class Member implements Serializable { public static final String TABLE = "m_member"; @Id(strategy = "identity") private Long id; @Column(name="phone") private String phone; // 手机号(账号) @Column(name="name") private String name; // 姓名 @Column(name="member_type") private String memberType; // 账号类型 @Column(name="gender") private String gender; // 性别 @Column(name="balance") private BigDecimal balance;// 余额 @Column(name="points") private Integer points; // 积分 @Column(name="status") private String status; // 状态 } ``` ### DAO 层 ```java @Dao public interface MemberDao extends SqlToyRepository { @Query(""" SELECT id,phone,name,member_type,gender,address,points,balance,status FROM m_member WHERE 1=1 #[and phone = :phone] #[and name = :name] #[and status = :status] """) Page list(Page pageable, Map params); } ``` ### Controller 层 ```java @Tag(name="成员") @Auth @ClientCallable @RestController @RequestMapping("member") public class MemberController { final LightDao dao; final MemberDao memberDao; final MemberMapper memberMapper; @Operation(summary="新增成员") @Auth(MemberMenu.MEMBER_ADD) @PostMapping("add") public Resp add(@Valid @RequestBody MemberVo memberVo) { Member member = memberMapper.toEntity(memberVo); dao.save(member); return Resp.ok(); } // ... 其他增删改查方法 } ``` ### Service 层 `MemberService` 实现了 `IMemberLoader` 接口,支持会员登录认证: ```java @Component @RequiredArgsConstructor public class MemberService implements IMemberLoader { final LightDao lightDao; final MemberDao memberDao; final MemberMapper memberMapper; /** * 会员注册 */ @Transactional public void register(MemberVo memberVo) { Member member = memberMapper.toEntity(memberVo); member.setId(null); member.setPasswordHash(PasswordUtil.encodePassword(member.getPasswordHash(), member.getPhone())); member.setStatus(MemberStatus.NORMAL.getValue()); member.setCreateTime(new Date()); member.setUpdateTime(new Date()); lightDao.save(member); } /** * 后台添加会员,生成随机密码 * @return 生成的8位随机密码 */ public String addMember(MemberVo memberVo) { Member member = memberMapper.toEntity(memberVo); member.setId(null); String password = PasswordUtil.generatePassword(8); member.setPasswordHash(PasswordUtil.encodePassword(password, member.getPhone())); member.setStatus(MemberStatus.NORMAL.getValue()); member.setCreateTime(new Date()); member.setUpdateTime(new Date()); lightDao.save(member); return password; } /** * 重置密码 * @return 新密码 */ public String resetPassword(String phone) { Member member = memberDao.getByPhone(phone); if (member == null) return null; String password = PasswordUtil.generatePassword(8); member.setPasswordHash(PasswordUtil.encodePassword(password, phone)); member.setUpdateTime(new Date()); lightDao.update(member); return password; } /** * 实现 IMemberLoader,供系统加载会员信息 */ @Override public UserInfo loadMember(String username, String password) { Member member = memberDao.getByPhone(username); if (member == null) return null; if (StringUtil.isNotEmpty(password)) { String encodedPassword = PasswordUtil.encodePassword(password, username); if (!Objects.equals(member.getPasswordHash(), encodedPassword)) { return null; } } UserInfo userInfo = new UserInfo(); userInfo.setId(member.getId().toString()); userInfo.setUserType(Current.TYPE_MEMBER); userInfo.setUsername(member.getPhone()); userInfo.setName(member.getName()); userInfo.setPassword(member.getPasswordHash()); userInfo.setSuper(false); userInfo.setSubType(member.getMemberType()); return userInfo; } /** * 根据手机号获取会员信息 */ public MemberVo getMemberByPhone(String phone) { Member member = memberDao.getByPhone(phone); return memberMapper.toVo(member); } } ``` ### 启动类配置 ```java @SpringBootApplication public class Main implements Module { //系统模块名 @Override public String name() { return "会员管理系统"; } @Override public void start(ApplicationContext applicationContext) { regMenu(MemberMenu.class); // 注册菜单 regFixedDict(MemberStatus.class); // 注册状态字典 regFixedDict(MemberType.class); // 注册类型字典 regConfigs(MemberConfig.class); // 注册配置项 addGlobalStyle("css/global.css"); // 注册全局样式表 setGlobalScripts("js/init.js"); // 注册全局JS } public static void main(String[] args) { SpringApplication.run(Main.class, args); } } ``` ### 配置项 (MemberConfig) `MemberConfig` 定义了会员管理系统的配置项,通过 `@Item` 注解声明: ```java public enum MemberConfig implements IConfigItem { @Item(title = "欢迎标题", defaultValue = "欢迎使用会员管理系统", front = true) WellComeTitle } ``` 配置项可通过以下方式获取: - 后端:`Config.getStr("MemberConfig.WellComeTitle")` - 前端:`window._configs['MemberConfig.WellComeTitle']`(仅 `front=true` 时可用) ## 前端指南 ### 全局资源 easy-demo 注册了全局样式和脚本: **全局样式 (`css/global.css`)**:隐藏首页面包屑导航栏 ```css .h-layout:has( .h-layout-content>.home) .breadcrumb-bar{ display: none; } ``` **全局脚本 (`js/init.js`)**:在 Vue 应用创建完成后执行初始化逻辑 ```javascript addEventListener('appCreated', (e) => { let app = e.data console.log("app创建完成,欢迎标题为" + _configs['MemberConfig.WellComeTitle']) }) ``` 可通过 `Module` 的以下方法注册全局资源: - `addGlobalStyle(path)` - 注册全局 CSS 样式表 - `setGlobalScripts(path)` - 注册全局 JS 脚本(非 ESM 模块) ### 列表页面 (member.vue) ```vue ``` ### 对话框 (memberDialog.vue) 通过 `Dialog` 组件引用,配合后端 `@ClientCallable` 注解自动生成的前端控制器调用。 ## 独立前端项目 本项目提供了独立的前端示例,可用于开发不依赖 EasyBoot 内置前端框架的独立应用(如小程序、App 等)。 ### 目录结构 ``` frontend ├── tsconfig.app.json # TypeScript 应用配置 ├── tsconfig.json # TypeScript 基础配置 ├── tsconfig.node.json # Node 环境 TypeScript 配置 └── src └── api └── client.ts # 后端 API 客户端封装 ``` ### 核心功能 `client.ts` 封装了以下功能: | 功能 | 说明 | | ---- | ---- | | `login()` | 会员登录 | | `logout()` | 退出登录 | | `getToken()` | 获取认证 Token | | `getUserInfo()` | 获取用户信息 | | `ajax` | HTTP 请求封装(get/post/put/delete/upload/download) | | `useController()` | 获取后端 Controller 调用接口 | | `getDicts()` | 获取数据字典 | | `encrypt()` | AES 加密 | ### 使用示例 ```typescript import { ajax, login, useController, getDicts } from './api/client' // 1. 登录(会员模式) await login('13800138000', 'password123', true) // 2. 获取控制器并调用 const controller = await useController('memberController') const result = await controller.list({ page: 0, pageSize: 10 }) // 3. 获取字典 const dicts = await getDicts(['MemberStatus', 'MemberType']) ``` ### 独立客户端登录模式 独立前端默认使用**会员登录模式** (`setClientModel('member')`),适用于: - 移动端 H5 应用 - 微信小程序 - App 应用 - 其他需要独立部署的前端 详细文档请参阅 [独立前端](https://gitee.com/qoder/easy-boot/blob/1.1/frontend/README.md)。 ## 数据库初始化 执行 `doc/sql/platform_mysql.sql` 初始基础数据: 执行 `doc/sql/m_member.sql` 创建成员表: ```shell mvn exec:java "-Dsql.file=doc/sql/platform_mysql.sql": mvn exec:java "-Dsql.file=doc/sql/schema.sql" ``` ## 快速运行 1. 确保 MySQL 数据库已安装并运行 2. 创建数据库 `easy_example` 3. 修改 `src/main/resources/application-dev.yml` 中的数据库连接配置 4. 执行 上述命令 初始化数据库 5. 运行 `Main.java` 的 main 方法启动项目 6. 访问 http://localhost:8080 ## 相关文档 - [EasyBoot 主文档](https://gitee.com/qoder/easy-boot/blob/1.1/README.md) - [独立前端说明](https://gitee.com/qoder/easy-boot/blob/1.1/frontend/README.md) - [Sqltoy 文档](https://gitee.com/sagacity/sagacity-sqltoy) - [Vue3 文档](https://cn.vuejs.org/) - [HeyUI 文档](https://v2.heyui.top/)