102 Commits

Author SHA1 Message Date
6bbe9cbdd1 Merge branch 'dyf-device' 2025-07-19 10:21:11 +08:00
3feafc2cd9 删除设备类型 2025-07-19 10:20:07 +08:00
13986bb493 APP设备分享功能开发 2025-07-19 09:36:35 +08:00
f2921ff12f 分页查询设备-设备类型 2025-07-19 09:17:14 +08:00
ec89dd8c1e 新增设备 校验 2025-07-18 18:12:36 +08:00
57322c9c87 蓝牙名称 2025-07-18 17:57:58 +08:00
7d91426414 Merge branch 'dyf-device' 2025-07-18 15:17:18 +08:00
ad06811747 撤回设备 2025-07-18 15:06:39 +08:00
dyf
aeaa906bc9 Merge pull request 'feat(fys-demo): 添加视频上传和处理功能' (#5) from liwenlong/fys-Multi-tenant:jingquan into main
Reviewed-on: #5
2025-07-18 14:03:18 +08:00
36092932bf feat(fys-demo): 添加视频上传和处理功能
- 新增 VideoUploadController 控制器处理视频上传
- 添加视频帧提取和转换为 RGB565 格式功能
- 实现视频文件大小和格式校验
- 优化临时文件创建和清理逻辑
- 引入 javacv-platform依赖进行视频处理
2025-07-18 13:27:26 +08:00
34188f20dd 帐号状态(0正常 1停用) 2025-07-18 11:18:30 +08:00
0fa0e4ab1b 帐号状态(0正常 1停用) 2025-07-18 10:36:02 +08:00
e321dcd652 修改客户状态 2025-07-18 10:23:04 +08:00
78e2538f71 Merge branch 'dyf-device' 2025-07-17 16:41:08 +08:00
faef79e56d return R.ok(); 2025-07-17 16:29:25 +08:00
7b1615ce4d WEB端解绑设备 2025-07-17 16:20:22 +08:00
171eeabea1 Merge branch 'dyf-device' 2025-07-17 09:24:10 +08:00
cc776300ec 删除设备 逻辑修改 2025-07-17 09:23:11 +08:00
04df7e3ec7 可靠点阵生成工具 - 终极版 2025-07-16 08:46:21 +08:00
7be94fe1d2 产品参数bug修改 2025-07-15 15:59:32 +08:00
6f24759361 发送指令显示工具 2025-07-15 15:58:12 +08:00
530ee83488 新增绑定时间字段 2025-07-14 14:23:17 +08:00
f938716e2d 分页查询APP用户信息列表 2025-07-14 10:03:51 +08:00
bbf1c6cfd5 分页查询设备:设备类型自动更新 2025-07-14 09:13:30 +08:00
082f890009 登录查询用户新增用户类型查询条件 2025-07-14 09:02:13 +08:00
800b825892 登录查询用户新增用户类型查询条件 2025-07-14 08:53:53 +08:00
cfafbc54f7 Merge branch 'dyf-device' 2025-07-12 14:01:00 +08:00
fdb64b1dcc 小程序:相关接口 2025-07-12 13:57:31 +08:00
fbbe90207e 解绑问题修复 2025-07-12 10:41:13 +08:00
2f38f08538 Merge remote-tracking branch 'origin/main' 2025-07-12 09:56:42 +08:00
eb1552d982 绑定蓝牙问题修复 2025-07-12 09:56:26 +08:00
dyf
1eb2502a21 revert 2815e27240
revert 晶全代码同步,app接口开发
2025-07-11 16:20:24 +08:00
2815e27240 晶全代码同步,app接口开发 2025-07-11 16:03:36 +08:00
f119dd158b 操作视频信息 2025-07-11 14:06:25 +08:00
a109f187b9 Merge branch 'main' into jingquan 2025-07-11 11:37:59 +08:00
b5ebc8855d Merge branch 'main' into jingquan 2025-07-11 11:36:41 +08:00
99aef4b353 Merge branch 'main' into dyf-device 2025-07-11 11:36:17 +08:00
a423ac0f8b app设备解绑 2025-07-11 11:34:30 +08:00
82b1494bc7 app支持上传多个文件2 2025-07-11 10:44:25 +08:00
c3b7849190 app支持上传多个文件 2025-07-10 18:45:43 +08:00
33b718c048 Merge remote-tracking branch 'origin/dyf-device' 2025-07-10 18:29:56 +08:00
a708889117 app删除文件 2025-07-10 18:12:41 +08:00
3250dd3f83 WEB端查看APP客户设备绑定 2025-07-10 15:44:57 +08:00
4cc02e1040 Merge remote-tracking branch 'origin/main' into dyf-device
# Conflicts:
#	fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AppDeviceVo.java
#	fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceMapper.xml
2025-07-10 15:16:57 +08:00
185d521472 WEB端查看APP客户设备绑定 2025-07-10 15:14:18 +08:00
7e688e16b3 导出数据设备 2025-07-10 14:57:59 +08:00
b876d051d8 app设备列表添加蓝牙名称 2025-07-10 13:33:32 +08:00
d75658e81e WEB端查看APP客户设备绑定 2025-07-10 10:55:47 +08:00
1dc00f0431 Merge remote-tracking branch 'origin/main' into dyf-device 2025-07-10 10:11:03 +08:00
2a6b9eafb3 mqtt优化 2025-07-10 09:43:40 +08:00
f0bfc4aa35 app:查看APP客户设备绑定 2025-07-10 09:39:57 +08:00
ff81b791fc 设备列表查询 2025-07-10 08:57:36 +08:00
87f2e3a8b5 web:prod 配置 2025-07-10 08:40:45 +08:00
c075c09ee7 web:更新设备信息 2025-07-09 16:59:54 +08:00
3fb692e7fb web:撤回设备 2025-07-09 16:29:25 +08:00
d219105b73 Merge remote-tracking branch 'origin/dyf-device'
# Conflicts:
#	fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceServiceImpl.java
#	fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceMapper.xml
2025-07-09 13:45:27 +08:00
908ca6753e app设备类型查询 2025-07-09 13:41:08 +08:00
8a66e5ca51 分配客户 2025-07-09 13:41:03 +08:00
0d3b48bbbb web:设备管理 2025-07-08 15:25:45 +08:00
ca47160c92 Merge remote-tracking branch 'origin/main' into dyf-device 2025-07-08 14:46:35 +08:00
64daff1647 web:设备管理 2025-07-08 14:46:05 +08:00
f41bb097fd 添加设备编号 2025-07-08 14:43:28 +08:00
b5ae17c3e3 Merge remote-tracking branch 'origin/dyf-device' 2025-07-08 11:35:03 +08:00
cad7a9b725 Merge remote-tracking branch 'origin/dyf-device' 2025-07-08 11:26:24 +08:00
08b1f73af1 设备类型管理 2025-07-08 11:09:14 +08:00
628cc1fa99 设备列表 2025-07-08 10:26:14 +08:00
b26cb873b5 Merge remote-tracking branch 'origin/main' into dyf-device
# Conflicts:
#	fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceMapper.java
#	fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceServiceImpl.java
2025-07-08 09:05:31 +08:00
43f6f2ca0b 设备绑定,解绑 2025-07-08 09:00:14 +08:00
d301e9da3c 短信验证码 2025-07-07 15:34:02 +08:00
26cba479e2 Merge remote-tracking branch 'origin/main' into dyf-device 2025-07-07 11:41:04 +08:00
f338ef47d1 修改APP用户信息 2025-07-07 11:40:46 +08:00
952077da92 新增客户 2025-07-07 10:56:14 +08:00
6b2ebf2414 mqtt协议 2025-07-07 09:46:39 +08:00
04766447e6 图片转Rgb565C 2025-07-05 17:04:56 +08:00
2a06c18f35 WEB端查看APP客户设备绑定 2025-07-05 16:29:31 +08:00
ad82ab5fca APP/小程序用户设备绑定 2025-07-05 15:55:46 +08:00
ec513015a9 删除设备controller 2025-07-05 15:03:01 +08:00
5322e84a92 Merge remote-tracking branch 'origin/main' into dyf-device 2025-07-05 14:10:10 +08:00
407103a71e 修改成晶全服务器配置 2025-07-05 14:08:27 +08:00
2d34120b45 WEB:分页查询设备列表 2025-07-04 15:49:23 +08:00
3947f9b6f0 WEB:分页查询设备列表 2025-07-04 15:42:10 +08:00
3f4b7f0186 Merge remote-tracking branch 'origin/main' 2025-07-04 15:11:31 +08:00
f2a6f16cdd 操作说明和产品参数 2025-07-04 15:10:36 +08:00
d456236599 WEB:导入设备数据 2025-07-04 11:02:22 +08:00
3129db352e Merge branch 'dyf-device' 2025-07-04 08:34:52 +08:00
e8aee3039a WEB:导出数据设备 2025-07-03 17:53:10 +08:00
0271a84bc2 WEB:设备类型管理 2025-07-03 16:58:08 +08:00
4e83e3570a WEB:客户管理 2025-07-03 15:30:18 +08:00
5bc56ca36d WEB:客户管理 2025-07-03 14:17:53 +08:00
c3a9f4a365 app文件管理 2025-07-03 14:07:32 +08:00
b06e071196 WEB:客户管理 2025-07-03 11:39:49 +08:00
abe9dc2fe8 分页查询客户 2025-07-03 10:08:09 +08:00
fe6de8f5bc Merge remote-tracking branch 'origin/main' into dyf-device 2025-07-02 17:54:56 +08:00
5917234ca8 新增客户 2025-07-02 17:53:53 +08:00
3e07891760 操作视频管理 2025-07-02 16:36:40 +08:00
2a81385554 新增设备 2025-07-02 15:29:09 +08:00
5336170b2d app登录优化,操作视频管理模块接口实现 2025-07-02 15:27:32 +08:00
4220428f92 fel 2025-07-02 14:47:17 +08:00
a487e7ae67 清空所有客户端缓存 2025-07-02 14:16:11 +08:00
a69aad227a 设备类型管理 2025-07-02 11:25:41 +08:00
6b802f4546 APP:客户设备管理 2025-07-02 09:52:53 +08:00
24c511b15e app登录提交 2025-07-01 16:04:47 +08:00
185 changed files with 9817 additions and 892 deletions

View File

@ -9,7 +9,6 @@ import org.springframework.boot.context.metrics.buffering.BufferingApplicationSt
*
* @author Lion Li
*/
@SpringBootApplication
public class DromaraApplication {

View File

@ -29,6 +29,9 @@ import com.fuyuanshen.web.service.SysRegisterService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -63,7 +66,6 @@ public class AppAuthController {
@PostMapping("/login")
public R<LoginVo> login(@RequestBody AppSmsLoginBody appSmsLoginBody) {
// SmsLoginBody loginBody = JsonUtils.parseObject(body, SmsLoginBody.class);
LoginHelper.getLoginUser();
ValidatorUtils.validate(appSmsLoginBody);
SmsLoginBody loginBody = new SmsLoginBody();
loginBody.setPhonenumber(appSmsLoginBody.getPhonenumber());
@ -98,7 +100,7 @@ public class AppAuthController {
*/
@PostMapping("/logout")
public R<Void> logout() {
// loginService.logout();
loginService.logout();
return R.ok("退出成功");
}
@ -158,4 +160,14 @@ public class AppAuthController {
return R.ok(result);
}
@GetMapping("/test")
public void testSend() {
// 在创建完SmsBlend实例后再未手动调用注销的情况下框架会持有该实例可以直接通过指定configId来获取想要的配置如果你想使用
// 负载均衡形式获取实例只要使用getSmsBlend的无参重载方法即可如果你仅有一个配置也可以使用该方法
SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
SmsResponse smsResponse = smsBlend.sendMessage("18656573389", "123");
}
}

View File

@ -1,23 +1,18 @@
package com.fuyuanshen.app.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.fuyuanshen.app.domain.bo.AppUserBo;
import com.fuyuanshen.app.domain.vo.AppUserVo;
import com.fuyuanshen.app.domain.vo.DeviceVo;
import com.fuyuanshen.app.service.DeviceService;
import com.fuyuanshen.app.service.IAppUserService;
import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo;
import com.fuyuanshen.app.domain.dto.APPReNameDTO;
import com.fuyuanshen.app.domain.vo.APPDeviceTypeVo;
import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo;
import com.fuyuanshen.app.service.AppDeviceBizService;
import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.core.validate.AddGroup;
import com.fuyuanshen.common.core.validate.EditGroup;
import com.fuyuanshen.common.excel.utils.ExcelUtil;
import com.fuyuanshen.common.idempotent.annotation.RepeatSubmit;
import com.fuyuanshen.common.log.annotation.Log;
import com.fuyuanshen.common.log.enums.BusinessType;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.web.core.BaseController;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import com.fuyuanshen.equipment.domain.dto.AppDeviceBo;
import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria;
import com.fuyuanshen.equipment.domain.vo.AppDeviceVo;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
@ -26,8 +21,7 @@ import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* APP 设备信息管理
* @date 2025-06-27
* APP设备信息管理
*/
@Validated
@RequiredArgsConstructor
@ -35,15 +29,79 @@ import java.util.List;
@RequestMapping("/app/device")
public class AppDeviceController extends BaseController {
private final DeviceService deviceService;
private final AppDeviceBizService appDeviceService;
/**
* 查询设备信息列表
* 查询设备列表
*/
@GetMapping("/list")
public TableDataInfo<DeviceVo> list(AppUserBo bo, PageQuery pageQuery) {
return deviceService.queryPageList(bo, pageQuery);
public TableDataInfo<AppDeviceVo> list(DeviceQueryCriteria bo, PageQuery pageQuery) {
return appDeviceService.queryAppDeviceList(bo,pageQuery);
}
/**
* 绑定设备
*/
@PostMapping("/bind")
public R<Void> bind(@RequestBody AppDeviceBo bo) {
return toAjax(appDeviceService.bindDevice(bo));
}
/**
* 解绑设备
*/
@DeleteMapping("/unBind")
public R<Void> unBind(Long id) {
return toAjax(appDeviceService.unBindDevice(id));
}
/**
* 查询设备类型列表
*/
@GetMapping(value = "/typeList")
public R<List<APPDeviceTypeVo>> getTypeList() {
List<APPDeviceTypeVo> typeList = appDeviceService.getTypeList();
return R.ok(typeList);
}
/**
* 重命名设备
* @param reNameDTO
* @return
*/
@PostMapping(value = "/reName")
public R<String> reName(@Validated @RequestBody APPReNameDTO reNameDTO) {
appDeviceService.reName(reNameDTO);
return R.ok("重命名成功!!!");
}
/**
* 获取设备详细信息
*
* @param id 主键
*/
@GetMapping("/{id}")
public R<AppDeviceDetailVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(appDeviceService.getInfo(id));
}
/**
* 人员信息登记
*/
@PostMapping(value = "/registerPersonInfo")
public R<Void> registerPersonInfo(@Validated(AddGroup.class) @RequestBody AppPersonnelInfoBo bo) {
return toAjax(appDeviceService.registerPersonInfo(bo));
}
/**
* 发送信息
*/
@PostMapping(value = "/sendMessage")
public R<Void> sendMessage(@RequestBody AppDeviceBo bo) {
return toAjax(appDeviceService.sendMessage(bo));
}
}

View File

@ -0,0 +1,110 @@
package com.fuyuanshen.app.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.util.RandomUtil;
import com.fuyuanshen.app.domain.bo.AppDeviceShareBo;
import com.fuyuanshen.app.domain.vo.AppDeviceShareDetailVo;
import com.fuyuanshen.app.domain.vo.AppDeviceShareVo;
import com.fuyuanshen.app.service.AppDeviceShareService;
import com.fuyuanshen.app.service.IAppDeviceShareService;
import com.fuyuanshen.common.core.constant.Constants;
import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.core.validate.AddGroup;
import com.fuyuanshen.common.idempotent.annotation.RepeatSubmit;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.ratelimiter.annotation.RateLimiter;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.common.web.core.BaseController;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.time.Duration;
import java.util.LinkedHashMap;
import static com.fuyuanshen.common.core.constant.GlobalConstants.DEVICE_SHARE_CODES_KEY;
/**
* APP 设备分享
*
* @author Lion Li
* @date 2025-07-16
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/app/deviceShare")
public class AppDeviceShareController extends BaseController {
private final IAppDeviceShareService deviceShareService;
private final AppDeviceShareService appDeviceShareService;
/**
* 分享管理列表
*/
@GetMapping("/deviceShareList")
public TableDataInfo<AppDeviceShareVo> list(AppDeviceShareBo bo, PageQuery pageQuery) {
return deviceShareService.queryPageList(bo, pageQuery);
}
/**
* 获取设备分享详细信息
*
* @param id 主键
*/
@GetMapping("/{id}")
public R<AppDeviceShareDetailVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(appDeviceShareService.getInfo(id));
}
/**
* 新增设备分享
*/
@RepeatSubmit()
@PostMapping("/deviceShare")
public R<Void> deviceShare(@Validated(AddGroup.class) @RequestBody AppDeviceShareBo bo) {
return toAjax(appDeviceShareService.deviceShare(bo));
}
/**
* 移除分享用户
*
* @param ids 主键串
*/
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(appDeviceShareService.remove(ids));
}
/**
* 短信验证码
*
* @param phonenumber 用户手机号
*/
@SaIgnore
@RateLimiter(key = "#phonenumber", time = 60, count = 1)
@GetMapping("/sms/code")
public R<Void> smsCode(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) {
String key = DEVICE_SHARE_CODES_KEY + phonenumber;
String code = RandomUtil.randomNumbers(4);
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
map.put("code", code);
SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, map);
if (!smsResponse.isSuccess()) {
return R.fail(smsResponse.getData().toString());
}
return R.ok();
}
}

View File

@ -0,0 +1,55 @@
package com.fuyuanshen.app.controller;
import com.fuyuanshen.app.domain.bo.AppBusinessFileBo;
import com.fuyuanshen.app.domain.dto.AppFileDto;
import com.fuyuanshen.app.domain.vo.AppFileVo;
import com.fuyuanshen.app.service.AppFileService;
import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.web.core.BaseController;
import jakarta.validation.constraints.NotEmpty;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* APP 文件管理
* @date 2025-06-27
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/app/file")
public class AppFileController extends BaseController {
private final AppFileService appFileService;
/**
* 查询文件列表
*/
@GetMapping("/list")
public R<List<AppFileVo>> list(AppBusinessFileBo bo) {
return R.ok(appFileService.list(bo));
}
/**
* 上传文件
*/
@PostMapping("/upload")
public R<Void> upload(@Validated @ModelAttribute AppFileDto bo) {
return toAjax(appFileService.add(bo));
}
/**
* 文件删除
*/
@DeleteMapping("/delete/{ids}")
public R<Void> delete(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
if(ids == null || ids.length == 0){
return R.fail("请选择要删除的文件");
}
return toAjax(appFileService.delete(ids));
}
}

View File

@ -0,0 +1,71 @@
package com.fuyuanshen.app.controller;
import com.fuyuanshen.app.domain.bo.AppOperationVideoBo;
import com.fuyuanshen.app.domain.vo.AppOperationVideoVo;
import com.fuyuanshen.app.service.IAppOperationVideoService;
import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.core.domain.model.AppLoginUser;
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
import com.fuyuanshen.common.web.core.BaseController;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* APP 操作视频管理
* @date 2025-06-27
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/app/operationVideo")
public class AppOperationVideoController extends BaseController {
private final IAppOperationVideoService appOperationVideoService;
/**
* 查询操作视频列表
*/
@GetMapping("/listOperationVideos")
public R<List<AppOperationVideoVo>> listOperationVideos(AppOperationVideoBo bo) {
return R.ok(appOperationVideoService.queryList(bo));
}
/**
* 查询操作视频详情信息
*/
@GetMapping("/getOperationVideoInfo")
public R<AppOperationVideoVo> getOperationVideoInfo(AppOperationVideoBo bo) {
return R.ok(appOperationVideoService.queryById(bo.getId()));
}
/**
* 操作视频添加
*/
@PostMapping("/addOperationVideo")
public R<Void> addOperationVideo(@RequestBody AppOperationVideoBo bo) {
AppLoginUser loginUser = AppLoginHelper.getLoginUser();
if (loginUser != null) {
bo.setCreateBy(loginUser.getUserId());
}
return toAjax(appOperationVideoService.insertByBo(bo));
}
/**
* 操作视频编辑
*/
@PostMapping("/editOperationVideo")
public R<Void> editOperationVideo(@RequestBody AppOperationVideoBo bo) {
return toAjax(appOperationVideoService.updateByBo(bo));
}
/**
* 操作视频删除
*/
@DeleteMapping("/deleteOperationVideo/{id}")
public R<Void> deleteOperationVideo(@PathVariable Long id) {
return toAjax(appOperationVideoService.deleteWithValidByIds(List.of(id), true));
}
}

View File

@ -0,0 +1,21 @@
package com.fuyuanshen.app.domain.dto;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
@Data
public class AppFileDto {
private Long deviceId;
/**
* 文件类型(1:操作说明2:产品参数)
*/
private Long fileType;
/**
* 文件
*/
private MultipartFile[] files;
}

View File

@ -0,0 +1,8 @@
package com.fuyuanshen.app.domain.dto;
import lombok.Data;
@Data
public class AppVideoDto {
}

View File

@ -22,4 +22,5 @@ public class AppSmsLoginBody {
*/
@NotBlank(message = "租户ID不能为空")
private String tenantId;
}

View File

@ -0,0 +1,167 @@
package com.fuyuanshen.app.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fuyuanshen.app.domain.AppPersonnelInfo;
import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo;
import com.fuyuanshen.app.domain.dto.APPReNameDTO;
import com.fuyuanshen.app.domain.vo.APPDeviceTypeVo;
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.utils.MapstructUtils;
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.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 lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
@Slf4j
@Service
@RequiredArgsConstructor
public class AppDeviceBizService {
private final APPDeviceMapper appDeviceMapper;
private final DeviceMapper deviceMapper;
private final AppPersonnelInfoMapper appPersonnelInfoMapper;
private final DeviceTypeMapper deviceTypeMapper;
public List<APPDeviceTypeVo> getTypeList() {
Long userId = AppLoginHelper.getUserId();
return appDeviceMapper.getTypeList(userId);
}
public void reName(APPReNameDTO reNameDTO) {
UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", reNameDTO.getId())
.eq("binding_user_id", AppLoginHelper.getUserId())
.set("device_name", reNameDTO.getDeviceName());
deviceMapper.update(updateWrapper);
}
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 TableDataInfo<AppDeviceVo> queryAppDeviceList(DeviceQueryCriteria bo, PageQuery pageQuery) {
if (bo.getBindingUserId() == null) {
Long userId = AppLoginHelper.getUserId();
bo.setBindingUserId(userId);
}
Page<AppDeviceVo> result = deviceMapper.queryAppBindDeviceList(pageQuery.build(), bo);
return TableDataInfo.build(result);
}
public int bindDevice(AppDeviceBo bo) {
Integer mode = bo.getCommunicationMode();
Long userId = AppLoginHelper.getUserId();
if (mode == CommunicationModeEnum.FOUR_G.getValue()) {
String deviceImei = bo.getDeviceImei();
QueryWrapper<Device> qw = new QueryWrapper<Device>()
.eq("device_imei", deviceImei);
List<Device> devices = deviceMapper.selectList(qw);
if (devices.isEmpty()) {
throw new RuntimeException("请先将设备入库!!!");
}
Device device = devices.get(0);
if (device.getBindingStatus() != null && device.getBindingStatus() == BindingStatusEnum.BOUND.getCode()) {
throw new RuntimeException("设备已绑定");
}
UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
deviceUpdateWrapper.eq("id", device.getId())
.set("binding_status", BindingStatusEnum.BOUND.getCode())
.set("binding_user_id", userId)
.set("binding_time", new Date());
return deviceMapper.update(null, deviceUpdateWrapper);
} else if (mode == CommunicationModeEnum.BLUETOOTH.getValue()) {
String deviceMac = bo.getDeviceMac();
QueryWrapper<Device> qw = new QueryWrapper<Device>()
.eq("device_mac", deviceMac);
List<Device> devices = deviceMapper.selectList(qw);
if (devices.isEmpty()) {
throw new RuntimeException("请先将设备入库!!!");
}
Device device = devices.get(0);
if (device.getBindingStatus() != null && device.getBindingStatus() == BindingStatusEnum.BOUND.getCode()) {
throw new RuntimeException("设备已绑定");
}
UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
deviceUpdateWrapper.eq("id", device.getId())
.set("binding_status", BindingStatusEnum.BOUND.getCode())
.set("binding_user_id", userId)
.set("binding_time", new Date());
return deviceMapper.update(null, deviceUpdateWrapper);
} else {
throw new RuntimeException("通讯方式错误");
}
}
public int unBindDevice(Long id) {
Device device = deviceMapper.selectById(id);
if (device == null) {
throw new RuntimeException("请先将设备入库!!!");
}
UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
deviceUpdateWrapper.eq("id", device.getId())
.set("binding_status", BindingStatusEnum.UNBOUND.getCode())
.set("binding_user_id", null)
.set("binding_time", null);
return deviceMapper.update(null, deviceUpdateWrapper);
}
public AppDeviceDetailVo getInfo(Long id) {
Device device = deviceMapper.selectById(id);
AppDeviceDetailVo vo = new AppDeviceDetailVo();
vo.setDeviceId(device.getId());
vo.setDeviceName(device.getDeviceName());
vo.setDevicePic(device.getDevicePic());
vo.setDeviceImei(device.getDeviceImei());
vo.setDeviceMac(device.getDeviceMac());
vo.setDeviceStatus(device.getDeviceStatus());
DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType());
if(deviceType!=null){
vo.setCommunicationMode(Integer.valueOf(deviceType.getCommunicationMode()));
vo.setTypeName(deviceType.getTypeName());
}
vo.setBluetoothName(device.getBluetoothName());
AppPersonnelInfo appPersonnelInfo = appPersonnelInfoMapper.selectById(device.getId());
if(appPersonnelInfo != null){
AppPersonnelInfoVo personnelInfoVo = MapstructUtils.convert(appPersonnelInfo, AppPersonnelInfoVo.class);
vo.setPersonnelInfo(personnelInfoVo);
}
return vo;
}
public boolean registerPersonInfo(AppPersonnelInfoBo bo) {
AppPersonnelInfo appPersonnelInfo = MapstructUtils.convert(bo, AppPersonnelInfo.class);
return appPersonnelInfoMapper.insertOrUpdate(appPersonnelInfo);
}
}

View File

@ -0,0 +1,132 @@
package com.fuyuanshen.app.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fuyuanshen.app.domain.AppDeviceShare;
import com.fuyuanshen.app.domain.AppPersonnelInfo;
import com.fuyuanshen.app.domain.bo.AppDeviceShareBo;
import com.fuyuanshen.app.domain.vo.AppDeviceShareDetailVo;
import com.fuyuanshen.app.domain.vo.AppDeviceShareVo;
import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo;
import com.fuyuanshen.app.mapper.AppDeviceShareMapper;
import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper;
import com.fuyuanshen.common.core.constant.Constants;
import com.fuyuanshen.common.core.constant.GlobalConstants;
import com.fuyuanshen.common.core.exception.ServiceException;
import com.fuyuanshen.common.core.exception.user.CaptchaExpireException;
import com.fuyuanshen.common.core.utils.MessageUtils;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.DeviceType;
import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
@RequiredArgsConstructor
@Slf4j
@Service
public class AppDeviceShareService {
private final AppDeviceShareMapper appDeviceShareMapper;
private final DeviceMapper deviceMapper;
private final DeviceTypeMapper deviceTypeMapper;
private final AppPersonnelInfoMapper appPersonnelInfoMapper;
public AppDeviceShareDetailVo getInfo(Long id) {
LambdaQueryWrapper<AppDeviceShare> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(AppDeviceShare::getDeviceId, id);
List<AppDeviceShareVo> appDeviceShareVos = appDeviceShareMapper.selectVoList(queryWrapper);
if(appDeviceShareVos==null || appDeviceShareVos.isEmpty()){
return null;
}
AppDeviceShareVo shareVo = appDeviceShareVos.get(0);
AppDeviceShareDetailVo shareDetailVo = new AppDeviceShareDetailVo();
shareDetailVo.setId(shareVo.getId());
shareDetailVo.setDeviceId(shareVo.getDeviceId());
shareDetailVo.setPhonenumber(shareVo.getPhonenumber());
shareDetailVo.setPermission(shareVo.getPermission());
Device device = deviceMapper.selectById(shareVo.getDeviceId());
shareDetailVo.setDeviceName(device.getDeviceName());
shareDetailVo.setDeviceImei(device.getDeviceImei());
shareDetailVo.setDeviceMac(device.getDeviceMac());
DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType());
if(deviceType!=null){
shareDetailVo.setCommunicationMode(Integer.valueOf(deviceType.getCommunicationMode()));
}
shareDetailVo.setDevicePic(device.getDevicePic());
shareDetailVo.setTypeName(deviceType.getTypeName());
shareDetailVo.setBluetoothName(device.getBluetoothName());
shareDetailVo.setDeviceStatus(device.getDeviceStatus());
shareDetailVo.setSendMsg(device.getSendMsg());
LambdaQueryWrapper<AppPersonnelInfo> qw = new LambdaQueryWrapper<>();
qw.eq(AppPersonnelInfo::getDeviceId, device.getId());
List<AppPersonnelInfoVo> appPersonnelInfoVos = appPersonnelInfoMapper.selectVoList(qw);
if(appPersonnelInfoVos!=null && !appPersonnelInfoVos.isEmpty()){
shareDetailVo.setPersonnelInfo(appPersonnelInfoVos.get(0));
}
return shareDetailVo;
}
/**
* 校验短信验证码
*/
private boolean validateSmsCode(String tenantId, String phonenumber, String smsCode) {
String code = RedisUtils.getCacheObject(GlobalConstants.DEVICE_SHARE_CODES_KEY + phonenumber);
if (StringUtils.isBlank(code)) {
throw new ServiceException("验证码失效");
}
return code.equals(smsCode);
}
public int deviceShare(AppDeviceShareBo bo) {
validateSmsCode(AppLoginHelper.getTenantId(), bo.getPhonenumber(), bo.getSmsCode());
Device device = deviceMapper.selectById(bo.getDeviceId());
if(device==null){
throw new ServiceException("设备不存在");
}
Long userId = AppLoginHelper.getUserId();
LambdaQueryWrapper<AppDeviceShare> lqw = new LambdaQueryWrapper<>();
lqw.eq(AppDeviceShare::getDeviceId, bo.getDeviceId());
lqw.eq(AppDeviceShare::getPhonenumber, bo.getPhonenumber());
Long count = appDeviceShareMapper.selectCount(lqw);
if(count>0){
UpdateWrapper<AppDeviceShare> uw = new UpdateWrapper<>();
uw.eq("device_id", bo.getDeviceId());
uw.eq("phonenumber", bo.getPhonenumber());
uw.set("permission", bo.getPermission());
uw.set("update_by", userId);
uw.set("update_time", new Date());
return appDeviceShareMapper.update(uw);
}else {
AppDeviceShare appDeviceShare = new AppDeviceShare();
appDeviceShare.setDeviceId(bo.getDeviceId());
appDeviceShare.setPhonenumber(bo.getPhonenumber());
appDeviceShare.setPermission(bo.getPermission());
appDeviceShare.setCreateBy(userId);
return appDeviceShareMapper.insert(appDeviceShare);
}
}
public int remove(Long[] ids) {
return appDeviceShareMapper.deleteByIds(Arrays.asList(ids));
}
}

View File

@ -0,0 +1,82 @@
package com.fuyuanshen.app.service;
import com.fuyuanshen.app.domain.bo.AppBusinessFileBo;
import com.fuyuanshen.app.domain.dto.AppFileDto;
import com.fuyuanshen.app.domain.vo.AppBusinessFileVo;
import com.fuyuanshen.app.domain.vo.AppFileVo;
import com.fuyuanshen.common.core.exception.ServiceException;
import com.fuyuanshen.common.oss.core.OssClient;
import com.fuyuanshen.common.oss.factory.OssFactory;
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
import com.fuyuanshen.system.domain.vo.SysOssVo;
import com.fuyuanshen.system.service.ISysOssService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* 登录校验方法
*
* @author Lion Li
*/
@RequiredArgsConstructor
@Slf4j
@Service
public class AppFileService {
private final ISysOssService sysOssService;
private final IAppBusinessFileService appBusinessFileService;
public List<AppFileVo> list(AppBusinessFileBo bo) {
bo.setCreateBy(AppLoginHelper.getUserId());
return appBusinessFileService.queryAppFileList(bo);
}
public Boolean add(AppFileDto bo) {
MultipartFile[] files = bo.getFiles();
if(files == null || files.length == 0){
throw new ServiceException("请选择要上传的文件");
}
if(files.length > 5){
throw new ServiceException("最多只能上传5个文件");
}
for (int i = 0; i < files.length; i++) {
MultipartFile file = files[i];
// 上传文件
SysOssVo upload = sysOssService.upload(file);
if (upload == null) {
return false;
}
AppBusinessFileBo appBusinessFileBo = new AppBusinessFileBo();
appBusinessFileBo.setFileId(upload.getOssId());
appBusinessFileBo.setBusinessId(bo.getDeviceId());
appBusinessFileBo.setFileType(bo.getFileType());
appBusinessFileBo.setCreateBy(AppLoginHelper.getUserId());
appBusinessFileService.insertByBo(appBusinessFileBo);
}
return true;
}
public Boolean delete(Long[] ids) {
AppBusinessFileBo bo = new AppBusinessFileBo();
bo.setCreateBy(AppLoginHelper.getUserId());
bo.setIds(List.of(ids));
List<AppBusinessFileVo> appBusinessFileVos = appBusinessFileService.queryList(bo);
List<Long> fileIds = appBusinessFileVos.stream().map(AppBusinessFileVo::getFileId).toList();
List<SysOssVo> list = sysOssService.listByIds(fileIds);
for (SysOssVo sysOss : list) {
OssClient storage = OssFactory.instance(sysOss.getService());
storage.delete(sysOss.getUrl());
}
return appBusinessFileService.deleteWithValidByIds(List.of(ids), true);
}
}

View File

@ -63,7 +63,7 @@ public class AppLoginService {
/**
* 退出登录
*/
/*public void logout() {
public void logout() {
try {
AppLoginUser loginUser = AppLoginHelper.getLoginUser();
if (ObjectUtil.isNull(loginUser)) {
@ -81,7 +81,7 @@ public class AppLoginService {
} catch (NotLoginException ignored) {
}
}
}*/
}
/**
* 记录登录信息

View File

@ -1,58 +0,0 @@
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.bo.AppUserBo;
import com.fuyuanshen.app.domain.vo.AppRoleVo;
import com.fuyuanshen.app.domain.vo.AppUserVo;
import com.fuyuanshen.app.domain.vo.DeviceVo;
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.domain.model.LoginUser;
import com.fuyuanshen.common.core.enums.LoginType;
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.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.LoginHelper;
import com.fuyuanshen.common.tenant.exception.TenantException;
import com.fuyuanshen.common.tenant.helper.TenantHelper;
import com.fuyuanshen.system.domain.vo.SysTenantVo;
import com.fuyuanshen.system.service.ISysTenantService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
/**
* 登录校验方法
*
* @author Lion Li
*/
@RequiredArgsConstructor
@Slf4j
@Service
public class DeviceService {
public TableDataInfo<DeviceVo> queryPageList(AppUserBo bo, PageQuery pageQuery) {
return null;
}
}

View File

@ -0,0 +1,102 @@
package com.fuyuanshen.mp.controller;
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.AppLoginUser;
import com.fuyuanshen.common.core.domain.model.LoginUser;
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;
import com.fuyuanshen.equipment.domain.UserApp;
import com.fuyuanshen.equipment.enums.AppUserTypeEnum;
import com.fuyuanshen.mp.domian.dto.AuthUserDto;
import com.fuyuanshen.mp.service.MPAuthService;
import com.fuyuanshen.mp.service.MPService;
import com.fuyuanshen.system.domain.bo.SysTenantBo;
import com.fuyuanshen.system.domain.vo.SysClientVo;
import com.fuyuanshen.system.domain.vo.SysTenantVo;
import com.fuyuanshen.system.domain.vo.SysUserVo;
import com.fuyuanshen.system.service.ISysClientService;
import com.fuyuanshen.system.service.ISysConfigService;
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.IAuthStrategy;
import com.fuyuanshen.web.service.SysRegisterService;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* APP认证
*
* @author Lion Li
*/
@Slf4j
@SaIgnore
@RequiredArgsConstructor
@RestController
@RequestMapping("/mp")
public class MPAuthController {
private final AppLoginService loginService;
private final SysRegisterService registerService;
private final ISysConfigService configService;
private final ISysTenantService tenantService;
private final ISysClientService clientService;
private final MPAuthService mpAuthService;
private final MPService mpService;
@Operation(summary = "小程序登录授权")
@PostMapping(value = "/login")
public ResponseEntity<Object> login(@RequestBody AuthUserDto authUser, HttpServletRequest request) throws Exception {
Long phoneNumber = authUser.getPhoneNumber();
// 判断小程序用户是否存在,不存在创建
UserApp mpUser = mpService.getMpUser(phoneNumber);
if (mpUser == null) {
RegisterBody registerBody = new RegisterBody();
registerBody.setUsername(phoneNumber.toString());
registerBody.setUserType(AppUserTypeEnum.XCX_USER.getCode());
registerBody.setTenantId("894078");
registerBody.setPassword("123456");
mpAuthService.register(registerBody);
}
// 去登录
SysClientVo client = clientService.queryByClientId("ca839698e245d60aa2f0e59bd52b34f8");
UserApp user = mpService.loadUserByUsername(phoneNumber.toString());
LoginUser loginUser = mpAuthService.buildLoginUser(user);
LoginVo login = mpAuthService.login(loginUser, client);
// 返回登录信息
return ResponseEntity.ok(login);
}
}

View File

@ -0,0 +1,37 @@
package com.fuyuanshen.mp.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import com.fuyuanshen.common.core.domain.ResponseVO;
import com.fuyuanshen.equipment.service.DeviceService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author: 默苍璃
* @date: 2025-07-1208:36
*/
@Slf4j
@RestController
@RequestMapping("/mp")
@RequiredArgsConstructor
@Tag(name = "小程序:相关接口")
@SaIgnore
public class MPController {
private final DeviceService deviceService;
@GetMapping("/queryDevice")
@Operation(summary = "检查是否存在设备MAC号")
public ResponseVO<Boolean> queryDevice(@Parameter(name = "设备mac值") String mac) {
return ResponseVO.success(deviceService.queryDevice(mac));
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fuyuanshen.mp.domian.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
/**
* @author Zheng Jie
* @date 2018-11-30
*/
@Getter
@Setter
public class AuthUserDto {
@Schema(name = "用户名")
private String username;
@Schema(name = "手机号APP/小程序 登录)")
private Long phoneNumber;
@Schema(name = "密码")
private String password;
@Schema(name = "验证码")
private String code;
@Schema(name = "验证码的key")
private String uuid = "";
}

View File

@ -0,0 +1,8 @@
package com.fuyuanshen.mp.mapper;
/**
* @author: 默苍璃
* @date: 2025-07-1210:16
*/
public interface MPMapper {
}

View File

@ -0,0 +1,164 @@
package com.fuyuanshen.mp.service;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.fuyuanshen.app.domain.vo.AppUserVo;
import com.fuyuanshen.app.service.IAppRoleService;
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.PostDTO;
import com.fuyuanshen.common.core.domain.dto.RoleDTO;
import com.fuyuanshen.common.core.domain.model.AppLoginUser;
import com.fuyuanshen.common.core.domain.model.LoginUser;
import com.fuyuanshen.common.core.domain.model.PasswordLoginBody;
import com.fuyuanshen.common.core.domain.model.RegisterBody;
import com.fuyuanshen.common.core.enums.LoginType;
import com.fuyuanshen.common.core.enums.UserType;
import com.fuyuanshen.common.core.exception.user.UserException;
import com.fuyuanshen.common.core.utils.*;
import com.fuyuanshen.common.json.utils.JsonUtils;
import com.fuyuanshen.common.log.event.LogininforEvent;
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.exception.TenantException;
import com.fuyuanshen.common.tenant.helper.TenantHelper;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.UserApp;
import com.fuyuanshen.equipment.service.AppUserService;
import com.fuyuanshen.system.domain.SysUser;
import com.fuyuanshen.system.domain.bo.SysUserBo;
import com.fuyuanshen.system.domain.vo.*;
import com.fuyuanshen.system.service.ISysTenantService;
import com.fuyuanshen.system.service.ISysUserService;
import com.fuyuanshen.web.domain.vo.LoginVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.*;
import java.util.function.Supplier;
/**
* 登录校验方法
*
* @author Lion Li
*/
@RequiredArgsConstructor
@Slf4j
@Service
public class MPAuthService {
private final ISysUserService userService;
private final AppUserService appUserService;
/**
* 小程序注册
*/
public void register(RegisterBody registerBody) {
String tenantId = registerBody.getTenantId();
String username = registerBody.getUsername();
String password = registerBody.getPassword();
// 校验用户类型是否存在
String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
UserApp sysUser = new UserApp();
sysUser.setUserName(username);
sysUser.setNickName(username);
sysUser.setPhonenumber(username);
sysUser.setTenantId(tenantId);
sysUser.setUserType(registerBody.getUserType());
sysUser.setPassword(BCrypt.hashpw(password));
sysUser.setUserType(userType);
appUserService.saveMpUser(sysUser);
}
/**
* 记录登录信息
*
* @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());
// com.fuyuanshen.web.listener.UserActionListener
SpringUtils.context().publishEvent(logininforEvent);
}
public LoginVo login(LoginUser loginUser, SysClientVo client) {
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
LoginHelper.login(loginUser, model);
LoginVo loginVo = new LoginVo();
loginVo.setAccessToken(StpUtil.getTokenValue());
loginVo.setExpireIn(StpUtil.getTokenTimeout());
loginVo.setClientId(client.getClientId());
return loginVo;
}
/**
* 构建登录用户
*/
public LoginUser buildLoginUser(UserApp user) {
LoginUser loginUser = new LoginUser();
Long userId = user.getUserId();
loginUser.setTenantId(user.getTenantId());
loginUser.setUserId(userId);
loginUser.setDeptId(user.getDeptId());
loginUser.setUsername(user.getUserName());
loginUser.setNickname(user.getNickName());
loginUser.setUserType(user.getUserType());
// 用户级别
// loginUser.setUserLevel(user.getUserLevel());
// pid
// loginUser.setPid(user.getPid());
// loginUser.setMenuPermission(permissionService.getMenuPermission(userId));
// loginUser.setRolePermission(permissionService.getRolePermission(userId));
// if (ObjectUtil.isNotNull(user.getDeptId())) {
// Opt<SysDeptVo> deptOpt = Opt.of(user.getDeptId()).map(deptService::selectDeptById);
// loginUser.setDeptName(deptOpt.map(SysDeptVo::getDeptName).orElse(StringUtils.EMPTY));
// loginUser.setDeptCategory(deptOpt.map(SysDeptVo::getDeptCategory).orElse(StringUtils.EMPTY));
// }
// List<SysRoleVo> roles = roleService.selectRolesByUserId(userId);
// // List<SysPostVo> posts = postService.selectPostsByUserId(userId);
// loginUser.setRoles(BeanUtil.copyToList(roles, RoleDTO.class));
// loginUser.setPosts(BeanUtil.copyToList(posts, PostDTO.class));
return loginUser;
}
}

View File

@ -0,0 +1,26 @@
package com.fuyuanshen.mp.service;
import com.fuyuanshen.equipment.domain.UserApp;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 登录校验方法
*
* @author Lion Li
*/
public interface MPService {
/**
* 获取小程序用户信息
*
* @param phoneNumber 手机号
*/
UserApp getMpUser(Long phoneNumber);
UserApp loadUserByUsername(String username);
}

View File

@ -0,0 +1,12 @@
package com.fuyuanshen.mp.service.impl;
/**
* 登录校验方法
*
* @author Lion Li
*/
public class MPAuthServiceImpl {
}

View File

@ -0,0 +1,43 @@
package com.fuyuanshen.mp.service.impl;
import com.fuyuanshen.equipment.domain.UserApp;
import com.fuyuanshen.equipment.mapper.UserAppMapper;
import com.fuyuanshen.equipment.service.AppUserService;
import com.fuyuanshen.mp.service.MPService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 登录校验方法
*
* @author Lion Li
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class MPServiceImpl implements MPService {
private final AppUserService appUserService;
/**
* 获取小程序用户信息
*
* @param phoneNumber 手机号
*/
@Override
public UserApp getMpUser(Long phoneNumber) {
return appUserService.getMpUser(phoneNumber);
}
@Override
public UserApp loadUserByUsername(String username) {
return appUserService.loadUserByUsername(username);
}
}

View File

@ -111,6 +111,7 @@ public class AuthController {
return R.ok(loginVo);
}
/**
* 获取跳转URL
*
@ -133,6 +134,7 @@ public class AuthController {
return R.ok("操作成功", authorizeUrl);
}
/**
* 前端回调绑定授权(需要token)
*

View File

@ -63,11 +63,12 @@ public class CaptchaController {
String code = RandomUtil.randomNumbers(4);
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
// 验证码模板id 自行处理 (查数据库或写死均可)
String templateId = "";
String templateId = "SMS_322180518";
LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
map.put("code", code);
SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, templateId, map);
// SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, templateId, map);
SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, map);
if (!smsResponse.isSuccess()) {
log.error("验证码短信发送异常 => {}", smsResponse);
return R.fail(smsResponse.getData().toString());

View File

@ -157,6 +157,11 @@ public class SysLoginService {
loginUser.setUsername(user.getUserName());
loginUser.setNickname(user.getNickName());
loginUser.setUserType(user.getUserType());
// 用户级别
loginUser.setUserLevel(user.getUserLevel());
// pid
loginUser.setPid(user.getPid());
loginUser.setMenuPermission(permissionService.getMenuPermission(userId));
loginUser.setRolePermission(permissionService.getRolePermission(userId));
if (ObjectUtil.isNotNull(user.getDeptId())) {
@ -242,7 +247,7 @@ public class SysLoginService {
log.info("登录租户:{} 已被停用.", tenantId);
throw new TenantException("tenant.blocked");
} else if (ObjectUtil.isNotNull(tenant.getExpireTime())
&& new Date().after(tenant.getExpireTime())) {
&& new Date().after(tenant.getExpireTime())) {
log.info("登录租户:{} 已超过有效期.", tenantId);
throw new TenantException("tenant.expired");
}

View File

@ -14,12 +14,10 @@ import com.fuyuanshen.common.core.constant.SystemConstants;
import com.fuyuanshen.common.core.domain.model.AppLoginUser;
import com.fuyuanshen.common.core.domain.model.SmsLoginBody;
import com.fuyuanshen.common.core.enums.LoginType;
import com.fuyuanshen.common.core.enums.UserType;
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.StringUtils;
import com.fuyuanshen.common.core.utils.ValidatorUtils;
import com.fuyuanshen.common.core.utils.*;
import com.fuyuanshen.common.json.utils.JsonUtils;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
@ -60,9 +58,9 @@ public class AppSmsAuthStrategy implements IAuthStrategy {
AppUserVo user = loadUserByPhonenumber(phonenumber);
if (ObjectUtil.isNull(user)) {
//新增Appuser
addAppUser(tenantId, phonenumber);
user = appUserMapper.selectVoOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhonenumber, phonenumber));
AppUser appUser = addAppUser(tenantId, phonenumber);
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));
// throw new UserException("user.not.exists", phonenumber);
}
@ -89,7 +87,7 @@ public class AppSmsAuthStrategy implements IAuthStrategy {
return loginVo;
}
private void addAppUser(String tenantId, String phonenumber) {
private AppUser addAppUser(String tenantId, String phonenumber) {
AppUser appUser = new AppUser();
appUser.setPhonenumber(phonenumber);
appUser.setUserName(phonenumber);
@ -98,6 +96,7 @@ public class AppSmsAuthStrategy implements IAuthStrategy {
appUser.setLoginIp(ServletUtils.getClientIP());
appUser.setTenantId(tenantId);
appUserMapper.insert(appUser);
return appUser;
}
@ -114,7 +113,9 @@ public class AppSmsAuthStrategy implements IAuthStrategy {
}
private AppUserVo loadUserByPhonenumber(String phonenumber) {
AppUserVo user = appUserMapper.selectVoOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhonenumber, phonenumber));
AppUserVo user = appUserMapper.selectVoOne(new LambdaQueryWrapper<AppUser>()
.eq(AppUser::getPhonenumber, phonenumber)
.eq(AppUser::getUserType, UserType.APP_USER.getUserType()));
if (ObjectUtil.isNull(user)) {
log.info("登录用户:{} 不存在.", phonenumber);
// throw new UserException("user.not.exists", phonenumber);
@ -126,5 +127,4 @@ public class AppSmsAuthStrategy implements IAuthStrategy {
}
return user;
}
}

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://localhost:3306/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: root
password: Jq_123456#
# # 从库数据源
# slave:
# lazy: true
@ -98,13 +98,13 @@ spring:
spring.data:
redis:
# 地址
host: 123.207.99.140
host: 47.120.79.150
# 端口默认为6379
port: 6379
# 数据库索引
database: 2
# redis 密码必须配置
password: ccxx11234
password: xhYc_djkl382^#780!
# 连接超时时间
timeout: 10s
# 是否开启ssl
@ -174,11 +174,15 @@ sms:
# 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
supplier: alibaba
# 有些称为accessKey有些称之为apiKey也有称为sdkKey或者appId。
access-key-id: 您的accessKey
access-key-id: LTAI5tJdDNpZootsPQ5hdELx
# 称为accessSecret有些称之为apiSecret
access-key-secret: 您的accessKeySecret
signature: 您的短信签名
sdk-app-id: 您的sdkAppId
access-key-secret: mU4WtffcCXpHPz5tLwQpaGtLsJXONt
#模板ID 非必须配置如果使用sendMessage的快速发送需此配置
template-id: SMS_322180518
#模板变量 上述模板的变量
templateName: code
signature: 湖北星汉研创科技
# sdk-app-id: 您的sdkAppId
config2:
# 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
supplier: tencent
@ -293,3 +297,12 @@ file:
pic: C:\eladmin\file\ #设备图片存储路径
#ip: http://fuyuanshen.com:81/ #服务器地址
ip: https://fuyuanshen.com/ #服务器地址
# MQTT配置
mqtt:
username: admin
password: #YtvpSfCNG
url: tcp://47.120.79.150:2883
subClientId: fys_subClient
subTopic: worker/alert/#,worker/location/#
pubTopic: worker/location
pubClientId: fys_pubClient

View File

@ -0,0 +1,304 @@
--- # 监控中心配置
spring.boot.admin.client:
# 增加客户端开关
enabled: false
url: http://localhost:9090/admin
instance:
service-host-type: IP
metadata:
username: ${spring.boot.admin.client.username}
userpassword: ${spring.boot.admin.client.password}
username: @monitor.username@
password: @monitor.password@
--- # snail-job 配置
snail-job:
enabled: false
# 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
group: "fys_group"
# SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config` 表
token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT"
server:
host: 127.0.0.1
port: 17888
# 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段
namespace: ${spring.profiles.active}
# 随主应用端口漂移
port: 2${server.port}
# 客户端ip指定
host:
# RPC类型: netty, grpc
rpc-type: grpc
--- # 数据源配置
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
dynamic:
# 性能分析插件(有性能损耗 不建议生产环境使用)
p6spy: true
# 设置默认的数据源或者数据源组,默认值即为 master
primary: master
# 严格模式 匹配不到数据源则报错
strict: true
datasource:
# 主库数据源
master:
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=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: Jq_123456#
# # 从库数据源
# slave:
# lazy: true
# type: ${spring.datasource.type}
# driverClassName: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
# username:
# password:
# oracle:
# type: ${spring.datasource.type}
# driverClassName: oracle.jdbc.OracleDriver
# url: jdbc:oracle:thin:@//localhost:1521/XE
# username: ROOT
# password: root
# postgres:
# type: ${spring.datasource.type}
# driverClassName: org.postgresql.Driver
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
# username: root
# password: root
# sqlserver:
# type: ${spring.datasource.type}
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
# username: SA
# password: root
hikari:
# 最大连接池数量
maxPoolSize: 20
# 最小空闲线程数量
minIdle: 10
# 配置获取连接等待超时的时间
connectionTimeout: 30000
# 校验超时时间
validationTimeout: 5000
# 空闲连接存活最大时间默认10分钟
idleTimeout: 600000
# 此属性控制池中连接的最长生命周期值0表示无限生命周期默认30分钟
maxLifetime: 1800000
# 多久检查一次连接的活性
keepaliveTime: 30000
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
spring.data:
redis:
# 地址
host: 47.120.79.150
# 端口默认为6379
port: 6379
# 数据库索引
database: 2
# redis 密码必须配置
password: xhYc_djkl382^#780!
# 连接超时时间
timeout: 10s
# 是否开启ssl
ssl.enabled: false
# redisson 配置
redisson:
# redis key前缀
keyPrefix:
# 线程池数量
threads: 4
# Netty线程池数量
nettyThreads: 8
# 单节点配置
singleServerConfig:
# 客户端名称 不能用中文
clientName: fys-Vue-Plus
# 最小空闲连接数
connectionMinimumIdleSize: 8
# 连接池大小
connectionPoolSize: 32
# 连接空闲超时,单位:毫秒
idleConnectionTimeout: 10000
# 命令等待超时,单位:毫秒
timeout: 3000
# 发布和订阅连接池大小
subscriptionConnectionPoolSize: 50
--- # mail 邮件发送
mail:
enabled: false
host: smtp.163.com
port: 465
# 是否需要用户名密码验证
auth: true
# 发送方遵循RFC-822标准
from: xxx@163.com
# 用户名注意如果使用foxmail邮箱此处user为qq号
user: xxx@163.com
# 密码注意某些邮箱需要为SMTP服务单独设置密码详情查看相关帮助
pass: xxxxxxxxxx
# 使用 STARTTLS安全连接STARTTLS是对纯文本通信协议的扩展。
starttlsEnable: true
# 使用SSL安全连接
sslEnable: true
# SMTP超时时长单位毫秒缺省值不超时
timeout: 0
# Socket连接超时值单位毫秒缺省值不超时
connectionTimeout: 0
--- # sms 短信 支持 阿里云 腾讯云 云片 等等各式各样的短信服务商
# https://sms4j.com/doc3/ 差异配置文档地址 支持单厂商多配置,可以配置多个同时使用
sms:
# 配置源类型用于标定配置来源(interface,yaml)
config-type: yaml
# 用于标定yml中的配置是否开启短信拦截接口配置不受此限制
restricted: true
# 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效
minute-max: 1
# 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效
account-max: 30
# 以下配置来自于 com.fuyuanshen.sms4j.provider.config.BaseConfig类中
blends:
# 唯一ID 用于发送短信寻找具体配置 随便定义别用中文即可
# 可以同时存在两个相同厂商 例如: ali1 ali2 两个不同的阿里短信账号 也可用于区分租户
config1:
# 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
supplier: alibaba
# 有些称为accessKey有些称之为apiKey也有称为sdkKey或者appId。
access-key-id: 您的accessKey
# 称为accessSecret有些称之为apiSecret
access-key-secret: 您的accessKeySecret
signature: 您的短信签名
sdk-app-id: 您的sdkAppId
config2:
# 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
supplier: tencent
access-key-id: 您的accessKey
access-key-secret: 您的accessKeySecret
signature: 您的短信签名
sdk-app-id: 您的sdkAppId
--- # 三方授权
justauth:
# 前端外网访问地址
address: http://localhost:80
type:
maxkey:
# maxkey 服务器地址
# 注意 如下均配置均不需要修改 maxkey 已经内置好了数据
server-url: http://sso.maxkey.top
client-id: 876892492581044224
client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8
redirect-uri: ${justauth.address}/social-callback?source=maxkey
topiam:
# topiam 服务器地址
server-url: http://127.0.0.1:1898/api/v1/authorize/y0q************spq***********8ol
client-id: 449c4*********937************759
client-secret: ac7***********1e0************28d
redirect-uri: ${justauth.address}/social-callback?source=topiam
scopes: [openid, email, phone, profile]
qq:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=qq
union-id: false
weibo:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=weibo
gitee:
client-id: 91436b7940090d09c72c7daf85b959cfd5f215d67eea73acbf61b6b590751a98
client-secret: 02c6fcfd70342980cd8dd2f2c06c1a350645d76c754d7a264c4e125f9ba915ac
redirect-uri: ${justauth.address}/social-callback?source=gitee
dingtalk:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=dingtalk
baidu:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=baidu
csdn:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=csdn
coding:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=coding
coding-group-name: xx
oschina:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=oschina
alipay_wallet:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=alipay_wallet
alipay-public-key: MIIB**************DAQAB
wechat_open:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=wechat_open
wechat_mp:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=wechat_mp
wechat_enterprise:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=wechat_enterprise
agent-id: 1000002
gitlab:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=gitlab
gitea:
# 前端改动 https://gitee.com/JavaLionLi/plus-ui/pulls/204
# gitea 服务器地址
server-url: https://demo.gitea.com
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=gitea
# 文件存储路径
file:
mac:
path: ~/file/
avatar: ~/avatar/
linux:
path: /home/eladmin/file/
avatar: /home/eladmin/avatar/
windows:
path: C:\eladmin\file\
avatar: C:\eladmin\avatar\
# 文件大小 /M
maxSize: 100
avatarMaxSize: 5
device:
pic: C:\eladmin\file\ #设备图片存储路径
ip: http://fuyuanshen.com:81/ #服务器地址
app_avatar:
pic: C:\eladmin\file\ #设备图片存储路径
#ip: http://fuyuanshen.com:81/ #服务器地址
ip: https://fuyuanshen.com/ #服务器地址
# MQTT配置
mqtt:
username: admin
password: fys123456
url: tcp://47.107.152.87:1883
subClientId: fys_subClient_01
subTopic: worker/alert/#,worker/location/#
pubTopic: worker/location
pubClientId: fys_pubClient_01

View File

@ -52,9 +52,9 @@ spring:
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
url: jdbc:mysql://localhost: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: root
password: Jz_5623_cl1
# # 从库数据源
# slave:
# lazy: true
@ -105,9 +105,9 @@ spring.data:
# 端口默认为6379
port: 6379
# 数据库索引
database: 0
database: 1
# redis 密码必须配置
password: fys123
password: re_fs_11520631
# 连接超时时间
timeout: 10s
# 是否开启ssl
@ -272,3 +272,37 @@ justauth:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=gitea
# MQTT配置
mqtt:
username: admin
password: #YtvpSfCNG
url: tcp://47.120.79.150:2883
subClientId: fys_subClient
subTopic: worker/alert/#,worker/location/#
pubTopic: worker/location
pubClientId: fys_pubClient
# 文件存储路径
file:
mac:
path: ~/file/
avatar: ~/avatar/
linux:
path: /home/eladmin/file/
avatar: /home/eladmin/avatar/
windows:
path: C:\eladmin\file\
avatar: C:\eladmin\avatar\
# 文件大小 /M
maxSize: 100
avatarMaxSize: 5
device:
pic: C:\eladmin\file\ #设备图片存储路径
ip: http://fuyuanshen.com:81/ #服务器地址
app_avatar:
pic: C:\eladmin\file\ #设备图片存储路径
#ip: http://fuyuanshen.com:81/ #服务器地址
ip: https://fuyuanshen.com/ #服务器地址

View File

@ -1,7 +1,7 @@
# 开发环境配置
server:
# 服务器的HTTP端口默认为8080
port: 8001
port: 8000
servlet:
# 应用的访问路径
context-path: /
@ -39,6 +39,7 @@ logging:
org.springframework: warn
org.mybatis.spring.mapper: error
org.apache.fury: warn
com.fuyuanshen.web.service.impl.ClientServiceImpl: debug
config: classpath:logback-plus.xml
# 用户配置
@ -135,7 +136,7 @@ tenant:
# https://baomidou.com/config/
mybatis-plus:
# 自定义配置 是否全局开启逻辑删除 关闭后 所有逻辑删除功能将失效
enableLogicDelete: true
enableLogicDelete: false
# 多包名使用 例如 com.fuyuanshen.**.mapper,org.xxx.**.mapper
mapperPackage: com.fuyuanshen.**.mapper
# 对应的 XML 文件位置
@ -213,6 +214,10 @@ springdoc:
packages-to-scan: com.fuyuanshen.workflow
- group: 设备管理模块
packages-to-scan: com.fuyuanshen.equipment
- group: 客户管理模块
packages-to-scan: com.fuyuanshen.customer
- group: APP模块
packages-to-scan: com.fuyuanshen.app
# 防止XSS攻击
xss:

View File

@ -16,12 +16,12 @@
<!-- 控制台输出 -->
<appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-console.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-console.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大 1天 -->
<maxHistory>1</maxHistory>
</rollingPolicy>
<!-- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> -->
<!-- &lt;!&ndash; 日志文件名格式 &ndash;&gt; -->
<!-- <fileNamePattern>${log.path}/sys-console.%d{yyyy-MM-dd}.log</fileNamePattern> -->
<!-- &lt;!&ndash; 日志最大 1天 &ndash;&gt; -->
<!-- <maxHistory>1</maxHistory> -->
<!-- </rollingPolicy> -->
<encoder>
<pattern>${log.pattern}</pattern>
<charset>utf-8</charset>
@ -36,12 +36,12 @@
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<!-- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> -->
<!-- &lt;!&ndash; 日志文件名格式 &ndash;&gt; -->
<!-- <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern> -->
<!-- &lt;!&ndash; 日志最大的历史 60天 &ndash;&gt; -->
<!-- <maxHistory>60</maxHistory> -->
<!-- </rollingPolicy> -->
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
@ -58,12 +58,12 @@
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<!-- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> -->
<!-- &lt;!&ndash; 日志文件名格式 &ndash;&gt; -->
<!-- <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern> -->
<!-- &lt;!&ndash; 日志最大的历史 60天 &ndash;&gt; -->
<!-- <maxHistory>60</maxHistory> -->
<!-- </rollingPolicy> -->
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>

View File

@ -15,6 +15,10 @@
fys-common-core 核心模块
</description>
<properties>
<hutool.version>5.8.35</hutool.version>
</properties>
<dependencies>
<!-- Spring框架基本的核心工具 -->
<dependency>
@ -56,6 +60,13 @@
<artifactId>hutool-core</artifactId>
</dependency>
<!--工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
@ -66,6 +77,33 @@
<artifactId>hutool-extra</artifactId>
</dependency>
<!-- excel工具 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.4.0</version>
</dependency>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.12.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>5.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-full</artifactId>
<version>5.4.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>

View File

@ -17,6 +17,11 @@ public interface GlobalConstants {
*/
String CAPTCHA_CODE_KEY = GLOBAL_REDIS_KEY + "captcha_codes:";
/**
* 设备分享验证码 redis key
*/
String DEVICE_SHARE_CODES_KEY = GLOBAL_REDIS_KEY + "device_share_codes:";
/**
* 防重提交 redis key
*/

View File

@ -22,6 +22,11 @@ public interface TenantConstants {
*/
String TENANT_ADMIN_ROLE_KEY = "admin";
/**
* 富源晟内部员工 roleKey
*/
String FYS_ROLE_KEY = "fel";
/**
* 租户管理员角色名称
*/

View File

@ -18,7 +18,7 @@ import java.util.List;
@AllArgsConstructor
public class PageResult<T> implements Serializable {
private List<T> content;
private List<T> rows;
private long totalElements;
private long total;
}

View File

@ -1,5 +1,6 @@
package com.fuyuanshen.common.core.domain.model;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.fuyuanshen.common.core.domain.dto.PostDTO;
@ -31,6 +32,7 @@ public class LoginUser implements Serializable {
* 用户ID
*/
private Long userId;
private Long pid;
/**
* 部门ID
@ -132,6 +134,11 @@ public class LoginUser implements Serializable {
*/
private String deviceType;
/**
* 用户等级
*/
private Byte userLevel;
/**
* 获取登录id
*/

View File

@ -21,7 +21,13 @@ public enum UserType {
/**
* 移动客户端用户
*/
APP_USER("app_user");
APP_USER("app_user"),
/**
* 小程序 用户
*/
XCX_USER("xcx_user");
/**
* 用户类型标识(用于 token、权限识别等

View File

@ -0,0 +1,41 @@
/*
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fuyuanshen.common.core.exception;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
/**
* @author Zheng Jie
* @date 2018-11-23
* 统一异常处理
*/
@Getter
public class BadRequestException extends RuntimeException{
private Integer status = BAD_REQUEST.value();
public BadRequestException(String msg){
super(msg);
}
public BadRequestException(HttpStatus status,String msg){
super(msg);
this.status = status.value();
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fuyuanshen.common.core.exception;
import org.springframework.util.StringUtils;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
public class EntityExistException extends RuntimeException {
public EntityExistException(Class clazz, String field, String val) {
super(EntityExistException.generateMessage(clazz.getSimpleName(), field, val));
}
private static String generateMessage1(String entity, String field, String val) {
return StringUtils.capitalize(entity) + " with " + field + " " + val + " existed";
}
private static String generateMessage(String entity, String field, String val) {
return field + " " + val + " 已存在";
}
}

View File

@ -0,0 +1,34 @@
/*
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fuyuanshen.common.core.exception;
import org.springframework.util.StringUtils;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
public class EntityNotFoundException extends RuntimeException {
public EntityNotFoundException(Class clazz, String field, String val) {
super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), field, val));
}
private static String generateMessage(String entity, String field, String val) {
return StringUtils.capitalize(entity)
+ " with " + field + " "+ val + " does not exist";
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fuyuanshen.common.core.exception.handler;
import lombok.Data;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
@Data
public class ApiError {
private Integer status = 400;
private Long timestamp;
private String message;
private ApiError() {
timestamp = System.currentTimeMillis();
}
public static ApiError error(String message){
ApiError apiError = new ApiError();
apiError.setMessage(message);
return apiError;
}
public static ApiError error(Integer status, String message){
ApiError apiError = new ApiError();
apiError.setStatus(status);
apiError.setMessage(message);
return apiError;
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fuyuanshen.common.core.utils;
import java.io.Closeable;
/**
* @author Zheng Jie
* @description 用于关闭各种连接,缺啥补啥
* @date 2021-03-05
**/
public class CloseUtil {
public static void close(Closeable closeable) {
if (null != closeable) {
try {
closeable.close();
} catch (Exception e) {
// 静默关闭
}
}
}
public static void close(AutoCloseable closeable) {
if (null != closeable) {
try {
closeable.close();
} catch (Exception e) {
// 静默关闭
}
}
}
}

View File

@ -0,0 +1,90 @@
package com.fuyuanshen.common.core.utils;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class ImageToCArrayConverterUtils {
public static void main(String[] args) {
try {
convertImageToCArray("E:\\workspace\\6170_强光_160_80_2.jpg", "E:\\workspace\\output.c", 160, 80);
System.out.println("转换成功!");
} catch (IOException e) {
System.err.println("转换失败: " + e.getMessage());
}
}
public static void convertImageToCArray(String inputPath, String outputPath,
int width, int height) throws IOException {
// 读取原始图片
BufferedImage originalImage = ImageIO.read(new File(inputPath));
// 调整图片尺寸
BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
resizedImage.getGraphics().drawImage(
originalImage, 0, 0, width, height, null);
// 转换像素数据为RGB565格式高位在前
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int rgb = resizedImage.getRGB(x, y);
// 提取RGB分量
int r = (rgb >> 16) & 0xFF;
int g = (rgb >> 8) & 0xFF;
int b = rgb & 0xFF;
// 转换为RGB5655位红6位绿5位蓝
int r5 = (r >> 3) & 0x1F;
int g6 = (g >> 2) & 0x3F;
int b5 = (b >> 3) & 0x1F;
// 组合为16位值
int rgb565 = (r5 << 11) | (g6 << 5) | b5;
// 高位在前(大端序)写入字节
byteStream.write((rgb565 >> 8) & 0xFF); // 高字节
byteStream.write(rgb565 & 0xFF); // 低字节
}
}
byte[] imageData = byteStream.toByteArray();
// 生成C语言数组文件
try (FileOutputStream fos = new FileOutputStream(outputPath)) {
// 写入注释行(包含尺寸信息)
String header = String.format("/* 0X10,0X10,0X00,0X%02X,0X00,0X%02X,0X01,0X1B, */\n",
width, height);
fos.write(header.getBytes());
// 写入数组声明
fos.write("const unsigned char gImage_data[] = {\n".getBytes());
// 写入数据每行16个字节
for (int i = 0; i < imageData.length; i++) {
// 写入0X前缀
fos.write(("0X" + String.format("%02X", imageData[i] & 0xFF)).getBytes());
// 添加逗号(最后一个除外)
if (i < imageData.length - 1) {
fos.write(',');
}
// 换行和缩进
if ((i + 1) % 16 == 0) {
fos.write('\n');
} else {
fos.write(' ');
}
}
// 写入数组结尾
fos.write("\n};\n".getBytes());
}
}
}

View File

@ -0,0 +1,413 @@
/*
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fuyuanshen.common.core.utils.file;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import com.fuyuanshen.common.core.exception.BadRequestException;
import com.fuyuanshen.common.core.utils.CloseUtil;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* File工具类扩展 hutool 工具包
*
* @author Zheng Jie
* @date 2018-12-27
*/
@Slf4j
public class FileUtil extends cn.hutool.core.io.FileUtil {
/**
* 系统临时目录
* <br>
* windows 包含路径分割符但Linux 不包含,
* 在windows \\==\ 前提下,
* 为安全起见 同意拼装 路径分割符,
* <pre>
* java.io.tmpdir
* windows : C:\Users/xxx\AppData\Local\Temp\
* linux: /temp
* </pre>
*/
public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator;
/**
* 定义GB的计算常量
*/
private static final int GB = 1024 * 1024 * 1024;
/**
* 定义MB的计算常量
*/
private static final int MB = 1024 * 1024;
/**
* 定义KB的计算常量
*/
private static final int KB = 1024;
/**
* 格式化小数
*/
private static final DecimalFormat DF = new DecimalFormat("0.00");
public static final String IMAGE = "图片";
public static final String TXT = "文档";
public static final String MUSIC = "音乐";
public static final String VIDEO = "视频";
public static final String OTHER = "其他";
/**
* MultipartFile转File
*/
public static File toFile(MultipartFile multipartFile) {
// 获取文件名
String fileName = multipartFile.getOriginalFilename();
// 获取文件后缀
String prefix = "." + getExtensionName(fileName);
File file = null;
try {
// 用uuid作为文件名防止生成的临时文件重复
file = new File(SYS_TEM_DIR + IdUtil.simpleUUID() + prefix);
// MultipartFile to File
multipartFile.transferTo(file);
} catch (IOException e) {
log.error(e.getMessage(), e);
}
return file;
}
/**
* 获取文件扩展名,不带 .
*/
public static String getExtensionName(String filename) {
if ((filename != null) && (!filename.isEmpty())) {
int dot = filename.lastIndexOf('.');
if ((dot > -1) && (dot < (filename.length() - 1))) {
return filename.substring(dot + 1);
}
}
return filename;
}
/**
* Java文件操作 获取不带扩展名的文件名
*/
public static String getFileNameNoEx(String filename) {
if ((filename != null) && (!filename.isEmpty())) {
int dot = filename.lastIndexOf('.');
if (dot > -1) {
return filename.substring(0, dot);
}
}
return filename;
}
/**
* 文件大小转换
*/
public static String getSize(long size) {
String resultSize;
if (size / GB >= 1) {
//如果当前Byte的值大于等于1GB
resultSize = DF.format(size / (float) GB) + "GB ";
} else if (size / MB >= 1) {
//如果当前Byte的值大于等于1MB
resultSize = DF.format(size / (float) MB) + "MB ";
} else if (size / KB >= 1) {
//如果当前Byte的值大于等于1KB
resultSize = DF.format(size / (float) KB) + "KB ";
} else {
resultSize = size + "B ";
}
return resultSize;
}
/**
* inputStream 转 File
*/
static File inputStreamToFile(InputStream ins, String name){
File file = new File(SYS_TEM_DIR + name);
if (file.exists()) {
return file;
}
OutputStream os = null;
try {
os = Files.newOutputStream(file.toPath());
int bytesRead;
int len = 8192;
byte[] buffer = new byte[len];
while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
os.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
CloseUtil.close(os);
CloseUtil.close(ins);
}
return file;
}
/**
* 将文件名解析成文件的上传路径
*/
public static File upload(MultipartFile file, String filePath) {
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS");
// 过滤非法文件名
String name = getFileNameNoEx(verifyFilename(file.getOriginalFilename()));
String suffix = getExtensionName(file.getOriginalFilename());
String nowStr = "-" + format.format(date);
try {
String fileName = name + nowStr + "." + suffix;
String path = filePath + fileName;
// getCanonicalFile 可解析正确各种路径
File dest = new File(path).getCanonicalFile();
// 检测是否存在目录
if (!dest.getParentFile().exists()) {
if (!dest.getParentFile().mkdirs()) {
System.out.println("was not successful.");
}
}
// 文件写入
file.transferTo(dest);
return dest;
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return null;
}
/**
* 导出excel
*/
public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
File file = new File(tempPath);
BigExcelWriter writer = ExcelUtil.getBigWriter(file);
// 处理数据以防止CSV注入
List<Map<String, Object>> sanitizedList = list.parallelStream().map(map -> {
Map<String, Object> sanitizedMap = new LinkedHashMap<>();
map.forEach((key, value) -> {
if (value instanceof String) {
String strValue = (String) value;
// 检查并处理以特殊字符开头的值
if (strValue.startsWith("=") || strValue.startsWith("+") || strValue.startsWith("-") || strValue.startsWith("@")) {
strValue = "'" + strValue; // 添加单引号前缀
}
sanitizedMap.put(key, strValue);
} else {
sanitizedMap.put(key, value);
}
});
return sanitizedMap;
}).collect(Collectors.toList());
// 一次性写出内容,使用默认样式,强制输出标题
writer.write(sanitizedList, true);
SXSSFSheet sheet = (SXSSFSheet)writer.getSheet();
//上面需要强转SXSSFSheet 不然没有trackAllColumnsForAutoSizing方法
sheet.trackAllColumnsForAutoSizing();
//列宽自适应
writer.autoSizeColumnAll();
//response为HttpServletResponse对象
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
//test.xls是弹出下载对话框的文件名不能为中文中文请自行编码
response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
ServletOutputStream out = response.getOutputStream();
// 终止后删除临时文件
file.deleteOnExit();
writer.flush(out, true);
//此处记得关闭输出Servlet流
IoUtil.close(out);
}
public static String getFileType(String type) {
String documents = "txt doc pdf ppt pps xlsx xls docx";
String music = "mp3 wav wma mpa ram ra aac aif m4a";
String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg";
String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";
if (image.contains(type)) {
return IMAGE;
} else if (documents.contains(type)) {
return TXT;
} else if (music.contains(type)) {
return MUSIC;
} else if (video.contains(type)) {
return VIDEO;
} else {
return OTHER;
}
}
public static void checkSize(long maxSize, long size) {
// 1M
int len = 1024 * 1024;
if (size > (maxSize * len)) {
throw new BadRequestException("文件超出规定大小:" + maxSize + "MB");
}
}
/**
* 判断两个文件是否相同
*/
public static boolean check(File file1, File file2) {
String img1Md5 = getMd5(file1);
String img2Md5 = getMd5(file2);
if(img1Md5 != null){
return img1Md5.equals(img2Md5);
}
return false;
}
/**
* 判断两个文件是否相同
*/
public static boolean check(String file1Md5, String file2Md5) {
return file1Md5.equals(file2Md5);
}
private static byte[] getByte(File file) {
// 得到文件长度
byte[] b = new byte[(int) file.length()];
InputStream in = null;
try {
in = Files.newInputStream(file.toPath());
try {
System.out.println(in.read(b));
} catch (IOException e) {
log.error(e.getMessage(), e);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
return null;
} finally {
CloseUtil.close(in);
}
return b;
}
private static String getMd5(byte[] bytes) {
// 16进制字符
char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
try {
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
mdTemp.update(bytes);
byte[] md = mdTemp.digest();
int j = md.length;
char[] str = new char[j * 2];
int k = 0;
// 移位 输出字符串
for (byte byte0 : md) {
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return null;
}
/**
* 下载文件
*
* @param request /
* @param response /
* @param file /
*/
public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) {
response.setCharacterEncoding(request.getCharacterEncoding());
response.setContentType("application/octet-stream");
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
IOUtils.copy(fis, response.getOutputStream());
response.flushBuffer();
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
if (fis != null) {
try {
fis.close();
if (deleteOnExit) {
file.deleteOnExit();
}
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}
}
/**
* 验证并过滤非法的文件名
* @param fileName 文件名
* @return 文件名
*/
public static String verifyFilename(String fileName) {
// 过滤掉特殊字符
fileName = fileName.replaceAll("[\\\\/:*?\"<>|~\\s]", "");
// 去掉文件名开头和结尾的空格和点
fileName = fileName.trim().replaceAll("^[. ]+|[. ]+$", "");
// 不允许文件名超过255在Mac和Linux中或260在Windows中个字符
int maxFileNameLength = 255;
if (System.getProperty("os.name").startsWith("Windows")) {
maxFileNameLength = 260;
}
if (fileName.length() > maxFileNameLength) {
fileName = fileName.substring(0, maxFileNameLength);
}
// 过滤掉控制字符
fileName = fileName.replaceAll("[\\p{Cntrl}]", "");
// 过滤掉 ".." 路径
fileName = fileName.replaceAll("\\.{2,}", "");
// 去掉文件名开头的 ".."
fileName = fileName.replaceAll("^\\.+/", "");
// 保留文件名中最后一个 "." 字符,过滤掉其他 "."
fileName = fileName.replaceAll("^(.*)(\\.[^.]*)$", "$1").replaceAll("\\.", "") +
fileName.replaceAll("^(.*)(\\.[^.]*)$", "$2");
return fileName;
}
public static String getMd5(File file) {
return getMd5(getByte(file));
}
}

View File

@ -39,8 +39,8 @@ public class EncryptUtilsTest {
loginBody.setClientId("e5cd7e4891bf95d1d19206ce24a7b32e");
loginBody.setGrantType("password");
loginBody.setTenantId("894078");
loginBody.setCode("9");
loginBody.setUuid("64d5a9107e4949f3ba8f57ede00bd034");
loginBody.setCode("0");
loginBody.setUuid("1c285b27f516486f9535face77023aeb");
// loginBody.setUsername("admin");
// loginBody.setPassword("admin123");
loginBody.setUsername("dyf");

View File

@ -37,7 +37,7 @@ public enum BusinessType {
EXPORT,
/**
* 导入
*
*/
IMPORT,

View File

@ -0,0 +1,24 @@
package com.fuyuanshen.common.sms.controller;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author: 默苍璃
* @date: 2025-07-0714:02
*/
@RestController
public class TestSMSController {
@GetMapping("/test")
public void testSend() {
// 在创建完SmsBlend实例后再未手动调用注销的情况下框架会持有该实例可以直接通过指定configId来获取想要的配置如果你想使用
// 负载均衡形式获取实例只要使用getSmsBlend的无参重载方法即可如果你仅有一个配置也可以使用该方法
SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
SmsResponse smsResponse = smsBlend.sendMessage("18656573389", "1234");
}
}

View File

@ -58,4 +58,5 @@ public class ResourcesConfig implements WebMvcConfigurer {
public GlobalExceptionHandler globalExceptionHandler() {
return new GlobalExceptionHandler();
}
}

View File

@ -15,6 +15,11 @@
<dependencies>
<dependency>
<groupId>com.fuyuanshen</groupId>
<artifactId>fys-equipment</artifactId>
</dependency>
<!-- 通用工具-->
<dependency>
<groupId>com.fuyuanshen</groupId>

View File

@ -0,0 +1,105 @@
package com.fuyuanshen.app.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.fuyuanshen.common.idempotent.annotation.RepeatSubmit;
import com.fuyuanshen.common.log.annotation.Log;
import com.fuyuanshen.common.web.core.BaseController;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.core.validate.AddGroup;
import com.fuyuanshen.common.core.validate.EditGroup;
import com.fuyuanshen.common.log.enums.BusinessType;
import com.fuyuanshen.common.excel.utils.ExcelUtil;
import com.fuyuanshen.app.domain.vo.AppBusinessFileVo;
import com.fuyuanshen.app.domain.bo.AppBusinessFileBo;
import com.fuyuanshen.app.service.IAppBusinessFileService;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
/**
* app业务文件
*
* @author Lion Li
* @date 2025-07-03
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/app/businessFile")
public class AppBusinessFileController extends BaseController {
private final IAppBusinessFileService appBusinessFileService;
/**
* 查询app业务文件列表
*/
@SaCheckPermission("app:businessFile:list")
@GetMapping("/list")
public TableDataInfo<AppBusinessFileVo> list(AppBusinessFileBo bo, PageQuery pageQuery) {
return appBusinessFileService.queryPageList(bo, pageQuery);
}
/**
* 导出app业务文件列表
*/
@SaCheckPermission("app:businessFile:export")
@Log(title = "app业务文件", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(AppBusinessFileBo bo, HttpServletResponse response) {
List<AppBusinessFileVo> list = appBusinessFileService.queryList(bo);
ExcelUtil.exportExcel(list, "app业务文件", AppBusinessFileVo.class, response);
}
/**
* 获取app业务文件详细信息
*
* @param id 主键
*/
@SaCheckPermission("app:businessFile:query")
@GetMapping("/{id}")
public R<AppBusinessFileVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(appBusinessFileService.queryById(id));
}
/**
* 新增app业务文件
*/
@SaCheckPermission("app:businessFile:add")
@Log(title = "app业务文件", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody AppBusinessFileBo bo) {
return toAjax(appBusinessFileService.insertByBo(bo));
}
/**
* 修改app业务文件
*/
@SaCheckPermission("app:businessFile:edit")
@Log(title = "app业务文件", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody AppBusinessFileBo bo) {
return toAjax(appBusinessFileService.updateByBo(bo));
}
/**
* 删除app业务文件
*
* @param ids 主键串
*/
@SaCheckPermission("app:businessFile:remove")
@Log(title = "app业务文件", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(appBusinessFileService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,105 @@
//package com.fuyuanshen.app.controller;
//
//import java.util.List;
//
//import lombok.RequiredArgsConstructor;
//import jakarta.servlet.http.HttpServletResponse;
//import jakarta.validation.constraints.*;
//import cn.dev33.satoken.annotation.SaCheckPermission;
//import org.springframework.web.bind.annotation.*;
//import org.springframework.validation.annotation.Validated;
//import com.fuyuanshen.common.idempotent.annotation.RepeatSubmit;
//import com.fuyuanshen.common.log.annotation.Log;
//import com.fuyuanshen.common.web.core.BaseController;
//import com.fuyuanshen.common.mybatis.core.page.PageQuery;
//import com.fuyuanshen.common.core.domain.R;
//import com.fuyuanshen.common.core.validate.AddGroup;
//import com.fuyuanshen.common.core.validate.EditGroup;
//import com.fuyuanshen.common.log.enums.BusinessType;
//import com.fuyuanshen.common.excel.utils.ExcelUtil;
//import com.fuyuanshen.app.domain.vo.AppDeviceShareVo;
//import com.fuyuanshen.app.domain.bo.AppDeviceShareBo;
//import com.fuyuanshen.app.service.IAppDeviceShareService;
//import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
//
///**
// * 设备分享
// *
// * @author Lion Li
// * @date 2025-07-16
// */
//@Validated
//@RequiredArgsConstructor
//@RestController
//@RequestMapping("/app/deviceShare")
//public class AppDeviceShareController extends BaseController {
//
// private final IAppDeviceShareService appDeviceShareService;
//
// /**
// * 查询设备分享列表
// */
// @SaCheckPermission("app:deviceShare:list")
// @GetMapping("/list")
// public TableDataInfo<AppDeviceShareVo> list(AppDeviceShareBo bo, PageQuery pageQuery) {
// return appDeviceShareService.queryPageList(bo, pageQuery);
// }
//
// /**
// * 导出设备分享列表
// */
// @SaCheckPermission("app:deviceShare:export")
// @Log(title = "设备分享", businessType = BusinessType.EXPORT)
// @PostMapping("/export")
// public void export(AppDeviceShareBo bo, HttpServletResponse response) {
// List<AppDeviceShareVo> list = appDeviceShareService.queryList(bo);
// ExcelUtil.exportExcel(list, "设备分享", AppDeviceShareVo.class, response);
// }
//
// /**
// * 获取设备分享详细信息
// *
// * @param id 主键
// */
// @SaCheckPermission("app:deviceShare:query")
// @GetMapping("/{id}")
// public R<AppDeviceShareVo> getInfo(@NotNull(message = "主键不能为空")
// @PathVariable Long id) {
// return R.ok(appDeviceShareService.queryById(id));
// }
//
// /**
// * 新增设备分享
// */
// @SaCheckPermission("app:deviceShare:add")
// @Log(title = "设备分享", businessType = BusinessType.INSERT)
// @RepeatSubmit()
// @PostMapping()
// public R<Void> add(@Validated(AddGroup.class) @RequestBody AppDeviceShareBo bo) {
// return toAjax(appDeviceShareService.insertByBo(bo));
// }
//
// /**
// * 修改设备分享
// */
// @SaCheckPermission("app:deviceShare:edit")
// @Log(title = "设备分享", businessType = BusinessType.UPDATE)
// @RepeatSubmit()
// @PutMapping()
// public R<Void> edit(@Validated(EditGroup.class) @RequestBody AppDeviceShareBo bo) {
// return toAjax(appDeviceShareService.updateByBo(bo));
// }
//
// /**
// * 删除设备分享
// *
// * @param ids 主键串
// */
// @SaCheckPermission("app:deviceShare:remove")
// @Log(title = "设备分享", businessType = BusinessType.DELETE)
// @DeleteMapping("/{ids}")
// public R<Void> remove(@NotEmpty(message = "主键不能为空")
// @PathVariable Long[] ids) {
// return toAjax(appDeviceShareService.deleteWithValidByIds(List.of(ids), true));
// }
//}

View File

@ -0,0 +1,105 @@
package com.fuyuanshen.app.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.fuyuanshen.common.idempotent.annotation.RepeatSubmit;
import com.fuyuanshen.common.log.annotation.Log;
import com.fuyuanshen.common.web.core.BaseController;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.core.validate.AddGroup;
import com.fuyuanshen.common.core.validate.EditGroup;
import com.fuyuanshen.common.log.enums.BusinessType;
import com.fuyuanshen.common.excel.utils.ExcelUtil;
import com.fuyuanshen.app.domain.vo.AppOperationVideoVo;
import com.fuyuanshen.app.domain.bo.AppOperationVideoBo;
import com.fuyuanshen.app.service.IAppOperationVideoService;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
/**
* 操作视频
*
* @author Lion Li
* @date 2025-07-02
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/app/operationVideo")
public class AppOperationVideoController extends BaseController {
private final IAppOperationVideoService appOperationVideoService;
/**
* 查询操作视频列表
*/
@SaCheckPermission("app:operationVideo:list")
@GetMapping("/list")
public TableDataInfo<AppOperationVideoVo> list(AppOperationVideoBo bo, PageQuery pageQuery) {
return appOperationVideoService.queryPageList(bo, pageQuery);
}
/**
* 导出操作视频列表
*/
@SaCheckPermission("app:operationVideo:export")
@Log(title = "操作视频", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(AppOperationVideoBo bo, HttpServletResponse response) {
List<AppOperationVideoVo> list = appOperationVideoService.queryList(bo);
ExcelUtil.exportExcel(list, "操作视频", AppOperationVideoVo.class, response);
}
/**
* 获取操作视频详细信息
*
* @param id 主键
*/
@SaCheckPermission("app:operationVideo:query")
@GetMapping("/{id}")
public R<AppOperationVideoVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(appOperationVideoService.queryById(id));
}
/**
* 新增操作视频
*/
@SaCheckPermission("app:operationVideo:add")
@Log(title = "操作视频", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody AppOperationVideoBo bo) {
return toAjax(appOperationVideoService.insertByBo(bo));
}
/**
* 修改操作视频
*/
@SaCheckPermission("app:operationVideo:edit")
@Log(title = "操作视频", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody AppOperationVideoBo bo) {
return toAjax(appOperationVideoService.updateByBo(bo));
}
/**
* 删除操作视频
*
* @param ids 主键串
*/
@SaCheckPermission("app:operationVideo:remove")
@Log(title = "操作视频", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(appOperationVideoService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,105 @@
package com.fuyuanshen.app.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.fuyuanshen.common.idempotent.annotation.RepeatSubmit;
import com.fuyuanshen.common.log.annotation.Log;
import com.fuyuanshen.common.web.core.BaseController;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.core.validate.AddGroup;
import com.fuyuanshen.common.core.validate.EditGroup;
import com.fuyuanshen.common.log.enums.BusinessType;
import com.fuyuanshen.common.excel.utils.ExcelUtil;
import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo;
import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo;
import com.fuyuanshen.app.service.IAppPersonnelInfoService;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
/**
* 人员信息登记
*
* @author Lion Li
* @date 2025-07-02
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/app/personnelInfo")
public class AppPersonnelInfoController extends BaseController {
private final IAppPersonnelInfoService appPersonnelInfoService;
/**
* 查询人员信息登记列表
*/
@SaCheckPermission("app:personnelInfo:list")
@GetMapping("/list")
public TableDataInfo<AppPersonnelInfoVo> list(AppPersonnelInfoBo bo, PageQuery pageQuery) {
return appPersonnelInfoService.queryPageList(bo, pageQuery);
}
/**
* 导出人员信息登记列表
*/
@SaCheckPermission("app:personnelInfo:export")
@Log(title = "人员信息登记", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(AppPersonnelInfoBo bo, HttpServletResponse response) {
List<AppPersonnelInfoVo> list = appPersonnelInfoService.queryList(bo);
ExcelUtil.exportExcel(list, "人员信息登记", AppPersonnelInfoVo.class, response);
}
/**
* 获取人员信息登记详细信息
*
* @param id 主键
*/
@SaCheckPermission("app:personnelInfo:query")
@GetMapping("/{id}")
public R<AppPersonnelInfoVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(appPersonnelInfoService.queryById(id));
}
/**
* 新增人员信息登记
*/
@SaCheckPermission("app:personnelInfo:add")
@Log(title = "人员信息登记", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody AppPersonnelInfoBo bo) {
return toAjax(appPersonnelInfoService.insertByBo(bo));
}
/**
* 修改人员信息登记
*/
@SaCheckPermission("app:personnelInfo:edit")
@Log(title = "人员信息登记", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody AppPersonnelInfoBo bo) {
return toAjax(appPersonnelInfoService.updateByBo(bo));
}
/**
* 删除人员信息登记
*
* @param ids 主键串
*/
@SaCheckPermission("app:personnelInfo:remove")
@Log(title = "人员信息登记", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(appPersonnelInfoService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -2,6 +2,7 @@ package com.fuyuanshen.app.controller;
import java.util.List;
import com.fuyuanshen.common.core.enums.UserType;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
@ -36,12 +37,14 @@ public class AppUserController extends BaseController {
private final IAppUserService appUserService;
/**
* 查询APP用户信息列表
*/
// @SaCheckPermission("app:user:list")
@GetMapping("/list")
public TableDataInfo<AppUserVo> list(AppUserBo bo, PageQuery pageQuery) {
bo.setUserType(UserType.APP_USER.getUserType());
return appUserService.queryPageList(bo, pageQuery);
}

View File

@ -0,0 +1,112 @@
package com.fuyuanshen.app.controller.equipment;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fuyuanshen.app.domain.APPDevice;
import com.fuyuanshen.app.domain.APPDeviceType;
import com.fuyuanshen.app.domain.query.APPDeviceQueryCriteria;
import com.fuyuanshen.app.service.equipment.APPDeviceService;
import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.core.domain.ResponseVO;
import com.fuyuanshen.common.core.validate.EditGroup;
import com.fuyuanshen.common.idempotent.annotation.RepeatSubmit;
import com.fuyuanshen.common.log.annotation.Log;
import com.fuyuanshen.common.log.enums.BusinessType;
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.bo.UserAppBo;
import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria;
import com.fuyuanshen.equipment.domain.vo.AppDeviceVo;
import com.fuyuanshen.equipment.service.AppUserService;
import com.fuyuanshen.equipment.service.DeviceService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @Description:
* @Author: WY
* @Date: 2025/5/16
**/
@Slf4j
@Tag(name = "APP客户设备管理", description = "APP客户设备管理")
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/app/device")
public class APPDeviceController extends BaseController {
private final APPDeviceService appDeviceService;
private final AppUserService appUserService;
private final DeviceService deviceService;
@PostMapping(value = "/list")
@Operation(summary = "APP客户设备列表")
public TableDataInfo<APPDevice> appDeviceList(@RequestBody APPDeviceQueryCriteria criteria) {
Page<APPDevice> page = new Page<>(criteria.getPage(), criteria.getSize());
return appDeviceService.appDeviceList(page, criteria);
}
@PostMapping(value = "/typeList")
@Operation(summary = "APP客户设备类型列表")
public ResponseVO<List<APPDeviceType>> appTypeList(@RequestBody APPDeviceQueryCriteria criteria) {
List<APPDeviceType> typeList = appDeviceService.appTypeList(criteria);
return ResponseVO.success(typeList);
}
@PostMapping(value = "/bind")
@Operation(summary = "APP客户设备绑定")
public ResponseVO<String> appBindDevice(@RequestBody APPDeviceQueryCriteria criteria) {
appDeviceService.appBindDevice(criteria);
return ResponseVO.success("绑定成功!");
}
@GetMapping
@Operation(summary = "WEB端查看APP客户设备绑定")
public TableDataInfo<AppDeviceVo> queryAPPDevice(DeviceQueryCriteria bo, PageQuery pageQuery) {
return deviceService.queryAppDeviceList(bo, pageQuery);
}
// @PostMapping(value = "/unbind")
// @Operation(summary = "设备解绑")
// public ResponseVO<String> unbindAPPDevice(@Validated @ModelAttribute APPUnbindDTO deviceForm) {
// appDeviceService.unbindAPPDevice(deviceForm);
// return ResponseVO.success("解绑成功!!!");
// }
/**
* app设备解绑
*
* @param id
* @return
*/
@Operation(summary = "设备解绑")
@DeleteMapping("/unBind")
public R<Void> unBind(Long id) {
return toAjax(deviceService.unBindDevice(id));
}
/**
* 修改APP用户信息
*/
// @SaCheckPermission("app:user:edit")
@Log(title = "APP用户信息", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody UserAppBo bo) {
return toAjax(appUserService.updateByBo(bo));
}
}

View File

@ -0,0 +1,75 @@
// package com.fuyuanshen.app.controller.mp;
//
// import io.swagger.v3.oas.annotations.tags.Tag;
// import lombok.RequiredArgsConstructor;
// import lombok.extern.slf4j.Slf4j;
// import org.springframework.http.ResponseEntity;
// import org.springframework.web.bind.annotation.GetMapping;
// import org.springframework.web.bind.annotation.RequestBody;
// import org.springframework.web.bind.annotation.RequestMapping;
// import org.springframework.web.bind.annotation.RestController;
//
// import java.util.ArrayList;
// import java.util.HashMap;
// import java.util.List;
// import java.util.Map;
//
// /**
// * @author: 默苍璃
// * @date: 2025-06-2313:56
// */
// @Slf4j
// @RestController
// @RequestMapping("/mp")
// @RequiredArgsConstructor
// @Tag(name = "小程序:相关接口")
// public class MPController {
// //
// // private final TokenProvider tokenProvider;
// // private final SecurityProperties properties;
// // private final OnlineUserService onlineUserService;
// // private final DeviceService deviceService;
// // private final MPService mpService;
// //
// // @Log("小程序用户登录")
// // @ApiOperation("小程序登录授权")
// // @AnonymousPostMapping(value = "/login")
// // public ResponseEntity<Object> login(@RequestBody AuthUserDto authUser, HttpServletRequest request) throws Exception {
// //
// // // 获取用户信息
// // User user = new User();
// // user.setUsername("MP");
// // user.setPassword("MP");
// // AuthorityDto authorityDto = new AuthorityDto();
// // authorityDto.setAuthority("MP");
// // List<AuthorityDto> authorityDtos = new ArrayList<>();
// // authorityDtos.add(authorityDto);
// // user.setPhone(authUser.getPhoneNumber());
// // JwtUserDto jwtUser = new JwtUserDto(null, user, null, authorityDtos);
// //
// // Authentication authentication = new UsernamePasswordAuthenticationToken(jwtUser, null, authorityDtos);
// // SecurityContextHolder.getContext().setAuthentication(authentication);
// // // 生成令牌
// // String token = tokenProvider.createToken(jwtUser);
// // // 返回 token 与 用户信息
// // Map<String, Object> authInfo = new HashMap<String, Object>(2) {{
// // put("token", properties.getTokenStartWith() + token);
// // put("user", jwtUser);
// // }};
// //
// // // 保存在线信息
// // onlineUserService.save(jwtUser, token, request);
// //
// // // 返回登录信息
// // return ResponseEntity.ok(authInfo);
// // }
// //
// //
// // @GetMapping("/queryDevice")
// // @ApiOperation("是否存在设备MAC号")
// // public ResponseVO<Boolean> queryDevice(@ApiParam("设备mac值") String mac) {
// // return ResponseVO.success(mpService.queryDevice(mac));
// // }
//
//
// }

View File

@ -0,0 +1,106 @@
package com.fuyuanshen.app.domain;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fuyuanshen.common.tenant.core.TenantEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* @Description: 设备表
* @Author: WY
* @Date: 2025/5/16
**/
@Data
@TableName("app_device")
public class APPDevice extends TenantEntity {
@TableId(value = "app_device_id", type = IdType.AUTO)
@Schema(name = "ID")
private Long id;
@Schema(name = "设备类型")
private Long deviceType;
@Schema(name = "设备类型名称")
private String deviceTypeName;
@Schema(name = "客户号")
private Long customerId;
@Schema(name = "所属客户")
private String customerName;
/*@Schema(name = "设备编号")
private String deviceNo;*/
@Schema(name = "设备名称")
private String deviceName;
@Schema(name = "设备图片")
private String devicePic;
@Schema(name = "设备MAC")
private String deviceMac;
@Schema(name = "设备IMEI")
private String deviceImei;
@Schema(name = "设备SN")
private String deviceSn;
@Schema(name = "经度")
private String longitude;
@Schema(name = "纬度")
private String latitude;
@Schema(name = "备注")
private String remark;
@TableField(exist = false)
@Schema(name = "设备类型名称")
private String typeName;
/**
* 租户ID
*/
@TableField(value = "tenant_id")
@Schema(hidden = true)
private String tenantId;
/**
* 设备状态
* 0 失效
* 1 正常
*/
@Schema(name = "设备状态")
private Integer deviceStatus;
/**
* 绑定状态
* 0 未绑定
* 1 已绑定
*/
@Schema(name = "绑定状态")
private Integer bindingStatus;
/**
* 绑定类型
* 0 APP
* 1 小程序
*/
@Schema(name = "绑定类型")
private Integer bindingType;
public void copy(APPDevice source) {
BeanUtil.copyProperties(source, this, CopyOptions.create().setIgnoreNullValue(true));
}
}

View File

@ -0,0 +1,56 @@
package com.fuyuanshen.app.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fuyuanshen.common.tenant.core.TenantEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.io.Serializable;
/**
* @Description: 设备类型
* @Author: WY
* @Date: 2025/5/14
**/
@Data
@TableName("app_device_type")
public class APPDeviceType extends TenantEntity {
@TableId(value = "id", type = IdType.AUTO)
@Schema(name = "ID", hidden = true)
private Long id;
@Schema(name = "客户号")
private Long customerId;
@Schema(name = "创建该类型的客户")
private Long ownerCustomerId;
/**
* 租户ID
*/
// @TableField(value = "tenant_id")
// @ApiModelProperty(hidden = true)
// private Long tenantId;
@NotBlank(message = "设备类型名称不能为空")
@Schema(name = "类型名称", required = true)
private String typeName;
@Schema(name = "是否支持蓝牙")
private Boolean isSupportBle;
@Schema(name = "定位方式", example = "0:无;1:GPS;2:基站;3:wifi;4:北斗")
private String locateMode;
@Schema(name = "联网方式", example = "0:无;1:4G;2:WIFI")
private String networkWay;
@Schema(name = "通讯方式", example = "0:4G;1:蓝牙")
private String communicationMode;
}

View File

@ -0,0 +1,51 @@
package com.fuyuanshen.app.domain;
import com.fuyuanshen.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* app业务文件对象 app_business_file
*
* @author Lion Li
* @date 2025-07-03
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("app_business_file")
public class AppBusinessFile extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 文件id
*/
private Long fileId;
/**
* 业务id
*/
private Long businessId;
/**
* 文件类型(1:操作说明2:产品参数)
*/
private Long fileType;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,51 @@
package com.fuyuanshen.app.domain;
import com.fuyuanshen.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* 设备分享对象 app_device_share
*
* @author Lion Li
* @date 2025-07-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("app_device_share")
public class AppDeviceShare extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
private Long id;
/**
* 设备ID
*/
private Long deviceId;
/**
* 手机号
*/
private String phonenumber;
/**
* 功能权限1灯光模式2激光模式3开机画面4人员信息登记5发送信息6产品信息
以逗号分隔
*/
private String permission;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,51 @@
package com.fuyuanshen.app.domain;
import com.fuyuanshen.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* 操作视频对象 app_operation_video
*
* @author Lion Li
* @date 2025-07-02
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("app_operation_video")
public class AppOperationVideo extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 视频名称
*/
private String videoName;
/**
* 视频链接
*/
private String videoUrl;
/**
* 设备di
*/
private Long deviceId;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,50 @@
package com.fuyuanshen.app.domain;
import com.fuyuanshen.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* 人员信息登记对象 app_personnel_info
*
* @author Lion Li
* @date 2025-07-02
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("app_personnel_info")
public class AppPersonnelInfo extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
private Long id;
/**
* 设备id
*/
private Long deviceId;
/**
* 人员姓名
*/
private String name;
/**
* 单位名称
*/
private String unitName;
/**
* 发送信息
*/
private String sendMsg;
}

View File

@ -0,0 +1,52 @@
package com.fuyuanshen.app.domain.bo;
import com.fuyuanshen.app.domain.AppBusinessFile;
import com.fuyuanshen.common.core.validate.EditGroup;
import com.fuyuanshen.common.mybatis.core.domain.BaseEntity;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.List;
/**
* app业务文件业务对象 app_business_file
*
* @author Lion Li
* @date 2025-07-03
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = AppBusinessFile.class, reverseConvertGenerate = false)
public class AppBusinessFileBo extends BaseEntity {
/**
* 主键id
*/
@NotNull(message = "主键id不能为空", groups = { EditGroup.class })
private Long id;
/**
* 文件id
*/
private Long fileId;
/**
* 业务id
*/
private Long businessId;
/**
* 文件类型(1:操作说明2:产品参数)
*/
private Long fileType;
/**
* 备注
*/
private String remark;
private List<Long> ids;
}

View File

@ -0,0 +1,49 @@
package com.fuyuanshen.app.domain.bo;
import com.fuyuanshen.app.domain.AppDeviceShare;
import com.fuyuanshen.common.mybatis.core.domain.BaseEntity;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
/**
* 设备分享业务对象 app_device_share
*
* @author Lion Li
* @date 2025-07-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = AppDeviceShare.class, reverseConvertGenerate = false)
public class AppDeviceShareBo extends BaseEntity {
/**
* 主键id
*/
private Long id;
/**
* 设备ID
*/
private Long deviceId;
/**
* 手机号
*/
private String phonenumber;
/**
* 功能权限1灯光模式2激光模式3开机画面4人员信息登记5发送信息6产品信息
以逗号分隔
*/
private String permission;
/**
* 备注
*/
private String remark;
private String smsCode;
}

View File

@ -0,0 +1,49 @@
package com.fuyuanshen.app.domain.bo;
import com.fuyuanshen.app.domain.AppOperationVideo;
import com.fuyuanshen.common.core.validate.EditGroup;
import com.fuyuanshen.common.mybatis.core.domain.BaseEntity;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
/**
* 操作视频业务对象 app_operation_video
*
* @author Lion Li
* @date 2025-07-02
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = AppOperationVideo.class, reverseConvertGenerate = false)
public class AppOperationVideoBo extends BaseEntity {
/**
* 主键id
*/
@NotNull(message = "主键id不能为空", groups = { EditGroup.class })
private Long id;
/**
* 视频名称
*/
private String videoName;
/**
* 视频链接
*/
private String videoUrl;
/**
* 设备di
*/
private Long deviceId;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,56 @@
package com.fuyuanshen.app.domain.bo;
import com.fuyuanshen.app.domain.AppPersonnelInfo;
import com.fuyuanshen.common.core.validate.AddGroup;
import com.fuyuanshen.common.core.validate.EditGroup;
import com.fuyuanshen.common.mybatis.core.domain.BaseEntity;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
/**
* 人员信息登记业务对象 app_personnel_info
*
* @author Lion Li
* @date 2025-07-02
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = AppPersonnelInfo.class, reverseConvertGenerate = false)
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;
/**
* 人员姓名
*/
private String name;
/**
* 部门名称
*/
private String deptName;
/**
* 单位名称
*/
private String unitName;
/**
* 发送信息
*/
private String sendMsg;
}

View File

@ -0,0 +1,21 @@
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;
/**
* @author: 默苍璃
* @date: 2025-06-1818:36
*/
@Data
public class APPReNameDTO {
private Long id;
@NotBlank(message = "设备名称不能为空")
private String deviceName;
}

View File

@ -0,0 +1,26 @@
package com.fuyuanshen.app.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* @author: 默苍璃
* @date: 2025-06-1818:36
*/
@Data
public class APPUnbindDTO {
// @NotBlank(message = "设备MAC不能为空")
@Schema(name = "设备MAC", required = true)
private String deviceMac;
@Schema(name = "设备IMEI")
private String deviceImei;
@NotNull(message = "客户号不能为空")
@Schema(name = "客户号")
private Long customerId;
}

View File

@ -0,0 +1,65 @@
package com.fuyuanshen.app.domain.query;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.sql.Timestamp;
import java.util.List;
import java.util.Set;
/**
* @Description:
* @Author: WY
* @Date: 2025/5/16
**/
@Data
public class APPDeviceQueryCriteria {
@Schema(name = "设备名称")
private String deviceName;
@Schema(name = "设备类型")
private Long deviceType;
@Schema(name = "设备MAC")
private String deviceMac;
@Schema(name = "设备IMEI")
private String deviceImei;
@Schema(name = "设备SN")
private String deviceSn;
/**
* 设备状态
* 0 失效
* 1 正常
*/
@Schema(name = "设备状态 0 失效 1 正常 ")
private Integer deviceStatus;
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
@Schema(name = "创建时间")
private List<Timestamp> createTime;
@Schema(name = "页码", example = "1")
private Integer page = 1;
@Schema(name = "每页数据量", example = "10")
private Integer size = 10;
@Schema(name = "客户id")
private Long customerId;
private Set<Long> customerIds;
@Schema(name = "当前所有者")
private Long currentOwnerId;
@Schema(name = "租户ID")
private Long tenantId;
@Schema(name = "通讯方式", example = "0:4G;1:蓝牙")
private Integer communicationMode;
}

View File

@ -0,0 +1,15 @@
package com.fuyuanshen.app.domain.vo;
import lombok.Data;
@Data
public class APPDeviceTypeVo {
private Long id;
private String typeName;
private String communicationMode;
}

View File

@ -0,0 +1,62 @@
package com.fuyuanshen.app.domain.vo;
import com.fuyuanshen.app.domain.AppBusinessFile;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import com.fuyuanshen.common.excel.annotation.ExcelDictFormat;
import com.fuyuanshen.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* app业务文件视图对象 app_business_file
*
* @author Lion Li
* @date 2025-07-03
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = AppBusinessFile.class)
public class AppBusinessFileVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 文件id
*/
@ExcelProperty(value = "文件id")
private Long fileId;
/**
* 业务id
*/
@ExcelProperty(value = "业务id")
private Long businessId;
/**
* 文件类型(1:操作说明2:产品参数)
*/
@ExcelProperty(value = "文件类型(1:操作说明2:产品参数)")
private Long fileType;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,72 @@
package com.fuyuanshen.app.domain.vo;
import cn.idev.excel.annotation.ExcelProperty;
import lombok.Data;
import java.io.Serial;
@Data
public class AppDeviceDetailVo {
@Serial
private static final long serialVersionUID = 1L;
/**
* 设备ID
*/
@ExcelProperty(value = "设备ID")
private Long deviceId;
/**
* 手机号
*/
@ExcelProperty(value = "手机号")
private String phonenumber;
/**
* 设备名称
*/
private String deviceName;
/**
* 设备IMEI
*/
private String deviceImei;
/**
* 设备MAC
*/
private String deviceMac;
/**
* 通讯方式 0:4G;1:蓝牙
*/
private Integer communicationMode;
/**
* 设备图片
*/
private String devicePic;
/**
* 设备类型
*/
private String typeName;
/**
* 蓝牙名称
*/
private String bluetoothName;
/**
* 设备状态
* 0 失效
* 1 正常
*/
private Integer deviceStatus;
/**
* 人员信息
*/
private AppPersonnelInfoVo personnelInfo;
}

View File

@ -0,0 +1,107 @@
package com.fuyuanshen.app.domain.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import com.fuyuanshen.app.domain.AppDeviceShare;
import com.fuyuanshen.common.excel.annotation.ExcelDictFormat;
import com.fuyuanshen.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 设备分享视图对象 app_device_share
*
* @author Lion Li
* @date 2025-07-16
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = AppDeviceShare.class)
public class AppDeviceShareDetailVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 设备ID
*/
@ExcelProperty(value = "设备ID")
private Long deviceId;
/**
* 手机号
*/
@ExcelProperty(value = "手机号")
private String phonenumber;
/**
* 功能权限1灯光模式2激光模式3开机画面4人员信息登记5发送信息6产品信息
以逗号分隔
*/
@ExcelProperty(value = "功能权限", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "1=灯光模式2激光模式3开机画面4人员信息登记5发送信息6产品信息")
private String permission;
/**
* 设备名称
*/
private String deviceName;
/**
* 设备IMEI
*/
private String deviceImei;
/**
* 设备MAC
*/
private String deviceMac;
/**
* 通讯方式 0:4G;1:蓝牙
*/
private Integer communicationMode;
/**
* 设备图片
*/
private String devicePic;
/**
* 设备类型
*/
private String typeName;
/**
* 蓝牙名称
*/
private String bluetoothName;
/**
* 设备状态
* 0 失效
* 1 正常
*/
private Integer deviceStatus;
/**
* 人员信息
*/
private AppPersonnelInfoVo personnelInfo;
/**
* 发送信息
*/
private String sendMsg;
}

View File

@ -0,0 +1,72 @@
package com.fuyuanshen.app.domain.vo;
import com.fuyuanshen.app.domain.AppDeviceShare;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import com.fuyuanshen.common.excel.annotation.ExcelDictFormat;
import com.fuyuanshen.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 设备分享视图对象 app_device_share
*
* @author Lion Li
* @date 2025-07-16
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = AppDeviceShare.class)
public class AppDeviceShareVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 设备ID
*/
@ExcelProperty(value = "设备ID")
private Long deviceId;
/**
* 设备名称
*/
@ExcelProperty(value = "设备名称")
private String deviceName;
/**
* 手机号
*/
@ExcelProperty(value = "手机号")
private String phonenumber;
/**
* 功能权限1灯光模式2激光模式3开机画面4人员信息登记5发送信息6产品信息
以逗号分隔
*/
@ExcelProperty(value = "功能权限", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "1=灯光模式2激光模式3开机画面4人员信息登记5发送信息6产品信息")
private String permission;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
// 设备图片
private String devicePic;
}

View File

@ -0,0 +1,26 @@
package com.fuyuanshen.app.domain.vo;
import lombok.Data;
@Data
public class AppFileVo {
private Long id;
/**
* 业务id
*/
private String businessId;
/**
* 文件id
*/
private Long fileId;
/**
* 文件名称
*/
private String fileName;
/**
* 文件url
*/
private String fileUrl;
}

View File

@ -0,0 +1,62 @@
package com.fuyuanshen.app.domain.vo;
import com.fuyuanshen.app.domain.AppOperationVideo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import com.fuyuanshen.common.excel.annotation.ExcelDictFormat;
import com.fuyuanshen.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 操作视频视图对象 app_operation_video
*
* @author Lion Li
* @date 2025-07-02
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = AppOperationVideo.class)
public class AppOperationVideoVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 视频名称
*/
@ExcelProperty(value = "视频名称")
private String videoName;
/**
* 视频链接
*/
@ExcelProperty(value = "视频链接")
private String videoUrl;
/**
* 设备di
*/
@ExcelProperty(value = "设备di")
private Long deviceId;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,68 @@
package com.fuyuanshen.app.domain.vo;
import com.fuyuanshen.app.domain.AppPersonnelInfo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import com.fuyuanshen.common.excel.annotation.ExcelDictFormat;
import com.fuyuanshen.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 人员信息登记视图对象 app_personnel_info
*
* @author Lion Li
* @date 2025-07-02
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = AppPersonnelInfo.class)
public class AppPersonnelInfoVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ExcelProperty(value = "主键")
private Long id;
/**
* 设备id
*/
@ExcelProperty(value = "设备id")
private Long deviceId;
/**
* 人员姓名
*/
@ExcelProperty(value = "人员姓名")
private String name;
/**
* 部门名称
*/
@ExcelProperty(value = "部门名称")
private String deptName;
/**
* 单位名称
*/
@ExcelProperty(value = "单位名称")
private String unitName;
/**
* 发送信息
*/
@ExcelProperty(value = "发送信息")
private String sendMsg;
}

View File

@ -1,6 +1,9 @@
package com.fuyuanshen.app.domain.vo;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fuyuanshen.app.domain.AppUser;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
@ -120,4 +123,10 @@ public class AppUserVo implements Serializable {
* 部门ID
*/
private Long deptId;
/**
* 创建时间
*/
private Date createTime;
}

View File

@ -0,0 +1,48 @@
package com.fuyuanshen.app.enums;
import com.fasterxml.jackson.annotation.JsonValue;
/**
* 用户类型枚举
*
* @author: 默苍璃
* @date: 2025-06-1811:14
*/
public enum UserType {
APP(0, "APP"), MINI_PROGRAM(1, "小程序");
private final int value;
private final String description;
UserType(int value, String description) {
this.value = value;
this.description = description;
}
@JsonValue
public int getValue() {
return value;
}
public String getDescription() {
return description;
}
/**
* 根据值获取对应的枚举
*
* @param value 枚举值
* @return 对应的枚举对象
*/
public static UserType fromValue(int value) {
for (UserType userType : values()) {
if (userType.getValue() == value) {
return userType;
}
}
throw new IllegalArgumentException("Invalid user type value: " + value);
}
}

View File

@ -0,0 +1,20 @@
package com.fuyuanshen.app.mapper;
import com.fuyuanshen.app.domain.AppBusinessFile;
import com.fuyuanshen.app.domain.bo.AppBusinessFileBo;
import com.fuyuanshen.app.domain.vo.AppBusinessFileVo;
import com.fuyuanshen.app.domain.vo.AppFileVo;
import com.fuyuanshen.common.mybatis.core.mapper.BaseMapperPlus;
import java.util.List;
/**
* app业务文件Mapper接口
*
* @author Lion Li
* @date 2025-07-03
*/
public interface AppBusinessFileMapper extends BaseMapperPlus<AppBusinessFile, AppBusinessFileVo> {
List<AppFileVo> queryAppFileList(AppBusinessFileBo bo);
}

View File

@ -0,0 +1,15 @@
package com.fuyuanshen.app.mapper;
import com.fuyuanshen.app.domain.AppDeviceShare;
import com.fuyuanshen.app.domain.vo.AppDeviceShareVo;
import com.fuyuanshen.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 设备分享Mapper接口
*
* @author Lion Li
* @date 2025-07-16
*/
public interface AppDeviceShareMapper extends BaseMapperPlus<AppDeviceShare, AppDeviceShareVo> {
}

View File

@ -0,0 +1,17 @@
package com.fuyuanshen.app.mapper;
import com.fuyuanshen.app.domain.AppOperationVideo;
import com.fuyuanshen.app.domain.vo.AppOperationVideoVo;
import com.fuyuanshen.common.mybatis.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Mapper;
/**
* 操作视频Mapper接口
*
* @author Lion Li
* @date 2025-07-02
*/
@Mapper
public interface AppOperationVideoMapper extends BaseMapperPlus<AppOperationVideo, AppOperationVideoVo> {
}

View File

@ -0,0 +1,17 @@
package com.fuyuanshen.app.mapper;
import com.fuyuanshen.app.domain.AppPersonnelInfo;
import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo;
import com.fuyuanshen.common.mybatis.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Mapper;
/**
* 人员信息登记Mapper接口
*
* @author Lion Li
* @date 2025-07-02
*/
@Mapper
public interface AppPersonnelInfoMapper extends BaseMapperPlus<AppPersonnelInfo, AppPersonnelInfoVo> {
}

View File

@ -0,0 +1,44 @@
package com.fuyuanshen.app.mapper.equipment;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fuyuanshen.app.domain.APPDevice;
import com.fuyuanshen.app.domain.APPDeviceType;
import com.fuyuanshen.app.domain.query.APPDeviceQueryCriteria;
import com.fuyuanshen.app.domain.vo.APPDeviceTypeVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @Description:
* @Author: WY
* @Date: 2025/5/16
**/
@Mapper
public interface APPDeviceMapper extends BaseMapper<APPDevice> {
/**
* APP用户设备列表
*
* @param page
* @param criteria
* @return
*/
IPage<APPDevice> appDeviceList(Page<APPDevice> page,@Param("criteria") APPDeviceQueryCriteria criteria);
/**
* 分页查询APP/小程序设备
*
* @param criteria
* @param page
* @return
*/
IPage<APPDevice> queryAll(Page<APPDevice> page, @Param("criteria") APPDeviceQueryCriteria criteria);
List<APPDeviceTypeVo> getTypeList(@Param("userId") Long userId);
}

View File

@ -0,0 +1,29 @@
package com.fuyuanshen.app.mapper.equipment;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fuyuanshen.app.domain.APPDeviceType;
import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author 97433
* @description 针对表【app_device_type(设备类型表)】的数据库操作Mapper
* @createDate 2025-06-24 11:16:18
* @Entity system.domain.AppDeviceType
*/
@Mapper
public interface AppDeviceTypeMapper extends BaseMapper<APPDeviceType> {
/**
* 查询设备类型列表
*
* @param criteria 查询条件
* @return 设备类型列表
*/
List<APPDeviceType> appTypeList(@Param("criteria") DeviceQueryCriteria criteria);
}

View File

@ -0,0 +1,72 @@
package com.fuyuanshen.app.service;
import com.fuyuanshen.app.domain.vo.AppBusinessFileVo;
import com.fuyuanshen.app.domain.bo.AppBusinessFileBo;
import com.fuyuanshen.app.domain.vo.AppFileVo;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* app业务文件Service接口
*
* @author Lion Li
* @date 2025-07-03
*/
public interface IAppBusinessFileService {
/**
* 查询app业务文件
*
* @param id 主键
* @return app业务文件
*/
AppBusinessFileVo queryById(Long id);
/**
* 分页查询app业务文件列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return app业务文件分页列表
*/
TableDataInfo<AppBusinessFileVo> queryPageList(AppBusinessFileBo bo, PageQuery pageQuery);
/**
* 查询符合条件的app业务文件列表
*
* @param bo 查询条件
* @return app业务文件列表
*/
List<AppBusinessFileVo> queryList(AppBusinessFileBo bo);
/**
* 新增app业务文件
*
* @param bo app业务文件
* @return 是否新增成功
*/
Boolean insertByBo(AppBusinessFileBo bo);
/**
* 修改app业务文件
*
* @param bo app业务文件
* @return 是否修改成功
*/
Boolean updateByBo(AppBusinessFileBo bo);
/**
* 校验并批量删除app业务文件信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
List<AppFileVo> queryAppFileList(AppBusinessFileBo bo);
}

View File

@ -0,0 +1,68 @@
package com.fuyuanshen.app.service;
import com.fuyuanshen.app.domain.vo.AppDeviceShareVo;
import com.fuyuanshen.app.domain.bo.AppDeviceShareBo;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 设备分享Service接口
*
* @author Lion Li
* @date 2025-07-16
*/
public interface IAppDeviceShareService {
/**
* 查询设备分享
*
* @param id 主键
* @return 设备分享
*/
AppDeviceShareVo queryById(Long id);
/**
* 分页查询设备分享列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 设备分享分页列表
*/
TableDataInfo<AppDeviceShareVo> queryPageList(AppDeviceShareBo bo, PageQuery pageQuery);
/**
* 查询符合条件的设备分享列表
*
* @param bo 查询条件
* @return 设备分享列表
*/
List<AppDeviceShareVo> queryList(AppDeviceShareBo bo);
/**
* 新增设备分享
*
* @param bo 设备分享
* @return 是否新增成功
*/
Boolean insertByBo(AppDeviceShareBo bo);
/**
* 修改设备分享
*
* @param bo 设备分享
* @return 是否修改成功
*/
Boolean updateByBo(AppDeviceShareBo bo);
/**
* 校验并批量删除设备分享信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@ -0,0 +1,68 @@
package com.fuyuanshen.app.service;
import com.fuyuanshen.app.domain.vo.AppOperationVideoVo;
import com.fuyuanshen.app.domain.bo.AppOperationVideoBo;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 操作视频Service接口
*
* @author Lion Li
* @date 2025-07-02
*/
public interface IAppOperationVideoService {
/**
* 查询操作视频
*
* @param id 主键
* @return 操作视频
*/
AppOperationVideoVo queryById(Long id);
/**
* 分页查询操作视频列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 操作视频分页列表
*/
TableDataInfo<AppOperationVideoVo> queryPageList(AppOperationVideoBo bo, PageQuery pageQuery);
/**
* 查询符合条件的操作视频列表
*
* @param bo 查询条件
* @return 操作视频列表
*/
List<AppOperationVideoVo> queryList(AppOperationVideoBo bo);
/**
* 新增操作视频
*
* @param bo 操作视频
* @return 是否新增成功
*/
Boolean insertByBo(AppOperationVideoBo bo);
/**
* 修改操作视频
*
* @param bo 操作视频
* @return 是否修改成功
*/
Boolean updateByBo(AppOperationVideoBo bo);
/**
* 校验并批量删除操作视频信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@ -0,0 +1,71 @@
package com.fuyuanshen.app.service;
import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo;
import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.fuyuanshen.equipment.domain.dto.AppDeviceBo;
import java.util.Collection;
import java.util.List;
/**
* 人员信息登记Service接口
*
* @author Lion Li
* @date 2025-07-02
*/
public interface IAppPersonnelInfoService {
/**
* 查询人员信息登记
*
* @param id 主键
* @return 人员信息登记
*/
AppPersonnelInfoVo queryById(Long id);
/**
* 分页查询人员信息登记列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 人员信息登记分页列表
*/
TableDataInfo<AppPersonnelInfoVo> queryPageList(AppPersonnelInfoBo bo, PageQuery pageQuery);
/**
* 查询符合条件的人员信息登记列表
*
* @param bo 查询条件
* @return 人员信息登记列表
*/
List<AppPersonnelInfoVo> queryList(AppPersonnelInfoBo bo);
/**
* 新增人员信息登记
*
* @param bo 人员信息登记
* @return 是否新增成功
*/
Boolean insertByBo(AppPersonnelInfoBo bo);
/**
* 修改人员信息登记
*
* @param bo 人员信息登记
* @return 是否修改成功
*/
Boolean updateByBo(AppPersonnelInfoBo bo);
/**
* 校验并批量删除人员信息登记信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
boolean registerPersonInfo(AppPersonnelInfoBo bo);
}

View File

@ -0,0 +1,79 @@
package com.fuyuanshen.app.service.equipment;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.fuyuanshen.app.domain.APPDevice;
import com.fuyuanshen.app.domain.APPDeviceType;
import com.fuyuanshen.app.domain.dto.APPReNameDTO;
import com.fuyuanshen.app.domain.dto.APPUnbindDTO;
import com.fuyuanshen.app.domain.query.APPDeviceQueryCriteria;
import com.fuyuanshen.app.domain.vo.APPDeviceTypeVo;
import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.equipment.domain.dto.AppDeviceBo;
import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria;
import java.util.List;
/**
* @Description:
* @Author: WY
* @Date: 2025/5/16
**/
public interface APPDeviceService extends IService<APPDevice> {
/**
* APP用户设备列表
*
* @param criteria
*/
TableDataInfo<APPDevice> appDeviceList(Page<APPDevice> page, APPDeviceQueryCriteria criteria);
/**
* APP用户设备类型列表
*
* @param criteria
* @return
*/
List<APPDeviceType> appTypeList(APPDeviceQueryCriteria criteria);
/**
* APP/小程序用户设备绑定
*
* @param criteria
*/
void appBindDevice(APPDeviceQueryCriteria criteria);
/**
* 分页查询APP/小程序设备绑定
*
* @param criteria
* @param page
* @return
*/
TableDataInfo<APPDevice> queryAll(Page<APPDevice> page, APPDeviceQueryCriteria criteria);
/**
* APP/小程序用户设备解绑
*
* @param deviceForm
*/
void unbindAPPDevice(APPUnbindDTO deviceForm);
List<APPDeviceTypeVo> getTypeList();
void reName(APPReNameDTO reNameDTO);
/**
* WEB端查看APP客户设备绑定
*
* @param criteria
* @return
*/
TableDataInfo<APPDevice> queryAppDeviceList(DeviceQueryCriteria criteria);
int sendMessage(AppDeviceBo bo);
}

View File

@ -0,0 +1,142 @@
package com.fuyuanshen.app.service.impl;
import com.fuyuanshen.app.domain.vo.AppFileVo;
import com.fuyuanshen.common.core.utils.MapstructUtils;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
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.AppBusinessFileBo;
import com.fuyuanshen.app.domain.vo.AppBusinessFileVo;
import com.fuyuanshen.app.domain.AppBusinessFile;
import com.fuyuanshen.app.mapper.AppBusinessFileMapper;
import com.fuyuanshen.app.service.IAppBusinessFileService;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* app业务文件Service业务层处理
*
* @author Lion Li
* @date 2025-07-03
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class AppBusinessFileServiceImpl implements IAppBusinessFileService {
private final AppBusinessFileMapper baseMapper;
/**
* 查询app业务文件
*
* @param id 主键
* @return app业务文件
*/
@Override
public AppBusinessFileVo queryById(Long id){
return baseMapper.selectVoById(id);
}
/**
* 分页查询app业务文件列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return app业务文件分页列表
*/
@Override
public TableDataInfo<AppBusinessFileVo> queryPageList(AppBusinessFileBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<AppBusinessFile> lqw = buildQueryWrapper(bo);
Page<AppBusinessFileVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的app业务文件列表
*
* @param bo 查询条件
* @return app业务文件列表
*/
@Override
public List<AppBusinessFileVo> queryList(AppBusinessFileBo bo) {
LambdaQueryWrapper<AppBusinessFile> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<AppBusinessFile> buildQueryWrapper(AppBusinessFileBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<AppBusinessFile> lqw = Wrappers.lambdaQuery();
lqw.orderByAsc(AppBusinessFile::getId);
lqw.eq(bo.getFileId()!=null, AppBusinessFile::getFileId, bo.getFileId());
lqw.eq(bo.getBusinessId() != null, AppBusinessFile::getBusinessId, bo.getBusinessId());
lqw.eq(bo.getFileType() != null, AppBusinessFile::getFileType, bo.getFileType());
lqw.in(bo.getIds()!=null, AppBusinessFile::getId, bo.getIds());
return lqw;
}
/**
* 新增app业务文件
*
* @param bo app业务文件
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(AppBusinessFileBo bo) {
AppBusinessFile add = MapstructUtils.convert(bo, AppBusinessFile.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改app业务文件
*
* @param bo app业务文件
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(AppBusinessFileBo bo) {
AppBusinessFile update = MapstructUtils.convert(bo, AppBusinessFile.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(AppBusinessFile entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除app业务文件信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
@Override
public List<AppFileVo> queryAppFileList(AppBusinessFileBo bo) {
return baseMapper.queryAppFileList(bo);
}
}

View File

@ -0,0 +1,149 @@
package com.fuyuanshen.app.service.impl;
import com.fuyuanshen.common.core.utils.MapstructUtils;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
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 com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.mapper.DeviceMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.fuyuanshen.app.domain.bo.AppDeviceShareBo;
import com.fuyuanshen.app.domain.vo.AppDeviceShareVo;
import com.fuyuanshen.app.domain.AppDeviceShare;
import com.fuyuanshen.app.mapper.AppDeviceShareMapper;
import com.fuyuanshen.app.service.IAppDeviceShareService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 设备分享Service业务层处理
*
* @author Lion Li
* @date 2025-07-16
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class AppDeviceShareServiceImpl implements IAppDeviceShareService {
private final AppDeviceShareMapper baseMapper;
private final DeviceMapper deviceMapper;
/**
* 查询设备分享
*
* @param id 主键
* @return 设备分享
*/
@Override
public AppDeviceShareVo queryById(Long id){
return baseMapper.selectVoById(id);
}
/**
* 分页查询设备分享列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 设备分享分页列表
*/
@Override
public TableDataInfo<AppDeviceShareVo> queryPageList(AppDeviceShareBo bo, PageQuery pageQuery) {
Long userId = AppLoginHelper.getUserId();
bo.setCreateBy(userId);
LambdaQueryWrapper<AppDeviceShare> lqw = buildQueryWrapper(bo);
Page<AppDeviceShareVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
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());
}
});
return TableDataInfo.build(result);
}
/**
* 查询符合条件的设备分享列表
*
* @param bo 查询条件
* @return 设备分享列表
*/
@Override
public List<AppDeviceShareVo> queryList(AppDeviceShareBo bo) {
LambdaQueryWrapper<AppDeviceShare> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<AppDeviceShare> buildQueryWrapper(AppDeviceShareBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<AppDeviceShare> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getDeviceId() != null, AppDeviceShare::getDeviceId, bo.getDeviceId());
lqw.eq(StringUtils.isNotBlank(bo.getPhonenumber()), AppDeviceShare::getPhonenumber, bo.getPhonenumber());
lqw.eq(StringUtils.isNotBlank(bo.getPermission()), AppDeviceShare::getPermission, bo.getPermission());
lqw.eq(bo.getCreateBy()!=null, AppDeviceShare::getCreateBy, bo.getCreateBy());
return lqw;
}
/**
* 新增设备分享
*
* @param bo 设备分享
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(AppDeviceShareBo bo) {
AppDeviceShare add = MapstructUtils.convert(bo, AppDeviceShare.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改设备分享
*
* @param bo 设备分享
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(AppDeviceShareBo bo) {
AppDeviceShare update = MapstructUtils.convert(bo, AppDeviceShare.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(AppDeviceShare entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除设备分享信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
}

View File

@ -0,0 +1,134 @@
package com.fuyuanshen.app.service.impl;
import com.fuyuanshen.common.core.utils.MapstructUtils;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
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.AppOperationVideoBo;
import com.fuyuanshen.app.domain.vo.AppOperationVideoVo;
import com.fuyuanshen.app.domain.AppOperationVideo;
import com.fuyuanshen.app.mapper.AppOperationVideoMapper;
import com.fuyuanshen.app.service.IAppOperationVideoService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 操作视频Service业务层处理
*
* @author Lion Li
* @date 2025-07-02
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class AppOperationVideoServiceImpl implements IAppOperationVideoService {
private final AppOperationVideoMapper baseMapper;
/**
* 查询操作视频
*
* @param id 主键
* @return 操作视频
*/
@Override
public AppOperationVideoVo queryById(Long id){
return baseMapper.selectVoById(id);
}
/**
* 分页查询操作视频列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 操作视频分页列表
*/
@Override
public TableDataInfo<AppOperationVideoVo> queryPageList(AppOperationVideoBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<AppOperationVideo> lqw = buildQueryWrapper(bo);
Page<AppOperationVideoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的操作视频列表
*
* @param bo 查询条件
* @return 操作视频列表
*/
@Override
public List<AppOperationVideoVo> queryList(AppOperationVideoBo bo) {
LambdaQueryWrapper<AppOperationVideo> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<AppOperationVideo> buildQueryWrapper(AppOperationVideoBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<AppOperationVideo> lqw = Wrappers.lambdaQuery();
lqw.orderByAsc(AppOperationVideo::getId);
lqw.like(StringUtils.isNotBlank(bo.getVideoName()), AppOperationVideo::getVideoName, bo.getVideoName());
lqw.eq(StringUtils.isNotBlank(bo.getVideoUrl()), AppOperationVideo::getVideoUrl, bo.getVideoUrl());
lqw.eq(bo.getDeviceId() != null, AppOperationVideo::getDeviceId, bo.getDeviceId());
return lqw;
}
/**
* 新增操作视频
*
* @param bo 操作视频
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(AppOperationVideoBo bo) {
AppOperationVideo add = MapstructUtils.convert(bo, AppOperationVideo.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改操作视频
*
* @param bo 操作视频
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(AppOperationVideoBo bo) {
AppOperationVideo update = MapstructUtils.convert(bo, AppOperationVideo.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(AppOperationVideo entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除操作视频信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
}

View File

@ -0,0 +1,146 @@
package com.fuyuanshen.app.service.impl;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.fuyuanshen.common.core.utils.MapstructUtils;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
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.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.dto.AppDeviceBo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo;
import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo;
import com.fuyuanshen.app.domain.AppPersonnelInfo;
import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper;
import com.fuyuanshen.app.service.IAppPersonnelInfoService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 人员信息登记Service业务层处理
*
* @author Lion Li
* @date 2025-07-02
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class AppPersonnelInfoServiceImpl implements IAppPersonnelInfoService {
private final AppPersonnelInfoMapper baseMapper;
/**
* 查询人员信息登记
*
* @param id 主键
* @return 人员信息登记
*/
@Override
public AppPersonnelInfoVo queryById(Long id){
return baseMapper.selectVoById(id);
}
/**
* 分页查询人员信息登记列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 人员信息登记分页列表
*/
@Override
public TableDataInfo<AppPersonnelInfoVo> queryPageList(AppPersonnelInfoBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<AppPersonnelInfo> lqw = buildQueryWrapper(bo);
Page<AppPersonnelInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的人员信息登记列表
*
* @param bo 查询条件
* @return 人员信息登记列表
*/
@Override
public List<AppPersonnelInfoVo> queryList(AppPersonnelInfoBo bo) {
LambdaQueryWrapper<AppPersonnelInfo> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<AppPersonnelInfo> buildQueryWrapper(AppPersonnelInfoBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<AppPersonnelInfo> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getDeviceId() != null, AppPersonnelInfo::getDeviceId, bo.getDeviceId());
lqw.like(StringUtils.isNotBlank(bo.getName()), AppPersonnelInfo::getName, bo.getName());
lqw.like(StringUtils.isNotBlank(bo.getUnitName()), AppPersonnelInfo::getUnitName, bo.getUnitName());
lqw.eq(StringUtils.isNotBlank(bo.getSendMsg()), AppPersonnelInfo::getSendMsg, bo.getSendMsg());
return lqw;
}
/**
* 新增人员信息登记
*
* @param bo 人员信息登记
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(AppPersonnelInfoBo bo) {
AppPersonnelInfo add = MapstructUtils.convert(bo, AppPersonnelInfo.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改人员信息登记
*
* @param bo 人员信息登记
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(AppPersonnelInfoBo bo) {
AppPersonnelInfo update = MapstructUtils.convert(bo, AppPersonnelInfo.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(AppPersonnelInfo entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除人员信息登记信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
@Override
public boolean registerPersonInfo(AppPersonnelInfoBo bo) {
AppPersonnelInfo appPersonnelInfo = MapstructUtils.convert(bo, AppPersonnelInfo.class);
return baseMapper.insertOrUpdate(appPersonnelInfo);
}
}

View File

@ -0,0 +1,240 @@
package com.fuyuanshen.app.service.impl.equipment;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
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.fuyuanshen.app.domain.APPDevice;
import com.fuyuanshen.app.domain.APPDeviceType;
import com.fuyuanshen.app.domain.dto.APPReNameDTO;
import com.fuyuanshen.app.domain.dto.APPUnbindDTO;
import com.fuyuanshen.app.domain.query.APPDeviceQueryCriteria;
import com.fuyuanshen.app.domain.vo.APPDeviceTypeVo;
import com.fuyuanshen.app.enums.UserType;
import com.fuyuanshen.app.mapper.equipment.APPDeviceMapper;
import com.fuyuanshen.app.mapper.equipment.AppDeviceTypeMapper;
import com.fuyuanshen.app.service.equipment.APPDeviceService;
import com.fuyuanshen.common.core.exception.BadRequestException;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
import com.fuyuanshen.common.satoken.utils.LoginHelper;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.DeviceType;
import com.fuyuanshen.equipment.domain.dto.AppDeviceBo;
import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria;
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 lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
/**
* @Description:
* @Author: WY
* @Date: 2025/5/16
**/
@Slf4j
@Service
@RequiredArgsConstructor
public class APPDeviceServiceImpl extends ServiceImpl<APPDeviceMapper, APPDevice> implements APPDeviceService {
private final APPDeviceMapper appDeviceMapper;
private final DeviceMapper deviceMapper;
private final AppDeviceTypeMapper appDeviceTypeMapper;
private final DeviceTypeMapper deviceTypeMapper;
/**
* APP用户设备列表
*
* @param criteria
*/
@Override
public TableDataInfo<APPDevice> appDeviceList(Page<APPDevice> page, APPDeviceQueryCriteria criteria) {
// criteria.setCustomerId(SecurityUtils.getCurrentUserId());
// IPage<APPDevice> devices = appDeviceMapper.appDeviceList(page, criteria);
// return new PageResult<>(devices.getRecords(), devices.getTotal());
return null;
}
/**
* APP用户设备类型列表
*
* @param criteria
* @return
*/
@Override
public List<APPDeviceType> appTypeList(APPDeviceQueryCriteria criteria) {
// criteria.setCustomerId(SecurityUtils.getCurrentUserId());
// return appDeviceTypeMapper.appTypeList(criteria);
return null;
}
/**
* APP/小程序用户设备绑定
*
* @param criteria
*/
@Override
@Transactional
public void appBindDevice(APPDeviceQueryCriteria criteria) {
List<Device> devices = new ArrayList<>();
if (criteria.getCommunicationMode().equals(CommunicationModeEnum.BLUETOOTH.getValue())) {
devices = deviceMapper.selectList(new QueryWrapper<Device>()
.eq("original_device_id", null)
.eq("device_mac", criteria.getDeviceMac()));
if (CollectionUtil.isEmpty(devices)) {
throw new BadRequestException("请先将设备入库!!!");
}
List<APPDevice> appDevices = appDeviceMapper.selectList(new QueryWrapper<APPDevice>()
.eq("device_mac", criteria.getDeviceMac()).eq("binding_type", UserType.APP.getValue()));
if (CollectionUtil.isNotEmpty(appDevices)) {
throw new BadRequestException("该设备已绑定!!!");
}
}
if (criteria.getCommunicationMode().equals(CommunicationModeEnum.FOUR_G.getValue())) {
devices = deviceMapper.selectList(new QueryWrapper<Device>()
.eq("original_device_id", null)
.eq("device_imei", criteria.getDeviceImei()));
if (CollectionUtil.isEmpty(devices)) {
throw new BadRequestException("请先将设备入库!!!");
}
List<APPDevice> appDevices = appDeviceMapper.selectList(new QueryWrapper<APPDevice>()
.eq("device_imei", criteria.getDeviceImei()).eq("binding_type", UserType.APP.getValue()));
if (CollectionUtil.isNotEmpty(appDevices)) {
throw new BadRequestException("该设备已绑定!!!");
}
}
Device device = devices.get(0);
device.setBindingStatus(BindingStatusEnum.BOUND.getCode());
deviceMapper.updateById(device);
APPDevice appDevice = new APPDevice();
BeanUtil.copyProperties(device, appDevice);
appDevice.setBindingType(UserType.APP.getValue());
appDevice.setBindingStatus(BindingStatusEnum.BOUND.getCode());
Long userId = LoginHelper.getUserId();
appDevice.setCustomerId(userId);
appDevice.setCreateTime(new Timestamp(System.currentTimeMillis()));
// 设备类型名称
appDevice.setDeviceTypeName(device.getTypeName());
appDeviceMapper.insert(appDevice);
APPDeviceType appDeviceType = appDeviceTypeMapper.selectById(device.getDeviceType());
if (appDeviceType == null) {
DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType());
APPDeviceType type = new APPDeviceType();
BeanUtil.copyProperties(deviceType, type);
type.setCustomerId(userId);
appDeviceTypeMapper.insert(type);
}
}
/**
* 分页查询APP/小程序设备
*
* @param criteria
* @param page
* @return
*/
@Override
public TableDataInfo<APPDevice> queryAll(Page<APPDevice> page, APPDeviceQueryCriteria criteria) {
IPage<APPDevice> devices = appDeviceMapper.queryAll(page, criteria);
return new TableDataInfo<>(devices.getRecords(), devices.getTotal());
}
/**
* APP/小程序用户设备解绑
*
* @param deviceForm
*/
@Override
@Transactional
public void unbindAPPDevice(APPUnbindDTO deviceForm) {
// QueryWrapper<APPDevice> queryWrapper = new QueryWrapper<>();
// QueryWrapper<Device> qw = new QueryWrapper<>();
// if (StringUtils.isNotEmpty(deviceForm.getDeviceMac())) {
// queryWrapper.eq("device_mac", deviceForm.getDeviceMac());
// qw.eq("device_mac", deviceForm.getDeviceMac());
// }
// if (StringUtils.isNotEmpty(deviceForm.getDeviceImei())) {
// queryWrapper.eq("device_imei", deviceForm.getDeviceImei());
// qw.eq("device_imei", deviceForm.getDeviceImei());
// }
// queryWrapper.eq("binding_type", UserType.APP.getValue());
// APPDevice appDevice = appDeviceMapper.selectOne(queryWrapper);
// appDeviceMapper.delete(queryWrapper);
//
// List<Device> devices = deviceMapper.selectList(qw);
// List<Long> ids = devices.stream()
// .map(Device::getId)
// .collect(Collectors.toList());
// if (CollectionUtil.isNotEmpty(ids)) {
// appDeviceTypeMapper.deleteBatchIds(ids);
// }
// Device device = new Device();
// device.setId(appDevice.getId());
// device.setBindingStatus(BindingStatusEnum.UNBOUND.getCode());
// deviceMapper.updateById(device);
}
@Override
public List<APPDeviceTypeVo> getTypeList() {
Long userId = AppLoginHelper.getUserId();
return appDeviceMapper.getTypeList(userId);
}
@Override
public void reName(APPReNameDTO reNameDTO) {
UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", reNameDTO.getId())
.eq("binding_user_id", AppLoginHelper.getUserId())
.set("device_name", reNameDTO.getDeviceName());
deviceMapper.update(updateWrapper);
}
/**
* WEB端查看APP客户设备绑定
*
* @param criteria
* @return
*/
@Override
public TableDataInfo<APPDevice> queryAppDeviceList(DeviceQueryCriteria criteria) {
// Page<AppDeviceVo> result = baseMapper.queryAppDeviceList(pageQuery.build(), bo);
// return TableDataInfo.build(result);
return null;
}
@Override
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);
}
}

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fuyuanshen.app.mapper.AppBusinessFileMapper">
<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="businessId != null">
and a.business_id = #{businessId}
</if>
<if test="fileId != null">
and a.file_id = #{fileId}
</if>
<if test="fileType != null">
and a.file_type = #{fileType}
</if>
<if test="createBy != null">
and a.create_by = #{createBy}
</if>
order by a.create_time desc
</select>
</mapper>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fuyuanshen.app.mapper.AppDeviceShareMapper">
</mapper>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fuyuanshen.app.mapper.AppOperationVideoMapper">
</mapper>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fuyuanshen.app.mapper.AppPersonnelInfoMapper">
</mapper>

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.fuyuanshen.app.mapper.equipment.APPDeviceMapper">
<resultMap id="BaseResultMap" type="com.fuyuanshen.app.domain.APPDevice">
<id column="id" property="id"/>
<result column="device_type" property="deviceType"/>
<result column="customer_id" property="customerId"/>
<!--<result column="device_no" property="deviceNo"/>-->
<result column="device_name" property="deviceName"/>
<result column="device_pic" property="devicePic"/>
<result column="device_mac" property="deviceMac"/>
<result column="device_sn" property="deviceSn"/>
<result column="device_status" property="deviceStatus"/>
<result column="remark" property="remark"/>
<result column="create_by" property="createBy"/>
<result column="update_by" property="updateBy"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
<result column="binding_status" property="bindingStatus"/>
</resultMap>
<!-- APP用户设备列表 -->
<select id="appDeviceList" resultType="com.fuyuanshen.app.domain.APPDevice">
select d.* from app_device as d
<where>
<!-- 时间范围等其他条件保持原样 -->
<if test="criteria.deviceName != null and criteria.deviceName.trim() != ''">
and d.device_name like concat('%', TRIM(#{criteria.deviceName}), '%')
</if>
<if test="criteria.deviceMac != null and criteria.deviceMac.trim() != ''">
and d.device_mac = #{criteria.deviceMac}
</if>
<if test="criteria.deviceImei != null and criteria.deviceImei.trim() != ''">
and d.device_imei = #{criteria.deviceImei}
</if>
<if test="criteria.deviceSn != null">
and d.device_sn = #{criteria.deviceSn}
</if>
<if test="criteria.deviceType != null">
and d.device_type = #{criteria.deviceType}
</if>
<if test="criteria.deviceStatus != null">
and d.device_status = #{criteria.deviceStatus}
</if>
<if test="criteria.createTime != null and criteria.createTime.size() != 0">
and d.create_time between #{criteria.createTime[0]} and #{criteria.createTime[1]}
</if>
<if test="criteria.tenantId != null">
AND tenant_id = #{criteria.tenantId}
</if>
and d.customer_id = #{criteria.customerId}
</where>
order by d.create_time desc
</select>
<!-- 分页查询APP/小程序设备 -->
<select id="queryAll" resultType="com.fuyuanshen.app.domain.APPDevice">
select d.* from app_device as d
<where>
<!-- 时间范围等其他条件保持原样 -->
<if test="criteria.deviceName != null and criteria.deviceName.trim() != ''">
and d.device_name like concat('%', TRIM(#{criteria.deviceName}), '%')
</if>
<if test="criteria.deviceMac != null and criteria.deviceMac.trim() != ''">
and d.device_mac = #{criteria.deviceMac}
</if>
<if test="criteria.deviceImei != null and criteria.deviceImei.trim() != ''">
and d.device_imei = #{criteria.deviceImei}
</if>
<if test="criteria.deviceSn != null">
and d.device_sn = #{criteria.deviceSn}
</if>
<if test="criteria.deviceType != null">
and d.device_type = #{criteria.deviceType}
</if>
<if test="criteria.deviceStatus != null">
and d.device_status = #{criteria.deviceStatus}
</if>
<if test="criteria.createTime != null and criteria.createTime.size() != 0">
and d.create_time between #{criteria.createTime[0]} and #{criteria.createTime[1]}
</if>
and d.customer_id = #{criteria.customerId}
</where>
order by d.create_time desc
</select>
<select id="getTypeList" resultType="com.fuyuanshen.app.domain.vo.APPDeviceTypeVo">
SELECT dt.id, dt.type_name, dt.communication_mode
FROM device_type dt
WHERE EXISTS(select 1
from device d
where d.device_type = dt.id
and d.binding_user_id = #{userId}
AND d.binding_status = 1)
</select>
</mapper>

Some files were not shown because too many files have changed in this diff Show More