fix (farm): 大屏

- 大屏模拟数据维护
This commit is contained in:
达富斌
2025-11-21 00:06:16 +08:00
parent c99967d0b9
commit e430062aa5
14 changed files with 320 additions and 15 deletions

View File

@@ -24,6 +24,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
@@ -137,6 +138,10 @@ public class DigitalCockpitController {
public CommonResult<List<YieldStatisticsRespVO>> getYieldStatisticsInfo(@RequestParam("baseId") String baseId, public CommonResult<List<YieldStatisticsRespVO>> getYieldStatisticsInfo(@RequestParam("baseId") String baseId,
@RequestParam("year") String year) { @RequestParam("year") String year) {
List<YieldStatisticsRespVO> res = productionPlanService.getCultivatingYieldInfo(baseId, year); List<YieldStatisticsRespVO> res = productionPlanService.getCultivatingYieldInfo(baseId, year);
res = Arrays.asList(
new YieldStatisticsRespVO("红玫瑰",10000,20000),
new YieldStatisticsRespVO("褚橙",25000,50000)
);
return success(res); return success(res);
} }

View File

@@ -6,10 +6,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.farm.controller.admin.managementcenter.largescreen.foundationinfo.vo.FoundationInfoPageReqVO; import cn.iocoder.yudao.module.farm.controller.admin.managementcenter.largescreen.foundationinfo.vo.*;
import cn.iocoder.yudao.module.farm.controller.admin.managementcenter.largescreen.foundationinfo.vo.FoundationInfoRespVO;
import cn.iocoder.yudao.module.farm.controller.admin.managementcenter.largescreen.foundationinfo.vo.FoundationInfoSaveReqVO;
import cn.iocoder.yudao.module.farm.dal.dataobject.foundationinfo.FoundationInfoDO; import cn.iocoder.yudao.module.farm.dal.dataobject.foundationinfo.FoundationInfoDO;
import cn.iocoder.yudao.module.farm.service.foundationinfo.CockpitMockInfoService;
import cn.iocoder.yudao.module.farm.service.foundationinfo.FoundationInfoService; import cn.iocoder.yudao.module.farm.service.foundationinfo.FoundationInfoService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
@@ -34,6 +33,8 @@ public class FoundationInfoController {
@Resource @Resource
private FoundationInfoService foundationInfoService; private FoundationInfoService foundationInfoService;
@Resource
private CockpitMockInfoService cockpitMockInfoService;
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "创建基础信息") @Operation(summary = "创建基础信息")
@@ -93,17 +94,16 @@ public class FoundationInfoController {
@GetMapping("/data-toggle/get") @GetMapping("/data-toggle/get")
@Operation(summary = "数据切换-获取") @Operation(summary = "数据切换-获取")
@Parameter(name = "data", description = "数据", required = true) @Parameter(name = "baseId", description = "数据", required = true)
public CommonResult<String> getDataToggle(@RequestParam("data") String data) { public CommonResult<List<DataToggleRespVO>> getDataToggle(@RequestParam("baseId") String baseId) {
String res = ""; return success(cockpitMockInfoService.getDataToggle(baseId));
return success(res);
} }
@PostMapping("/data-toggle/create") @PostMapping("/data-toggle/create")
@Operation(summary = "数据切换-保存") @Operation(summary = "数据切换-保存")
@Parameter(name = "data", description = "数据", required = true) public CommonResult<String> createDataToggle(@Valid @RequestBody List<DataToggleReqVO> createReqVO) {
public CommonResult<String> createDataToggle(@RequestParam("data") String data) { cockpitMockInfoService.createDataToggle(createReqVO);
return success("success"); return success("success");
} }
} }

View File

@@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.farm.controller.admin.managementcenter.largescreen.foundationinfo.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @description: TODO
* @author: binda
* @date: 2025/11/20 22:26
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DataToggleReqVO {
private String baseId;
private String flag;
private String type;
private Object data;
}

View File

@@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.farm.controller.admin.managementcenter.largescreen.foundationinfo.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @description: TODO
* @author: binda
* @date: 2025/11/20 22:26
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DataToggleRespVO {
private String id;
private String baseId;
private String flag;
private String type;
private Object data;
}

View File

@@ -0,0 +1,69 @@
package cn.iocoder.yudao.module.farm.dal.dataobject.foundationinfo;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.*;
/**
* @description: 驾驶舱模拟数据
* @author: binda
* @date: 2025/11/20 22:50
*/
@TableName("farm_cockpit_mock_info")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CockpitMockInfoDO extends BaseDO {
/**
* 基础id
*/
private String id;
/**
* 数据维护开关 (1: 开; 0: 关;)
*/
private String flag;
/**
* 数据类型
*/
private String type;
/**
* mock数据
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private String jsonData;
/**
* 基地id
*/
private String baseId;
/**
* 基地
*/
private String baseName;
/**
* 地块ID
*/
private String plotId;
/**
* 地块
*/
private String plotName;
/**
* 租户id
*/
private String tenantId;
}

View File

@@ -0,0 +1,17 @@
package cn.iocoder.yudao.module.farm.dal.mysql.foundationinfo;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.farm.dal.dataobject.foundationinfo.CockpitMockInfoDO;
import org.apache.ibatis.annotations.Mapper;
/**
* @description:
* @author: binda
* @date: 2025/11/20 22:53
*/
@Mapper
public interface CockpitMockInfoMapper extends BaseMapperX<CockpitMockInfoDO> {
}

View File

@@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.farm.service.foundationinfo;
import cn.iocoder.yudao.module.farm.controller.admin.managementcenter.largescreen.foundationinfo.vo.DataToggleReqVO;
import cn.iocoder.yudao.module.farm.controller.admin.managementcenter.largescreen.foundationinfo.vo.DataToggleRespVO;
import java.util.List;
/**
* @description:
* @author: binda
* @date: 2025/11/20 22:56
*/
public interface CockpitMockInfoService {
void createDataToggle(List<DataToggleReqVO> createReqVO);
List<DataToggleRespVO> getDataToggle(String baseId);
}

View File

@@ -0,0 +1,109 @@
package cn.iocoder.yudao.module.farm.service.foundationinfo;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import cn.idev.excel.util.StringUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.farm.controller.admin.managementcenter.largescreen.foundationinfo.vo.DataToggleReqVO;
import cn.iocoder.yudao.module.farm.controller.admin.managementcenter.largescreen.foundationinfo.vo.DataToggleRespVO;
import cn.iocoder.yudao.module.farm.dal.dataobject.foundationinfo.CockpitMockInfoDO;
import cn.iocoder.yudao.module.farm.dal.mysql.foundationinfo.CockpitMockInfoMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @description: TODO
* @author: binda
* @date: 2025/11/20 22:57
*/
@Service
public class CockpitMockInfoServiceImpl implements CockpitMockInfoService {
@Resource
private CockpitMockInfoMapper cockpitMockInfoMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public void createDataToggle(List<DataToggleReqVO> createReqVO) {
if (CollectionUtils.isEmpty(createReqVO)) {
return;
}
// 1. 处理 baseId 为 null 的情况,设置为 "0"
for (DataToggleReqVO vo : createReqVO) {
if (vo.getBaseId() == null) {
vo.setBaseId("0");
}
}
// 2. 获取所有需要处理的 baseId(包括全局数据 baseId=0)
Set<String> baseIds = createReqVO.stream()
.map(DataToggleReqVO::getBaseId)
.collect(Collectors.toSet());
// 3. 删除这些 baseId 对应的所有现有数据
if (!baseIds.isEmpty()) {
cockpitMockInfoMapper.delete(new LambdaQueryWrapper<CockpitMockInfoDO>()
.in(CockpitMockInfoDO::getBaseId, baseIds));
}
// 4. 保存新的数据
List<CockpitMockInfoDO> saveList = new ArrayList<>();
for (DataToggleReqVO vo : createReqVO) {
CockpitMockInfoDO entity = new CockpitMockInfoDO();
entity.setId(IdUtil.fastUUID());
entity.setBaseId(vo.getBaseId());
entity.setFlag(vo.getFlag());
entity.setType(vo.getType());
// 将 data 对象转换为 JSON 字符串
if (vo.getData() != null) {
entity.setJsonData(JSONUtil.toJsonStr(vo.getData()));
}
saveList.add(entity);
}
// 5. 批量插入新数据
if (!saveList.isEmpty()) {
cockpitMockInfoMapper.insertBatch(saveList);
}
}
@Override
public List<DataToggleRespVO> getDataToggle(String baseId) {
// 查询数据库记录
List<CockpitMockInfoDO> entityList = cockpitMockInfoMapper.selectList(
new LambdaQueryWrapper<CockpitMockInfoDO>()
.eq(CockpitMockInfoDO::getBaseId, baseId)
);
// 转换为响应VO
List<DataToggleRespVO> result = new ArrayList<>();
for (CockpitMockInfoDO entity : entityList) {
DataToggleRespVO vo = BeanUtils.toBean(entity, DataToggleRespVO.class);
// 特殊处理 jsonData 到 data 的转换
if (StringUtils.isNotBlank(entity.getJsonData())) {
try {
Object data = JSONUtil.parse(entity.getJsonData());
vo.setData(data);
} catch (Exception e) {
vo.setData(entity.getJsonData());
}
}
result.add(vo);
}
return result;
}
}

View File

@@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.module.farm.controller.admin.managementcenter.largescreen.foundationinfo.vo.FoundationInfoPageReqVO; import cn.iocoder.yudao.module.farm.controller.admin.managementcenter.largescreen.foundationinfo.vo.FoundationInfoPageReqVO;
import cn.iocoder.yudao.module.farm.controller.admin.managementcenter.largescreen.foundationinfo.vo.FoundationInfoSaveReqVO; import cn.iocoder.yudao.module.farm.controller.admin.managementcenter.largescreen.foundationinfo.vo.FoundationInfoSaveReqVO;
import cn.iocoder.yudao.module.farm.dal.dataobject.foundationinfo.FoundationInfoDO; import cn.iocoder.yudao.module.farm.dal.dataobject.foundationinfo.FoundationInfoDO;
import cn.iocoder.yudao.module.farm.dal.mysql.foundationinfo.CockpitMockInfoMapper;
import cn.iocoder.yudao.module.farm.dal.mysql.foundationinfo.FoundationInfoMapper; import cn.iocoder.yudao.module.farm.dal.mysql.foundationinfo.FoundationInfoMapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -29,6 +30,8 @@ public class FoundationInfoServiceImpl implements FoundationInfoService {
@Resource @Resource
private FoundationInfoMapper foundationInfoMapper; private FoundationInfoMapper foundationInfoMapper;
@Resource
private CockpitMockInfoMapper cockpitMockMapper;
@Override @Override
public String createFoundationInfo(FoundationInfoSaveReqVO createReqVO) { public String createFoundationInfo(FoundationInfoSaveReqVO createReqVO) {

View File

@@ -475,7 +475,7 @@ public class ProductionPlanServiceImpl implements ProductionPlanService {
@Override @Override
public List<YieldStatisticsRespVO> getCultivatingYieldInfo(String baseId, String year) { public List<YieldStatisticsRespVO> getCultivatingYieldInfo(String baseId, String year) {
return null; return Collections.EMPTY_LIST;
} }
@Override @Override

View File

@@ -0,0 +1,13 @@
<?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="cn.iocoder.yudao.module.farm.dal.mysql.foundationinfo.CockpitMockInfoMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>

View File

@@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.security.config.SecurityProperties; import cn.iocoder.yudao.framework.security.config.SecurityProperties;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*; import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.diy.LoginForTenantReqVO; import cn.iocoder.yudao.module.system.controller.admin.auth.vo.diy.LoginForTenantReqVO;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.diy.TenantRespVO; import cn.iocoder.yudao.module.system.controller.admin.auth.vo.diy.TenantRespVO;
@@ -42,6 +43,7 @@ import java.util.Set;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - 认证") @Tag(name = "管理后台 - 认证")
@@ -86,11 +88,13 @@ public class AuthController {
@PermitAll @PermitAll
@Operation(summary = "登出系统") @Operation(summary = "登出系统")
public CommonResult<Boolean> logout(HttpServletRequest request) { public CommonResult<Boolean> logout(HttpServletRequest request) {
log.info("logout 之前: tenantId ==> {}", TenantContextHolder.getTenantId() );
String token = SecurityFrameworkUtils.obtainAuthorization(request, String token = SecurityFrameworkUtils.obtainAuthorization(request,
securityProperties.getTokenHeader(), securityProperties.getTokenParameter()); securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
if (StrUtil.isNotBlank(token)) { if (StrUtil.isNotBlank(token)) {
authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType()); authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType());
} }
log.info("logout 之后: tenantId ==> {}", TenantContextHolder.getTenantId() );
return success(true); return success(true);
} }
@@ -166,8 +170,12 @@ public class AuthController {
@PostMapping("/login-by-tenant") @PostMapping("/login-by-tenant")
@Operation(summary = "登录 (切换租户之后调用)") @Operation(summary = "登录 (切换租户之后调用)")
public CommonResult<AuthLoginRespVO> getPhoneNumber4Login(@RequestBody @Valid TenantTokenReqVO reqVO) { public CommonResult<AuthLoginRespVO> getPhoneNumber4Login(@RequestBody @Valid TenantTokenReqVO reqVO) {
// 强行清楚 本地线程 中的租户ID , 请设置为当前将要登录的租户ID
TenantContextHolder.clear();
TenantContextHolder.setTenantId(Long.valueOf(reqVO.getTenantId()));
AuthLoginRespVO login = authService.getPhoneNumber4Login(reqVO); AuthLoginRespVO login = authService.getPhoneNumber4Login(reqVO);
if (login != null) { if (login != null) {
// log.info("tenantId ===> {}", getLoginUser().getTenantId());
return success(login); return success(login);
} else { } else {
return error(405, "该手机号不是平台用户"); return error(405, "该手机号不是平台用户");

View File

@@ -251,7 +251,8 @@ public class AdminAuthServiceImpl implements AdminAuthService {
createLoginLog(userId, username, logType, LoginResultEnum.SUCCESS); createLoginLog(userId, username, logType, LoginResultEnum.SUCCESS);
// 确保租户上下文中有正确的租户ID // 确保租户上下文中有正确的租户ID
ensureTenantContext(userId); // ensureTenantContext(userId);
ensureTenantContextPlus(userId);
// 创建访问令牌 // 创建访问令牌
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(userId, getUserType().getValue(), OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(userId, getUserType().getValue(),
@@ -294,6 +295,19 @@ public class AdminAuthServiceImpl implements AdminAuthService {
} }
} }
private void ensureTenantContextPlus(Long userId) {
// 如果TenantContextHolder中没有租户ID,尝试从用户信息中获取并设置
Long currentTenantId = TenantContextHolder.getTenantId();
// 设置到租户上下文中
if (currentTenantId != null) {
TenantContextHolder.setTenantId(currentTenantId);
log.info("[ensureTenantContext][设置租户上下文: {}]", currentTenantId);
} else {
log.warn("[ensureTenantContext][用户({}) 无法获取租户ID,可能导致登录后无法获取租户信息]", userId);
}
}
@Override @Override
public AuthLoginRespVO refreshToken(String refreshToken) { public AuthLoginRespVO refreshToken(String refreshToken) {
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, OAuth2ClientConstants.CLIENT_ID_DEFAULT); OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, OAuth2ClientConstants.CLIENT_ID_DEFAULT);

View File

@@ -694,6 +694,9 @@ public class AdminUserServiceImpl implements AdminUserService {
.collect(Collectors.toList()); .collect(Collectors.toList());
Set<Long> userIds = permissionService.getUserRoleIdListByRoleId(roleIds); Set<Long> userIds = permissionService.getUserRoleIdListByRoleId(roleIds);
if (null == userIds || userIds.size() == 0) {
return Collections.EMPTY_LIST;
}
List<AdminUserDO> userList = userMapper.selectByIds(userIds); List<AdminUserDO> userList = userMapper.selectByIds(userIds);
return userList; return userList;