diff --git a/backend-java/src/main/java/com/competition/modules/biz/contest/controller/ContestNoticeController.java b/backend-java/src/main/java/com/competition/modules/biz/contest/controller/ContestNoticeController.java index 26244ab..1631605 100644 --- a/backend-java/src/main/java/com/competition/modules/biz/contest/controller/ContestNoticeController.java +++ b/backend-java/src/main/java/com/competition/modules/biz/contest/controller/ContestNoticeController.java @@ -17,6 +17,7 @@ import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.List; @Tag(name = "赛事公告") @@ -27,6 +28,34 @@ public class ContestNoticeController { private final IContestNoticeService noticeService; + /** + * 解析日期时间字符串,兼容 ISO 格式(带毫秒和 Z 时区标记) + */ + private LocalDateTime parseDateTime(String dateTime) { + if (!StringUtils.hasText(dateTime)) { + return null; + } + // 尝试 ISO 格式(yyyy-MM-dd'T'HH:mm:ss.SSSZ 或 yyyy-MM-dd'T'HH:mm:ss'Z') + try { + // 处理带 Z 的 ISO 格式 + if (dateTime.endsWith("Z")) { + return LocalDateTime.parse(dateTime.substring(0, dateTime.length() - 1)); + } + // 处理带毫秒的格式 + if (dateTime.contains(".") && dateTime.indexOf(".") + 4 == dateTime.length()) { + return LocalDateTime.parse(dateTime.substring(0, dateTime.indexOf("."))); + } + return LocalDateTime.parse(dateTime); + } catch (Exception e) { + // 尝试空格分隔格式 + try { + return LocalDateTime.parse(dateTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + } catch (Exception ex) { + return null; + } + } + } + @PostMapping @RequirePermission("notice:create") @Operation(summary = "创建公告") @@ -38,7 +67,7 @@ public class ContestNoticeController { notice.setNoticeType(dto.getNoticeType()); notice.setPriority(dto.getPriority()); if (StringUtils.hasText(dto.getPublishTime())) { - notice.setPublishTime(LocalDateTime.parse(dto.getPublishTime())); + notice.setPublishTime(parseDateTime(dto.getPublishTime())); } // 设置当前租户 ID(租户隔离) notice.setTenantId(SecurityUtil.getCurrentTenantId()); @@ -102,7 +131,7 @@ public class ContestNoticeController { notice.setNoticeType(dto.getNoticeType()); notice.setPriority(dto.getPriority()); if (StringUtils.hasText(dto.getPublishTime())) { - notice.setPublishTime(LocalDateTime.parse(dto.getPublishTime())); + notice.setPublishTime(parseDateTime(dto.getPublishTime())); } noticeService.updateById(notice); return Result.success(); diff --git a/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestServiceImpl.java b/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestServiceImpl.java index c9c7bc3..e7b895d 100644 --- a/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestServiceImpl.java +++ b/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestServiceImpl.java @@ -18,6 +18,8 @@ import com.competition.modules.biz.contest.mapper.ContestMapper; import com.competition.modules.biz.contest.mapper.ContestRegistrationMapper; import com.competition.modules.biz.contest.mapper.ContestWorkMapper; import com.competition.modules.biz.contest.service.IContestService; +import com.competition.modules.sys.entity.SysTenant; +import com.competition.modules.sys.mapper.SysTenantMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -37,6 +39,7 @@ public class ContestServiceImpl extends ServiceImpl i private final ContestAttachmentMapper contestAttachmentMapper; private final ContestRegistrationMapper contestRegistrationMapper; private final ContestWorkMapper contestWorkMapper; + private final SysTenantMapper sysTenantMapper; // 支持两种日期格式:ISO 格式 (T 分隔) 和空格分隔格式 private static final DateTimeFormatter ISO_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME; @@ -204,6 +207,24 @@ public class ContestServiceImpl extends ServiceImpl i List attachments = contestAttachmentMapper.selectList(attWrapper); result.put("attachments", attachments); + // 查询授权租户的详细信息 + List tenantIds = contest.getContestTenants(); + if (tenantIds != null && !tenantIds.isEmpty()) { + List> tenantInfoList = new ArrayList<>(); + for (Integer tenantId : tenantIds) { + SysTenant tenant = sysTenantMapper.selectById(tenantId.longValue()); + if (tenant != null) { + Map tenantInfo = new LinkedHashMap<>(); + tenantInfo.put("id", tenant.getId()); + tenantInfo.put("name", tenant.getName()); + tenantInfo.put("code", tenant.getCode()); + tenantInfo.put("tenantType", tenant.getTenantType()); + tenantInfoList.add(tenantInfo); + } + } + result.put("contestTenantInfos", tenantInfoList); + } + return result; } diff --git a/frontend/src/api/contests.ts b/frontend/src/api/contests.ts index f258329..10c4bb5 100644 --- a/frontend/src/api/contests.ts +++ b/frontend/src/api/contests.ts @@ -12,7 +12,14 @@ export interface Contest { endTime: string; address?: string; content?: string; + visibility?: "public" | "designated" | "internal"; // 可见范围 contestTenants?: number[]; + contestTenantInfos?: Array<{ + id: number; + name: string; + code: string; + tenantType?: string; + }>; coverUrl?: string; posterUrl?: string; contactName?: string; diff --git a/frontend/src/views/contests/Detail.vue b/frontend/src/views/contests/Detail.vue index 3d5fef6..9de6736 100644 --- a/frontend/src/views/contests/Detail.vue +++ b/frontend/src/views/contests/Detail.vue @@ -250,6 +250,60 @@
+ + + +