GlobalAward首次提交
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
package com.ai.da.controller;
|
||||
|
||||
import com.ai.da.common.response.Response;
|
||||
import com.ai.da.model.dto.ContestantDTO;
|
||||
import com.ai.da.service.GlobalAwardService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/global-award")
|
||||
public class GlobalAwardController {
|
||||
|
||||
@Resource
|
||||
private GlobalAwardService globalAwardService;
|
||||
|
||||
@PostMapping("/uploads/pdf")
|
||||
public Response<String> uploadPdf(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "email", required = false) String email) throws Exception {
|
||||
return Response.success(globalAwardService.uploadPdf(file, email));
|
||||
}
|
||||
|
||||
@PostMapping("/uploads/video")
|
||||
public Response<String> uploadVideo(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "email", required = false) String email) throws Exception {
|
||||
return Response.success(globalAwardService.uploadVideo(file, email));
|
||||
}
|
||||
|
||||
@PostMapping("/contestants/save")
|
||||
public Response<Map<String,Object>> submit(@RequestBody ContestantDTO request) {
|
||||
return Response.success(globalAwardService.saveContestant(request));
|
||||
}
|
||||
|
||||
@GetMapping("/contestants/by-email")
|
||||
public Response<ContestantDTO> getContestantByEmail(@RequestParam("email") String email) {
|
||||
ContestantDTO dto = globalAwardService.getContestantByEmail(email);
|
||||
return Response.success(dto);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
12
src/main/java/com/ai/da/mapper/primary/ContestantMapper.java
Normal file
12
src/main/java/com/ai/da/mapper/primary/ContestantMapper.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.ai.da.mapper.primary;
|
||||
|
||||
import com.ai.da.mapper.primary.entity.Contestant;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface ContestantMapper extends BaseMapper<Contestant> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.ai.da.mapper.primary.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* submissions 表对应实体 — 参赛选手信息 (Contestant)
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@TableName("submissions")
|
||||
public class Contestant {
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String email;
|
||||
|
||||
@TableField("first_name")
|
||||
private String firstName;
|
||||
|
||||
@TableField("last_name")
|
||||
private String lastName;
|
||||
|
||||
private String gender;
|
||||
|
||||
private String occupation;
|
||||
|
||||
private Integer age;
|
||||
|
||||
@TableField("country_region_city")
|
||||
private String countryRegionCity;
|
||||
|
||||
@TableField("phone_number")
|
||||
private String phoneNumber;
|
||||
|
||||
@TableField("portfolio_url")
|
||||
private String portfolioUrl;
|
||||
|
||||
@TableField("design_title")
|
||||
private String designTitle;
|
||||
|
||||
@TableField("design_description")
|
||||
private String designDescription;
|
||||
|
||||
@TableField("pdf_path")
|
||||
private String pdfPath;
|
||||
|
||||
@TableField("video_path")
|
||||
private String videoPath;
|
||||
|
||||
@TableField("created_at")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@TableField("updated_at")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
@TableField("created_by")
|
||||
private Long createdBy;
|
||||
}
|
||||
|
||||
|
||||
29
src/main/java/com/ai/da/model/dto/ContestantDTO.java
Normal file
29
src/main/java/com/ai/da/model/dto/ContestantDTO.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.ai.da.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Contestant request DTO for Global Award
|
||||
*/
|
||||
@Data
|
||||
public class ContestantDTO {
|
||||
private String email;
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private String gender;
|
||||
private String occupation;
|
||||
private Integer age;
|
||||
private String countryRegionCity;
|
||||
private String phoneNumber;
|
||||
private String portfolioUrl;
|
||||
private String designTitle;
|
||||
private String designDescription;
|
||||
private String pdfPath;
|
||||
private String videoPath;
|
||||
/**
|
||||
* 是否确认覆盖已存在记录(false 表示发现已有记录时仅返回 existingRecord,不覆盖)
|
||||
*/
|
||||
private Boolean confirm = false;
|
||||
}
|
||||
|
||||
|
||||
15
src/main/java/com/ai/da/service/GlobalAwardService.java
Normal file
15
src/main/java/com/ai/da/service/GlobalAwardService.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package com.ai.da.service;
|
||||
|
||||
import com.ai.da.model.dto.ContestantDTO;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface GlobalAwardService {
|
||||
String uploadPdf(MultipartFile file, String email) throws Exception;
|
||||
String uploadVideo(MultipartFile file, String email) throws Exception;
|
||||
Map<String, Object> saveContestant(ContestantDTO request);
|
||||
com.ai.da.model.dto.ContestantDTO getContestantByEmail(String email);
|
||||
}
|
||||
|
||||
|
||||
190
src/main/java/com/ai/da/service/impl/GlobalAwardServiceImpl.java
Normal file
190
src/main/java/com/ai/da/service/impl/GlobalAwardServiceImpl.java
Normal file
@@ -0,0 +1,190 @@
|
||||
package com.ai.da.service.impl;
|
||||
|
||||
import com.ai.da.common.config.exception.BusinessException;
|
||||
import com.ai.da.mapper.primary.ContestantMapper;
|
||||
import com.ai.da.mapper.primary.entity.Contestant;
|
||||
import com.ai.da.model.dto.ContestantDTO;
|
||||
import com.ai.da.service.GlobalAwardService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import com.ai.da.common.utils.MinioUtil;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class GlobalAwardServiceImpl implements GlobalAwardService {
|
||||
|
||||
@Resource
|
||||
private ContestantMapper contestantMapper;
|
||||
|
||||
@Value("${file.upload.dir:uploads}")
|
||||
private String uploadDir;
|
||||
|
||||
private static final DateTimeFormatter YYYY_MM_DD = DateTimeFormatter.ofPattern("yyyy/MM");
|
||||
@Value("${minio.bucket:contestants}")
|
||||
private String minioBucket;
|
||||
|
||||
@Resource
|
||||
private MinioUtil minioUtil;
|
||||
|
||||
@Override
|
||||
public String uploadPdf(MultipartFile file, String email) throws Exception {
|
||||
validatePdf(file);
|
||||
String path = storeFile(file, email, "pdf");
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadVideo(MultipartFile file, String email) throws Exception {
|
||||
validateVideo(file);
|
||||
String path = storeFile(file, email, "video");
|
||||
return path;
|
||||
}
|
||||
|
||||
private void validatePdf(MultipartFile file) {
|
||||
if (file == null || file.isEmpty()) {
|
||||
throw new BusinessException("file is empty");
|
||||
}
|
||||
String ct = file.getContentType();
|
||||
if (ct == null || !ct.toLowerCase().contains("pdf")) {
|
||||
throw new BusinessException("only pdf allowed");
|
||||
}
|
||||
// size limit example 20MB
|
||||
if (file.getSize() > 20L * 1024 * 1024) {
|
||||
throw new BusinessException("pdf too large");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateVideo(MultipartFile file) {
|
||||
if (file == null || file.isEmpty()) {
|
||||
throw new BusinessException("file is empty");
|
||||
}
|
||||
String ct = file.getContentType();
|
||||
if (ct == null || !(ct.toLowerCase().contains("mp4") || ct.toLowerCase().contains("video") )) {
|
||||
throw new BusinessException("invalid video type");
|
||||
}
|
||||
// size limit example 100MB
|
||||
if (file.getSize() > 100L * 1024 * 1024) {
|
||||
throw new BusinessException("video too large");
|
||||
}
|
||||
}
|
||||
|
||||
private String normalizeEmail(String email) {
|
||||
if (email == null) {
|
||||
return "anonymous";
|
||||
}
|
||||
return email.replaceAll("[^a-zA-Z0-9]", "_");
|
||||
}
|
||||
|
||||
private String storeFile(MultipartFile file, String email, String kind) throws IOException {
|
||||
String normalized = normalizeEmail(email);
|
||||
String datePart = LocalDateTime.now().format(YYYY_MM_DD);
|
||||
String ext = "";
|
||||
String original = file.getOriginalFilename();
|
||||
if (original != null && original.contains(".")) {
|
||||
ext = original.substring(original.lastIndexOf('.'));
|
||||
}
|
||||
String filename = System.currentTimeMillis() + "_" + UUID.randomUUID().toString() + ext;
|
||||
String relativePath = "contestants/" + normalized + "/" + datePart + "/" + filename;
|
||||
|
||||
String uploadedPath = minioUtil.upload(minioBucket, relativePath, file, null);
|
||||
log.info("uploaded via MinioUtil: {}", uploadedPath);
|
||||
return uploadedPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> saveContestant(ContestantDTO request) {
|
||||
Map<String,Object> resp = new HashMap<>();
|
||||
if (request.getEmail() == null) {
|
||||
throw new IllegalArgumentException("email required");
|
||||
}
|
||||
|
||||
QueryWrapper<Contestant> qw = new QueryWrapper<>();
|
||||
qw.eq("email", request.getEmail());
|
||||
Contestant existing = contestantMapper.selectOne(qw);
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
if (existing == null) {
|
||||
Contestant toInsert = Contestant.builder()
|
||||
.email(request.getEmail())
|
||||
.firstName(request.getFirstName())
|
||||
.lastName(request.getLastName())
|
||||
.gender(request.getGender())
|
||||
.occupation(request.getOccupation())
|
||||
.age(request.getAge())
|
||||
.countryRegionCity(request.getCountryRegionCity())
|
||||
.phoneNumber(request.getPhoneNumber())
|
||||
.portfolioUrl(request.getPortfolioUrl())
|
||||
.designTitle(request.getDesignTitle())
|
||||
.designDescription(request.getDesignDescription())
|
||||
.pdfPath(request.getPdfPath())
|
||||
.videoPath(request.getVideoPath())
|
||||
.createdAt(now)
|
||||
.updatedAt(now)
|
||||
.build();
|
||||
contestantMapper.insert(toInsert);
|
||||
resp.put("success", true);
|
||||
return resp;
|
||||
} else {
|
||||
// update existing contestant
|
||||
existing.setFirstName(request.getFirstName());
|
||||
existing.setLastName(request.getLastName());
|
||||
existing.setGender(request.getGender());
|
||||
existing.setOccupation(request.getOccupation());
|
||||
existing.setAge(request.getAge());
|
||||
existing.setCountryRegionCity(request.getCountryRegionCity());
|
||||
existing.setPhoneNumber(request.getPhoneNumber());
|
||||
existing.setPortfolioUrl(request.getPortfolioUrl());
|
||||
existing.setDesignTitle(request.getDesignTitle());
|
||||
existing.setDesignDescription(request.getDesignDescription());
|
||||
existing.setPdfPath(request.getPdfPath());
|
||||
existing.setVideoPath(request.getVideoPath());
|
||||
existing.setUpdatedAt(now);
|
||||
contestantMapper.updateById(existing);
|
||||
resp.put("success", true);
|
||||
return resp;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContestantDTO getContestantByEmail(String email) {
|
||||
if (email == null) {
|
||||
throw new BusinessException("email required");
|
||||
}
|
||||
QueryWrapper<Contestant> qw = new QueryWrapper<>();
|
||||
qw.eq("email", email);
|
||||
Contestant existing = contestantMapper.selectOne(qw);
|
||||
if (existing == null) {
|
||||
return null;
|
||||
}
|
||||
ContestantDTO dto = new ContestantDTO();
|
||||
dto.setEmail(existing.getEmail());
|
||||
dto.setFirstName(existing.getFirstName());
|
||||
dto.setLastName(existing.getLastName());
|
||||
dto.setGender(existing.getGender());
|
||||
dto.setOccupation(existing.getOccupation());
|
||||
dto.setAge(existing.getAge());
|
||||
dto.setCountryRegionCity(existing.getCountryRegionCity());
|
||||
dto.setPhoneNumber(existing.getPhoneNumber());
|
||||
dto.setPortfolioUrl(existing.getPortfolioUrl());
|
||||
dto.setDesignTitle(existing.getDesignTitle());
|
||||
dto.setDesignDescription(existing.getDesignDescription());
|
||||
dto.setPdfPath(existing.getPdfPath());
|
||||
dto.setVideoPath(existing.getVideoPath());
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user