@@ -22,6 +22,7 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value ;
import org.springframework.stereotype.Service ;
import org.springframework.web.multipart.MultipartFile ;
import org.springframework.transaction.annotation.Transactional ;
import jakarta.annotation.Resource ;
@@ -29,6 +30,20 @@ import java.io.IOException;
import java.time.LocalDateTime ;
import java.time.format.DateTimeFormatter ;
import java.util.* ;
import java.io.ByteArrayOutputStream ;
import java.io.IOException ;
import jakarta.servlet.http.HttpServletResponse ;
import org.apache.poi.ss.usermodel.Cell ;
import org.apache.poi.ss.usermodel.Row ;
import org.apache.poi.ss.usermodel.Sheet ;
import org.apache.poi.xssf.usermodel.XSSFWorkbook ;
import java.nio.file.Files ;
import java.nio.file.Path ;
import java.nio.file.Paths ;
import java.io.FileOutputStream ;
import java.time.format.DateTimeFormatter ;
@Service
@Slf4j
@@ -128,6 +143,7 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
}
@Override
@Transactional ( rollbackFor = Exception . class )
public Map < String , Object > saveContestant ( ContestantDTO request ) {
Map < String , Object > resp = new HashMap < > ( ) ;
if ( request . getEmail ( ) = = null ) {
@@ -142,7 +158,14 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
LocalDateTime now = LocalDateTime . now ( ) ;
if ( existing = = null ) {
// 生成唯一的参赛选手编号( 从10000开始) , 使用数据库行锁保证并发安全与原子性
QueryWrapper < Contestant > numQw = new QueryWrapper < > ( ) ;
numQw . isNotNull ( " contestant_number " ) . orderByDesc ( " contestant_number " ) . last ( " FOR UPDATE " ) ;
Contestant maxRow = contestantMapper . selectOne ( numQw ) ;
Integer nextContestantNumber = ( maxRow = = null | | maxRow . getContestantNumber ( ) = = null ) ? 10000 : maxRow . getContestantNumber ( ) + 1 ;
Contestant toInsert = Contestant . builder ( )
. contestantNumber ( nextContestantNumber )
. email ( request . getEmail ( ) )
. firstName ( request . getFirstName ( ) )
. lastName ( request . getLastName ( ) )
@@ -160,6 +183,7 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
. build ( ) ;
contestantMapper . insert ( toInsert ) ;
resp . put ( " success " , true ) ;
resp . put ( " contestant_number " , nextContestantNumber ) ;
sendSiteMsg ( toInsert . getId ( ) , toInsert . getEmail ( ) ) ;
return resp ;
} else {
@@ -178,10 +202,109 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
existing . setUpdatedAt ( now ) ;
contestantMapper . updateById ( existing ) ;
resp . put ( " success " , true ) ;
resp . put ( " contestant_number " , existing . getContestantNumber ( ) ) ;
return resp ;
}
}
@Override
public byte [ ] exportContestants ( ) throws Exception {
List < Contestant > list = contestantMapper . selectList ( new QueryWrapper < > ( ) ) ;
try ( XSSFWorkbook workbook = new XSSFWorkbook ( ) ; ByteArrayOutputStream out = new ByteArrayOutputStream ( ) ) {
Sheet sheet = workbook . createSheet ( " contestants " ) ;
int rowIdx = 0 ;
Row header = sheet . createRow ( rowIdx + + ) ;
String [ ] headers = new String [ ] {
" contestantNumber " , " email " , " firstName " , " lastName " , " gender " , " occupation " ,
" age " , " countryRegionCity " , " phoneNumber " , " designTitle " , " designDescription " ,
" pdfPath " , " videoPath " , " createdAt " , " updatedAt "
} ;
for ( int i = 0 ; i < headers . length ; i + + ) {
Cell c = header . createCell ( i ) ;
c . setCellValue ( headers [ i ] ) ;
}
for ( Contestant cst : list ) {
Row r = sheet . createRow ( rowIdx + + ) ;
int ci = 0 ;
r . createCell ( ci + + ) . setCellValue ( cst . getContestantNumber ( ) = = null ? " " : cst . getContestantNumber ( ) . toString ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getEmail ( ) = = null ? " " : cst . getEmail ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getFirstName ( ) = = null ? " " : cst . getFirstName ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getLastName ( ) = = null ? " " : cst . getLastName ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getGender ( ) = = null ? " " : cst . getGender ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getOccupation ( ) = = null ? " " : cst . getOccupation ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getAge ( ) = = null ? " " : cst . getAge ( ) . toString ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getCountryRegionCity ( ) = = null ? " " : cst . getCountryRegionCity ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getPhoneNumber ( ) = = null ? " " : cst . getPhoneNumber ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getDesignTitle ( ) = = null ? " " : cst . getDesignTitle ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getDesignDescription ( ) = = null ? " " : cst . getDesignDescription ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getPdfPath ( ) = = null ? " " : cst . getPdfPath ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getVideoPath ( ) = = null ? " " : cst . getVideoPath ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getCreatedAt ( ) = = null ? " " : cst . getCreatedAt ( ) . toString ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getUpdatedAt ( ) = = null ? " " : cst . getUpdatedAt ( ) . toString ( ) ) ;
}
workbook . write ( out ) ;
out . flush ( ) ;
return out . toByteArray ( ) ;
} catch ( IOException e ) {
log . error ( " export contestants failed " , e ) ;
throw e ;
}
}
@Override
public void saveContestantsToLocal ( ) throws Exception {
List < Contestant > list = contestantMapper . selectList ( new QueryWrapper < > ( ) ) ;
DateTimeFormatter fmt = DateTimeFormatter . ofPattern ( " yyyyMMdd_HHmmss " ) ;
String ts = LocalDateTime . now ( ) . format ( fmt ) ;
Path exportDir = Paths . get ( uploadDir = = null ? " uploads " : uploadDir , " exports " ) ;
Files . createDirectories ( exportDir ) ;
Path outPath = exportDir . resolve ( " contestants_ " + ts + " .xlsx " ) ;
try ( XSSFWorkbook workbook = new XSSFWorkbook ( ) ; FileOutputStream fos = new FileOutputStream ( outPath . toFile ( ) ) ) {
Sheet sheet = workbook . createSheet ( " contestants " ) ;
int rowIdx = 0 ;
Row header = sheet . createRow ( rowIdx + + ) ;
String [ ] headers = new String [ ] {
" contestantNumber " , " email " , " firstName " , " lastName " , " gender " , " occupation " ,
" age " , " countryRegionCity " , " phoneNumber " , " designTitle " , " designDescription " ,
" pdfPath " , " videoPath " , " createdAt " , " updatedAt "
} ;
for ( int i = 0 ; i < headers . length ; i + + ) {
Cell c = header . createCell ( i ) ;
c . setCellValue ( headers [ i ] ) ;
}
for ( Contestant cst : list ) {
Row r = sheet . createRow ( rowIdx + + ) ;
int ci = 0 ;
r . createCell ( ci + + ) . setCellValue ( cst . getContestantNumber ( ) = = null ? " " : cst . getContestantNumber ( ) . toString ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getEmail ( ) = = null ? " " : cst . getEmail ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getFirstName ( ) = = null ? " " : cst . getFirstName ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getLastName ( ) = = null ? " " : cst . getLastName ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getGender ( ) = = null ? " " : cst . getGender ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getOccupation ( ) = = null ? " " : cst . getOccupation ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getAge ( ) = = null ? " " : cst . getAge ( ) . toString ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getCountryRegionCity ( ) = = null ? " " : cst . getCountryRegionCity ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getPhoneNumber ( ) = = null ? " " : cst . getPhoneNumber ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getDesignTitle ( ) = = null ? " " : cst . getDesignTitle ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getDesignDescription ( ) = = null ? " " : cst . getDesignDescription ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getPdfPath ( ) = = null ? " " : cst . getPdfPath ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getVideoPath ( ) = = null ? " " : cst . getVideoPath ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getCreatedAt ( ) = = null ? " " : cst . getCreatedAt ( ) . toString ( ) ) ;
r . createCell ( ci + + ) . setCellValue ( cst . getUpdatedAt ( ) = = null ? " " : cst . getUpdatedAt ( ) . toString ( ) ) ;
}
workbook . write ( fos ) ;
fos . flush ( ) ;
log . info ( " Exported contestants to local file: {} " , outPath . toString ( ) ) ;
} catch ( IOException e ) {
log . error ( " save contestants to local failed " , e ) ;
throw e ;
}
}
@Override
public ContestantDTO getContestantByID ( String id ) {
if ( id = = null ) {