1
0

14 Commits

Author SHA1 Message Date
f70c3fa399 Merge branch 'dyf-device' 2025-07-23 19:23:57 +08:00
d849be68ed 删除设备:分配记录 2025-07-23 19:22:25 +08:00
f80debbf2b 登录问题修复 2025-07-23 15:51:25 +08:00
ad59eea2a9 删除设备:分配记录 2025-07-23 14:27:08 +08:00
da6b888934 Merge branch 'dyf-device' 2025-07-23 10:54:20 +08:00
619356209b 删除设备 2025-07-23 10:53:26 +08:00
d84a7cde3b 帐号状态(0正常 1停用)status 2025-07-23 09:52:28 +08:00
e4dbee15dd 设备分享功能开发 2025-07-22 18:37:02 +08:00
33e53de5a1 设备主题 2025-07-22 16:13:39 +08:00
3bce279d7b 修改客户-用户名重复校验 2025-07-22 09:58:49 +08:00
9338b0d24b 设备详情功能开发 2025-07-21 15:24:26 +08:00
879e485056 Merge branch 'dyf-device' 2025-07-21 08:39:55 +08:00
69c4cc2004 APP设备分享功能开发2 2025-07-19 14:28:07 +08:00
a7340c744e APP客户设备绑定-绑定时间 2025-07-19 14:22:36 +08:00
53 changed files with 359 additions and 681 deletions

View File

@ -94,10 +94,10 @@
</dependency>
<!-- demo模块 -->
<dependency>
<!--<dependency>
<groupId>com.fuyuanshen</groupId>
<artifactId>fys-demo</artifactId>
</dependency>
</dependency>-->
<!-- 工作流模块 -->
<dependency>

View File

@ -4,13 +4,14 @@ import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.exception.NotLoginException;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.fuyuanshen.app.model.AppSmsLoginBody;
import com.fuyuanshen.app.service.AppLoginService;
import com.fuyuanshen.common.core.constant.SystemConstants;
import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.core.domain.model.AppLoginBody;
import com.fuyuanshen.common.core.domain.model.AppSmsRegisterBody;
import com.fuyuanshen.common.core.domain.model.PasswordLoginBody;
import com.fuyuanshen.common.core.domain.model.RegisterBody;
import com.fuyuanshen.common.core.domain.model.SmsLoginBody;
import com.fuyuanshen.common.core.utils.*;
import com.fuyuanshen.common.encrypt.annotation.ApiEncrypt;
import com.fuyuanshen.common.json.utils.JsonUtils;
import com.fuyuanshen.common.satoken.utils.LoginHelper;
import com.fuyuanshen.common.tenant.helper.TenantHelper;
@ -23,8 +24,8 @@ import com.fuyuanshen.system.service.ISysTenantService;
import com.fuyuanshen.web.domain.vo.LoginTenantVo;
import com.fuyuanshen.web.domain.vo.LoginVo;
import com.fuyuanshen.web.domain.vo.TenantListVo;
import com.fuyuanshen.web.service.AppRegisterService;
import com.fuyuanshen.web.service.IAuthStrategy;
import com.fuyuanshen.web.service.SysRegisterService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -50,7 +51,7 @@ import java.util.List;
public class AppAuthController {
private final AppLoginService loginService;
private final AppRegisterService registerService;
private final SysRegisterService registerService;
private final ISysConfigService configService;
private final ISysTenantService tenantService;
private final ISysClientService clientService;
@ -63,15 +64,15 @@ public class AppAuthController {
*/
// @ApiEncrypt
@PostMapping("/login")
public R<LoginVo> login(@RequestBody AppLoginBody appLoginBody) {
public R<LoginVo> login(@RequestBody AppSmsLoginBody appSmsLoginBody) {
// SmsLoginBody loginBody = JsonUtils.parseObject(body, SmsLoginBody.class);
ValidatorUtils.validate(appLoginBody);
PasswordLoginBody loginBody = new PasswordLoginBody();
loginBody.setUsername(appLoginBody.getUserName());
loginBody.setPassword(appLoginBody.getPassword());
loginBody.setTenantId(appLoginBody.getTenantId());
loginBody.setClientId("835b15335d389c9fcfdf99421fa8019b");
loginBody.setGrantType("appPassword");
ValidatorUtils.validate(appSmsLoginBody);
SmsLoginBody loginBody = new SmsLoginBody();
loginBody.setPhonenumber(appSmsLoginBody.getPhonenumber());
loginBody.setSmsCode(appSmsLoginBody.getSmsCode());
loginBody.setTenantId(appSmsLoginBody.getTenantId());
loginBody.setClientId("ca839698e245d60aa2f0e59bd52b34f8");
loginBody.setGrantType("appSms");
// 授权类型和客户端id
String clientId = loginBody.getClientId();
String grantType = loginBody.getGrantType();
@ -106,8 +107,12 @@ public class AppAuthController {
/**
* 用户注册
*/
@ApiEncrypt
@PostMapping("/register")
public R<Void> register(@Validated @RequestBody AppSmsRegisterBody user) {
public R<Void> register(@Validated @RequestBody RegisterBody user) {
if (!configService.selectRegisterEnabled(user.getTenantId())) {
return R.fail("当前系统没有开启注册功能!");
}
registerService.register(user);
return R.ok();
}

View File

@ -11,6 +11,7 @@ import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.web.core.BaseController;
import com.fuyuanshen.equipment.domain.dto.AppDeviceBo;
import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo;
import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria;
import com.fuyuanshen.equipment.domain.vo.AppDeviceVo;
import jakarta.validation.constraints.NotNull;
@ -101,7 +102,7 @@ public class AppDeviceController extends BaseController {
* 发送信息
*/
@PostMapping(value = "/sendMessage")
public R<Void> sendMessage(@RequestBody AppDeviceBo bo) {
public R<Void> sendMessage(@RequestBody AppDeviceSendMsgBo bo) {
return toAjax(appDeviceService.sendMessage(bo));
}
}

View File

@ -55,6 +55,14 @@ public class AppDeviceShareController extends BaseController {
return deviceShareService.queryPageList(bo, pageQuery);
}
/**
* 他人分享管理列表
*/
@GetMapping("/otherDeviceShareList")
public TableDataInfo<AppDeviceShareVo> otherDeviceShareList(AppDeviceShareBo bo, PageQuery pageQuery) {
return deviceShareService.otherDeviceShareList(bo, pageQuery);
}
/**
* 获取设备分享详细信息
*

View File

@ -1,62 +0,0 @@
package com.fuyuanshen.app.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import com.fuyuanshen.app.domain.dto.APPForgotPasswordDTO;
import com.fuyuanshen.app.domain.dto.APPForgotPasswordSmsDTO;
import com.fuyuanshen.app.domain.dto.APPUpdateUserDTO;
import com.fuyuanshen.app.domain.vo.APPUserInfoVo;
import com.fuyuanshen.app.service.IAppUserService;
import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.web.core.BaseController;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* APP 用户管理
* @date 2025-06-27
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/app/user")
public class AppUserController extends BaseController {
private final IAppUserService appUserService;
/**
* 个人中心
*/
@GetMapping("/getUserInfo")
public R<APPUserInfoVo> getUserInfo() {
return R.ok(appUserService.getUserInfo());
}
/**
* 修改个人信息
*/
@PostMapping("/updateUser")
public R<Void> updateUser(@Validated @ModelAttribute APPUpdateUserDTO bo) {
return toAjax(appUserService.updateUser(bo));
}
/**
* 忘记密码
*/
@SaIgnore
@PostMapping("/forgotPassword")
public R<Void> forgotPassword(@RequestBody APPForgotPasswordDTO bo) {
return toAjax(appUserService.forgotPassword(bo));
}
/**
* 发送忘记密码短信
*/
@SaIgnore
@PostMapping("/sendForgotPasswordSms")
public R<Void> sendForgotPasswordSms(@Validated @RequestBody APPForgotPasswordSmsDTO dto) throws Exception {
return toAjax(appUserService.sendForgotPasswordSms(dto));
}
}

View File

@ -1,5 +1,6 @@
package com.fuyuanshen.app.service;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -11,25 +12,33 @@ import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo;
import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo;
import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper;
import com.fuyuanshen.app.mapper.equipment.APPDeviceMapper;
import com.fuyuanshen.common.core.exception.ServiceException;
import com.fuyuanshen.common.core.utils.MapstructUtils;
import com.fuyuanshen.common.core.utils.ObjectUtils;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.DeviceType;
import com.fuyuanshen.equipment.domain.dto.AppDeviceBo;
import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo;
import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria;
import com.fuyuanshen.equipment.domain.vo.AppDeviceVo;
import com.fuyuanshen.equipment.enums.BindingStatusEnum;
import com.fuyuanshen.equipment.enums.CommunicationModeEnum;
import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeMapper;
import com.fuyuanshen.equipment.utils.c.ReliableTextToBitmap;
import com.fuyuanshen.system.mqtt.config.MqttGateway;
import com.fuyuanshen.system.mqtt.constants.MqttConstants;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@ -41,6 +50,7 @@ public class AppDeviceBizService {
private final DeviceMapper deviceMapper;
private final AppPersonnelInfoMapper appPersonnelInfoMapper;
private final DeviceTypeMapper deviceTypeMapper;
private final MqttGateway mqttGateway;
public List<APPDeviceTypeVo> getTypeList() {
@ -57,12 +67,31 @@ public class AppDeviceBizService {
}
public int sendMessage(AppDeviceBo bo) {
UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", bo.getDeviceId())
.eq("binding_user_id", AppLoginHelper.getUserId())
.set("send_msg", bo.getSendMsg());
return deviceMapper.update(updateWrapper);
public int sendMessage(AppDeviceSendMsgBo bo) {
List<Long> deviceIds = bo.getDeviceIds();
if(deviceIds == null || deviceIds.isEmpty()){
throw new ServiceException("请选择设备");
}
for (Long deviceId : deviceIds){
Device deviceObj = deviceMapper.selectById(deviceId);
if(deviceObj==null) {
throw new ServiceException("设备不存在"+deviceId);
}
byte[] msg = ReliableTextToBitmap.textToBitmapBytes(bo.getSendMsg());
Map<String,Object> linkHashMap = new HashMap<>();
linkHashMap.put("message",msg);
String sendMsg = JSON.toJSONString(linkHashMap);
mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+deviceObj.getDeviceImei(), 1 ,sendMsg);
log.info("发送设备消息:{}", bo.getSendMsg());
UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", deviceId)
.eq("binding_user_id", AppLoginHelper.getUserId())
.set("send_msg", bo.getSendMsg());
deviceMapper.update(updateWrapper);
}
return 1;
}
@ -138,6 +167,9 @@ public class AppDeviceBizService {
public AppDeviceDetailVo getInfo(Long id) {
Device device = deviceMapper.selectById(id);
if (device == null) {
throw new RuntimeException("请先将设备入库!!!");
}
AppDeviceDetailVo vo = new AppDeviceDetailVo();
vo.setDeviceId(device.getId());
vo.setDeviceName(device.getDeviceName());
@ -152,7 +184,11 @@ public class AppDeviceBizService {
}
vo.setBluetoothName(device.getBluetoothName());
AppPersonnelInfo appPersonnelInfo = appPersonnelInfoMapper.selectById(device.getId());
vo.setSendMsg(device.getSendMsg());
QueryWrapper<AppPersonnelInfo> qw = new QueryWrapper<AppPersonnelInfo>()
.eq("device_id", device.getId());
AppPersonnelInfo appPersonnelInfo = appPersonnelInfoMapper.selectOne(qw);
if(appPersonnelInfo != null){
AppPersonnelInfoVo personnelInfoVo = MapstructUtils.convert(appPersonnelInfo, AppPersonnelInfoVo.class);
vo.setPersonnelInfo(personnelInfoVo);
@ -161,7 +197,41 @@ public class AppDeviceBizService {
}
public boolean registerPersonInfo(AppPersonnelInfoBo bo) {
AppPersonnelInfo appPersonnelInfo = MapstructUtils.convert(bo, AppPersonnelInfo.class);
return appPersonnelInfoMapper.insertOrUpdate(appPersonnelInfo);
Long deviceId = bo.getDeviceId();
Device deviceObj = deviceMapper.selectById(deviceId);
if(deviceObj == null){
throw new RuntimeException("请先将设备入库!!!");
}
QueryWrapper<AppPersonnelInfo> qw = new QueryWrapper<AppPersonnelInfo>()
.eq("device_id", deviceId);
List<AppPersonnelInfoVo> appPersonnelInfoVos = appPersonnelInfoMapper.selectVoList(qw);
// unitName,position,name,id
byte[] unitName = ReliableTextToBitmap.textToBitmapBytes(bo.getUnitName());
byte[] position = ReliableTextToBitmap.textToBitmapBytes(bo.getPosition());
byte[] name = ReliableTextToBitmap.textToBitmapBytes(bo.getName());
byte[] id = ReliableTextToBitmap.textToBitmapBytes(bo.getCode());
Map<String,Object> linkHashMap = new HashMap<>();
linkHashMap.put("unitName",unitName);
linkHashMap.put("position",position);
linkHashMap.put("name",name);
linkHashMap.put("id",id);
String personnelInfo = JSON.toJSONString(linkHashMap);
mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+deviceObj.getDeviceImei(), 1 ,personnelInfo);
log.info("发送点阵数据到设备消息:{}", bo);
if(ObjectUtils.length(appPersonnelInfoVos) == 0){
AppPersonnelInfo appPersonnelInfo = MapstructUtils.convert(bo, AppPersonnelInfo.class);
return appPersonnelInfoMapper.insertOrUpdate(appPersonnelInfo);
}else {
UpdateWrapper<AppPersonnelInfo> uw = new UpdateWrapper<>();
uw.eq("device_id", deviceId)
.set("name", bo.getName())
.set("position", bo.getPosition())
.set("unit_name", bo.getUnitName())
.set("code",bo.getCode());
return appPersonnelInfoMapper.update(null, uw)>0;
}
}
}

View File

@ -95,7 +95,10 @@ public class AppDeviceShareService {
return code.equals(smsCode);
}
public int deviceShare(AppDeviceShareBo bo) {
validateSmsCode(AppLoginHelper.getTenantId(), bo.getPhonenumber(), bo.getSmsCode());
boolean flag = validateSmsCode(AppLoginHelper.getTenantId(), bo.getPhonenumber(), bo.getSmsCode());
if(!flag){
throw new ServiceException("验证码错误");
}
Device device = deviceMapper.selectById(bo.getDeviceId());
if(device==null){

View File

@ -2,11 +2,14 @@ package com.fuyuanshen.app.service;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.fuyuanshen.app.domain.vo.AppRoleVo;
import com.fuyuanshen.app.domain.vo.AppUserVo;
import com.fuyuanshen.common.core.constant.Constants;
import com.fuyuanshen.common.core.constant.SystemConstants;
import com.fuyuanshen.common.core.constant.TenantConstants;
import com.fuyuanshen.common.core.domain.dto.RoleDTO;
import com.fuyuanshen.common.core.domain.model.AppLoginUser;
import com.fuyuanshen.common.core.enums.LoginType;
import com.fuyuanshen.common.core.exception.user.UserException;
@ -28,10 +31,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.*;
import java.util.function.Supplier;
/**

View File

@ -1,129 +0,0 @@
package com.fuyuanshen.web.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fuyuanshen.app.domain.AppUser;
import com.fuyuanshen.app.domain.vo.AppUserVo;
import com.fuyuanshen.app.mapper.AppUserMapper;
import com.fuyuanshen.common.core.constant.Constants;
import com.fuyuanshen.common.core.constant.GlobalConstants;
import com.fuyuanshen.common.core.domain.model.AppSmsRegisterBody;
import com.fuyuanshen.common.core.exception.BadRequestException;
import com.fuyuanshen.common.core.exception.user.CaptchaException;
import com.fuyuanshen.common.core.exception.user.CaptchaExpireException;
import com.fuyuanshen.common.core.exception.user.UserException;
import com.fuyuanshen.common.core.utils.MessageUtils;
import com.fuyuanshen.common.core.utils.ServletUtils;
import com.fuyuanshen.common.core.utils.SpringUtils;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.log.event.LogininforEvent;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.common.tenant.helper.TenantHelper;
import com.fuyuanshen.common.web.config.properties.CaptchaProperties;
import com.fuyuanshen.system.mapper.SysUserMapper;
import com.fuyuanshen.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Date;
/**
* 注册校验方法
*
* @author Lion Li
*/
@RequiredArgsConstructor
@Service
public class AppRegisterService {
private final ISysUserService userService;
private final SysUserMapper userMapper;
private final CaptchaProperties captchaProperties;
private final AppUserMapper appUserMapper;
/**
* 注册
*/
public void register(AppSmsRegisterBody registerBody) {
String phoneNumber = registerBody.getPhoneNumber();
LambdaQueryWrapper<AppUser> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(AppUser::getPhonenumber, phoneNumber);
AppUserVo appUserVo = appUserMapper.selectVoOne(wrapper);
if (appUserVo != null) {
throw new BadRequestException("该手机号已被注册");
}
String verificationCode = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + phoneNumber);
if (verificationCode == null) {
throw new BadRequestException("验证码已过期");
}
if(!registerBody.getVerificationCode().equals(verificationCode)){
throw new BadRequestException("验证码错误");
}
String tenantId = registerBody.getTenantId();
String username = registerBody.getPhoneNumber();
String password = registerBody.getPassword();
AppUser appUser = new AppUser();
appUser.setUserName(username);
appUser.setNickName(username);
appUser.setPhonenumber(phoneNumber);
appUser.setPassword(password);
appUser.setUserType("app_user");
appUser.setTenantId(tenantId);
appUser.setLoginIp(ServletUtils.getClientIP());
appUser.setStatus("0");
appUser.setDelFlag("0");
appUser.setCreateTime(new Date());
boolean exist = TenantHelper.dynamic(tenantId, () -> {
return appUserMapper.exists(new LambdaQueryWrapper<AppUser>()
.eq(AppUser::getUserName, appUser.getUserName()));
});
if (exist) {
throw new UserException("user.register.save.error", username);
}
appUserMapper.insert(appUser);
recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success"));
}
/**
* 校验验证码
*
* @param username 用户名
* @param code 验证码
* @param uuid 唯一标识
*/
public void validateCaptcha(String tenantId, String username, String code, String uuid) {
String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.blankToDefault(uuid, "");
String captcha = RedisUtils.getCacheObject(verifyKey);
RedisUtils.deleteObject(verifyKey);
if (captcha == null) {
recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
throw new CaptchaExpireException();
}
if (!code.equalsIgnoreCase(captcha)) {
recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"));
throw new CaptchaException();
}
}
/**
* 记录登录信息
*
* @param tenantId 租户ID
* @param username 用户名
* @param status 状态
* @param message 消息内容
* @return
*/
private void recordLogininfor(String tenantId, String username, String status, String message) {
LogininforEvent logininforEvent = new LogininforEvent();
logininforEvent.setTenantId(tenantId);
logininforEvent.setUsername(username);
logininforEvent.setStatus(status);
logininforEvent.setMessage(message);
logininforEvent.setRequest(ServletUtils.getRequest());
SpringUtils.context().publishEvent(logininforEvent);
}
}

View File

@ -1,122 +0,0 @@
package com.fuyuanshen.web.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fuyuanshen.app.domain.AppUser;
import com.fuyuanshen.app.domain.vo.AppUserVo;
import com.fuyuanshen.app.mapper.AppUserMapper;
import com.fuyuanshen.app.service.AppLoginService;
import com.fuyuanshen.common.core.constant.Constants;
import com.fuyuanshen.common.core.constant.GlobalConstants;
import com.fuyuanshen.common.core.constant.SystemConstants;
import com.fuyuanshen.common.core.domain.model.AppLoginUser;
import com.fuyuanshen.common.core.domain.model.PasswordLoginBody;
import com.fuyuanshen.common.core.enums.LoginType;
import com.fuyuanshen.common.core.exception.user.CaptchaException;
import com.fuyuanshen.common.core.exception.user.CaptchaExpireException;
import com.fuyuanshen.common.core.exception.user.UserException;
import com.fuyuanshen.common.core.utils.MessageUtils;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.core.utils.ValidatorUtils;
import com.fuyuanshen.common.json.utils.JsonUtils;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
import com.fuyuanshen.common.satoken.utils.LoginHelper;
import com.fuyuanshen.common.tenant.helper.TenantHelper;
import com.fuyuanshen.common.web.config.properties.CaptchaProperties;
import com.fuyuanshen.system.domain.vo.SysClientVo;
import com.fuyuanshen.web.domain.vo.LoginVo;
import com.fuyuanshen.web.service.IAuthStrategy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 密码认证策略
*
* @author Michelle.Chung
*/
@Slf4j
@Service("appPassword" + IAuthStrategy.BASE_NAME)
@RequiredArgsConstructor
public class AppPasswordAuthStrategy implements IAuthStrategy {
private final CaptchaProperties captchaProperties;
private final AppLoginService loginService;
private final AppUserMapper appUserMapper;
@Override
public LoginVo login(String body, SysClientVo client) {
PasswordLoginBody loginBody = JsonUtils.parseObject(body, PasswordLoginBody.class);
ValidatorUtils.validate(loginBody);
String tenantId = loginBody.getTenantId();
String username = loginBody.getUsername();
String password = loginBody.getPassword();
String code = loginBody.getCode();
String uuid = loginBody.getUuid();
// boolean captchaEnabled = captchaProperties.getEnable();
// // 验证码开关
// if (captchaEnabled) {
// validateCaptcha(tenantId, username, code, uuid);
// }
AppLoginUser loginUser = TenantHelper.dynamic(tenantId, () -> {
AppUserVo user = loadUserByUsername(username);
loginService.checkLogin(LoginType.PASSWORD, tenantId, username, () -> !password.equals(user.getPassword()));
// 此处可根据登录用户的数据不同 自行创建 loginUser
return loginService.buildLoginUser(user);
});
loginUser.setClientKey(client.getClientKey());
loginUser.setDeviceType(client.getDeviceType());
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());
model.setActiveTimeout(client.getActiveTimeout());
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
// 生成token
AppLoginHelper.login(loginUser, model);
LoginVo loginVo = new LoginVo();
loginVo.setAccessToken(StpUtil.getTokenValue());
loginVo.setExpireIn(StpUtil.getTokenTimeout());
loginVo.setClientId(client.getClientId());
return loginVo;
}
/**
* 校验验证码
*
* @param username 用户名
* @param code 验证码
* @param uuid 唯一标识
*/
private void validateCaptcha(String tenantId, String username, String code, String uuid) {
String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.blankToDefault(uuid, "");
String captcha = RedisUtils.getCacheObject(verifyKey);
RedisUtils.deleteObject(verifyKey);
if (captcha == null) {
loginService.recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
throw new CaptchaExpireException();
}
if (!code.equalsIgnoreCase(captcha)) {
loginService.recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"));
throw new CaptchaException();
}
}
private AppUserVo loadUserByUsername(String username) {
AppUserVo user = appUserMapper.selectVoOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getUserName, username));
if (ObjectUtil.isNull(user)) {
log.info("登录用户:{} 不存在.", username);
throw new UserException("user.not.exists", username);
} else if (SystemConstants.DISABLE.equals(user.getStatus())) {
log.info("登录用户:{} 已被停用.", username);
throw new UserException("user.blocked", username);
}
return user;
}
}

View File

@ -59,6 +59,7 @@ public class AppSmsAuthStrategy implements IAuthStrategy {
if (ObjectUtil.isNull(user)) {
//新增Appuser
AppUser appUser = addAppUser(tenantId, phonenumber);
user = new AppUserVo();
MapstructUtils.convert(appUser, user);
// user = appUserMapper.selectVoOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhonenumber, phonenumber));
// loginService.recordLogininfor(tenantId, phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists", phonenumber));
@ -70,6 +71,7 @@ public class AppSmsAuthStrategy implements IAuthStrategy {
});
loginUser.setClientKey(client.getClientKey());
loginUser.setDeviceType(client.getDeviceType());
loginUser.setUserType(UserType.APP_USER.getUserType());
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置

View File

@ -49,9 +49,9 @@ spring:
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
url: jdbc:mysql://120.79.224.186:3366/fys-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
url: jdbc:mysql://47.120.79.150:3306/fys-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
password: 1fys@QWER..
password: Jq_123456#
# # 从库数据源
# slave:
# lazy: true
@ -98,13 +98,13 @@ spring:
spring.data:
redis:
# 地址
host: 120.79.224.186
host: 47.120.79.150
# 端口默认为6379
port: 26379
port: 6379
# 数据库索引
database: 2
# redis 密码必须配置
password: 1fys@QWER..
password: xhYc_djkl382^#780!
# 连接超时时间
timeout: 10s
# 是否开启ssl
@ -300,9 +300,9 @@ file:
# MQTT配置
mqtt:
username: admin
password: fys123456
url: tcp://47.107.152.87:1883
password: #YtvpSfCNG
url: tcp://47.120.79.150:2883
subClientId: fys_subClient
subTopic: worker/alert/#,worker/location/#
pubTopic: worker/location
subTopic: A/#,worker/location/#
pubTopic: B/#
pubClientId: fys_pubClient

View File

@ -4,7 +4,7 @@ spring.servlet.multipart.location: /fys/server/temp
--- # 监控中心配置
spring.boot.admin.client:
# 增加客户端开关
enabled: false
enabled: true
url: http://localhost:9090/admin
instance:
service-host-type: IP
@ -16,7 +16,7 @@ spring.boot.admin.client:
--- # snail-job 配置
snail-job:
enabled: false
enabled: true
# 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
group: "fys_group"
# SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config`表

View File

@ -1,7 +1,7 @@
# 开发环境配置
server:
# 服务器的HTTP端口默认为8080
port: 8001
port: 8000
servlet:
# 应用的访问路径
context-path: /

View File

@ -22,11 +22,6 @@ public interface GlobalConstants {
*/
String DEVICE_SHARE_CODES_KEY = GLOBAL_REDIS_KEY + "device_share_codes:";
/**
* 验证码 redis key
*/
String APP_FORGOT_PASSWORD_SMS_KEY = GLOBAL_REDIS_KEY + "app_sms_forgotPassword:";
/**
* 防重提交 redis key
*/

View File

@ -1,22 +0,0 @@
package com.fuyuanshen.common.core.domain.model;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
public class AppLoginBody {
/**
* 手机号不能为空
*/
@NotBlank(message = "手机号不能为空")
private String userName;
/**
* 密码不能为空
*/
@NotBlank(message = "密码不能为空")
private String password;
private String tenantId;
}

View File

@ -1,22 +0,0 @@
package com.fuyuanshen.common.core.domain.model;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
public class AppSmsRegisterBody {
@NotBlank(message = "手机号不能为空")
private String phoneNumber;
@NotBlank(message = "密码不能为空")
private String password;
@NotBlank(message = "验证码不能为空")
private String verificationCode;
/**
* 租户ID
*/
private String tenantId;
}

View File

@ -18,14 +18,14 @@ public class PasswordLoginBody extends LoginBody {
* 用户名
*/
@NotBlank(message = "{user.username.not.blank}")
// @Length(min = 2, max = 30, message = "{user.username.length.valid}")
@Length(min = 2, max = 30, message = "{user.username.length.valid}")
private String username;
/**
* 用户密码
*/
@NotBlank(message = "{user.password.not.blank}")
// @Length(min = 5, max = 30, message = "{user.password.length.valid}")
@Length(min = 5, max = 30, message = "{user.password.length.valid}")
private String password;
}

View File

@ -36,6 +36,11 @@ public class AppPersonnelInfo extends TenantEntity {
*/
private String name;
/**
* 职位
*/
private String position;
/**
* 单位名称
*/
@ -46,5 +51,6 @@ public class AppPersonnelInfo extends TenantEntity {
*/
private String sendMsg;
private String code;
}

View File

@ -1,14 +1,13 @@
package com.fuyuanshen.app.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fuyuanshen.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
import java.util.Date;
/**
* APP用户信息对象 app_user
@ -96,9 +95,5 @@ public class AppUser extends TenantEntity {
*/
private String remark;
/**
* 地区
*/
private String region;
}

View File

@ -23,13 +23,11 @@ public class AppPersonnelInfoBo extends BaseEntity {
/**
* 主键
*/
@NotNull(message = "主键不能为空", groups = { AddGroup.class, EditGroup.class })
private Long id;
/**
* 设备id
*/
@NotNull(message = "设备id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long deviceId;
/**
@ -37,6 +35,11 @@ public class AppPersonnelInfoBo extends BaseEntity {
*/
private String name;
/**
* 职位
*/
private String position;
/**
* 部门名称
*/
@ -52,5 +55,8 @@ public class AppPersonnelInfoBo extends BaseEntity {
*/
private String sendMsg;
/**
* ID号
*/
private String code;
}

View File

@ -1,19 +0,0 @@
package com.fuyuanshen.app.domain.dto;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
public class APPForgotPasswordDTO {
@NotBlank(message = "手机号不能为空")
private String phoneNumber;
@NotBlank(message = "密码不能为空")
private String password;
@NotBlank(message = "验证码不能为空")
private String verificationCode;
}

View File

@ -1,12 +0,0 @@
package com.fuyuanshen.app.domain.dto;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
public class APPForgotPasswordSmsDTO {
@NotBlank(message = "手机号不能为空")
private String phoneNumber;
}

View File

@ -1,6 +1,8 @@
package com.fuyuanshen.app.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;

View File

@ -1,33 +0,0 @@
package com.fuyuanshen.app.domain.dto;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
/**
* @author: 默苍璃
* @date: 2025-06-1818:36
*/
@Data
public class APPUpdateUserDTO {
/**
* 用户昵称
*/
private String nickName;
/**
* 用户地区
*/
private String region;
/**
* 用户性别
*/
private String gender;
/**
* 用户头像
*/
private MultipartFile file;
}

View File

@ -1,39 +0,0 @@
package com.fuyuanshen.app.domain.vo;
import lombok.Data;
@Data
public class APPUserInfoVo {
/**
* 用户ID
*/
private Long id;
/**
* 用户昵称
*/
private String nickName;
/**
* 性别
*/
private String gender;
/**
* 手机号码
*/
private String phone;
/**
* 头像地址
*/
private String avatarPath;
/**
* 地区
*/
private String region;
}

View File

@ -69,4 +69,9 @@ public class AppDeviceDetailVo {
* 人员信息
*/
private AppPersonnelInfoVo personnelInfo;
/**
* 发送信息
*/
private String sendMsg;
}

View File

@ -41,6 +41,10 @@ public class AppDeviceShareVo implements Serializable {
@ExcelProperty(value = "设备ID")
private Long deviceId;
/**
* 设备IMEI
*/
private String deviceImei;
/**
* 设备名称
*/

View File

@ -23,8 +23,4 @@ public class AppFileVo {
* 文件url
*/
private String fileUrl;
/**
* 文件类型(1:操作说明2:产品参数)
*/
private Long fileType;
}

View File

@ -47,10 +47,10 @@ public class AppPersonnelInfoVo implements Serializable {
private String name;
/**
* 部门名称
* 岗位
*/
@ExcelProperty(value = "部门名称")
private String deptName;
@ExcelProperty(value = "岗位")
private String position;
/**
* 单位名称
@ -59,10 +59,10 @@ public class AppPersonnelInfoVo implements Serializable {
private String unitName;
/**
* 发送信息
* ID号
*/
@ExcelProperty(value = "发送信息")
private String sendMsg;
@ExcelProperty(value = "ID号")
private String code;
}

View File

@ -1,8 +1,12 @@
package com.fuyuanshen.app.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fuyuanshen.app.domain.AppDeviceShare;
import com.fuyuanshen.app.domain.bo.AppDeviceShareBo;
import com.fuyuanshen.app.domain.vo.AppDeviceShareVo;
import com.fuyuanshen.common.mybatis.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
/**
* 设备分享Mapper接口
@ -11,5 +15,5 @@ import com.fuyuanshen.common.mybatis.core.mapper.BaseMapperPlus;
* @date 2025-07-16
*/
public interface AppDeviceShareMapper extends BaseMapperPlus<AppDeviceShare, AppDeviceShareVo> {
IPage<AppDeviceShareVo> otherDeviceShareList(@Param("bo") AppDeviceShareBo bo, Page<AppDeviceShareVo> page);
}

View File

@ -14,5 +14,4 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface AppUserMapper extends BaseMapperPlus<AppUser, AppUserVo> {
AppUser appFindByUsername(String phoneNumber);
}

View File

@ -65,4 +65,6 @@ public interface IAppDeviceShareService {
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
TableDataInfo<AppDeviceShareVo> otherDeviceShareList(AppDeviceShareBo bo, PageQuery pageQuery);
}

View File

@ -1,13 +1,9 @@
package com.fuyuanshen.app.service;
import com.fuyuanshen.app.domain.bo.AppUserBo;
import com.fuyuanshen.app.domain.dto.APPForgotPasswordDTO;
import com.fuyuanshen.app.domain.dto.APPForgotPasswordSmsDTO;
import com.fuyuanshen.app.domain.dto.APPUpdateUserDTO;
import com.fuyuanshen.app.domain.vo.APPUserInfoVo;
import com.fuyuanshen.app.domain.vo.AppUserVo;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.fuyuanshen.app.domain.bo.AppUserBo;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
@ -69,12 +65,4 @@ public interface IAppUserService {
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
APPUserInfoVo getUserInfo();
int updateUser(APPUpdateUserDTO bo);
int forgotPassword(APPForgotPasswordDTO bo);
int sendForgotPasswordSms(APPForgotPasswordSmsDTO dto);
}

View File

@ -1,5 +1,6 @@
package com.fuyuanshen.app.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fuyuanshen.common.core.utils.MapstructUtils;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
@ -68,6 +69,7 @@ public class AppDeviceShareServiceImpl implements IAppDeviceShareService {
if(device != null){
r.setDevicePic(device.getDevicePic());
r.setDeviceName(device.getDeviceName());
r.setDeviceImei(device.getDeviceImei());
}
});
return TableDataInfo.build(result);
@ -146,4 +148,22 @@ public class AppDeviceShareServiceImpl implements IAppDeviceShareService {
}
return baseMapper.deleteByIds(ids) > 0;
}
@Override
public TableDataInfo<AppDeviceShareVo> otherDeviceShareList(AppDeviceShareBo bo, PageQuery pageQuery) {
String username = AppLoginHelper.getUsername();
bo.setPhonenumber(username);
Page<AppDeviceShareVo> page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
IPage<AppDeviceShareVo> result = baseMapper.otherDeviceShareList(bo, page);
List<AppDeviceShareVo> records = result.getRecords();
records.forEach(r -> {
Device device = deviceMapper.selectById(r.getDeviceId());
if(device != null){
r.setDevicePic(device.getDevicePic());
r.setDeviceName(device.getDeviceName());
r.setDeviceImei(device.getDeviceImei());
}
});
return TableDataInfo.build(result);
}
}

View File

@ -7,7 +7,6 @@ import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@ -67,8 +66,6 @@ public class AppOperationVideoServiceImpl implements IAppOperationVideoService {
*/
@Override
public List<AppOperationVideoVo> queryList(AppOperationVideoBo bo) {
Long userId = AppLoginHelper.getUserId();
bo.setCreateBy(userId);
LambdaQueryWrapper<AppOperationVideo> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}

View File

@ -1,37 +1,24 @@
package com.fuyuanshen.app.service.impl;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fuyuanshen.app.domain.AppUser;
import com.fuyuanshen.app.domain.bo.AppUserBo;
import com.fuyuanshen.app.domain.dto.APPForgotPasswordDTO;
import com.fuyuanshen.app.domain.dto.APPForgotPasswordSmsDTO;
import com.fuyuanshen.app.domain.dto.APPUpdateUserDTO;
import com.fuyuanshen.app.domain.vo.APPUserInfoVo;
import com.fuyuanshen.app.domain.vo.AppUserVo;
import com.fuyuanshen.app.mapper.AppUserMapper;
import com.fuyuanshen.app.service.IAppUserService;
import com.fuyuanshen.common.core.constant.GlobalConstants;
import com.fuyuanshen.common.core.domain.model.AppLoginUser;
import com.fuyuanshen.common.core.exception.BadRequestException;
import com.fuyuanshen.common.core.utils.MapstructUtils;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
import com.fuyuanshen.system.domain.vo.SysOssVo;
import com.fuyuanshen.system.service.ISysOssService;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.fuyuanshen.app.domain.bo.AppUserBo;
import com.fuyuanshen.app.domain.vo.AppUserVo;
import com.fuyuanshen.app.domain.AppUser;
import com.fuyuanshen.app.mapper.AppUserMapper;
import com.fuyuanshen.app.service.IAppUserService;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* Service业务层处理
@ -46,8 +33,6 @@ public class AppUserServiceImpl implements IAppUserService {
private final AppUserMapper baseMapper;
private final ISysOssService sysOssService;
/**
* 查询APP用户信息
*
@ -154,75 +139,4 @@ public class AppUserServiceImpl implements IAppUserService {
}
return baseMapper.deleteByIds(ids) > 0;
}
@Override
public APPUserInfoVo getUserInfo() {
String username = AppLoginHelper.getUsername();
QueryWrapper<AppUser> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_name", username);
List<AppUser> appUsers = baseMapper.selectList(queryWrapper);
if(appUsers.isEmpty()){
throw new BadRequestException("用户不存在");
}
AppUser user = appUsers.get(0);
// AppUserVo user = baseMapper.selectVoById(userId);
APPUserInfoVo appUserVo = new APPUserInfoVo();
appUserVo.setId(user.getUserId());
appUserVo.setNickName(user.getNickName());
appUserVo.setGender(user.getSex());
appUserVo.setPhone(user.getPhonenumber());
appUserVo.setRegion(user.getRegion());
if(user.getAvatar() != null){
SysOssVo oss = sysOssService.getById(user.getAvatar());
if(oss != null){
appUserVo.setAvatarPath(oss.getUrl());
}
}
return appUserVo;
}
@Override
public int updateUser(APPUpdateUserDTO bo) {
AppLoginUser appUser = AppLoginHelper.getLoginUser();
AppUserVo appUserVo = baseMapper.selectVoById(appUser.getUserId());
if(appUserVo == null){
throw new BadRequestException("用户不存在");
}
AppUser updUser= new AppUser();
updUser.setUserId(appUser.getUserId());
updUser.setNickName(bo.getNickName());
if(bo.getFile() != null){
SysOssVo oss = sysOssService.upload(bo.getFile());
updUser.setAvatar(oss.getOssId());
}
updUser.setRegion(bo.getRegion());
updUser.setSex(bo.getGender());
return baseMapper.update(updUser, new LambdaQueryWrapper<AppUser>().eq(AppUser::getUserId, appUser.getUserId()));
}
@Override
public int forgotPassword(APPForgotPasswordDTO bo) {
AppUser appUser = baseMapper.appFindByUsername(bo.getPhoneNumber());
if (appUser == null) {
throw new BadRequestException("手机号不存在");
}
String verificationCode = RedisUtils.getCacheObject(GlobalConstants.APP_FORGOT_PASSWORD_SMS_KEY + bo.getPhoneNumber());
if (verificationCode == null) {
throw new BadRequestException("验证码已过期");
}
if(!bo.getVerificationCode().equals(verificationCode)){
throw new BadRequestException("验证码错误");
}
appUser.setPassword(bo.getPassword());
baseMapper.updateById(appUser);
return 1;
}
@Override
public int sendForgotPasswordSms(APPForgotPasswordSmsDTO dto) {
return 1;
}
}

View File

@ -7,9 +7,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="queryAppFileList" resultType="com.fuyuanshen.app.domain.vo.AppFileVo">
select a.id,a.business_id,a.file_id,b.file_name,b.url fileUrl from app_business_file a left join sys_oss b on a.file_id = b.oss_id
where 1=1
<if test="createBy != null">
a.create_by = #{createBy}
</if>
<if test="businessId != null">
and a.business_id = #{businessId}
</if>

View File

@ -4,4 +4,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fuyuanshen.app.mapper.AppDeviceShareMapper">
<select id="otherDeviceShareList" resultType="com.fuyuanshen.app.domain.vo.AppDeviceShareVo">
SELECT * FROM app_device_share a where a.phonenumber = #{bo.phonenumber}
</select>
</mapper>

View File

@ -4,7 +4,4 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fuyuanshen.app.mapper.AppUserMapper">
<select id="appFindByUsername" resultType="com.fuyuanshen.app.domain.AppUser">
select * from app_user where user_name = #{phoneNumber}
</select>
</mapper>

View File

@ -92,7 +92,7 @@ public class Customer extends TenantEntity {
/**
* 帐号状态0正常 1停用
*/
private String status;
private String status = "0";
/**
* 删除标志0代表存在 1代表删除

View File

@ -1,9 +1,11 @@
package com.fuyuanshen.customer.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fuyuanshen.common.core.domain.model.LoginUser;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.satoken.utils.LoginHelper;
import com.fuyuanshen.customer.constant.ArrayConstants;
@ -92,6 +94,7 @@ public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> i
}
customer.setUserLevel((byte) (loginUser.getUserLevel() + 1));
customer.setPid(loginUser.getUserId());
customer.setStatus("0");
save(customer);
@ -106,18 +109,40 @@ public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> i
/**
* 修改客户
* 不是因为寂寞才想你,只是因为想你才寂寞。
*
* @param resources /
* @param customer /
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void updateCustomer(Customer resources) throws Exception {
if (resources.getEnabled()) {
resources.setStatus("0");
} else {
resources.setStatus("1");
public void updateCustomer(Customer customer) throws Exception {
UserQueryCriteria userQueryCriteria = new UserQueryCriteria();
if (StringUtils.isNotEmpty(customer.getUserName())) {
userQueryCriteria.setCustomerName(customer.getUserName());
List<Customer> customers = customerMapper.queryCustomers(userQueryCriteria);
if (!customers.isEmpty()) {
throw new BadRequestException("用户名已存在!!!");
}
}
saveOrUpdate(resources);
if (customer.getEnabled()) {
customer.setStatus("0");
} else {
// 强制下线
// StpUtil.logout(customer.getCustomerId());
// StpUtil.kickout(customer.getCustomerId());
customer.setStatus("1");
// 检查目标用户是否有有效的登录状态
if (StpUtil.isLogin(customer.getCustomerId())) {
// 用户已登录,可以执行踢出操作
StpUtil.kickout(customer.getCustomerId());
} else {
// 用户未登录,无法踢出
System.out.println("目标用户未登录,无法执行踢出操作");
}
}
saveOrUpdate(customer);
}

View File

@ -105,7 +105,6 @@ public class Device extends TenantEntity {
@Schema(name = "设备状态")
private Integer deviceStatus;
/**
* 绑定状态
* 0 未绑定
@ -121,7 +120,23 @@ public class Device extends TenantEntity {
private Long bindingUserId;
/**
* 绑定时间
*/
private Date bindingTime;
private String sendMsg;
/**
* 发布主题格式A/{device_id}
* pub_topic
*/
private String pubTopic;
/**
* 订阅主题格式B/{device_id}
* sub_topic
*/
private String subTopic;
}

View File

@ -30,5 +30,5 @@ public class AppDeviceBo {
private String sendMsg;
private String deviceId;
private Long deviceId;
}

View File

@ -0,0 +1,16 @@
package com.fuyuanshen.equipment.domain.dto;
import lombok.Data;
import java.util.List;
/**
* 绑定设备参数
*/
@Data
public class AppDeviceSendMsgBo {
private String sendMsg;
private List<Long> deviceIds;
}

View File

@ -1,10 +1,12 @@
package com.fuyuanshen.equipment.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class AppDeviceVo {
public class AppDeviceVo implements Serializable {
private Long id;
@ -39,7 +41,7 @@ public class AppDeviceVo {
private String typeName;
/**
* 蓝牙名称
* 蓝牙名称
*/
private String bluetoothName;
@ -49,4 +51,10 @@ public class AppDeviceVo {
* 1 正常
*/
private Integer deviceStatus;
/**
* 绑定时间
*/
private Date bindingTime;
}

View File

@ -85,6 +85,14 @@ public interface DeviceService extends IService<Device> {
*/
void unbindDevice(DeviceForm deviceForm);
/**
* WEB端查看APP客户设备绑定
*
* @param bo
* @param pageQuery
* @return
*/
TableDataInfo<AppDeviceVo> queryAppDeviceList(DeviceQueryCriteria bo, PageQuery pageQuery);
int bindDevice(AppDeviceBo bo);

View File

@ -186,7 +186,12 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
device.setCreateByName(loginUser.getNickname());
device.setTypeName(deviceTypes.getTypeName());
device.setDeviceType(deviceTypes.getId());
if (device.getDeviceImei() != null) {
device.setPubTopic("A/" + device.getDeviceImei());
device.setSubTopic("B/" + device.getDeviceImei());
}
// 0 未绑定
device.setBindingStatus(0);
deviceMapper.insert(device);
// 新增设备类型记录
@ -293,17 +298,26 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
for (Long id : ids) {
DeviceAssignments deviceAssignment = deviceAssignmentsMapper.selectById(id);
Device deviceType = deviceMapper.selectById(deviceAssignment.getDeviceId());
Device device = deviceMapper.selectById(deviceAssignment.getDeviceId());
if (StringUtils.isNotEmpty(deviceAssignment.getAssigneeName())) {
throw new BadRequestException(deviceType.getDeviceName() + ":设备已分配,请先解绑设备!!!");
throw new BadRequestException(device.getDeviceName() + ":设备已分配,请先解绑设备!!!");
}
if (device.getBindingStatus() != null && device.getBindingStatus().equals(1)) {
throw new BadRequestException(device.getDeviceName() + ":设备已绑定,请先解绑设备!!!");
}
// 接收者
if (Objects.equals(deviceAssignment.getAssigneeId(), deviceType.getOriginalOwnerId())) {
if (Objects.equals(deviceAssignment.getAssigneeId(), device.getOriginalOwnerId())) {
invalidIds.add(deviceAssignment.getDeviceId());
}
// 删除设备:分配记录
deviceAssignmentsMapper.delete(new LambdaQueryWrapper<DeviceAssignments>()
.eq(DeviceAssignments::getDeviceId, deviceAssignment.getDeviceId())
.eq(DeviceAssignments::getAssigneeId, deviceAssignment.getAssigneeId()));
}
deviceAssignmentsMapper.deleteByIds(ids);
@ -470,7 +484,13 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
}
/**
* WEB端查看APP客户设备绑定
*
* @param bo
* @param pageQuery
* @return
*/
@Override
public TableDataInfo<AppDeviceVo> queryAppDeviceList(DeviceQueryCriteria bo, PageQuery pageQuery) {
if (bo.getBindingUserId() == null) {

View File

@ -179,7 +179,7 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
List<Device> devices = deviceMapper.selectList(new QueryWrapper<Device>()
.eq("device_type", deviceTypeGrant.getDeviceTypeId()));
if (CollectionUtil.isNotEmpty(devices)) {
throw new RuntimeException("该设备类型已绑定设备,无法删除");
throw new RuntimeException("该设备类型已绑定设备,无法删除");
}
deviceTypeId.add(deviceTypeGrant.getDeviceTypeId());
}

View File

@ -38,13 +38,19 @@
<!-- 分页查询设备 -->
<select id="findAll" resultType="com.fuyuanshen.equipment.domain.Device">
select
da.id AS id,d.device_name,d.bluetooth_name,
d.device_pic, d.device_mac, d.device_sn, d.update_by,d.device_imei,
d.update_time, dg.id AS device_type, d.remark, d.binding_status,t.type_name AS typeName,
da.assignee_id AS customerId, da.assignee_name AS customerName, da.active AS deviceStatus,
da.create_time AS create_time , da.assigner_name AS createByName , da.id AS assignId
from device d
SELECT *
FROM (
SELECT
da.id AS id, d.device_name, d.bluetooth_name,
d.pub_topic, d.sub_topic, d.device_pic,
d.device_mac, d.device_sn, d.update_by,
d.device_imei, d.update_time, dg.id AS device_type,
d.remark, d.binding_status, t.type_name AS typeName,
da.assignee_id AS customerId, da.assignee_name AS customerName,
da.active AS deviceStatus, da.create_time AS create_time,
da.assigner_name AS createByName, da.id AS assignId,
ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY da.create_time DESC) AS rn
FROM device d
LEFT JOIN device_type t ON d.device_type = t.id
LEFT JOIN device_type_grants dg ON dg.device_type_id = t.id
LEFT JOIN device_assignments da ON da.device_id = d.id
@ -71,9 +77,12 @@
AND da.assignee_id = #{criteria.currentOwnerId}
AND dg.customer_id = #{criteria.currentOwnerId}
</where>
ORDER BY da.create_time DESC
) AS ranked
WHERE rn = 1
ORDER BY create_time DESC
</select>
<select id="findAllDevices" resultType="com.fuyuanshen.equipment.domain.Device">
select
d.id, d.customer_id, d.device_name,d.bluetooth_name,
@ -138,7 +147,8 @@
d.device_pic,
dt.type_name,
dt.communication_mode,
d.bluetooth_name
d.bluetooth_name,
d.binding_time
from device d
inner join device_type dt on d.device_type = dt.id
where d.binding_user_id = #{criteria.bindingUserId}

View File

@ -44,7 +44,7 @@ public class MqttOutboundConfiguration {
mqttPahoClientFactory
);
mqttPahoMessageHandler.setDefaultQos(1);
mqttPahoMessageHandler.setDefaultTopic("worker/location");
mqttPahoMessageHandler.setDefaultTopic("B/#");
mqttPahoMessageHandler.setAsync(true);
return mqttPahoMessageHandler;
}

View File

@ -0,0 +1,16 @@
package com.fuyuanshen.system.mqtt.constants;
public interface MqttConstants {
/**
* 全局发布消息的key
*/
String GLOBAL_PUB_KEY = "B/";
/**
* 全局订阅消息的key
*/
String GLOBAL_SUB_KEY = "A/";
}

View File

@ -27,5 +27,6 @@ public class ReceiverMessageHandler implements MessageHandler {
String timestamp = Objects.requireNonNull(headers.get("timestamp")).toString();
log.info("MQTT payload= {} \n receivedTopic = {} \n receivedQos = {} \n timestamp = {}"
,payload,receivedTopic,receivedQos,timestamp);
}
}