1. 环境准备与项目初始化
在开始构建用户管理模块前,我们需要先搭建好开发环境。这里我推荐使用HBuilderX作为开发工具,它内置了uniapp开发所需的所有插件和调试工具。安装完成后,通过以下步骤初始化项目:
- 从RuoYi官方仓库克隆前端模板:
git clone https://gitee.com/y_project/RuoYi-App.git- 安装依赖(建议使用pnpm提升安装速度):
cd RuoYi-App && pnpm install- 后端环境建议使用RuoYi-Cloud的最新版本,确保Nacos服务已启动。我在实际项目中遇到过版本不兼容的问题,所以特别提醒大家要检查版本对应关系:
| 前端版本 | 后端兼容版本 |
|---|---|
| v1.2.0 | RuoYi-Cloud 3.7.0+ |
配置中最容易出错的是Nacos服务发现配置。记得在application.yml中检查这两个关键配置:
spring: cloud: nacos: discovery: server-addr: 127.0.0.1:8848 config: server-addr: 127.0.0.1:88482. 后端用户模块开发实战
2.1 数据库设计与实体映射
用户表设计要考虑扩展性,这是我优化过的表结构:
CREATE TABLE `app_user` ( `user_id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID', `user_name` varchar(30) NOT NULL COMMENT '用户账号', `nick_name` varchar(30) NOT NULL COMMENT '用户昵称', `email` varchar(50) DEFAULT '' COMMENT '邮箱', `phonenumber` varchar(11) DEFAULT '' COMMENT '手机号码', `sex` char(1) DEFAULT '0' COMMENT '性别(0未知 1男 2女)', `avatar` varchar(100) DEFAULT '' COMMENT '头像地址', `status` char(1) DEFAULT '0' COMMENT '状态(0正常 1停用)', `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', `login_ip` varchar(50) DEFAULT '' COMMENT '最后登录IP', `login_date` datetime DEFAULT NULL COMMENT '最后登录时间', `create_by` varchar(64) DEFAULT '' COMMENT '创建者', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_by` varchar(64) DEFAULT '' COMMENT '更新者', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `remark` varchar(500) DEFAULT NULL COMMENT '备注', PRIMARY KEY (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';对应的Domain对象要加上Swagger注解方便调试:
@Data @ApiModel("用户实体") public class AppUser { @ApiModelProperty("用户ID") private Long userId; @NotBlank(message = "用户账号不能为空") @Size(min = 2, max = 30) @ApiModelProperty("用户账号") private String userName; // 其他字段省略... }2.2 业务逻辑层实现
Service层要处理好事务和异常,这是我的实现方案:
@Service public class AppUserServiceImpl implements IAppUserService { @Autowired private AppUserMapper userMapper; @Override @Transactional(readOnly = true) public List<AppUser> selectAppUserList() { return userMapper.selectAppUserList(); } @Override @Transactional(rollbackFor = Exception.class) public int insertAppUser(AppUser user) { // 用户名唯一性校验 if (userMapper.checkUserNameUnique(user.getUserName()) > 0) { throw new ServiceException("用户名已存在"); } user.setCreateTime(DateUtils.getNowDate()); return userMapper.insertAppUser(user); } }2.3 控制层RESTful设计
控制器要处理好参数校验和返回格式:
@RestController @RequestMapping("/app/user") @Api(tags = "用户管理") public class AppUserController extends BaseController { @Autowired private IAppUserService userService; @GetMapping("/list") @ApiOperation("获取用户列表") public TableDataInfo list(AppUser user) { startPage(); List<AppUser> list = userService.selectAppUserList(user); return getDataTable(list); } @PostMapping @ApiOperation("新增用户") public AjaxResult add(@Validated @RequestBody AppUser user) { return toAjax(userService.insertAppUser(user)); } }3. 前端uni-app集成
3.1 API请求封装
在api/user.js中封装用户相关接口:
import request from '@/utils/request' export function getUserList(params) { return request({ url: '/app/user/list', method: 'get', params }) } export function addUser(data) { return request({ url: '/app/user', method: 'post', data }) }3.2 页面组件开发
使用uni-ui的组件快速搭建界面:
<template> <view class="container"> <uni-card> <uni-table :data="userList"> <uni-table-column prop="userName" label="用户名"></uni-table-column> <uni-table-column prop="nickName" label="昵称"></uni-table-column> <uni-table-column label="操作"> <template #default="scope"> <uni-link @click="editUser(scope.row)">编辑</uni-link> </template> </uni-table-column> </uni-table> <uni-pagination :total="total" @change="handlePageChange" /> </uni-card> </view> </template> <script> import { getUserList } from '@/api/user' export default { data() { return { userList: [], total: 0, queryParams: { pageNum: 1, pageSize: 10 } } }, mounted() { this.loadData() }, methods: { async loadData() { const res = await getUserList(this.queryParams) this.userList = res.rows this.total = res.total }, handlePageChange(e) { this.queryParams.pageNum = e.current this.loadData() } } } </script>4. 跨平台适配与调试技巧
4.1 条件编译处理平台差异
不同平台需要特殊处理的地方:
<template> <!-- #ifdef MP-WEIXIN --> <button open-type="getUserInfo">微信授权</button> <!-- #endif --> <!-- #ifdef H5 --> <button @click="h5Login">H5登录</button> <!-- #endif --> </template> <script> export default { methods: { // #ifdef MP-WEIXIN wxLogin() { uni.login({ success(res) { console.log(res.code) } }) }, // #endif // #ifdef H5 h5Login() { this.$refs.form.validate() } // #endif } } </script>4.2 性能优化实践
- 图片懒加载:
<image lazy-load :src="user.avatar" mode="aspectFill" ></image>- 分页加载优化:
// 使用z-paging组件实现上拉加载 <z-paging ref="paging" v-model="dataList" @query="queryList" > <!-- 列表内容 --> </z-paging>- 接口缓存策略:
// 在store中缓存用户数据 const userStore = defineStore('user', { state: () => ({ cache: new Map() }), actions: { async getUser(id) { if (this.cache.has(id)) { return this.cache.get(id) } const res = await getUserDetail(id) this.cache.set(id, res) return res } } })5. 常见问题解决方案
- 跨域问题:在gateway模块添加CORS配置
@Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("*"); config.addAllowedHeader("*"); config.addAllowedMethod("*"); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); }- 小程序真机调试白屏:检查以下配置
- 确保域名已加入小程序后台request合法域名
- 基础库版本不低于2.10.0
- 清除编译缓存后重新运行
- H5页面路由刷新404:配置Nginx重定向
location / { try_files $uri $uri/ /index.html; }- 表单验证最佳实践:
<uni-forms :model="form" :rules="rules" ref="form"> <uni-forms-item label="用户名" name="userName"> <uni-easyinput v-model="form.userName" /> </uni-forms-item> </uni-forms> <script> export default { data() { return { rules: { userName: { rules: [{ required: true, errorMessage: '请输入用户名' }] } } } } } </script>