uniapp-含有后端的登录注册页面编写

创建数据库

数据库结构

表名:user

列名数据类型描述
idint自增ID
usernamevarchar用户名
passwordvarchar密码
nicknamevarchar昵称

这个方案只保留了id、username、password和nickname四个字段,以最简单的方式存储用户基本信息。需要注意的是,密码应该进行安全处理(如加密),避免泄露敏感信息。如果后续有新增信息需求,则可以随时更改表结构,添加相应的列即可。

数据库代码

-- 创建 usertable 数据库CREATE DATABASE IF NOT EXISTS usertable;-- 切换至 usertable 数据库USE usertable;-- 创建 user 表CREATE TABLE IF NOT EXISTS user (id INT(11) NOT NULL AUTO_INCREMENT,username VARCHAR(100) NOT NULL UNIQUE,password VARCHAR(100) NOT NULL,nickname VARCHAR(100) NOT NULL,PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- 添加一些测试数据INSERT INTO user (username, password, nickname) VALUES ('user1', 'password1', '张三');INSERT INTO user (username, password, nickname) VALUES ('user2', 'password2', '李四');INSERT INTO user (username, password, nickname) VALUES ('user3', 'password3', '王五');

这段SQL代码用于创建一个名为user的表格,并且添加了一些简单的测试数据。其中,id列使用了自增主键约束,保证数据的唯一性。username列使用了unique约束,确保用户名的唯一性。请注意,utf8mb4是一种更高效和更通用的字符编码,支持更广泛的Unicode字符集,所以它比utf-8更推荐使用。

后端编写

创建项目(准备工作)




pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.11</version><relativePath/> </parent><groupId>com.example</groupId><artifactId>userTable</artifactId><version>0.0.1-SNAPSHOT</version><name>userTable</name><description>userTable</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.7.6</version></dependency><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-jpa</artifactId><version>2.5.6</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>5.6.3.Final</version></dependency><dependency><groupId>javax.persistence</groupId><artifactId>javax.persistence-api</artifactId><version>2.2</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.0</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.0</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.8.0</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.2</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.11.2</version><scope>runtime</scope></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId><version>0.11.2</version><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.8.0</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

application.properties

# ?????spring.datasource.url=jdbc:mysql://localhost:3306/usertable?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghaispring.datasource.username=rootspring.datasource.password=123456spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver# ???????server.port=8081# MyBatis-Plus ??mybatis-plus.mapper-locations=classpath:/mapper/*.xmlmybatis-plus.type-aliases-package=com.example.demo.entitymybatis-plus.global-config.db-config.id-type=automybatis-plus.configuration.map-underscore-to-camel-case=truemybatis-plus.configuration.use-generated-keys=truemybatis-plus.configuration.map-enum-as-ordinal=falsemybatis-plus.configuration.enum-handler=com.baomidou.mybatisplus.extension.handlers.MybatisEnumTypeHandler

Bean

User

import com.baomidou.mybatisplus.annotation.TableName;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@Data@AllArgsConstructor@NoArgsConstructor@TableName("user")// 声明对应的数据库表名(user)public class User {private Long id;private String username;private String password;private String nickname;}

Result

import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;@Data@Builder@AllArgsConstructor@NoArgsConstructorpublic class Result { private Integer code; // 状态码private String message; // 状态信息private Object data;// 数据}

config

CorsConfig

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.CorsRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;@Configurationpublic class CorsConfig {@Beanpublic WebMvcConfigurer corsConfigurer() {return new WebMvcConfigurerAdapter() {@Overridepublic void addCorsMappings(CorsRegistry registry) {// 允许来自本地的8080端口发起的跨域请求registry.addMapping("/api/**").allowedOrigins("*").allowedMethods("GET", "POST", "PUT", "DELETE").allowCredentials(true).maxAge(3600);}};}}

Mapper

UserMapper

import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.example.usertable.Bean.User;import org.apache.ibatis.annotations.Mapper;@Mapperpublic interface UserMapper extends BaseMapper<User> {}

Service

UserService

import com.baomidou.mybatisplus.core.metadata.IPage;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.baomidou.mybatisplus.extension.service.IService;import com.example.usertable.Bean.User;public interface UserService extends IService<User> {/** * 分页查询用户列表 */IPage<User> selectPage(Page<User> page);/** * 用户注册 */boolean register(User user);/** * 用户登录 */User login(String username, String password);}

ServiceImpl

UserServiceImpl

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.core.metadata.IPage;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.example.usertable.Bean.User;import com.example.usertable.Mapper.UserMapper;import com.example.usertable.Service.UserService;import lombok.AllArgsConstructor;import org.springframework.stereotype.Service;import org.springframework.util.StringUtils;@Service@AllArgsConstructorpublic class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {@Overridepublic IPage<User> selectPage(Page<User> page) {return baseMapper.selectPage(page, null);}/** * 注册新用户(需先检查用户名是否已被使用) */@Overridepublic boolean register(User user) {String username = user.getUsername();// 根据用户名查询用户User u = this.getOne(new QueryWrapper<User>().eq("username", username));if (u != null) {// 用户名已存在return false;} else {// 将用户保存到数据库return this.save(user);}}/** * 用户登录(根据用户名和密码查询用户) */@Overridepublic User login(String username, String password) {if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {// 用户名和密码不能为空return null;}return this.getOne(new QueryWrapper<User>().eq("username", username).eq("password", password));}}

Controller

UserController

import com.baomidou.mybatisplus.core.metadata.IPage;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.example.usertable.Bean.Result;import com.example.usertable.Bean.User;import com.example.usertable.Service.UserService;import lombok.AllArgsConstructor;import org.springframework.validation.annotation.Validated;import org.springframework.web.bind.annotation.*;@AllArgsConstructor@RestController@RequestMapping("/users")public class UserController {private final UserService userService;/** * 获取用户列表(分页) */@GetMapping("/")public Result list(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize) {// 构建分页对象Page<User> page = new Page<>(pageNum, pageSize);// 分页查询用户数据IPage<User> userPage = userService.page(page, null);return Result.builder().code(200).message("获取成功").data(userPage).build();}/** * 根据 ID 获取用户信息 */@GetMapping("/{id}")public Result detail(@PathVariable Long id) {// 查询用户信息User user = userService.getById(id);if (user != null) {return Result.builder().code(200).message("获取成功").data(user).build();} else {return Result.builder().code(404).message("用户不存在").build();}}/** * 注册 */@PostMapping("/register")public Result register(@RequestBody @Validated User user) {boolean success = userService.register(user);if (success) {return Result.builder().code(200).message("注册成功").data(user).build();} else {return Result.builder().code(500).message("用户名已存在").build();}}/** * 登录 */@PostMapping("/login")public Result login(@RequestBody User user) {String username = user.getUsername();String password = user.getPassword();// 查询用户User loginUser = userService.login(username, password);if (loginUser != null) {return Result.builder().code(200).message("登录成功").data(loginUser).build();} else {return Result.builder().code(401).message("用户名或密码错误").build();}}/** * 新增用户 */@PostMapping("/")public Result add(@RequestBody @Validated User user) {boolean success = userService.save(user);if (success) {return Result.builder().code(200).message("新增成功").data(user).build();} else {return Result.builder().code(500).message("新增失败").data(user).build();}}/** * 更新用户信息 */@PutMapping("/{id}")public Result update(@PathVariable Long id, @RequestBody @Validated User user) {user.setId(id);boolean success = userService.updateById(user);if (success) {return Result.builder().code(200).message("更新成功").data(user).build();} else {return Result.builder().code(500).message("更新失败").data(user).build();}}/** * 删除用户 */@DeleteMapping("/{id}")public Result delete(@PathVariable Long id) {boolean success = userService.removeById(id);if (success) {return Result.builder().code(200).message("删除成功").build();} else {return Result.builder().code(500).message("删除失败").build();}}}

Postman测试

测试所有的接口
以下是基于8081端口号的 Postman 测试:

1. 获取用户列表(分页)

请求地址:http://localhost:8081/users/

请求方法:GET

请求参数:

参数名称参数类型是否必须默认值参数说明
pageNumInteger1当前页码
pageSizeInteger10每页记录数

成功响应:

{"code": 200,"message": "获取成功","data": {"records": [{"id": 1,"username": "user1","password": "password1","nickname": "张三"},{"id": 2,"username": "user2","password": "password2","nickname": "李四"},{"id": 3,"username": "user3","password": "password3","nickname": "王五"}],"total": 0,"size": 10,"current": 1,"orders": [],"optimizeCountSql": true,"hitCount": false,"countId": null,"maxLimit": null,"searchCount": true,"pages": 0}}

2. 根据 ID 获取用户信息

请求地址:http://localhost:8081/users/{id}

请求方法:GET

请求路径参数:

参数名称参数类型是否必须示例值参数说明
idLong1用户 ID

成功响应:

{"code": 200,"message": "获取成功","data": {"id": 1,"username": "user1","password": "password1","nickname": "张三"}}

3. 注册

请求地址:http://localhost:8081/users/register

请求方法:POST

请求参数:

参数名称参数类型是否必须示例值参数说明
usernameStringuser-11用户名
passwordStringpass-11密码
nicknameStringlihua昵名

请求示例:

{"username": "user-11","password": "pass-11","nickname":"lihua"}

成功响应:

{"code": 200,"message": "注册成功","data": {"id": 4,"username": "user-11","password": "pass-11","nickname": "lihua"}}

失败响应:

{"code": 500,"message": "用户名已存在"}

4. 登录

请求地址:http://localhost:8081/users/login

请求方法:POST

请求参数:

参数名称参数类型是否必须示例值参数说明
usernameStringuser-1用户名
passwordStringpass-1密码

请求示例:

{"username": "user2","password": "password2"}

成功响应:

{"code": 200,"message": "登录成功","data": {"password": "password2","nickname": "李四","id": 2,"username": "user2"}}

失败响应:

{"code": 401,"message": "用户名或密码错误","data": null}

5. 新增用户

请求地址:http://localhost:8081/users/

请求方法:POST

请求参数:

参数名称参数类型是否必须示例值参数说明
usernameStringuser-12用户名
passwordStringpass-12密码
nicknameString小李昵名

请求示例:

{"username": "user-12","password": "pass-12","nickname": "小李"}

成功响应:

{"code": 200,"message": "新增成功","data": {"id": 5,"username": "user-12","password": "pass-12","nickname": "小李"}}

失败响应:

{"code": 500,"message": "新增失败"}

6. 更新用户信息

请求地址:http://localhost:8081/users/{id}

请求方法:PUT

请求路径参数:

参数名称参数类型是否必须示例值参数说明
usernameStringuser-12-update用户名
passwordStringpass-12-update密码
emailStringuser-12-update@example.com邮箱
phoneString12345678901手机号

请求示例:

{"username": "user-13","password": "pass-13","nickname": "小李"}

成功响应:

{"code": 200,"message": "更新成功","data": {"id": 1,"username": "user-13","password": "pass-13","nickname": "小李"}}

失败响应:

{"code": 500,"message": "更新失败"}

7. 删除用户

请求地址:http://localhost:8081/users/{id}

请求方法:DELETE

请求路径参数:

参数名称参数类型是否必须示例值参数说明
idLong12用户 ID

成功响应:

{"code": 200,"message": "删除成功"}

失败响应:

{"code": 500,"message": "删除失败"}

前端编写


页面编写

效果展示


文件目录

pages.json

manifest.json

{"name": "LoginAndRegister","appid" : "","description" : "","versionName" : "1.0.0","versionCode" : "100","transformPx" : false,/* 5+App特有相关 */"app-plus" : {"usingComponents" : true,"nvueStyleCompiler" : "uni-app","compilerVersion" : 3,"splashscreen" : {"alwaysShowBeforeRender" : true,"waiting" : true,"autoclose" : true,"delay" : 0},/* 模块配置 */"modules" : {},/* 应用发布信息 */"distribute" : {/* android打包配置 */"android" : {"permissions" : ["","","","","","","","","","","","","","",""]},/* ios打包配置 */"ios" : {},/* SDK配置 */"sdkConfigs" : {}}},/* 快应用特有相关 */"quickapp" : {},/* 小程序特有相关 */"mp-weixin" : {"appid" : "","setting" : {"urlCheck" : false},"usingComponents" : true},"mp-alipay" : {"usingComponents" : true},"mp-baidu" : {"usingComponents" : true},"mp-toutiao" : {"usingComponents" : true},"uniStatistics" : {"enable" : false},"vueVersion" : "2","h5" : {"devServer" : { "port" : 8080, //浏览器运行端口"disableHostCheck" : true, //设置跳过host检查"proxy" : {"/api" : {"target" : "http://localhost:8081", //目标接口域名 "changeOrigin" : true,//是否跨域 "secure" : false,// 设置支持https协议的代理 "pathRewrite":{"^/api":""} }}}}}

index.vue

<template><view class="content"><image class="logo" src="/static/logo.png"></image><view class="text-area"><text class="title">{{title}}</text><button @click="handleClick">点击我</button></view></view></template><script>export default {data() {return {title: 'Hello'}},onLoad() {},methods: {handleClick() {console.log('您点击了该按钮!')}}}</script><style>.content {display: flex;flex-direction: column;align-items: center;justify-content: center;}.logo {height: 200rpx;width: 200rpx;margin-top: 200rpx;margin-left: auto;margin-right: auto;margin-bottom: 50rpx;}.text-area {display: flex;justify-content: center;}.title {font-size: 36rpx;color: #8f8f94;}</style>

login.vue

<template><view class="login"><image class="logo" src="/static/logo.png"></image><view class="input-item"><input type="text" v-model="username" placeholder="请输入用户名"></view><view class="input-item"><input type="password" v-model="password" placeholder="请输入密码"></view><button @click="login" class="login-btn">登录</button><button @click="goToRegister" class="register-btn">注册</button></view></template><script>import axios from 'axios'export default {data() {return {username: '',password: ''}},methods: {login() {if (!this.username || !this.password) {uni.showToast({title: '请填写用户名和密码',icon: 'none'})return}// 发送请求验证用户axios.post('/api/users/login', {username: this.username,password: this.password}).then(res => {console.log(res.data.code)if (res.data.code === 200) {// 将用户信息保存到客户端本地缓存中uni.setStorageSync('userInfo', {id: res.data.data.id,username: res.data.data.username,password: res.data.data.password,nickname: res.data.data.nickname})// 跳转到首页uni.navigateTo({url: '/pages/index/index'})} else {uni.showToast({title: res.data.message,icon: 'none'})}}).catch(err => {uni.showToast({title: '网络请求失败,请重试',icon: 'none'})})},goToRegister() {uni.navigateTo({url: '/pages/register/register'})}}}</script><style scoped>.login {display: flex;flex-direction: column;justify-content: center;align-items: center;margin-top: 100rpx;}.logo {width: 200rpx;height: 200rpx;margin-bottom: 20rpx;}.login-form {width: 90%;padding: 40rpx;background-color: #fff;border-radius: 5rpx;}.input-item {width: 80%;margin: 10rpx 0;border-bottom: 1rpx solid #ddd;}input {width: 100%;height: 50rpx;padding: 10rpx;font-size: 16rpx;outline: none;border: none;}.login-btn {display: block;margin: 30rpx auto 0;width: 80%;height: 80rpx;line-height: 80rpx;text-align: center;background-color: #007aff;color: #fff;border-radius: 5rpx;font-size: 20rpx;}.register-btn {margin-top: 20rpx;color: #007aff;width: 60%;height: 80rpx;}</style>

register.vue

<template><view class="register"><image class="logo" src="/static/logo.png"></image><form class="register-form"><view class="input-item"><input type="text" v-model="nickname" placeholder="请输入昵称"></view><view class="input-item"><input type="text" v-model="username" placeholder="请输入用户名"></view><view class="input-item"><input type="password" v-model="password" placeholder="请输入密码"></view><view class="input-item"><input type="password" v-model="confirmPassword" placeholder="请确认密码"></view><button type="button" class="register-btn" @click="register">注册</button></form><button class="back-btn" @click="goBack">返回</button></view></template><script>import axios from 'axios';export default {data() {return {username: '',password: '',confirmPassword: '',nickname: ''};},methods: {async register() {if(!this.username || !this.password || !this.nickname) {uni.showToast({title: '请填写完整信息',icon: 'none'});return;}if(this.password !== this.confirmPassword) {uni.showToast({title: '两次输入密码不一致',icon: 'none'});return;}try {const response = await axios.post('/api/users/register', {username: this.username,password: this.password,nickname: this.nickname});const responseData = response.data;if(responseData.code === 200) {uni.showToast({title: responseData.message,icon: 'success'});uni.navigateTo({url: '/pages/login/login'});} else {uni.showToast({title: responseData.message,icon: 'none'});}} catch (error) {let errorMessage = '注册失败,请稍后再试';if(error.response) {if(error.response.status === 500) {errorMessage = error.response.data.message;}}uni.showToast({title: errorMessage,icon: 'none'});}},goBack() {uni.navigateBack();}}};</script><style scoped>.register {display: flex;flex-direction: column;justify-content: center;align-items: center;margin-top: 100rpx;}.logo {width: 200rpx;height: 200rpx;margin-bottom: 20rpx;}.register-form {width: 90%;padding: 40rpx;background-color: #fff;border-radius: 5rpx;}.input-item {margin: 10rpx 0;border-bottom: 1rpx solid #ddd;}input {width: 100%;height: 50rpx;padding: 10rpx;font-size: 16rpx;outline: none;border: none;}.register-btn {display: block;margin: 30rpx auto 0;width: 90%;height: 80rpx;line-height: 80rpx;text-align: center;background-color: #007aff;color: #fff;border-radius: 5rpx;font-size: 20rpx;}.back-btn {margin-top: 20rpx;color: #007aff;width: 60%;height: 80rpx;}</style>