Test login api (#304)

* 优化登录注册流程,跑通注册登录、接口 (#297)

* fix manager-api bug

* 优化登录注册流程,跑通注册登录、接口

* update package

* update:第一个注册的用户是超级管理员

---------

Co-authored-by: zhisheng <pzs034@gmail.com>
Co-authored-by: hrz <1710360675@qq.com>
This commit is contained in:
欣南科技
2025-03-12 23:31:59 +08:00
committed by GitHub
co-authored by zhisheng hrz
parent 29d59b3974
commit c458a1b59a
15 changed files with 65 additions and 92 deletions
@@ -51,7 +51,7 @@ public class LoginController {
throw new RenException("验证码错误,请重新获取");
}
// 按照用户名获取用户
SysUserDTO userDTO = sysUserService.getByUsername(login.getMobile());
SysUserDTO userDTO = sysUserService.getByUsername(login.getUsername());
// 判断用户是否存在
if (userDTO == null) {
throw new RenException("请检测用户和密码是否输入错误");
@@ -72,15 +72,16 @@ public class LoginController {
throw new RenException("验证码错误,请重新获取");
}
// 按照用户名获取用户
SysUserDTO userDTO = sysUserService.getByUsername(login.getMobile());
SysUserDTO userDTO = sysUserService.getByUsername(login.getUsername());
if (userDTO != null){
throw new RenException("此手机号码已经注册过");
}
userDTO = new SysUserDTO();
userDTO.setUsername(login.getMobile());
userDTO.setUsername(login.getUsername());
userDTO.setPassword(login.getPassword());
sysUserService.save(userDTO);
return new Result<Void>();
}
}
@@ -15,7 +15,7 @@ public class LoginDTO implements Serializable {
@Schema(description = "手机号码")
@NotBlank(message = "{sysuser.username.require}")
private String mobile;
private String username;
@Schema(description = "密码")
@NotBlank(message = "{sysuser.password.require}")
@@ -80,7 +80,6 @@ public class SysUserController {
//效验数据
ValidatorUtils.validateEntity(dto);
String newPassword = dto.getNewPassword();
String password = dto.getPassword();
//密码的强度
if (newPassword == null || newPassword.length() < 8) {
@@ -38,23 +38,6 @@ public interface SysUserService extends BaseService<SysUserEntity> {
*/
void updatePassword(Long id, String newPassword);
/**
* 根据部门ID,查询用户数
*/
int getCountByDeptId(Long deptId);
/**
* 根据部门ID,查询用户Id列表
*/
List<Long> getUserIdListByDeptId(List<Long> deptIdList);
/**
* 删除用户缓存
*
* @param userId
*/
void deleteUserCache(Long userId);
/**
* 验证密码强度
*
@@ -63,5 +46,4 @@ public interface SysUserService extends BaseService<SysUserEntity> {
*/
boolean isStrongPassword(String newPassword);
String getName(Long creator);
}
@@ -1,25 +1,23 @@
package xiaozhi.modules.sys.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xiaozhi.common.exception.ErrorCode;
import xiaozhi.common.exception.RenException;
import xiaozhi.common.page.PageData;
import xiaozhi.common.redis.RedisKeys;
import xiaozhi.common.redis.RedisUtils;
import xiaozhi.common.service.impl.BaseServiceImpl;
import xiaozhi.common.user.UserDetail;
import xiaozhi.common.utils.ConvertUtils;
import xiaozhi.modules.security.password.PasswordUtils;
import xiaozhi.modules.security.user.SecurityUser;
import xiaozhi.modules.sys.dao.SysUserDao;
import xiaozhi.modules.sys.dto.SysUserDTO;
import xiaozhi.modules.sys.entity.SysUserEntity;
import xiaozhi.modules.sys.enums.SuperAdminEnum;
import xiaozhi.modules.sys.service.SysUserService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
@@ -86,7 +84,13 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserDao, SysUserEntit
entity.setPassword(password);
//保存用户
entity.setSuperAdmin(SuperAdminEnum.NO.value());
Long userCount = getUserCount();
if (userCount == 0) {
entity.setSuperAdmin(SuperAdminEnum.YES.value());
} else {
entity.setSuperAdmin(SuperAdminEnum.NO.value());
}
insert(entity);
}
@@ -139,23 +143,11 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserDao, SysUserEntit
baseDao.updatePassword(id, newPassword);
}
@Override
public int getCountByDeptId(Long deptId) {
return baseDao.getCountByDeptId(deptId);
private Long getUserCount() {
QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<>();
return baseDao.selectCount(queryWrapper);
}
@Override
public List<Long> getUserIdListByDeptId(List<Long> deptIdList) {
return baseDao.getUserIdListByDeptId(deptIdList);
}
@Override
public void deleteUserCache(Long userId) {
// 删除缓存
redisUtils.delete(RedisKeys.getUserInfoKey(userId));
redisUtils.delete(RedisKeys.getDataScopeListKey(userId));
redisUtils.delete(RedisKeys.getSysUserName(userId));
}
@Override
public boolean isStrongPassword(String password) {
@@ -165,17 +157,4 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserDao, SysUserEntit
Matcher matcher = pattern.matcher(password);
return matcher.matches();
}
@Override
public String getName(Long id) {
String name = (String) redisUtils.get(RedisKeys.getSysUserName(id));
if (StringUtils.isBlank(name)) {
SysUserEntity sysUserEntity = selectById(id);
if (sysUserEntity != null) {
redisUtils.set(RedisKeys.getSysUserName(id), sysUserEntity.getUsername());
return sysUserEntity.getUsername();
}
}
return name;
}
}
@@ -30,5 +30,5 @@
10029=Cannot contain illegal characters
10030=The password is less than {0} digits.
10031=Weak password. The password must contain {0} of uppercase letters, lowercase letters, symbols and numbers.
10031=The password must consist of numbers, uppercase and lowercase letters, and special characters at the same time
10032=Exception in deleting this data
@@ -30,5 +30,5 @@
10028=\u5B9A\u65F6\u4EFB\u52A1\u5931\u8D25
10029=\u4E0D\u80FD\u5305\u542B\u975E\u6CD5\u5B57\u7B26
10030=\u5BC6\u7801\u957F\u5EA6\u4E0D\u8DB3{0}\u4F4D
10031=\u5F31\u5BC6\u7801
10032=\u5220\u9664\u672C\u6570\u636E\u5F02\u5E38\u5EA6\u4E0D\u591F\uFF0C\u9700\u8981\u540C\u65F6\u5305\u542B\u6570\u5B57,\u5C0F\u5199\u82F1\u6587,\u5927\u5199\u82F1\u6587
10031=\u5BC6\u7801\u5FC5\u987B\u540C\u65F6\u5305\u542B\u6570\u5B57\u3001\u5927\u5C0F\u5B57\u6BCD\u548C\u7279\u6B8A\u5B57\u7B26\u7EC4\u6210
10032=\u5220\u9664\u672C\u6570\u636E\u5F02\u5E38
@@ -30,5 +30,5 @@
10028=\u5B9A\u6642\u4EFB\u52D9\u5931\u6557
10029=\u4E0D\u80FD\u5305\u542B\u975E\u6CD5\u5B57\u7B26
10030=\u5BC6\u78BC\u9577\u5EA6\u4E0D\u8DB3{0}\u4F4D
10031=\u5F31\u5BC6\u78BC\uFF0C\u5BC6\u78BC\u9700\u8981\u5305\u542B\u5927\u5BEB\u5B57\u6BCD\uFF0C\u5C0F\u5BEB\u5B57\u6BCD\uFF0C\u7B26\u865F\uFF0C\u6578\u5B57\u5176\u4E2D{0}\u7A2E
10031=\u5BC6\u78BC\u5FC5\u9808\u540C\u6642\u5305\u542B\u6578\u5B57\u3001\u5927\u5C0F\u5B57\u6BCD\u548C\u7279\u6B8A\u5B57\u7B26\u7D44\u6210
10032=\u522A\u9664\u6B64\u6578\u64DA\u7570\u5E38
@@ -36,15 +36,4 @@
update sys_user set password = #{newPassword} where id = #{id}
</update>
<select id="getCountByDeptId" resultType="int">
select count(*) from sys_user where dept_id = #{value}
</select>
<select id="getUserIdListByDeptId" resultType="Long">
select id from sys_user where dept_id in
<foreach item="deptId" collection="list" open="(" separator="," close=")">
#{deptId}
</foreach>
</select>
</mapper>
+6 -1
View File
@@ -14,7 +14,8 @@
"vue": "^2.6.14",
"vue-axios": "^3.5.2",
"vue-router": "^3.6.5",
"vuex": "^3.6.2"
"vuex": "^3.6.2",
"xiaozhi": "file:"
},
"devDependencies": {
"@vue/cli-plugin-router": "~5.0.0",
@@ -9157,6 +9158,10 @@
}
}
},
"node_modules/xiaozhi": {
"resolved": "",
"link": true
},
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz",
+2 -1
View File
@@ -13,7 +13,8 @@
"vue": "^2.6.14",
"vue-axios": "^3.5.2",
"vue-router": "^3.6.5",
"vuex": "^3.6.2"
"vuex": "^3.6.2",
"xiaozhi": "file:"
},
"devDependencies": {
"@vue/cli-plugin-router": "~5.0.0",
+1 -1
View File
@@ -9,7 +9,7 @@ import user from './module/user.js'
*/
const DEV_API_SERVICE = 'https://apifoxmock.com/m1/5931378-5618560-default'
// 8002开发完成完成后使用这个
// const DEV_API_SERVICE = '/xiaozhi-esp32-api/api/v1'
// const DEV_API_SERVICE = '/xiaozhi-esp32-api'
/**
* 根据开发环境返回接口url
+11 -5
View File
@@ -25,7 +25,7 @@
</div>
<div class="input-box">
<img src="@/assets/login/password.png" alt="" class="input-icon"/>
<el-input v-model="form.password" placeholder="请输入密码"/>
<el-input v-model="form.password" type="password" placeholder="请输入密码"/>
</div>
<div style="display: flex; align-items: center; margin-top: 20px; width: 100%; gap: 10px;">
<div class="input-box" style="width: calc(100% - 130px); margin-top: 0;">
@@ -63,7 +63,7 @@
</template>
<script>
import {goToPage, showDanger, showSuccess} from '@/utils'
import {getUUID, goToPage, showDanger, showSuccess} from '@/utils'
import Api from '@/apis/api';
@@ -75,7 +75,8 @@ export default {
form: {
username: '',
password: '',
captcha: ''
captcha: '',
captchaId: ''
},
captchaUuid: '',
captchaUrl: ''
@@ -86,7 +87,7 @@ export default {
},
methods: {
fetchCaptcha() {
this.captchaUuid = Date.now().toString()
this.captchaUuid = getUUID();
Api.user.getCaptcha(this.captchaUuid, (res) => {
if (res.status === 200) {
@@ -95,7 +96,7 @@ export default {
} else {
console.error('验证码加载异常:', error);
showDanger('验证码加载失败,点击刷新');
showDanger('验证码加载失败,点击刷新')
}
});
},
@@ -114,10 +115,15 @@ export default {
return
}
this.form.captchaId = this.captchaUuid
Api.user.login(this.form, ({data}) => {
console.log(data)
showSuccess('登陆成功!')
goToPage('/home')
})
setTimeout(() => {
this.fetchCaptcha()
}, 1000)
},
goToRegister() {
+7 -5
View File
@@ -83,7 +83,7 @@
</template>
<script>
import {goToPage, showDanger, showSuccess} from '@/utils'
import {getUUID, goToPage, showDanger, showSuccess} from '@/utils'
import Api from '@/apis/api';
export default {
@@ -95,7 +95,7 @@ export default {
password: '',
confirmPassword: '',
captcha: '',
uuid: ''
captchaId: ''
},
captchaUrl: ''
}
@@ -106,8 +106,8 @@ export default {
methods: {
// 复用验证码获取方法
fetchCaptcha() {
this.form.uuid = Date.now().toString()
Api.user.getCaptcha(this.form.uuid, (res) => {
this.form.captchaId = getUUID();
Api.user.getCaptcha(this.form.captchaId, (res) => {
if (res.status === 200) {
const blob = new Blob([res.data], {type: res.data.type});
this.captchaUrl = URL.createObjectURL(blob);
@@ -147,7 +147,9 @@ export default {
this.fetchCaptcha()
}
})
setTimeout(() => {
this.fetchCaptcha()
}, 1000)
},
goToLogin() {
+14 -5
View File
@@ -1,14 +1,23 @@
const { defineConfig } = require('@vue/cli-service');
const dotenv = require('dotenv');
// 确保加载 .env 文件
dotenv.config();
module.exports = defineConfig({
devServer: {
// Bug 修复:将代理配置为环境变量中定义的 API 基础 URL
proxy: process.env.VUE_APP_API_BASE_URL,
client: {
overlay: false,
proxy: {
'/xiaozhi-esp32-api': {
target: process.env.VUE_APP_API_BASE_URL || 'http://localhost:8002', // 后端 API 的基础 URL
changeOrigin: true, // 允许跨域
// pathRewrite: {
// '^/api': '', // 路径重写
// },
},
},
client: {
overlay: false,
},
},
}
})
});