diff --git a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/controller/MetroBigActivityController.java b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/controller/MetroBigActivityController.java new file mode 100644 index 0000000..928bf1e --- /dev/null +++ b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/controller/MetroBigActivityController.java @@ -0,0 +1,389 @@ +package net.juntech.modules.ysdp.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import com.jeeplus.aop.logging.annotation.ApiLog; +import com.jeeplus.common.redis.RedisUtils; +import com.jeeplus.core.excel.EasyExcelUtils; +import com.jeeplus.core.excel.ExcelOptions; +import com.jeeplus.core.excel.annotation.ExportMode; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import net.juntech.modules.ysdp.domain.MetroBigActivity; +import net.juntech.modules.ysdp.service.MetroBigActivityService; +import net.juntech.modules.ysdp.service.dto.MetroBigActivityDTO; +import net.juntech.modules.ysdp.service.mapstruct.MetroBigActivityWrapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +/** + * 重大活动Controller + * @author claude + * @version 2026-08-27 + */ +@Tag(name = "重大活动") +@RestController +@RequestMapping(value = "/ysdp/metroBigActivity") +public class MetroBigActivityController { + + @Autowired + private MetroBigActivityService metroBigActivityService; + + @Autowired + private MetroBigActivityWrapper metroBigActivityWrapper; + + @Autowired + private RedisUtils redisUtils; + + @Autowired + private net.juntech.modules.ysdp.service.YsYunyingService ysYunyingService; + + /** + * 重大活动列表数据 + */ + @ApiLog("查询重大活动列表数据") + @Operation(summary = "查询重大活动列表数据") + @PreAuthorize("hasAuthority('ysdp:metroBigActivity:list')") + @GetMapping("list") + public ResponseEntity> list(MetroBigActivityDTO dto, + Page page) throws Exception { + QueryWrapper queryWrapper = new QueryWrapper<>(); + // 逻辑删除过滤 + queryWrapper.and(qw -> qw.isNull("del_flag").or().ne("del_flag", "1")); + if (dto.getActivityName() != null && !dto.getActivityName().trim().isEmpty()) { + queryWrapper.like("activity_name", dto.getActivityName()); + } + if (dto.getMetroLine() != null && !dto.getMetroLine().trim().isEmpty()) { + queryWrapper.eq("metro_line", dto.getMetroLine()); + } + if (dto.getMetroStation() != null && !dto.getMetroStation().trim().isEmpty()) { + queryWrapper.eq("metro_station", dto.getMetroStation()); + } + // 活动月份筛选(跨月活动也能被匹配) + if (dto.getActivityMonth() != null && !dto.getActivityMonth().trim().isEmpty()) { + String month = dto.getActivityMonth(); + queryWrapper.and(qw -> qw + .apply("DATE_FORMAT(start_date, '%Y-%m') = {0}", month) + .or().apply("DATE_FORMAT(end_date, '%Y-%m') = {0}", month) + .or().apply("(start_date <= LAST_DAY(STR_TO_DATE(CONCAT({0}, '-01'), '%Y-%m-%d')) " + + "AND end_date >= STR_TO_DATE(CONCAT({0}, '-01'), '%Y-%m-%d'))", month) + ); + } + queryWrapper.orderByDesc("start_date"); + IPage result = metroBigActivityService.pageWithName(page, queryWrapper); + // 填充线路名/车站名/状态字段(跨库单独查 ysdp 数据源) + fillLineAndStationName(result.getRecords()); + if (result.getRecords() != null) { + for (MetroBigActivityDTO record : result.getRecords()) { + record.setStatus(calcStatus(record.getStartDate(), record.getEndDate())); + } + } + return ResponseEntity.ok(result); + } + + /** + * 跨库注入线路名、车站名: + * - metro_line 存 ys_line.id,通过 YsYunyingService.getLinesByIds 批量查 → 拿 name 塞入 metroLineName + * - metro_station 存 ys_station.station_id,通过 getStationsByStationIds 批量查 → 拿 name 塞入 metroStationName + */ + private void fillLineAndStationName(List list) { + if (list == null || list.isEmpty()) { + return; + } + // 收集要查的 id + java.util.Set lineIds = new java.util.HashSet<>(); + java.util.Set stationIds = new java.util.HashSet<>(); + for (MetroBigActivityDTO d : list) { + if (d.getMetroLine() != null && !d.getMetroLine().isEmpty()) { + lineIds.add(d.getMetroLine()); + } + if (d.getMetroStation() != null && !d.getMetroStation().isEmpty()) { + stationIds.add(d.getMetroStation()); + } + } + // 批量查线路(复用 YsYunyingDTO:stationId=ys_line.id, stationName=name) + java.util.Map lineNameMap = new java.util.HashMap<>(); + if (!lineIds.isEmpty()) { + for (net.juntech.modules.ysdp.service.dto.YsYunyingDTO line : ysYunyingService.getLinesByIds(lineIds)) { + lineNameMap.put(line.getStationId(), line.getStationName()); + } + } + // 批量查车站 + java.util.Map stationNameMap = new java.util.HashMap<>(); + if (!stationIds.isEmpty()) { + for (net.juntech.modules.ysdp.service.dto.YsYunyingDTO st : ysYunyingService.getStationsByStationIds(stationIds)) { + stationNameMap.put(st.getStationId(), st.getStationName()); + } + } + // 回填 + for (MetroBigActivityDTO d : list) { + d.setMetroLineName(lineNameMap.get(d.getMetroLine())); + d.setMetroStationName(stationNameMap.get(d.getMetroStation())); + } + } + + /** + * 根据Id获取重大活动数据 + */ + @ApiLog("根据Id获取重大活动数据") + @Operation(summary = "根据Id获取重大活动数据") + @PreAuthorize("hasAnyAuthority('ysdp:metroBigActivity:view','ysdp:metroBigActivity:add','ysdp:metroBigActivity:edit')") + @GetMapping("queryById") + public ResponseEntity queryById(String id) { + return ResponseEntity.ok(metroBigActivityWrapper.toDTO(metroBigActivityService.getById(id))); + } + + /** + * 保存重大活动 + */ + @ApiLog("保存重大活动") + @Operation(summary = "保存重大活动") + @PreAuthorize("hasAnyAuthority('ysdp:metroBigActivity:add','ysdp:metroBigActivity:edit')") + @PostMapping("save") + public ResponseEntity save(@Valid @RequestBody MetroBigActivityDTO dto) { + // 校验:结束日期 >= 开始日期 + if (dto.getEndDate() != null && dto.getStartDate() != null + && dto.getEndDate().before(dto.getStartDate())) { + return ResponseEntity.badRequest().body("结束日期不能早于开始日期"); + } + metroBigActivityService.saveOrUpdate(metroBigActivityWrapper.toEntity(dto)); + return ResponseEntity.ok("保存重大活动成功"); + } + + /** + * 删除重大活动(逻辑删除) + */ + @ApiLog("删除重大活动") + @Operation(summary = "删除重大活动") + @PreAuthorize("hasAuthority('ysdp:metroBigActivity:del')") + @DeleteMapping("delete") + public ResponseEntity delete(String ids) { + String[] idArray = ids.split(","); + // 逻辑删除 + metroBigActivityService.removeByIds(Lists.newArrayList(idArray)); + return ResponseEntity.ok("删除重大活动成功"); + } + + /** + * 导出重大活动数据 + */ + @ApiLog("导出重大活动数据") + @Operation(summary = "导出重大活动数据") + @PreAuthorize("hasAnyAuthority('ysdp:metroBigActivity:export')") + @GetMapping("export") + public void exportFile(MetroBigActivityDTO dto, Page page, + ExcelOptions options, HttpServletResponse response) throws Exception { + String fileName = options.getFilename(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + // 逻辑删除过滤 + queryWrapper.and(qw -> qw.isNull("del_flag").or().ne("del_flag", "1")); + if (dto.getActivityName() != null && !dto.getActivityName().trim().isEmpty()) { + queryWrapper.like("activity_name", dto.getActivityName()); + } + if (dto.getMetroLine() != null && !dto.getMetroLine().trim().isEmpty()) { + queryWrapper.eq("metro_line", dto.getMetroLine()); + } + if (dto.getMetroStation() != null && !dto.getMetroStation().trim().isEmpty()) { + queryWrapper.eq("metro_station", dto.getMetroStation()); + } + if (ExportMode.current.equals(options.getMode())) { + // 导出当前页 + } else if (ExportMode.selected.equals(options.getMode())) { + queryWrapper.in("id", options.getSelectIds()); + } else { + page.setSize(-1); + page.setCurrent(0); + } + List result = metroBigActivityService.page(page, queryWrapper).getRecords(); + EasyExcelUtils.newInstance(metroBigActivityService, metroBigActivityWrapper) + .exportExcel(result, options.getSheetName(), MetroBigActivityDTO.class, + fileName, options.getExportFields(), response); + } + + /** + * 导入重大活动数据(支持按线路名/车站名自动匹配) + */ + @ApiLog("导入重大活动数据") + @Operation(summary = "导入重大活动数据") + @PreAuthorize("hasAnyAuthority('ysdp:metroBigActivity:import')") + @PostMapping("import") + public ResponseEntity importFile(MultipartFile file) throws Exception { + // 先用 EasyExcel 读取 Excel + List list = com.alibaba.excel.EasyExcel.read(file.getInputStream()) + .head(MetroBigActivityDTO.class) + .sheet() + .doReadSync(); + + if (list == null || list.isEmpty()) { + return ResponseEntity.ok("导入数据为空"); + } + + // 批量查询线路、车站的映射(名称 → id/station_id) + List allLines = ysYunyingService.getLineList(); + java.util.Map lineNameToId = new java.util.HashMap<>(); + for (net.juntech.modules.ysdp.service.dto.YsYunyingDTO line : allLines) { + // 支持 "7号线" 或 "7" 都能匹配 + lineNameToId.put(line.getName(), line.getId()); + if (line.getName() != null && line.getName().endsWith("号线")) { + lineNameToId.put(line.getName().replace("号线", ""), line.getId()); + } + } + + // 拿所有车站(跨线路) + java.util.Map stationNameToStationId = new java.util.HashMap<>(); + for (net.juntech.modules.ysdp.service.dto.YsYunyingDTO line : allLines) { + List stations = + ysYunyingService.getStationsByLineDbId(line.getId()); + for (net.juntech.modules.ysdp.service.dto.YsYunyingDTO st : stations) { + stationNameToStationId.put(st.getStationName(), st.getStationId()); + } + } + + // 转换:名称 → id + int successCount = 0; + StringBuilder errors = new StringBuilder(); + for (int i = 0; i < list.size(); i++) { + MetroBigActivityDTO dto = list.get(i); + try { + // 线路名 → ys_line.id + String lineId = lineNameToId.get(dto.getMetroLine()); + if (lineId == null) { + errors.append("第").append(i + 2).append("行:线路'").append(dto.getMetroLine()).append("'未找到
"); + continue; + } + // 车站名 → ys_station.station_id + String stationId = stationNameToStationId.get(dto.getMetroStation()); + if (stationId == null) { + errors.append("第").append(i + 2).append("行:车站'").append(dto.getMetroStation()).append("'未找到
"); + continue; + } + dto.setMetroLine(lineId); + dto.setMetroStation(stationId); + + // 保存 + MetroBigActivity entity = metroBigActivityWrapper.toEntity(dto); + metroBigActivityService.saveOrUpdate(entity); + successCount++; + } catch (Exception ex) { + errors.append("第").append(i + 2).append("行:保存失败 - ").append(ex.getMessage()).append("
"); + } + } + + String msg = "成功导入 " + successCount + " 条数据"; + if (errors.length() > 0) { + msg += "
失败信息:
" + errors.toString(); + } + return ResponseEntity.ok(msg); + } + + /** + * 下载导入模板(带示例数据) + */ + @ApiLog("下载导入重大活动数据模板") + @Operation(summary = "下载导入重大活动数据模板") + @PreAuthorize("hasAnyAuthority('ysdp:metroBigActivity:import')") + @GetMapping("import/template") + public void importFileTemplate(HttpServletResponse response) throws IOException { + String fileName = "重大活动数据导入模板.xlsx"; + List list = Lists.newArrayList(); + + // 添加示例数据(用户可以直接参考填写) + MetroBigActivityDTO example1 = new MetroBigActivityDTO(); + example1.setActivityName("CBE中国美容博览会"); + example1.setMetroLine("7号线"); + example1.setMetroStation("花木路"); + try { + java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd"); + example1.setStartDate(sdf.parse("2026-05-12")); + example1.setEndDate(sdf.parse("2026-05-14")); + } catch (Exception e) { + // ignore + } + example1.setVenue("新国际博览中心"); + example1.setRemark("示例:大型展会"); + + MetroBigActivityDTO example2 = new MetroBigActivityDTO(); + example2.setActivityName("上海国际车展"); + example2.setMetroLine("2号线"); + example2.setMetroStation("徐泾东"); + try { + java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd"); + example2.setStartDate(sdf.parse("2026-04-21")); + example2.setEndDate(sdf.parse("2026-04-28")); + } catch (Exception e) { + // ignore + } + example2.setVenue("国家会展中心"); + example2.setRemark("示例:国际A级车展"); + + list.add(example1); + list.add(example2); + + EasyExcelUtils.newInstance(metroBigActivityService, metroBigActivityWrapper) + .exportExcel(list, "重大活动数据", MetroBigActivityDTO.class, fileName, null, response); + } + + /** + * 获取所有线路(用于表单下拉) + * 数据源:juntech_ysdp(@DS("ysdp")),与单站客流查询同源 + * 返回:id=ys_line.id, lineId=ys_line.line_id, stationName=ys_line.name + */ + @ApiLog("获取所有线路") + @Operation(summary = "获取所有线路") + @GetMapping("lineOptions") + public ResponseEntity> lineOptions() { + return ResponseEntity.ok(ysYunyingService.getLineList()); + } + + /** + * 根据线路主键 id 获取车站列表(用于表单下拉联动) + * 数据源:juntech_ysdp(@DS("ysdp")) + * 返回:stationId=ys_station.station_id(业务ID), stationName=ys_station.name + */ + @ApiLog("根据线路获取车站") + @Operation(summary = "根据线路获取车站") + @GetMapping("stationOptions") + public ResponseEntity> stationOptions(String lineId) { + return ResponseEntity.ok(ysYunyingService.getStationsByLineDbId(lineId)); + } + + /** + * 根据开始/结束日期实时计算活动状态 + * @return 未开始 / 进行中 / 已结束 + */ + private String calcStatus(Date startDate, Date endDate) { + if (startDate == null || endDate == null) { + return ""; + } + try { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + String todayStr = sdf.format(new Date()); + Date today = sdf.parse(todayStr); + String startStr = sdf.format(startDate); + String endStr = sdf.format(endDate); + Date start = sdf.parse(startStr); + Date end = sdf.parse(endStr); + if (today.before(start)) { + return "未开始"; + } + if (today.after(end)) { + return "已结束"; + } + return "进行中"; + } catch (Exception e) { + return ""; + } + } +} diff --git a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/controller/TrafficApiController.java b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/controller/TrafficApiController.java index b27bfbb..00f9b37 100644 --- a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/controller/TrafficApiController.java +++ b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/controller/TrafficApiController.java @@ -42,6 +42,9 @@ public class TrafficApiController extends BaseApiController { @Autowired private YsYunyingMaxService ysYunyingMaxService; + @Autowired + private net.juntech.modules.ysdp.service.MetroBigActivityService metroBigActivityService; + /** * 客运页面重点关注的线路列表 */ @@ -331,6 +334,129 @@ public class TrafficApiController extends BaseApiController { return okJsonResponse(resultObj, cacheKey); } + /** + * 大屏查询:根据线路、车站、月份查询重大活动列表 + * 每条数据带实时计算的活动状态(未开始/进行中/已结束) + */ + @ApiLog("获取重大活动清单") + @Operation(summary = "获取重大活动清单") + @PostMapping("getBigActivityList/v1") + public ResponseEntity getBigActivityList( + @RequestParam(value = "metroLine", required = false, defaultValue = "") String metroLine, + @RequestParam(value = "metroStation", required = false, defaultValue = "") String metroStation, + @RequestParam(value = "activityMonth", required = false, defaultValue = "") String activityMonth, + HttpServletRequest request) { + if (!checkRequest(request)) { + return checkResult; + } + String cacheKey = Constant.API_CACHE_NAME_TRAFFIC_BIG_ACTIVITY + + metroLine + "_" + metroStation + "_" + activityMonth; + JSONArray resultArray = new JSONArray(); + try { + if (useCache(cacheKey, request)) { + resultArray = redisUtils.getJSONArray(cacheKey); + } else { + List list = + metroBigActivityService.queryActivityForScreen(metroLine, metroStation, activityMonth); + + // 跨库注入线路名/车站名(ys_line / ys_station 在 juntech_ysdp 库) + java.util.Set lineIds = new java.util.HashSet<>(); + java.util.Set stationIds = new java.util.HashSet<>(); + for (net.juntech.modules.ysdp.service.dto.MetroBigActivityDTO d : list) { + if (d.getMetroLine() != null && !d.getMetroLine().isEmpty()) lineIds.add(d.getMetroLine()); + if (d.getMetroStation() != null && !d.getMetroStation().isEmpty()) stationIds.add(d.getMetroStation()); + } + java.util.Map lineNameMap = new java.util.HashMap<>(); + if (!lineIds.isEmpty()) { + for (YsYunyingDTO line : ysYunyingService.getLinesByIds(lineIds)) { + lineNameMap.put(line.getStationId(), line.getStationName()); + } + } + java.util.Map stationNameMap = new java.util.HashMap<>(); + if (!stationIds.isEmpty()) { + for (YsYunyingDTO s : ysYunyingService.getStationsByStationIds(stationIds)) { + stationNameMap.put(s.getStationId(), s.getStationName()); + } + } + for (net.juntech.modules.ysdp.service.dto.MetroBigActivityDTO d : list) { + d.setMetroLineName(lineNameMap.get(d.getMetroLine())); + d.setMetroStationName(stationNameMap.get(d.getMetroStation())); + } + + java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd"); + java.util.Date todayDate; + try { + todayDate = sdf.parse(sdf.format(new java.util.Date())); + } catch (Exception ex) { + todayDate = new java.util.Date(); + } + + // 先收集到 List,计算状态并排序 + java.util.List tempList = new java.util.ArrayList<>(); + for (net.juntech.modules.ysdp.service.dto.MetroBigActivityDTO item : list) { + JSONObject obj = new JSONObject(); + obj.put("id", item.getId()); + obj.put("activityName", item.getActivityName()); + obj.put("metroLine", item.getMetroLine()); + obj.put("metroLineName", item.getMetroLineName()); + obj.put("metroStation", item.getMetroStation()); + obj.put("metroStationName", item.getMetroStationName()); + obj.put("startDate", item.getStartDate() != null ? sdf.format(item.getStartDate()) : ""); + obj.put("endDate", item.getEndDate() != null ? sdf.format(item.getEndDate()) : ""); + obj.put("venue", item.getVenue() == null ? "" : item.getVenue()); + obj.put("remark", item.getRemark() == null ? "" : item.getRemark()); + // 状态:未开始 / 进行中 / 已结束 + String status = ""; + int statusOrder = 3; // 默认排序:已结束=3 + if (item.getStartDate() != null && item.getEndDate() != null) { + java.util.Date start; + java.util.Date end; + try { + start = sdf.parse(sdf.format(item.getStartDate())); + end = sdf.parse(sdf.format(item.getEndDate())); + if (todayDate.before(start)) { + status = "未开始"; + statusOrder = 2; + } else if (todayDate.after(end)) { + status = "已结束"; + statusOrder = 3; + } else { + status = "进行中"; + statusOrder = 1; + } + } catch (Exception ignore) { + } + } + obj.put("status", status); + obj.put("statusOrder", statusOrder); // 用于排序 + tempList.add(obj); + } + + // 按状态排序:进行中(1) → 未开始(2) → 已结束(3) + tempList.sort((a, b) -> { + int orderA = (Integer) a.get("statusOrder"); + int orderB = (Integer) b.get("statusOrder"); + if (orderA != orderB) { + return Integer.compare(orderA, orderB); + } + // 同状态按开始日期排序 + String dateA = (String) a.get("startDate"); + String dateB = (String) b.get("startDate"); + return dateA.compareTo(dateB); + }); + + // 移除排序字段并加入结果 + for (JSONObject obj : tempList) { + obj.remove("statusOrder"); + resultArray.add(obj); + } + } + } catch (Exception ex) { + return badJsonResponse("获取重大活动清单异常", ex); + } + return okJsonResponse(resultArray, cacheKey); + } + /** * 清理客运页面所有接口缓存 */ diff --git a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/domain/MetroBigActivity.java b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/domain/MetroBigActivity.java new file mode 100644 index 0000000..c324c49 --- /dev/null +++ b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/domain/MetroBigActivity.java @@ -0,0 +1,69 @@ +package net.juntech.modules.ysdp.domain; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.jeeplus.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 重大活动Entity + * @author claude + * @version 2026-08-27 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("t_metro_big_activity") +public class MetroBigActivity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 活动名称 + */ + private String activityName; + + /** + * 地铁线路(对应 juntech_ysdp.ys_line.id 主键,UUID) + */ + private String metroLine; + + /** + * 关联站点(对应 juntech_ysdp.ys_station.station_id 业务ID,例:0313) + */ + private String metroStation; + + /** + * 活动开始日期 + */ + private Date startDate; + + /** + * 活动结束日期 + */ + private Date endDate; + + /** + * 举办场馆 + */ + private String venue; + + /** + * 备注 + */ + private String remark; + + /** + * 创建者 + */ + @TableField("create_by_id") + private String createByIdId; + + /** + * 更新者 + */ + @TableField("update_by_id") + private String updateByIdId; +} diff --git a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/mapper/MetroBigActivityMapper.java b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/mapper/MetroBigActivityMapper.java new file mode 100644 index 0000000..8683785 --- /dev/null +++ b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/mapper/MetroBigActivityMapper.java @@ -0,0 +1,38 @@ +package net.juntech.modules.ysdp.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.juntech.modules.ysdp.domain.MetroBigActivity; +import net.juntech.modules.ysdp.service.dto.MetroBigActivityDTO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 重大活动MAPPER接口 + * @author claude + * @version 2026-08-27 + */ +@InterceptorIgnore(tenantLine = "true") +public interface MetroBigActivityMapper extends BaseMapper { + + /** + * 大屏查询:根据线路、站点、月份查询活动列表(关联线路/站点名称) + * + * @param metroLine 线路 ID + * @param metroStation 站点 ID + * @param activityMonth 活动月份 yyyy-MM(按开始日期或结束日期落在此月) + * @return 活动列表 + */ + List queryActivityForScreen(@Param("metroLine") String metroLine, + @Param("metroStation") String metroStation, + @Param("activityMonth") String activityMonth); + + /** + * 后台分页查询(带线路/车站名关联) + */ + com.baomidou.mybatisplus.core.metadata.IPage selectPageWithName( + com.baomidou.mybatisplus.extension.plugins.pagination.Page page, + @Param(com.baomidou.mybatisplus.core.toolkit.Constants.WRAPPER) com.baomidou.mybatisplus.core.conditions.query.QueryWrapper queryWrapper); + +} diff --git a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/mapper/YsYunyingMapper.java b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/mapper/YsYunyingMapper.java index f688876..ec916e0 100644 --- a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/mapper/YsYunyingMapper.java +++ b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/mapper/YsYunyingMapper.java @@ -68,12 +68,29 @@ public interface YsYunyingMapper extends BaseMapper { public List getLineList(); /** - * 获取指定线路下的所有车站列表 - * @param lineId 线路编号(如 "03") + * 获取指定线路下的所有车站列表(按 ys_line.line_id 业务ID 查) + * @param lineId 线路编号(ys_line.line_id,如 "03") * @return 车站列表(含站名、所属所有线路) */ public List getStationsByLine(@Param("lineId") String lineId); + /** + * 按 ys_line 主键 id 获取该线路下的所有车站列表 + * @param id ys_line.id 主键 UUID + * @return 车站列表 + */ + public List getStationsByLineDbId(@Param("id") String id); + + /** + * 按 ys_line.id 列表批量查询线路 + */ + public List getLinesByIds(@Param("ids") java.util.Collection ids); + + /** + * 按 ys_station.station_id 列表批量查询车站 + */ + public List getStationsByStationIds(@Param("stationIds") java.util.Collection stationIds); + /** * 获取指定车站在指定日期各时段的进出站客流(当前车站本身) * @param stationId 车站编号 diff --git a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/mapper/xml/MetroBigActivityMapper.xml b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/mapper/xml/MetroBigActivityMapper.xml new file mode 100644 index 0000000..9740fc5 --- /dev/null +++ b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/mapper/xml/MetroBigActivityMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + diff --git a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/mapper/xml/YsYunyingMapper.xml b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/mapper/xml/YsYunyingMapper.xml index c164595..146e6e5 100644 --- a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/mapper/xml/YsYunyingMapper.xml +++ b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/mapper/xml/YsYunyingMapper.xml @@ -168,6 +168,7 @@ + + + + + + + + SELECT - CAST((SUM(a.pull_num) + SUM(a.departure_num)) / 10000 AS DECIMAL(10,2)) AS total + ROUND((SUM(a.pull_num) + SUM(a.departure_num)) / 100) AS total FROM ys_yunying a left join ys_station b on a.station_id = b.station_id WHERE diff --git a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/service/MetroBigActivityService.java b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/service/MetroBigActivityService.java new file mode 100644 index 0000000..c037c23 --- /dev/null +++ b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/service/MetroBigActivityService.java @@ -0,0 +1,40 @@ +package net.juntech.modules.ysdp.service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import net.juntech.modules.ysdp.domain.MetroBigActivity; +import net.juntech.modules.ysdp.mapper.MetroBigActivityMapper; +import net.juntech.modules.ysdp.service.dto.MetroBigActivityDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 重大活动Service + * @author claude + * @version 2026-08-27 + */ +@Service +@Transactional +public class MetroBigActivityService extends ServiceImpl { + + @Autowired + private MetroBigActivityMapper metroBigActivityMapper; + + /** + * 大屏查询接口 + */ + public List queryActivityForScreen(String metroLine, String metroStation, String activityMonth) { + return metroBigActivityMapper.queryActivityForScreen(metroLine, metroStation, activityMonth); + } + + /** + * 后台分页查询(带线路/车站名关联) + */ + public com.baomidou.mybatisplus.core.metadata.IPage pageWithName( + com.baomidou.mybatisplus.extension.plugins.pagination.Page page, + com.baomidou.mybatisplus.core.conditions.query.QueryWrapper queryWrapper) { + return metroBigActivityMapper.selectPageWithName(page, queryWrapper); + } +} diff --git a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/service/YsYunyingService.java b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/service/YsYunyingService.java index 67fe531..e83b130 100644 --- a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/service/YsYunyingService.java +++ b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/service/YsYunyingService.java @@ -92,12 +92,35 @@ public class YsYunyingService extends ServiceImpl { } /** - * 获取指定线路下的所有车站列表 + * 获取指定线路下的所有车站列表(按 ys_line.line_id 业务ID) */ public List getStationsByLine(String lineId) { return ysYunyingMapper.getStationsByLine(lineId); } + /** + * 按 ys_line 主键 id 获取车站列表 + */ + public List getStationsByLineDbId(String id) { + return ysYunyingMapper.getStationsByLineDbId(id); + } + + /** + * 按 ys_line 主键 id 列表批量查询线路信息(用于 Java 内存名称映射) + */ + public List getLinesByIds(java.util.Collection ids) { + if (ids == null || ids.isEmpty()) return java.util.Collections.emptyList(); + return ysYunyingMapper.getLinesByIds(ids); + } + + /** + * 按 ys_station.station_id 列表批量查询车站信息(用于 Java 内存名称映射) + */ + public List getStationsByStationIds(java.util.Collection stationIds) { + if (stationIds == null || stationIds.isEmpty()) return java.util.Collections.emptyList(); + return ysYunyingMapper.getStationsByStationIds(stationIds); + } + /** * 获取指定车站的进出站时段客流 */ diff --git a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/service/dto/MetroBigActivityDTO.java b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/service/dto/MetroBigActivityDTO.java new file mode 100644 index 0000000..c94a462 --- /dev/null +++ b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/service/dto/MetroBigActivityDTO.java @@ -0,0 +1,109 @@ +package net.juntech.modules.ysdp.service.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.jeeplus.core.query.Query; +import com.jeeplus.core.query.QueryType; +import com.jeeplus.core.service.dto.BaseDTO; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 重大活动DTO + * @author claude + * @version 2026-08-27 + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class MetroBigActivityDTO extends BaseDTO { + + private static final long serialVersionUID = 1L; + + /** + * 活动名称 + */ + @NotEmpty(message = "活动名称不能为空") + @Query(type = QueryType.LIKE) + @ExcelProperty("活动名称") + private String activityName; + + /** + * 地铁线路(juntech_ysdp.ys_line.id 主键 UUID) + */ + @NotEmpty(message = "地铁线路不能为空") + @Query(type = QueryType.EQ) + @ExcelProperty("地铁线路") + private String metroLine; + + /** + * 关联站点(juntech_ysdp.ys_station.station_id 业务ID) + */ + @NotEmpty(message = "关联站点不能为空") + @Query(type = QueryType.EQ) + @ExcelProperty("关联站点") + private String metroStation; + + /** + * 活动开始日期 + */ + @NotNull(message = "开始日期不能为空") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + @ExcelProperty("开始日期") + private Date startDate; + + /** + * 活动结束日期 + */ + @NotNull(message = "结束日期不能为空") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + @ExcelProperty("结束日期") + private Date endDate; + + /** + * 举办场馆 + */ + @ExcelProperty("举办场馆") + private String venue; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String remark; + + /** + * 举办月份查询字段(yyyy-MM),非表字段 + */ + private String activityMonth; + + /** + * 地铁线路名称(关联查询用,非表字段) + */ + private String metroLineName; + + /** + * 关联站点名称(关联查询用,非表字段) + */ + private String metroStationName; + + /** + * 状态(进行中/已结束/未开始,接口实时计算,非表字段) + */ + private String status; + + /** + * 创建者 + */ + @ExcelProperty("创建者") + private String createById; + + /** + * 更新者 + */ + @ExcelProperty("更新者") + private String updateById; +} diff --git a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/service/mapstruct/MetroBigActivityWrapper.java b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/service/mapstruct/MetroBigActivityWrapper.java new file mode 100644 index 0000000..efce704 --- /dev/null +++ b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/service/mapstruct/MetroBigActivityWrapper.java @@ -0,0 +1,19 @@ +package net.juntech.modules.ysdp.service.mapstruct; + +import com.jeeplus.core.mapstruct.EntityWrapper; +import net.juntech.modules.ysdp.domain.MetroBigActivity; +import net.juntech.modules.ysdp.service.dto.MetroBigActivityDTO; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; +import org.mapstruct.factory.Mappers; + +/** + * MetroBigActivityWrapper + * @author claude + * @version 2026-08-27 + */ +@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE, uses = {}) +public interface MetroBigActivityWrapper extends EntityWrapper { + + MetroBigActivityWrapper INSTANCE = Mappers.getMapper(MetroBigActivityWrapper.class); +} diff --git a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/utils/Constant.java b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/utils/Constant.java index 072f93c..0de1564 100644 --- a/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/utils/Constant.java +++ b/be/jeeplus-modules/juntech-ysdp/src/main/java/net/juntech/modules/ysdp/utils/Constant.java @@ -76,4 +76,9 @@ Constant { */ public static final String API_CACHE_NAME_TRAFFIC_LINE_LIST = "api_traffic_lineListV1_"; + /** + * 客运页面-重大活动清单 + */ + public static final String API_CACHE_NAME_TRAFFIC_BIG_ACTIVITY = "api_traffic_bigActivityV1_"; + } diff --git a/fe/src/api/ysdp/metroBigActivityService.js b/fe/src/api/ysdp/metroBigActivityService.js new file mode 100644 index 0000000..51afb77 --- /dev/null +++ b/fe/src/api/ysdp/metroBigActivityService.js @@ -0,0 +1,75 @@ +import request from "@/utils/httpRequest"; + +export default { + save: function (inputForm) { + return request({ + url: "/ysdp/metroBigActivity/save", + method: "post", + data: inputForm, + }); + }, + + delete: function (ids) { + return request({ + url: "/ysdp/metroBigActivity/delete", + method: "delete", + params: { ids: ids }, + }); + }, + + queryById: function (id) { + return request({ + url: "/ysdp/metroBigActivity/queryById", + method: "get", + params: { id: id }, + }); + }, + + list: function (params) { + return request({ + url: "/ysdp/metroBigActivity/list", + method: "get", + params: params, + }); + }, + + lineOptions: function () { + return request({ + url: "/ysdp/metroBigActivity/lineOptions", + method: "get", + }); + }, + + stationOptions: function (lineId) { + return request({ + url: "/ysdp/metroBigActivity/stationOptions", + method: "get", + params: { lineId: lineId }, + }); + }, + + exportTemplate: function () { + return request({ + url: "/ysdp/metroBigActivity/import/template", + method: "get", + responseType: "blob", + }); + }, + + exportExcel: function (params) { + return request({ + url: "/ysdp/metroBigActivity/export", + method: "get", + params: params, + responseType: "blob", + }); + }, + + importExcel: function (data) { + return request({ + url: "/ysdp/metroBigActivity/import", + method: "post", + data: data, + }); + }, +}; diff --git a/fe/src/views/ysdp/MetroBigActivityForm.vue b/fe/src/views/ysdp/MetroBigActivityForm.vue new file mode 100644 index 0000000..3ec0af2 --- /dev/null +++ b/fe/src/views/ysdp/MetroBigActivityForm.vue @@ -0,0 +1,173 @@ + + + diff --git a/fe/src/views/ysdp/MetroBigActivityList.vue b/fe/src/views/ysdp/MetroBigActivityList.vue new file mode 100644 index 0000000..426b783 --- /dev/null +++ b/fe/src/views/ysdp/MetroBigActivityList.vue @@ -0,0 +1,290 @@ + + +