基于SpringBoot+Vue+uni-app的Element UI手机品牌官网管理系统
项目概述
本系统采用SpringBoot作为后端框架,Vue.js结合uni-app实现前端与移动端展示,整合Element UI组件库构建响应式界面。系统设计目标是帮助企业快速搭建手机品牌官方网站,涵盖产品展示、用户管理、订单处理等功能模块。项目提供完整源码、数据库脚本、部署文档及技术讲解,适合作为毕业设计或企业级应用参考。
核心技术栈
后端:SpringBoot
SpringBoot内嵌Tomcat、Jetty等容器,无需单独部署服务器。其自动配置机制根据项目依赖智能调整环境,减少手动配置量。框架集成Spring Data JPA、Spring Security等子项目,支持快速开发RESTful API。开发者可借助起步依赖(Starter)快速引入所需功能,同时通过属性文件集中管理配置,提升开发效率。
前端:Vue.js + Element UI
Vue.js基于虚拟DOM实现高效UI更新,数据驱动视图自动同步。结合Element UI组件库,可快速构建表单、表格、弹窗等常见界面元素。本项目采用Vue Router管理单页路由,Vuex处理全局状态,前端代码结构清晰,易于维护扩展。
数据持久化:MyBatis-Plus
MyBatis-Plus在MyBatis基础上增强,提供通用Mapper和条件构造器,减少SQL编写量。内置代码生成器可自动生成Entity、Mapper、Service层代码,支持分页插件、乐观锁、逻辑删除等实用功能。框架兼容MySQL、PostgreSQL等多种数据库,适合企业级数据访问需求。
系统测试策略
测试目标
系统测试旨在验证功能完整性、逻辑正确性及用户体验流畅度。通过黑盒测试模拟用户操作场景,覆盖登录、CRUD、权限控制等核心流程,确保系统无严重缺陷。测试过程中重点检查边界值输入、必填项校验、异常数据容错等场景。
功能测试用例
登录模块测试
| 输入数据 | 预期结果 | 实际结果 | 分析 |
|---|---|---|---|
| 用户: admin, 密码: 123456, 验证码: 正确 | 登录成功 | 跳转首页 | 符合预期 |
| 用户: admin, 密码: 错误, 验证码: 正确 | 密码错误提示 | 显示"密码错误" | 符合预期 |
| 用户: admin, 密码: 正确, 验证码: 错误 | 验证码错误提示 | 显示"验证码不匹配" | 符合预期 |
| 用户: 空, 密码: 123456, 验证码: 正确 | 用户名必填提示 | 提示"请输入用户名" | 符合预期 |
| 用户: admin, 密码: 空, 验证码: 正确 | 密码必填提示 | 提示"请输入密码" | 符合预期 |
用户管理测试
| 操作 | 预期结果 | 实际结果 | 分析 |
|---|---|---|---|
| 添加有效用户信息 | 用户列表新增记录 | 列表中显示新用户 | 符合预期 |
| 修改用户信息 | 数据更新成功 | 页面信息变更 | 符合预期 |
| 删除用户(确认) | 用户从列表移除 | 删除后列表无此用户 | 符合预期 |
| 添加用户时用户名留空 | 非空校验提示 | 提示"用户名不能为空" | 符合预期 |
| 添加已存在的用户名 | 重复检查提示 | 提示"用户名已存在" | 符合预期 |
测试结论
通过全面黑盒测试,系统各功能模块逻辑正确,数据校验机制完善,用户操作反馈清晰。登录、权限管理、数据增删改查等核心功能均满足设计需求。系统在性能上响应快速,无明显卡顿或异常。最终测试结果表明,系统已达到上线标准,具备良好稳定性和可用性。
核心代码示例
登录接口实现
@IgnoreAuth
@PostMapping("/login")
public R loginAction(@RequestParam String username,
@RequestParam String password,
@RequestParam String captcha,
HttpServletRequest request) {
// 查询用户
UsersEntity user = userService.queryOne(
new QueryWrapper<UsersEntity>().eq("username", username));
if (user == null || !password.equals(user.getPassword())) {
return R.error(401, "账号或密码错误");
}
// 生成令牌
String token = tokenService.createToken(
user.getId(), username, "users", user.getRole());
return R.ok().put("accessToken", token);
}
// 令牌生成方法
@Override
public String createToken(Long userId, String username,
String tableName, String role) {
TokenEntity existing = this.getOne(
new QueryWrapper<TokenEntity>()
.eq("userid", userId)
.eq("role", role));
String tokenValue = RandomStringUtils.randomAlphanumeric(32);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.HOUR, 1); // 过期时间1小时
if (existing != null) {
existing.setToken(tokenValue);
existing.setExpireTime(calendar.getTime());
this.updateById(existing);
} else {
TokenEntity newToken = new TokenEntity();
newToken.setUserId(userId);
newToken.setUsername(username);
newToken.setTableName(tableName);
newToken.setRole(role);
newToken.setToken(tokenValue);
newToken.setExpireTime(calendar.getTime());
this.save(newToken);
}
return tokenValue;
}
拦截器配置
@Component
public class AuthInterceptor implements HandlerInterceptor {
private static final String TOKEN_HEADER = "Authorization";
@Autowired
private TokenService tokenService;
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 处理跨域
response.setHeader("Access-Control-Allow-Origin",
request.getHeader("Origin"));
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpStatus.OK.value());
return false;
}
// 检查是否忽略验证
if (handler instanceof HandlerMethod) {
HandlerMethod hm = (HandlerMethod) handler;
if (hm.getMethodAnnotation(IgnoreAuth.class) != null) {
return true;
}
}
// 获取令牌
String token = request.getHeader(TOKEN_HEADER);
if (StringUtils.isBlank(token)) {
sendUnauthorized(response, "请先登录");
return false;
}
// 验证令牌
TokenEntity tokenEntity = tokenService.getTokenEntity(token);
if (tokenEntity == null ||
tokenEntity.getExpireTime().before(new Date())) {
sendUnauthorized(response, "令牌无效或已过期");
return false;
}
// 设置会话属性
request.getSession().setAttribute("currentUserId",
tokenEntity.getUserId());
request.getSession().setAttribute("currentRole",
tokenEntity.getRole());
return true;
}
private void sendUnauthorized(HttpServletResponse response,
String message) throws IOException {
response.setContentType("application/json;charset=UTF-8");
PrintWriter writer = response.getWriter();
writer.write(JSON.toJSONString(R.error(401, message)));
writer.close();
}
}
数据库设计示例
-- 用户令牌表
CREATE TABLE `sys_token` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` BIGINT(20) NOT NULL COMMENT '用户ID',
`username` VARCHAR(100) NOT NULL COMMENT '用户名',
`table_name` VARCHAR(100) DEFAULT NULL COMMENT '关联表名',
`role` VARCHAR(50) DEFAULT NULL COMMENT '用户角色',
`token` VARCHAR(200) NOT NULL COMMENT '令牌值',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`expire_time` DATETIME NOT NULL COMMENT '过期时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_user_role` (`user_id`, `role`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户登录令牌表';
-- 示例数据
INSERT INTO `sys_token` VALUES
(1, 1, 'admin', 'users', '管理员',
'xk3m9d7f1a4b2c8e6p0q5r9s2t7u4v',
'2024-01-01 10:00:00', '2024-01-01 11:00:00'),
(2, 23, 'zhangsan', 'student', '学生',
'a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p',
'2024-01-02 14:30:00', '2024-01-02 15:30:00');
获取资源
如需完整项目源码、数据库文件、部署文档及详细技术讲解,请通过平台私信联系。系统包含500余套Java实战案例及微信小程序项目,提供定制化开发与就业辅导服务。感谢点赞、收藏与关注,更多优质项目请订阅专栏查看。