diff --git a/yudao-module-farm/pom.xml b/yudao-module-farm/pom.xml index f0136113..2dfa7f88 100644 --- a/yudao-module-farm/pom.xml +++ b/yudao-module-farm/pom.xml @@ -80,6 +80,13 @@ yudao-spring-boot-starter-mq + + + org.eclipse.paho + org.eclipse.paho.client.mqttv3 + 1.2.5 + + cn.iocoder.boot @@ -134,14 +141,10 @@ spring-websocket - - - - - - - - + + org.springframework.boot + spring-boot-starter-data-mongodb + diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/config/FarmMongoConfiguration.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/config/FarmMongoConfiguration.java new file mode 100644 index 00000000..b57e0dc7 --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/config/FarmMongoConfiguration.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.farm.config; + +import cn.iocoder.yudao.module.farm.dal.mongo.telemetry.DeviceTelemetryRepository; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; + +/** + * Enable Mongo repositories for the farm module. + */ +@Configuration +@EnableMongoRepositories(basePackageClasses = DeviceTelemetryRepository.class) +public class FarmMongoConfiguration { +} + + diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/config/MqttAutoConfiguration.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/config/MqttAutoConfiguration.java new file mode 100644 index 00000000..9195c575 --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/config/MqttAutoConfiguration.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.farm.config; + +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; +import cn.iocoder.yudao.module.farm.service.mqtt.MqttClientManager; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties(MqttProperties.class) +@ConditionalOnProperty(prefix = "mqtt", name = "broker") +public class MqttAutoConfiguration { + + @Bean + public MqttClient mqttClient(MqttProperties props) throws MqttException { + MqttConnectOptions options = new MqttConnectOptions(); + options.setCleanSession(props.isCleanSession()); + options.setKeepAliveInterval(props.getKeepAlive()); + if (props.getUsername() != null && !props.getUsername().isEmpty()) { + options.setUserName(props.getUsername()); + options.setPassword(props.getPassword() != null ? props.getPassword().toCharArray() : new char[0]); + } + MqttClient client = new MqttClient(props.getBroker(), props.getClientId(), new MemoryPersistence()); + client.connect(options); + return client; + } + + @Bean + @ConditionalOnProperty(prefix = "mqtt", name = "connections") + public java.util.Map multipleMqttClients(MqttProperties props, MqttClientManager manager) throws MqttException { + java.util.Map map = new java.util.HashMap<>(); + if (props.getConnections() != null) { + for (MqttConnectionProperties c : props.getConnections()) { + MqttClient cli = manager.createAndConnect( + c.getName(), c.getBroker(), c.getClientId(), c.getUsername(), c.getPassword(), c.isCleanSession(), c.getKeepAlive() + ); + map.put(c.getName(), cli); + } + } + return map; + } +} + + diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/config/MqttConnectionProperties.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/config/MqttConnectionProperties.java new file mode 100644 index 00000000..528c53f0 --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/config/MqttConnectionProperties.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.farm.config; + +public class MqttConnectionProperties { + + private String name; + private String broker; + private String deviceId; + private String clientId; + private String username; + private String password; + private boolean cleanSession = true; + private int keepAlive = 30; + private int qos = 1; + private boolean reconnect = true; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getBroker() { + return broker; + } + + public void setBroker(String broker) { + this.broker = broker; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public boolean isCleanSession() { + return cleanSession; + } + + public void setCleanSession(boolean cleanSession) { + this.cleanSession = cleanSession; + } + + public int getKeepAlive() { + return keepAlive; + } + + public void setKeepAlive(int keepAlive) { + this.keepAlive = keepAlive; + } + + public int getQos() { + return qos; + } + + public void setQos(int qos) { + this.qos = qos; + } + + public boolean isReconnect() { + return reconnect; + } + + public void setReconnect(boolean reconnect) { + this.reconnect = reconnect; + } +} + + diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/config/MqttProperties.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/config/MqttProperties.java new file mode 100644 index 00000000..6f176418 --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/config/MqttProperties.java @@ -0,0 +1,92 @@ +package cn.iocoder.yudao.module.farm.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "mqtt") +public class MqttProperties { + + private String broker; + private String clientId; + private String username; + private String password; + private boolean cleanSession = true; + private int keepAlive = 30; + private int qos = 1; + private boolean reconnect = true; + + private java.util.List connections; + + public String getBroker() { + return broker; + } + + public void setBroker(String broker) { + this.broker = broker; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public boolean isCleanSession() { + return cleanSession; + } + + public void setCleanSession(boolean cleanSession) { + this.cleanSession = cleanSession; + } + + public int getKeepAlive() { + return keepAlive; + } + + public void setKeepAlive(int keepAlive) { + this.keepAlive = keepAlive; + } + + public int getQos() { + return qos; + } + + public void setQos(int qos) { + this.qos = qos; + } + + public boolean isReconnect() { + return reconnect; + } + + public void setReconnect(boolean reconnect) { + this.reconnect = reconnect; + } + + public java.util.List getConnections() { + return connections; + } + + public void setConnections(java.util.List connections) { + this.connections = connections; + } +} + + diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/dict/DictController.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/dict/DictController.java index 8053c83e..5ff6ec2b 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/dict/DictController.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/dict/DictController.java @@ -307,12 +307,9 @@ public class DictController { @Operation(summary = "字典数据维护-下拉框列表-二级物种类别") @GetMapping("/list/two-library") - public CommonResult> getTwoLibraryList() { + public CommonResult> getTwoLibraryList() { try { - // 获取物种类别字典数据 - List dictList = sysDictService.getByTypeCode(CommonConstants.DICT_TYPE_CODE_3); - // 使用工具类构建二级树结构 - List twoList = TreeStructureUtil.buildTwoLevelTree(dictList); + List twoList = speciesLibraryService.getSpeciesTwoLevelTree(); return success(twoList); } catch (Exception e) { log.error("获取二级物种类别列表失败", e); diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/personnelmanagement/PersonnelManagementController.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/personnelmanagement/PersonnelManagementController.java index 5b4ba08b..a1d07510 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/personnelmanagement/PersonnelManagementController.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/personnelmanagement/PersonnelManagementController.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.util.List; import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @Tag(name = "管理后台 - 人员管理") @@ -38,7 +39,12 @@ public class PersonnelManagementController { @PostMapping("/create") @Operation(summary = "创建人员管理") public CommonResult createPersonnelManagement(@Valid @RequestBody PersonnelManagementSaveReqVO createReqVO) { - return success(personnelManagementService.createPersonnelManagement(createReqVO)); + String management = personnelManagementService.createPersonnelManagement(createReqVO); + if (management.length() > 0) { + return success(management); + } else { + return error(501,"手机号重复!"); + } } @PutMapping("/reset") diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/plotinfo/PlotInfoController.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/plotinfo/PlotInfoController.java index 10bbc378..595a4f42 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/plotinfo/PlotInfoController.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/plotinfo/PlotInfoController.java @@ -8,7 +8,9 @@ import jakarta.validation.Valid; import jakarta.validation.Valid; import jakarta.validation.Valid; import jakarta.servlet.http.HttpServletResponse; + import java.util.List; + import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; import jakarta.annotation.Resource; @@ -24,6 +26,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; @@ -44,14 +47,12 @@ public class PlotInfoController { @PostMapping("/create") @Operation(summary = "创建地块") - public CommonResult createPlotInfo(@Valid @RequestBody PlotInfoSaveReqVO createReqVO) { return success(plotInfoService.createPlotInfo(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新地块") - public CommonResult updatePlotInfo(@Valid @RequestBody PlotInfoSaveReqVO updateReqVO) { plotInfoService.updatePlotInfo(updateReqVO); return success(true); @@ -60,7 +61,6 @@ public class PlotInfoController { @DeleteMapping("/delete") @Operation(summary = "删除地块") @Parameter(name = "id", description = "编号", required = true) - public CommonResult deletePlotInfo(@RequestParam("id") String id) { plotInfoService.deletePlotInfo(id); return success(true); @@ -69,7 +69,6 @@ public class PlotInfoController { @DeleteMapping("/delete-list") @Parameter(name = "ids", description = "编号", required = true) @Operation(summary = "批量删除地块") - public CommonResult deletePlotInfoList(@RequestParam("ids") List ids) { plotInfoService.deletePlotInfoListByIds(ids); return success(true); @@ -78,7 +77,6 @@ public class PlotInfoController { @GetMapping("/get") @Operation(summary = "获得地块") @Parameter(name = "id", description = "编号", required = true, example = "1024") - public CommonResult getPlotInfo(@RequestParam("id") String id) { PlotInfoDO plotInfo = plotInfoService.getPlotInfo(id); return success(BeanUtils.toBean(plotInfo, PlotInfoRespVO.class)); @@ -86,7 +84,6 @@ public class PlotInfoController { @GetMapping("/page") @Operation(summary = "获得地块分页") - public CommonResult> getPlotInfoPage(@Valid PlotInfoPageReqVO pageReqVO) { PageResult pageResult = plotInfoService.getPlotInfoPage(pageReqVO); return success(BeanUtils.toBean(pageResult, PlotInfoRespVO.class)); @@ -94,15 +91,14 @@ public class PlotInfoController { @GetMapping("/export-excel") @Operation(summary = "导出地块 Excel") - @ApiAccessLog(operateType = EXPORT) public void exportPlotInfoExcel(@Valid PlotInfoPageReqVO pageReqVO, - HttpServletResponse response) throws IOException { + HttpServletResponse response) throws IOException { pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); List list = plotInfoService.getPlotInfoPage(pageReqVO).getList(); // 导出 Excel ExcelUtils.write(response, "地块.xls", "数据", PlotInfoRespVO.class, - BeanUtils.toBean(list, PlotInfoRespVO.class)); + BeanUtils.toBean(list, PlotInfoRespVO.class)); } } \ No newline at end of file diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/dataobject/mqtt/MqttConnectionDO.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/dataobject/mqtt/MqttConnectionDO.java new file mode 100644 index 00000000..cf907fe0 --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/dataobject/mqtt/MqttConnectionDO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.farm.dal.dataobject.mqtt; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +@TableName("farm_mqtt_connection") +@KeySequence("farm_mqtt_connection_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MqttConnectionDO extends BaseDO { + + @TableId + private Long id; + + private String tenantId; + + private String name; + + private String deviceId; + + private String broker; + + private String clientId; + + private String username; + + private String password; + + private Boolean cleanSession; + + private Integer keepAlive; + + private Integer qos; + + private Boolean reconnect; + + private Boolean status; +} + + diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/dataobject/personnelmanagement/SystemUserRoleDO.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/dataobject/personnelmanagement/SystemUserRoleDO.java new file mode 100644 index 00000000..70800305 --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/dataobject/personnelmanagement/SystemUserRoleDO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.farm.dal.dataobject.personnelmanagement; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +@TableName("system_user_role") +@KeySequence("system_user_role_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class SystemUserRoleDO extends BaseDO { + /** + * 自增主键 + */ + @TableId + private Long id; + /** + * 用户 ID + */ + private Long userId; + /** + * 角色 ID + */ + private Long roleId; +} diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mongo/telemetry/DeviceTelemetryDoc.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mongo/telemetry/DeviceTelemetryDoc.java new file mode 100644 index 00000000..30b1bc47 --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mongo/telemetry/DeviceTelemetryDoc.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.farm.dal.mongo.telemetry; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document(collection = "farm_device_telemetry") +public class DeviceTelemetryDoc { + + @Id + private String id; + private String tenantId; + private String deviceId; + private Long ts; + private String payloadJson; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getTenantId() { return tenantId; } + public void setTenantId(String tenantId) { this.tenantId = tenantId; } + public String getDeviceId() { return deviceId; } + public void setDeviceId(String deviceId) { this.deviceId = deviceId; } + public Long getTs() { return ts; } + public void setTs(Long ts) { this.ts = ts; } + public String getPayloadJson() { return payloadJson; } + public void setPayloadJson(String payloadJson) { this.payloadJson = payloadJson; } +} + + diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mongo/telemetry/DeviceTelemetryRepository.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mongo/telemetry/DeviceTelemetryRepository.java new file mode 100644 index 00000000..e7e3f102 --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mongo/telemetry/DeviceTelemetryRepository.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.module.farm.dal.mongo.telemetry; + +import org.springframework.data.mongodb.repository.MongoRepository; + +import java.util.List; + +public interface DeviceTelemetryRepository extends MongoRepository { + List findTop100ByTenantIdAndDeviceIdOrderByTsDesc(String tenantId, String deviceId); +} + + diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mysql/mqtt/MqttConnectionMapper.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mysql/mqtt/MqttConnectionMapper.java new file mode 100644 index 00000000..cea5038d --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mysql/mqtt/MqttConnectionMapper.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.farm.dal.mysql.mqtt; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.farm.dal.dataobject.mqtt.MqttConnectionDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface MqttConnectionMapper extends BaseMapperX { + + default MqttConnectionDO selectByDeviceIdAndTenant(String deviceId, String tenantId) { + return selectOne(new LambdaQueryWrapperX() + .eqIfPresent(MqttConnectionDO::getDeviceId, deviceId) + .eqIfPresent(MqttConnectionDO::getTenantId, tenantId) + .eq(MqttConnectionDO::getStatus, true) + ); + } +} + + diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mysql/personnelmanagement/SystemUserRoleMapper.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mysql/personnelmanagement/SystemUserRoleMapper.java new file mode 100644 index 00000000..15fc1aea --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mysql/personnelmanagement/SystemUserRoleMapper.java @@ -0,0 +1,9 @@ +package cn.iocoder.yudao.module.farm.dal.mysql.personnelmanagement; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.farm.dal.dataobject.personnelmanagement.SystemUserRoleDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface SystemUserRoleMapper extends BaseMapperX { +} diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/mqtt/DeviceMqttService.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/mqtt/DeviceMqttService.java new file mode 100644 index 00000000..74d55f56 --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/mqtt/DeviceMqttService.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.farm.service.mqtt; + +import cn.iocoder.yudao.module.farm.dal.dataobject.deviceinfo.DeviceInfoDO; +import cn.iocoder.yudao.module.farm.dal.mysql.deviceinfo.DeviceInfoMapper; +import org.eclipse.paho.client.mqttv3.IMqttMessageListener; +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.nio.charset.StandardCharsets; +import cn.iocoder.yudao.module.farm.service.telemetry.DeviceTelemetryService; + +@Service +public class DeviceMqttService { + + @Resource + private DeviceInfoMapper deviceInfoMapper; + @Resource + private MqttConnectionService mqttConnectionService; + @Resource + private DeviceTelemetryService deviceTelemetryService; + + private final Set subscribed = ConcurrentHashMap.newKeySet(); + + // 上报主题 + private String telemetryTopic(String deviceUniqueId) { + return "farm/" + deviceUniqueId + "/telemetry"; + } + + // 下发指令 + private String commandTopic(String deviceUniqueId) { + return "farm/" + deviceUniqueId + "/cmd"; + } + + public void publishTelemetry(String deviceUniqueId, String jsonPayload) throws MqttException { + MqttClient client = mqttConnectionService.getClientByDeviceId(deviceUniqueId); + if (client == null) return; + client.publish(telemetryTopic(deviceUniqueId), jsonPayload.getBytes(StandardCharsets.UTF_8), 1, false); + } + + public void sendCommand(String deviceUniqueId, String jsonCommand) throws MqttException { + MqttClient client = mqttConnectionService.getClientByDeviceId(deviceUniqueId); + if (client == null) return; + client.publish(commandTopic(deviceUniqueId), jsonCommand.getBytes(StandardCharsets.UTF_8), 1, false); + } + + public void subscribeTelemetry(String deviceUniqueId, IMqttMessageListener listener) throws MqttException { + MqttClient client = mqttConnectionService.getClientByDeviceId(deviceUniqueId); + if (client == null) return; + String topic = telemetryTopic(deviceUniqueId); + String key = client.getClientId() + "|" + topic; + if (subscribed.add(key)) { + client.subscribe(topic, 1, listener); + } + } + + public void subscribeCommands(String deviceUniqueId, IMqttMessageListener listener) throws MqttException { + MqttClient client = mqttConnectionService.getClientByDeviceId(deviceUniqueId); + if (client == null) return; + String topic = commandTopic(deviceUniqueId); + String key = client.getClientId() + "|" + topic; + if (subscribed.add(key)) { + client.subscribe(topic, 1, listener); + } + } + + // 订阅并自动入库 + public void subscribeTelemetryAndPersist(String deviceUniqueId) throws MqttException { + this.subscribeTelemetry(deviceUniqueId, (topic, message) -> { + String payload = new String(message.getPayload(), StandardCharsets.UTF_8); + deviceTelemetryService.saveTelemetry(deviceUniqueId, payload); + }); + } + + public DeviceInfoDO getDevice(String deviceUniqueId) { + return deviceInfoMapper.selectOne(DeviceInfoDO::getDeviceUniqueId, deviceUniqueId); + } +} + + diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/mqtt/MqttClientManager.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/mqtt/MqttClientManager.java new file mode 100644 index 00000000..62e65cd4 --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/mqtt/MqttClientManager.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.farm.service.mqtt; + +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Service +public class MqttClientManager { + + private final Map clients = new ConcurrentHashMap<>(); + + public MqttClient createAndConnect(String name, + String broker, + String clientId, + String username, + String password, + boolean cleanSession, + int keepAlive) throws MqttException { + MqttClient client = new MqttClient(broker, clientId, new MemoryPersistence()); + MqttConnectOptions options = new MqttConnectOptions(); + options.setCleanSession(cleanSession); + options.setKeepAliveInterval(keepAlive); + if (username != null && !username.isEmpty()) { + options.setUserName(username); + options.setPassword(password != null ? password.toCharArray() : new char[0]); + } + client.connect(options); + clients.put(name, client); + return client; + } + + public MqttClient get(String name) { + return clients.get(name); + } + + public void disconnectAndRemove(String name) { + MqttClient c = clients.remove(name); + if (c != null) { + try { c.disconnect(); } catch (Exception ignored) {} + try { c.close(); } catch (Exception ignored) {} + } + } +} + + diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/mqtt/MqttClientService.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/mqtt/MqttClientService.java new file mode 100644 index 00000000..3d3aada0 --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/mqtt/MqttClientService.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.farm.service.mqtt; + +import org.eclipse.paho.client.mqttv3.IMqttMessageListener; +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; +import java.nio.charset.StandardCharsets; + +@Service +public class MqttClientService { + + @Resource + private MqttConnectionService mqttConnectionService; + + public void publish(String deviceId, String topic, String payload, int qos, boolean retained) throws MqttException { + MqttClient client = mqttConnectionService.getClientByDeviceId(deviceId); + if (client == null) return; + client.publish(topic, payload.getBytes(StandardCharsets.UTF_8), qos, retained); + } + + public void subscribe(String deviceId, String topicFilter, int qos, IMqttMessageListener listener) throws MqttException { + MqttClient client = mqttConnectionService.getClientByDeviceId(deviceId); + if (client == null) return; + client.subscribe(topicFilter, qos, listener); + } +} + + diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/mqtt/MqttConnectionService.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/mqtt/MqttConnectionService.java new file mode 100644 index 00000000..8b80a79b --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/mqtt/MqttConnectionService.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.farm.service.mqtt; + +import cn.iocoder.yudao.module.farm.dal.dataobject.mqtt.MqttConnectionDO; +import cn.iocoder.yudao.module.farm.dal.mysql.mqtt.MqttConnectionMapper; +import org.eclipse.paho.client.mqttv3.IMqttMessageListener; +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; +import org.eclipse.paho.client.mqttv3.MqttMessage; +import org.springframework.stereotype.Service; + +import jakarta.annotation.PreDestroy; +import jakarta.annotation.Resource; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser; + +@Service +public class MqttConnectionService { + + @Resource + private MqttConnectionMapper connectionMapper; + + private final Map cache = new ConcurrentHashMap<>(); + + public MqttClient getClientByDeviceId(String deviceId) throws MqttException { + String tenantId = String.valueOf(getLoginUser().getTenantId()); + return this.getClientByDeviceId(deviceId, tenantId); + } + + public MqttClient getClientByDeviceId(String deviceId, String tenantId) throws MqttException { + String key = tenantId + ":" + deviceId; + MqttClient existing = cache.get(key); + if (existing != null) { + if (!existing.isConnected()) { + try { existing.reconnect(); } catch (Exception ignored) {} + } + if (existing.isConnected()) return existing; + } + + MqttConnectionDO cfg = connectionMapper.selectByDeviceIdAndTenant(deviceId, tenantId); + if (cfg == null) { + return null; + } + + MqttClient client = new MqttClient(cfg.getBroker(), cfg.getClientId(), new MemoryPersistence()); + MqttConnectOptions options = new MqttConnectOptions(); + options.setCleanSession(Boolean.TRUE.equals(cfg.getCleanSession())); + options.setAutomaticReconnect(Boolean.TRUE.equals(cfg.getReconnect())); + if (cfg.getKeepAlive() != null) options.setKeepAliveInterval(cfg.getKeepAlive()); + if (cfg.getUsername() != null && !cfg.getUsername().isEmpty()) { + options.setUserName(cfg.getUsername()); + options.setPassword(cfg.getPassword() != null ? cfg.getPassword().toCharArray() : new char[0]); + } + try { + String lwtTopic = "farm/" + deviceId + "/lwt"; + MqttMessage lwt = new MqttMessage("offline".getBytes(StandardCharsets.UTF_8)); + lwt.setQos(cfg.getQos() != null ? cfg.getQos() : 1); + lwt.setRetained(true); + options.setWill(lwtTopic, lwt.getPayload(), lwt.getQos(), lwt.isRetained()); + } catch (Exception ignored) {} + client.connect(options); + cache.put(key, client); + return client; + } + + public void publish(String deviceId, String topic, String payload, int qos, boolean retained) throws MqttException { + MqttClient c = getClientByDeviceId(deviceId); + if (c == null) return; + c.publish(topic, payload.getBytes(StandardCharsets.UTF_8), qos, retained); + } + + public void subscribe(String deviceId, String topicFilter, int qos, IMqttMessageListener listener) throws MqttException { + MqttClient c = getClientByDeviceId(deviceId); + if (c == null) return; + c.subscribe(topicFilter, qos, listener); + } + + public void reload(String deviceId) { + String tenantId = String.valueOf(getLoginUser().getTenantId()); + String key = tenantId + ":" + deviceId; + MqttClient old = cache.remove(key); + if (old != null) { + try { old.disconnect(); } catch (Exception ignored) {} + try { old.close(); } catch (Exception ignored) {} + } + } + + @PreDestroy + public void shutdown() { + for (Map.Entry e : cache.entrySet()) { + try { e.getValue().disconnect(); } catch (Exception ignored) {} + try { e.getValue().close(); } catch (Exception ignored) {} + } + cache.clear(); + } +} + + diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/personnelmanagement/PersonnelManagementServiceImpl.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/personnelmanagement/PersonnelManagementServiceImpl.java index b3599467..652fb2d7 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/personnelmanagement/PersonnelManagementServiceImpl.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/personnelmanagement/PersonnelManagementServiceImpl.java @@ -9,8 +9,10 @@ import cn.iocoder.yudao.module.farm.controller.admin.personnelmanagement.vo.Pers import cn.iocoder.yudao.module.farm.controller.admin.personnelmanagement.vo.PersonnelManagementSaveReqVO; import cn.iocoder.yudao.module.farm.dal.dataobject.personnelmanagement.PersonnelManagementDO; import cn.iocoder.yudao.module.farm.dal.dataobject.personnelmanagement.SystemUserDO; +import cn.iocoder.yudao.module.farm.dal.dataobject.personnelmanagement.SystemUserRoleDO; import cn.iocoder.yudao.module.farm.dal.mysql.personnelmanagement.PersonnelManagementMapper; import cn.iocoder.yudao.module.farm.dal.mysql.personnelmanagement.SystemUserMapper; +import cn.iocoder.yudao.module.farm.dal.mysql.personnelmanagement.SystemUserRoleMapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import jakarta.annotation.Resource; import org.springframework.security.crypto.password.PasswordEncoder; @@ -38,15 +40,21 @@ public class PersonnelManagementServiceImpl implements PersonnelManagementServic private SystemUserMapper userMapper; @Resource private PasswordEncoder passwordEncoder; + @Resource + private SystemUserRoleMapper systemUserRoleMapper; @Override public String createPersonnelManagement(PersonnelManagementSaveReqVO createReqVO) { LoginUser user = getLoginUser(); + // 插入 PersonnelManagementDO personnelManagement = BeanUtils.toBean(createReqVO, PersonnelManagementDO.class); personnelManagement.setId(IdUtil.fastUUID()); personnelManagement.setTenantId(String.valueOf(user.getTenantId())); - + SystemUserDO userDO = userMapper.selectByPhone(personnelManagement.getPhone()); + if (userDO != null) { + return ""; + } // 处理图片集合转换 handleImageConversion(personnelManagement, createReqVO); @@ -59,7 +67,14 @@ public class PersonnelManagementServiceImpl implements PersonnelManagementServic adminUserDO.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 String substring = personnelManagement.getPhone().substring(personnelManagement.getPhone().length() - 6); adminUserDO.setPassword(encodePassword(substring)); // 加密密码 - userMapper.insert(adminUserDO); + userMapper.insert(adminUserDO);// 系统用户同步新增 + // 用户角色关联 + for (String s : personnelManagement.getRole().split(",")) { + SystemUserRoleDO userRoleDO = new SystemUserRoleDO(); + userRoleDO.setUserId(adminUserDO.getId()); + userRoleDO.setRoleId(Long.valueOf(s)); + systemUserRoleMapper.insert(userRoleDO); + } personnelManagementMapper.insert(personnelManagement); // 返回 return personnelManagement.getId(); @@ -69,12 +84,25 @@ public class PersonnelManagementServiceImpl implements PersonnelManagementServic public void updatePersonnelManagement(PersonnelManagementSaveReqVO updateReqVO) { // 校验存在 validatePersonnelManagementExists(updateReqVO.getId()); + PersonnelManagementDO managementDO = personnelManagementMapper.selectById(updateReqVO.getId()); + + // 更新 PersonnelManagementDO updateObj = BeanUtils.toBean(updateReqVO, PersonnelManagementDO.class); - + SystemUserDO userDO = userMapper.selectByPhone(managementDO.getPhone()); + if (updateReqVO.getPhone() != null) userDO.setUsername(updateReqVO.getPhone()); + if (updateReqVO.getName() != null) userDO.setNickname(updateReqVO.getName()); + if (updateReqVO.getPhone() != null) userDO.setMobile(updateReqVO.getPhone()); + if (updateReqVO.getPicture() != null) userDO.setAvatar(updateReqVO.getPicture()); // 处理图片集合转换 handleImageConversion(updateObj, updateReqVO); - + for (String s : managementDO.getRole().split(",")) { + SystemUserRoleDO userRoleDO = new SystemUserRoleDO(); + userRoleDO.setUserId(userDO.getId()); + userRoleDO.setRoleId(Long.valueOf(s)); + systemUserRoleMapper.insert(userRoleDO); + } + userMapper.updateById(userDO); personnelManagementMapper.updateById(updateObj); } @@ -82,6 +110,10 @@ public class PersonnelManagementServiceImpl implements PersonnelManagementServic public void deletePersonnelManagement(String id) { // 校验存在 validatePersonnelManagementExists(id); + PersonnelManagementDO managementDO = personnelManagementMapper.selectById(id); + SystemUserDO userDO = userMapper.selectByPhone(managementDO.getPhone()); + userMapper.deleteById(userDO.getId()); + systemUserRoleMapper.delete(SystemUserRoleDO::getUserId, userDO.getId()); // 删除 personnelManagementMapper.deleteById(id); } diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/specieslibrary/SpeciesLibraryService.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/specieslibrary/SpeciesLibraryService.java index 4d54dae7..4a55f58c 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/specieslibrary/SpeciesLibraryService.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/specieslibrary/SpeciesLibraryService.java @@ -69,11 +69,11 @@ public interface SpeciesLibraryService { */ Map getSpeciesLibraryForLifeCycMap(); - /** - * 基于 speciesName1 -> speciesName2 -> cultivarName 构建三级树 - */ + List getSpeciesThreeLevelTree(); + + List getSpeciesTwoLevelTree(); /** * 物种与模型 * @return diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/specieslibrary/SpeciesLibraryServiceImpl.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/specieslibrary/SpeciesLibraryServiceImpl.java index cbf1d7c8..db550083 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/specieslibrary/SpeciesLibraryServiceImpl.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/specieslibrary/SpeciesLibraryServiceImpl.java @@ -305,6 +305,67 @@ public class SpeciesLibraryServiceImpl implements SpeciesLibraryService { return result; } + @Override + public List getSpeciesTwoLevelTree() { + List dictTree = twoDictService.getTwoDictTree(); + if (dictTree == null || dictTree.isEmpty()) { + return new ArrayList<>(); + } + + // 1级:parentId == null 的节点 + List level1Nodes = dictTree.stream() + .filter(n -> n != null && n.getParentId() == null) + .sorted(java.util.Comparator.comparing(TwoDictTreeRespVO::getName, java.util.Comparator.nullsLast(String::compareTo))) + .collect(Collectors.toList()); + + // 收集所有二级分类ID,一次性查询物种,避免 N+1 + List level2Ids = dictTree.stream() + .filter(n -> n != null && n.getParentId() != null) // 非根即二级(在当前两级分类中) + .map(TwoDictTreeRespVO::getId) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + // 批量查询所有二级分类下的物种,避免 N+1 查询 + Map> categoryToSpeciesMap; + if (level2Ids.isEmpty()) { + categoryToSpeciesMap = java.util.Collections.emptyMap(); + } else { + // 构建查询条件:查询所有二级分类下的物种 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(SpeciesLibraryDO::getCategory, level2Ids.stream().map(String::valueOf).collect(Collectors.toList())); + queryWrapper.eq(SpeciesLibraryDO::getTenantId, String.valueOf(getLoginUser().getTenantId())); + + List allSpecies = speciesLibraryMapper.selectList(queryWrapper); + + // 按分类ID分组 + categoryToSpeciesMap = allSpecies.stream() + .collect(Collectors.groupingBy(SpeciesLibraryDO::getCategory)); + } + + List result = new ArrayList<>(); + for (TwoDictTreeRespVO lvl1 : level1Nodes) { + SpeciesThreeLevelTreeRespVO lvl1Vo = new SpeciesThreeLevelTreeRespVO(); + lvl1Vo.setName(lvl1.getName()); + lvl1Vo.setId(lvl1.getId().toString()); + List lvl2Vos = new ArrayList<>(); + + if (lvl1.getChildren() != null && !lvl1.getChildren().isEmpty()) { + // 二级按名称排序 + List lvl2Children = new ArrayList<>(lvl1.getChildren()); + lvl2Children.sort(java.util.Comparator.comparing(TwoDictTreeRespVO::getName, java.util.Comparator.nullsLast(String::compareTo))); + for (TwoDictTreeRespVO lvl2 : lvl2Children) { + SpeciesThreeLevelTreeRespVO lvl2Vo = new SpeciesThreeLevelTreeRespVO(); + lvl2Vo.setName(lvl2.getName()); + lvl2Vo.setId(lvl2.getId().toString()); + lvl2Vos.add(lvl2Vo); + } + } + lvl1Vo.setChildren(lvl2Vos); + result.add(lvl1Vo); + } + return result; + } + private String splitSpeciesName(String speciesName, int index) { if (speciesName == null) { return ""; diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/telemetry/DeviceTelemetryService.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/telemetry/DeviceTelemetryService.java new file mode 100644 index 00000000..fdd310cf --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/telemetry/DeviceTelemetryService.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.farm.service.telemetry; + +import cn.iocoder.yudao.module.farm.dal.dataobject.deviceinfo.DeviceInfoDO; +import cn.iocoder.yudao.module.farm.dal.mongo.telemetry.DeviceTelemetryDoc; +import cn.iocoder.yudao.module.farm.dal.mongo.telemetry.DeviceTelemetryRepository; +import cn.iocoder.yudao.module.farm.dal.mysql.deviceinfo.DeviceInfoMapper; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; + +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser; + +@Service +public class DeviceTelemetryService { + + @Resource + private DeviceTelemetryRepository telemetryRepository; + @Resource + private DeviceInfoMapper deviceInfoMapper; + + public void saveTelemetry(String deviceUniqueId, String payloadJson) { + String tenantId = String.valueOf(getLoginUser().getTenantId()); + + DeviceTelemetryDoc doc = new DeviceTelemetryDoc(); + doc.setTenantId(tenantId); + doc.setDeviceId(deviceUniqueId); + doc.setTs(System.currentTimeMillis()); + doc.setPayloadJson(payloadJson); + telemetryRepository.save(doc); + + DeviceInfoDO device = deviceInfoMapper.selectOne(DeviceInfoDO::getDeviceUniqueId, deviceUniqueId); + if (device != null) { + device.setDataImage(payloadJson); + deviceInfoMapper.updateById(device); + } + } +} + + diff --git a/yudao-module-farm/src/main/resources/mapper/personnelmanagement/SystemUserRoleMapper.xml b/yudao-module-farm/src/main/resources/mapper/personnelmanagement/SystemUserRoleMapper.xml new file mode 100644 index 00000000..15a4d650 --- /dev/null +++ b/yudao-module-farm/src/main/resources/mapper/personnelmanagement/SystemUserRoleMapper.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/PersonnelMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/PersonnelMapper.java index e593e51c..65f728d7 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/PersonnelMapper.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/PersonnelMapper.java @@ -7,4 +7,7 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface PersonnelMapper extends BaseMapperX { + default PersonnelDO selectByPhone(String mobile) { + return selectOne(PersonnelDO::getPhone, mobile); + } } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java index 638d3f6b..7299790c 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java @@ -176,6 +176,27 @@ public class AdminUserServiceImpl implements AdminUserService { // 2.1 更新用户 AdminUserDO updateObj = BeanUtils.toBean(updateReqVO, AdminUserDO.class); userMapper.updateById(updateObj); + AdminUserDO adminUserDO = userMapper.selectById(updateObj.getId()); + PersonnelDO userDo = personnelMapper.selectByPhone(adminUserDO.getMobile()); + if (updateObj.getNickname() != null) userDo.setName(updateObj.getNickname()); + if (updateObj.getMobile() != null) userDo.setPhone(updateObj.getMobile()); + if (updateObj.getDeptId() != null) userDo.setDepartment(updateObj.getDeptId().toString()); + if (updateObj.getTenantId() != null) userDo.setTenantId(updateObj.getTenantId().toString()); + if (updateObj.getAvatar() != null) userDo.setPicture(updateObj.getAvatar()); + userDo.setAccountStatus(0); + List userPostDOS = convertList(updateObj.getPostIds(), + postId -> new UserPostDO().setUserId(updateObj.getId()).setPostId(postId)); + String roles = ""; + for (UserPostDO up : userPostDOS) { + if (roles.length() > 0) { + roles += "," + up.getPostId(); + } else { + roles = up.getPostId().toString(); + } + } + userDo.setRole(roles); + personnelMapper.updateById(userDo); + // 2.2 更新岗位 updateUserPost(updateReqVO, updateObj); @@ -262,7 +283,8 @@ public class AdminUserServiceImpl implements AdminUserService { public void deleteUser(Long id) { // 1. 校验用户存在 AdminUserDO user = validateUserExists(id); - + AdminUserDO adminUserDO = userMapper.selectById(id); + personnelMapper.delete(PersonnelDO::getPhone, adminUserDO.getMobile()); // 2.1 删除用户 userMapper.deleteById(id); // 2.2 删除用户关联数据 diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml index 131d3937..4a2e2a15 100644 --- a/yudao-server/src/main/resources/application-dev.yaml +++ b/yudao-server/src/main/resources/application-dev.yaml @@ -122,6 +122,7 @@ lock4j: acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒 expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒 + --- #################### 监控相关配置 #################### # Actuator 监控端点的配置项 diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 3c0b3c88..765b0521 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -108,7 +108,7 @@ aj: cache-number: 1000 # local 缓存的阈值,达到这个值,清除缓存 timing-clear: 180 # local定时清除过期缓存(单位秒),设置为0代表不执行 type: blockPuzzle # 验证码类型 default 三种都实例化。blockPuzzle 滑块拼图、clickWord 文字点选、pictureWord 文本输入 - water-mark: 芋道源码 # 右下角水印文字(我的水印),可使用 https://tool.chinaz.com/tools/unicode.aspx 中文转 Unicode,Linux 可能需要转 unicode + water-mark: 江西云戈 # 右下角水印文字(我的水印),可使用 https://tool.chinaz.com/tools/unicode.aspx 中文转 Unicode,Linux 可能需要转 unicode interference-options: 0 # 滑动干扰项(0/1/2) req-frequency-limit-enable: false # 接口请求次数一分钟限制是否开启 true|false req-get-lock-limit: 5 # 验证失败 5 次,get接口锁定