充电枪编辑功能

This commit is contained in:
三丙
2025-09-09 18:25:55 +08:00
parent 74fec1e044
commit 7a78c8a62a
11 changed files with 239 additions and 79 deletions

View File

@@ -16,6 +16,7 @@ import sanbing.jcpp.app.adapter.request.StationUpdateRequest;
import sanbing.jcpp.app.adapter.response.ApiResponse;
import sanbing.jcpp.app.adapter.response.PageResponse;
import sanbing.jcpp.app.adapter.response.StationOption;
import sanbing.jcpp.app.adapter.response.StationPileCascaderOption;
import sanbing.jcpp.app.dal.entity.Station;
import sanbing.jcpp.app.exception.JCPPException;
import sanbing.jcpp.app.service.StationService;
@@ -104,4 +105,14 @@ public class StationController extends BaseController {
List<StationOption> options = stationService.searchStationOptions(keyword, page, size);
return ResponseEntity.ok(ApiResponse.success("查询成功", options));
}
/**
* 获取充电站-充电桩级联选择器数据(用于级联选择组件)
*/
@GetMapping("/pile-cascader")
public ResponseEntity<ApiResponse<List<StationPileCascaderOption>>> getStationPileCascaderOptions(
@RequestParam(required = false) String keyword) {
List<StationPileCascaderOption> options = stationService.getStationPileCascaderOptions(keyword);
return ResponseEntity.ok(ApiResponse.success("查询成功", options));
}
}

View File

@@ -18,5 +18,18 @@ public class GunUpdateRequest {
@NoXss
private String gunName;
@NotBlank(message = "枪号不能为空")
private String gunNo;
@NotBlank(message = "充电枪编码不能为空")
@NoXss
private String gunCode;
@NotBlank(message = "所属充电站不能为空")
private String stationId;
@NotBlank(message = "所属充电桩不能为空")
private String pileId;
private GunRunStatusEnum runStatus;
}

View File

@@ -0,0 +1,73 @@
/**
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
* 微信mohan_88888
* 抖音:程序员三丙
* 付费课程知识星球https://t.zsxq.com/aKtXo
*/
package sanbing.jcpp.app.adapter.response;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.UUID;
/**
* 充电站-充电桩级联选择器选项响应
* 用于Ant Design Cascader组件
*
* @author 九筒
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StationPileCascaderOption {
private String value; // 选项的值充电站ID或充电桩ID
private String label; // 显示的标签
private boolean isLeaf; // 是否为叶子节点
private List<StationPileCascaderOption> children; // 子选项(充电站下的充电桩)
// 额外信息
private String stationId; // 充电站ID当是充电桩选项时
private String stationName; // 充电站名称
private String stationCode; // 充电站编码
private String pileId; // 充电桩ID当是充电桩选项时
private String pileName; // 充电桩名称(当是充电桩选项时)
private String pileCode; // 充电桩编码(当是充电桩选项时)
/**
* 创建充电站选项
*/
public static StationPileCascaderOption createStationOption(UUID stationId, String stationName, String stationCode, List<StationPileCascaderOption> piles) {
StationPileCascaderOption option = new StationPileCascaderOption();
option.setValue(stationId.toString());
option.setLabel(stationName + " (" + stationCode + ")");
option.setLeaf(false);
option.setChildren(piles);
option.setStationId(stationId.toString());
option.setStationName(stationName);
option.setStationCode(stationCode);
return option;
}
/**
* 创建充电桩选项
*/
public static StationPileCascaderOption createPileOption(UUID stationId, String stationName, String stationCode,
UUID pileId, String pileName, String pileCode) {
StationPileCascaderOption option = new StationPileCascaderOption();
option.setValue(pileId.toString());
option.setLabel(pileName + " (" + pileCode + ")");
option.setLeaf(true);
option.setChildren(null);
option.setStationId(stationId.toString());
option.setStationName(stationName);
option.setStationCode(stationCode);
option.setPileId(pileId.toString());
option.setPileName(pileName);
option.setPileCode(pileCode);
return option;
}
}

View File

@@ -11,6 +11,7 @@ import sanbing.jcpp.app.adapter.request.StationQueryRequest;
import sanbing.jcpp.app.adapter.request.StationUpdateRequest;
import sanbing.jcpp.app.adapter.response.PageResponse;
import sanbing.jcpp.app.adapter.response.StationOption;
import sanbing.jcpp.app.adapter.response.StationPileCascaderOption;
import sanbing.jcpp.app.dal.entity.Station;
import sanbing.jcpp.app.exception.JCPPException;
@@ -58,4 +59,9 @@ public interface StationService {
* 搜索充电站选项列表(支持关键字搜索和分页)
*/
List<StationOption> searchStationOptions(String keyword, int page, int size);
/**
* 获取充电站-充电桩级联选择器数据(用于级联选择组件)
*/
List<StationPileCascaderOption> getStationPileCascaderOptions(String keyword);
}

View File

@@ -86,10 +86,10 @@ public class DefaultGunService implements GunService {
.createdTime(existingGun.getCreatedTime())
.updatedTime(LocalDateTime.now()) // 更新时设置更新时间
.gunName(request.getGunName())
.gunNo(existingGun.getGunNo()) // 编号不允许修改
.gunCode(existingGun.getGunCode()) // 编码不允许修改
.stationId(existingGun.getStationId()) // 所属充电站不允许修改
.pileId(existingGun.getPileId()) // 所属充电桩不允许修改
.gunNo(request.getGunNo()) // 允许修改枪号
.gunCode(request.getGunCode()) // 允许修改编码
.stationId(UUID.fromString(request.getStationId())) // 允许修改所属充电站
.pileId(UUID.fromString(request.getPileId())) // 允许修改所属充电桩
.additionalInfo(existingGun.getAdditionalInfo())
.version(existingGun.getVersion())
.build();

View File

@@ -17,6 +17,8 @@ import sanbing.jcpp.app.adapter.request.StationQueryRequest;
import sanbing.jcpp.app.adapter.request.StationUpdateRequest;
import sanbing.jcpp.app.adapter.response.PageResponse;
import sanbing.jcpp.app.adapter.response.StationOption;
import sanbing.jcpp.app.adapter.response.StationPileCascaderOption;
import sanbing.jcpp.app.dal.entity.Pile;
import sanbing.jcpp.app.dal.entity.Station;
import sanbing.jcpp.app.dal.mapper.PileMapper;
import sanbing.jcpp.app.dal.mapper.StationMapper;
@@ -27,6 +29,7 @@ import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
@@ -190,4 +193,55 @@ public class DefaultStationService implements StationService {
))
.collect(Collectors.toList());
}
@Override
public List<StationPileCascaderOption> getStationPileCascaderOptions(String keyword) {
// 查询充电站
QueryWrapper<Station> stationWrapper = new QueryWrapper<>();
stationWrapper.select("id", "station_name", "station_code");
// 如果有关键字,按站名或编码模糊搜索
if (StringUtils.hasText(keyword)) {
stationWrapper.and(w -> w.like("station_name", keyword)
.or()
.like("station_code", keyword));
}
stationWrapper.orderByAsc("station_name");
List<Station> stations = stationMapper.selectList(stationWrapper);
if (stations.isEmpty()) {
return List.of();
}
// 查询所有充电桩
QueryWrapper<Pile> pileWrapper = new QueryWrapper<>();
pileWrapper.select("id", "pile_name", "pile_code", "station_id")
.in("station_id", stations.stream().map(Station::getId).collect(Collectors.toList()))
.orderByAsc("pile_name");
List<Pile> piles = pileMapper.selectList(pileWrapper);
// 按充电站ID分组充电桩
Map<UUID, List<Pile>> pilesByStation = piles.stream()
.collect(Collectors.groupingBy(Pile::getStationId));
// 构建级联选择器数据
return stations.stream()
.map(station -> {
List<Pile> stationPiles = pilesByStation.getOrDefault(station.getId(), List.of());
List<StationPileCascaderOption> pileOptions = stationPiles.stream()
.map(pile -> StationPileCascaderOption.createPileOption(
station.getId(), station.getStationName(), station.getStationCode(),
pile.getId(), pile.getPileName(), pile.getPileCode()
))
.collect(Collectors.toList());
return StationPileCascaderOption.createStationOption(
station.getId(), station.getStationName(), station.getStationCode(), pileOptions
);
})
.collect(Collectors.toList());
}
}