Compare commits
22 Commits
981fc35be4
...
release/3.
| Author | SHA1 | Date | |
|---|---|---|---|
| 4206bd5356 | |||
| 3273a61066 | |||
| d055331690 | |||
| 0073f910a7 | |||
| 6dcbfa025a | |||
| 65cde0b8f5 | |||
| b66877425e | |||
|
|
f53fca9a09 | ||
|
|
c8dc38575a | ||
|
|
c00d906083 | ||
| 4df3f9cc53 | |||
|
|
b0343be544 | ||
|
|
d33cb9f0bf | ||
|
|
40f2735831 | ||
|
|
d73442d1dd | ||
|
|
c8164cb997 | ||
| 01d3806d5f | |||
| 107e4e9771 | |||
|
|
716d720782 | ||
|
|
6b5bacc49b | ||
|
|
409bc7b1fd | ||
|
|
ec6a5df8af |
@@ -18,8 +18,8 @@ public class ModelConstants {
|
|||||||
|
|
||||||
// 模型名称常量
|
// 模型名称常量
|
||||||
public static final String PRINTBOARD_ADVANCED_T2I = "qwen-image";
|
public static final String PRINTBOARD_ADVANCED_T2I = "qwen-image";
|
||||||
public static final String MOODBOARD_ADVANCED = "doubao-seedream-3-0-t2i-250415";
|
public static final String MOODBOARD_ADVANCED = "doubao-seedream-4-5-251128";
|
||||||
public static final String PRINTBOARD_HIGH_T2I = "doubao-seedream-3-0-t2i-250415";
|
public static final String PRINTBOARD_HIGH_T2I = "doubao-seedream-4-0-250828-high";
|
||||||
public static final String PRINTBOARD_HIGH_I2I = "doubao-seedream-4-0-250828-fast";
|
public static final String PRINTBOARD_HIGH_I2I = "doubao-seedream-4-0-250828-fast";
|
||||||
public static final String PRINTBOARD_ADVANCED_I2I = "doubao-seedream-4-0-250828";
|
public static final String PRINTBOARD_ADVANCED_I2I = "doubao-seedream-4-0-250828";
|
||||||
public static final String IMAGEN_MODEL = "imagen-4.0-generate-001";
|
public static final String IMAGEN_MODEL = "imagen-4.0-generate-001";
|
||||||
|
|||||||
@@ -61,10 +61,7 @@ public class AuthenticationFilter extends OncePerRequestFilter {
|
|||||||
, "/api/account/schoolLogin", "/api/account/enterpriseLogin", "/api/account/organizationNameSearch",
|
, "/api/account/schoolLogin", "/api/account/enterpriseLogin", "/api/account/organizationNameSearch",
|
||||||
"/api/llm/stream",
|
"/api/llm/stream",
|
||||||
//GlobalAwardController
|
//GlobalAwardController
|
||||||
"/api/global-award/uploads/pdf/init", "/api/global-award/uploads/pdf/chunk", "/api/global-award/uploads/pdf/complete", "/api/global-award/uploads/pdf/status",
|
"/api/global-award"
|
||||||
"/api/global-award/uploads/video/init", "/api/global-award/uploads/video/chunk", "/api/global-award/uploads/video/complete", "/api/global-award/uploads/video/status",
|
|
||||||
"/api/global-award/contestants/save", "/api/global-award/contestants/by-email", "/api/global-award/checkEmail", "/api/global-award/checkCode","/api/global-award/contestants/export",
|
|
||||||
"/api/global-award/contestants/export/files"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import com.ai.da.common.response.Response;
|
|||||||
import com.ai.da.model.dto.*;
|
import com.ai.da.model.dto.*;
|
||||||
import com.ai.da.model.dto.ContestantDTO;
|
import com.ai.da.model.dto.ContestantDTO;
|
||||||
import com.ai.da.model.vo.CheckOTPVO;
|
import com.ai.da.model.vo.CheckOTPVO;
|
||||||
|
import com.ai.da.model.vo.ContestantCountVO;
|
||||||
|
import com.ai.da.model.vo.PageVisitCountVO;
|
||||||
import com.ai.da.service.GlobalAwardService;
|
import com.ai.da.service.GlobalAwardService;
|
||||||
import com.ai.da.service.upload.UploadService;
|
import com.ai.da.service.upload.UploadService;
|
||||||
import com.ai.da.service.upload.UploadTask;
|
import com.ai.da.service.upload.UploadTask;
|
||||||
@@ -192,11 +194,24 @@ public class GlobalAwardController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/contestants/count")
|
@GetMapping("/contestants/count")
|
||||||
@ApiOperation(value = "查询参赛者总数", notes = "查询数据库中参赛者的总数量")
|
@ApiOperation(value = "查询参赛者总数", notes = "查询数据库中参赛者的总数量和最大参赛者编号")
|
||||||
public Response<Long> getContestantCount() {
|
public Response<ContestantCountVO> getContestantCount() {
|
||||||
return Response.success(globalAwardService.getContestantCount());
|
return Response.success(globalAwardService.getContestantCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/page/visit")
|
||||||
|
@ApiOperation(value = "记录比赛页面访问量", notes = "记录比赛页面的访问量,包含两种统计方式:每次访问/刷新计一次,以及5秒内刷新只计一次")
|
||||||
|
public Response<Void> recordPageVisit(@ApiParam(value = "会话ID,用于5秒内去重判断", required = false) @RequestParam(value = "sessionId", required = false) String sessionId) {
|
||||||
|
globalAwardService.recordPageVisit(sessionId);
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/page/visit/count")
|
||||||
|
@ApiOperation(value = "获取比赛页面访问量", notes = "获取比赛页面的两种访问量:rawVisitCount(每次访问/刷新计一次)和 uniqueVisitCount(5秒内刷新只计一次)")
|
||||||
|
public Response<PageVisitCountVO> getPageVisitCount() {
|
||||||
|
return Response.success(globalAwardService.getPageVisitCount());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ public class Contestant {
|
|||||||
@TableField("pdf_size")
|
@TableField("pdf_size")
|
||||||
private Long pdfSize;
|
private Long pdfSize;
|
||||||
|
|
||||||
|
@TableField("portfolio_url")
|
||||||
|
private String portfolioUrl;
|
||||||
|
|
||||||
@TableField("created_at")
|
@TableField("created_at")
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
|||||||
17
src/main/java/com/ai/da/model/vo/ContestantCountVO.java
Normal file
17
src/main/java/com/ai/da/model/vo/ContestantCountVO.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package com.ai.da.model.vo;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ContestantCountVO {
|
||||||
|
|
||||||
|
private Long count;
|
||||||
|
|
||||||
|
private Integer maxContestantNumber;
|
||||||
|
}
|
||||||
23
src/main/java/com/ai/da/model/vo/PageVisitCountVO.java
Normal file
23
src/main/java/com/ai/da/model/vo/PageVisitCountVO.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package com.ai.da.model.vo;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class PageVisitCountVO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每次访问或刷新都计一次(不去重)
|
||||||
|
*/
|
||||||
|
private Long rawVisitCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 5秒内刷新只算一次(去重后的真实访客数)
|
||||||
|
*/
|
||||||
|
private Long uniqueVisitCount;
|
||||||
|
}
|
||||||
@@ -34,4 +34,8 @@ public class QueryUserConditionsVO extends PageQueryBaseVo {
|
|||||||
|
|
||||||
private Integer systemUser;
|
private Integer systemUser;
|
||||||
|
|
||||||
|
private Long subscriptionPlanId;
|
||||||
|
|
||||||
|
private Long organizationId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2912,72 +2912,71 @@ public class PythonService {
|
|||||||
|
|
||||||
private PrintToPython resolveDesignSinglePrint(List<DesignSinglePrint> printObject, String partialDesign) {
|
private PrintToPython resolveDesignSinglePrint(List<DesignSinglePrint> printObject, String partialDesign) {
|
||||||
PrintToPython printToPython = new PrintToPython();
|
PrintToPython printToPython = new PrintToPython();
|
||||||
// DesignPythonItemPrint printSingle = new DesignPythonItemPrint();
|
|
||||||
DesignPythonItemPrint printOverall = new DesignPythonItemPrint();
|
DesignPythonItemPrint printOverall = new DesignPythonItemPrint();
|
||||||
// printToPython.setSingle(printSingle);
|
|
||||||
printToPython.setOverall(printOverall);
|
printToPython.setOverall(printOverall);
|
||||||
printToPython.setPartial(StringUtil.isNullOrEmpty(partialDesign) ? null : partialDesign);
|
printToPython.setPartial(StringUtil.isNullOrEmpty(partialDesign) ? null : partialDesign);
|
||||||
if (Objects.isNull(printObject) || printObject.isEmpty()) {
|
if (Objects.isNull(printObject) || printObject.isEmpty()) {
|
||||||
return printToPython;
|
return printToPython;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 没有印花时的参数设置
|
// 1. 先对 printObject 按 priority 排序(升序)
|
||||||
// if (printObject.getIfSingle().equals(Boolean.FALSE) && CollectionUtil.isEmpty(printObject.getPrints())) {
|
List<DesignSinglePrint> sortedPrints = printObject.stream()
|
||||||
// return new DesignPythonItemPrint(new ArrayList<>(), false);
|
.sorted(Comparator.comparingInt(DesignSinglePrint::getPriority))
|
||||||
// }
|
.toList();
|
||||||
// DesignPythonItemPrint print = CopyUtil.copyObject(printObject, DesignPythonItemPrint.class);
|
|
||||||
|
|
||||||
int size = printObject.size();
|
// 2. 分别收集单印和非单印的数据
|
||||||
// 占位符填充数组
|
List<DesignSinglePrint> singlePrints = sortedPrints.stream()
|
||||||
List<List<Float>> locationS = new ArrayList<>(Collections.nCopies(size, null));
|
.filter(DesignSinglePrint::getIfSingle)
|
||||||
List<List<Float>> scaleS = new ArrayList<>(Collections.nCopies(size, null));
|
.toList();
|
||||||
List<Double> angleS = new ArrayList<>(Collections.nCopies(size, null));
|
|
||||||
ArrayList<String> pathsS = new ArrayList<>(Collections.nCopies(size, null));
|
|
||||||
|
|
||||||
List<List<Float>> locationO = new ArrayList<>(Collections.nCopies(size, null));
|
List<DesignSinglePrint> overallPrints = sortedPrints.stream()
|
||||||
List<List<Float>> scaleO = new ArrayList<>(Collections.nCopies(size, null));
|
.filter(p -> !p.getIfSingle())
|
||||||
List<Double> angleO = new ArrayList<>(Collections.nCopies(size, null));
|
.toList();
|
||||||
ArrayList<String> pathsO = new ArrayList<>(Collections.nCopies(size, null));
|
|
||||||
|
|
||||||
// 设置印花的位置、大小、旋转角度
|
// 3. 处理单印数据
|
||||||
// 优先级越大,越靠近顶层,在传输给python的数组中,越靠前
|
if (!singlePrints.isEmpty()) {
|
||||||
// List<DesignSinglePrint> prints = printObject.getPrints();
|
List<List<Float>> locationS = new ArrayList<>();
|
||||||
printObject.forEach(p -> {
|
List<List<Float>> scaleS = new ArrayList<>();
|
||||||
p.getLocation().set(0, p.getLocation().get(0));
|
List<Double> angleS = new ArrayList<>();
|
||||||
p.getLocation().set(1, p.getLocation().get(1));
|
List<String> pathsS = new ArrayList<>();
|
||||||
Integer priority = p.getPriority();
|
|
||||||
|
for (DesignSinglePrint p : singlePrints) {
|
||||||
setUriToMinioPath(p);
|
setUriToMinioPath(p);
|
||||||
// todo 下标越界问题
|
locationS.add(p.getLocation());
|
||||||
if (p.getIfSingle()) {
|
scaleS.add(p.getScale());
|
||||||
locationS.set(priority - 1, p.getLocation());
|
angleS.add(p.getAngle());
|
||||||
scaleS.set(priority - 1, p.getScale());
|
pathsS.add(p.getMinIOPath());
|
||||||
angleS.set(priority - 1, p.getAngle());
|
}
|
||||||
pathsS.set(priority - 1, p.getMinIOPath());
|
|
||||||
} else {
|
// 注意:如果 printOverall 中需要设置单印数据,请在这里添加相应的 setter
|
||||||
locationO.set(priority - 1, p.getLocation());
|
// 根据您的原始代码,似乎只设置了 overall(非单印)的数据
|
||||||
scaleO.set(priority - 1, p.getScale());
|
// 如果需要设置单印,请取消下面的注释并添加对应的字段
|
||||||
angleO.set(priority - 1, p.getAngle());
|
// printOverall.setSingleLocation(locationS);
|
||||||
pathsO.set(priority - 1, p.getMinIOPath());
|
// printOverall.setSingleScale(scaleS);
|
||||||
|
// printOverall.setSingleAngle(angleS);
|
||||||
|
// printOverall.setSinglePath(pathsS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 处理非单印数据(整体印花)
|
||||||
|
if (!overallPrints.isEmpty()) {
|
||||||
|
List<List<Float>> locationO = new ArrayList<>();
|
||||||
|
List<List<Float>> scaleO = new ArrayList<>();
|
||||||
|
List<Double> angleO = new ArrayList<>();
|
||||||
|
List<String> pathsO = new ArrayList<>();
|
||||||
|
|
||||||
|
for (DesignSinglePrint p : overallPrints) {
|
||||||
|
setUriToMinioPath(p);
|
||||||
|
locationO.add(p.getLocation());
|
||||||
|
scaleO.add(p.getScale());
|
||||||
|
angleO.add(p.getAngle());
|
||||||
|
pathsO.add(p.getMinIOPath());
|
||||||
}
|
}
|
||||||
// log.info("本次print打点locations###{}###fileVO{}", p.getLocation(), JSON.toJSONString(fileVO));
|
|
||||||
});
|
|
||||||
/*locationS.removeAll(Collections.singleton(null));
|
|
||||||
scaleS.removeAll(Collections.singleton(null));
|
|
||||||
angleS.removeAll(Collections.singleton(null));
|
|
||||||
pathsS.removeAll(Collections.singleton(null));
|
|
||||||
printSingle.setLocation(locationS);
|
|
||||||
printSingle.setPrint_scale_list(scaleS);
|
|
||||||
printSingle.setPrint_angle_list(angleS);
|
|
||||||
printSingle.setPrint_path_list(pathsS);*/
|
|
||||||
|
|
||||||
locationO.removeAll(Collections.singleton(null));
|
|
||||||
scaleO.removeAll(Collections.singleton(null));
|
|
||||||
angleO.removeAll(Collections.singleton(null));
|
|
||||||
pathsO.removeAll(Collections.singleton(null));
|
|
||||||
printOverall.setLocation(locationO);
|
printOverall.setLocation(locationO);
|
||||||
printOverall.setPrint_scale_list(scaleO);
|
printOverall.setPrint_scale_list(scaleO);
|
||||||
printOverall.setPrint_angle_list(angleO);
|
printOverall.setPrint_angle_list(angleO);
|
||||||
printOverall.setPrint_path_list(pathsO);
|
printOverall.setPrint_path_list(pathsO);
|
||||||
|
}
|
||||||
|
|
||||||
return printToPython;
|
return printToPython;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package com.ai.da.service;
|
|||||||
|
|
||||||
import com.ai.da.model.dto.ContestantDTO;
|
import com.ai.da.model.dto.ContestantDTO;
|
||||||
import com.ai.da.model.vo.CheckOTPVO;
|
import com.ai.da.model.vo.CheckOTPVO;
|
||||||
|
import com.ai.da.model.vo.ContestantCountVO;
|
||||||
|
import com.ai.da.model.vo.PageVisitCountVO;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -41,10 +43,26 @@ public interface GlobalAwardService {
|
|||||||
byte[] exportContestantFilesAsZip(Integer minContestantNumber, Integer maxContestantNumber) throws Exception;
|
byte[] exportContestantFilesAsZip(Integer minContestantNumber, Integer maxContestantNumber) throws Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询参赛者总数
|
* 查询参赛者总数和最大参赛者编号
|
||||||
* @return 参赛者数量
|
* @return 参赛者数量和最大参赛者编号
|
||||||
*/
|
*/
|
||||||
long getContestantCount();
|
ContestantCountVO getContestantCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录比赛页面的访问量
|
||||||
|
* <ul>
|
||||||
|
* <li>rawVisitCount: 每次访问或刷新都计一次(不去重)</li>
|
||||||
|
* <li>uniqueVisitCount: 5秒内刷新只算一次(基于会话去重)</li>
|
||||||
|
* </ul>
|
||||||
|
* @param sessionId 会话ID(用于5秒去重判断)
|
||||||
|
*/
|
||||||
|
void recordPageVisit(String sessionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取比赛页面的两种访问量
|
||||||
|
* @return 原始访问量和去重访问量
|
||||||
|
*/
|
||||||
|
PageVisitCountVO getPageVisitCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -787,6 +787,14 @@ public class ConvenientInquiryServiceImpl extends ServiceImpl<QuestionnaireMappe
|
|||||||
queryWrapper.lt("create_date", queryUserConditionsVO.getEndTime());
|
queryWrapper.lt("create_date", queryUserConditionsVO.getEndTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Objects.isNull(queryUserConditionsVO.getSubscriptionPlanId())) {
|
||||||
|
queryWrapper.eq("subscription_plan_id", queryUserConditionsVO.getSubscriptionPlanId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Objects.isNull(queryUserConditionsVO.getOrganizationId())) {
|
||||||
|
queryWrapper.eq("organization_id", queryUserConditionsVO.getOrganizationId());
|
||||||
|
}
|
||||||
|
|
||||||
// 排序
|
// 排序
|
||||||
if (!StringUtils.isNullOrEmpty(queryUserConditionsVO.getOrder()) && !StringUtils.isNullOrEmpty(queryUserConditionsVO.getOrderBy())) {
|
if (!StringUtils.isNullOrEmpty(queryUserConditionsVO.getOrder()) && !StringUtils.isNullOrEmpty(queryUserConditionsVO.getOrderBy())) {
|
||||||
String orderBy = "id";
|
String orderBy = "id";
|
||||||
|
|||||||
@@ -756,7 +756,7 @@ public class DesignServiceImpl extends ServiceImpl<DesignMapper, Design> impleme
|
|||||||
print.setPosition("[0.0,0.0]");
|
print.setPosition("[0.0,0.0]");
|
||||||
// print.setScale(1d);
|
// print.setScale(1d);
|
||||||
// todo mark 将print默认scale置为0.3
|
// todo mark 将print默认scale置为0.3
|
||||||
print.setScale(Arrays.toString(new Float[]{0.3f, 0.3f}));
|
print.setScale(Arrays.toString(new Float[]{1.0f, 1.0f}));
|
||||||
print.setAngle(0.0);
|
print.setAngle(0.0);
|
||||||
print.setPriority(1);
|
print.setPriority(1);
|
||||||
QueryWrapper<CollectionElement> getPrintboardLevel2TypeQw = new QueryWrapper<>();
|
QueryWrapper<CollectionElement> getPrintboardLevel2TypeQw = new QueryWrapper<>();
|
||||||
|
|||||||
@@ -1553,11 +1553,11 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
|
|||||||
if (imagePath != null) {
|
if (imagePath != null) {
|
||||||
requestBuilder.image(finalImagePath1);
|
requestBuilder.image(finalImagePath1);
|
||||||
}
|
}
|
||||||
if (useModel.equals(ModelConstants.PRINTBOARD_HIGH_I2I)) {
|
if (useModel.equals(ModelConstants.PRINTBOARD_HIGH_I2I)|| useModel.equals(ModelConstants.PRINTBOARD_HIGH_T2I)) {
|
||||||
GenerateImagesRequest.OptimizePromptOptions optimizePromptOptions = new GenerateImagesRequest.OptimizePromptOptions();
|
GenerateImagesRequest.OptimizePromptOptions optimizePromptOptions = new GenerateImagesRequest.OptimizePromptOptions();
|
||||||
optimizePromptOptions.setMode("fast");
|
optimizePromptOptions.setMode("fast");
|
||||||
requestBuilder.optimizePromptOptions(optimizePromptOptions);
|
requestBuilder.optimizePromptOptions(optimizePromptOptions);
|
||||||
//由于PRINTBOARD_HIGH_I2I与PRINTBOARD_ADVANCED_I2I使用模型一致,为了区别积分扣除,PRINTBOARD_HIGH_I2I加入了-fast,但传入模型时需要去掉-fast,用PRINTBOARD_ADVANCED_I2I的常量做替代
|
//由于PRINTBOARD_HIGH_T2I,PRINTBOARD_HIGH_I2I与PRINTBOARD_ADVANCED_I2I使用模型一致,为了区别积分扣除,PRINTBOARD_HIGH_I2I加入了-fast或者-high,但传入模型时需要去掉-fast或者-high,用PRINTBOARD_ADVANCED_I2I的常量做替代
|
||||||
requestBuilder.model(ModelConstants.PRINTBOARD_ADVANCED_I2I);
|
requestBuilder.model(ModelConstants.PRINTBOARD_ADVANCED_I2I);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3934,11 +3934,48 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
|
|||||||
}
|
}
|
||||||
|
|
||||||
public byte[] downloadVideoOrImage(String url) {
|
public byte[] downloadVideoOrImage(String url) {
|
||||||
try (CloseableHttpClient client = HttpClients.createDefault();
|
int maxRetries = 3;
|
||||||
InputStream in = client.execute(new HttpGet(url)).getEntity().getContent()) {
|
int retryDelayMs = 1000;
|
||||||
return IOUtils.toByteArray(in);
|
IOException lastException = null;
|
||||||
|
|
||||||
|
for (int attempt = 1; attempt <= maxRetries; attempt++) {
|
||||||
|
try {
|
||||||
|
return downloadWithTimeout(url, 30000, 60000);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
lastException = e;
|
||||||
|
log.warn("下载失败 (尝试 {}/{}): {}", attempt, maxRetries, e.getMessage());
|
||||||
|
|
||||||
|
if (attempt < maxRetries) {
|
||||||
|
try {
|
||||||
|
Thread.sleep((long) retryDelayMs * attempt); // 递增延迟
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw new RuntimeException(ie);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException("下载失败,已重试 " + maxRetries + " 次", lastException);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] downloadWithTimeout(String url, int connectTimeout, int socketTimeout) throws IOException {
|
||||||
|
RequestConfig requestConfig = RequestConfig.custom()
|
||||||
|
.setConnectTimeout(connectTimeout)
|
||||||
|
.setSocketTimeout(socketTimeout)
|
||||||
|
.setConnectionRequestTimeout(connectTimeout)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
try (CloseableHttpClient client = HttpClients.custom()
|
||||||
|
.setDefaultRequestConfig(requestConfig)
|
||||||
|
.build();
|
||||||
|
CloseableHttpResponse response = client.execute(new HttpGet(url))) {
|
||||||
|
|
||||||
|
int statusCode = response.getStatusLine().getStatusCode();
|
||||||
|
if (statusCode != 200) {
|
||||||
|
throw new IOException("HTTP Error: " + statusCode);
|
||||||
|
}
|
||||||
|
return IOUtils.toByteArray(response.getEntity().getContent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import com.ai.da.mapper.primary.entity.Notification;
|
|||||||
import com.ai.da.model.dto.ContestantDTO;
|
import com.ai.da.model.dto.ContestantDTO;
|
||||||
import com.ai.da.model.dto.PublishSysNotificationDTO;
|
import com.ai.da.model.dto.PublishSysNotificationDTO;
|
||||||
import com.ai.da.model.vo.CheckOTPVO;
|
import com.ai.da.model.vo.CheckOTPVO;
|
||||||
|
import com.ai.da.model.vo.ContestantCountVO;
|
||||||
|
import com.ai.da.model.vo.PageVisitCountVO;
|
||||||
import com.ai.da.service.GlobalAwardService;
|
import com.ai.da.service.GlobalAwardService;
|
||||||
import com.ai.da.service.MessageCenterService;
|
import com.ai.da.service.MessageCenterService;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
@@ -185,6 +187,7 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
|
|||||||
.videoSize(request.getVideoSize())
|
.videoSize(request.getVideoSize())
|
||||||
.pdfSize(request.getPdfSize())
|
.pdfSize(request.getPdfSize())
|
||||||
.contestantNumber(nextNumber)
|
.contestantNumber(nextNumber)
|
||||||
|
.portfolioUrl(request.getPortfolioUrl())
|
||||||
.createdAt(now)
|
.createdAt(now)
|
||||||
.updatedAt(now)
|
.updatedAt(now)
|
||||||
.build();
|
.build();
|
||||||
@@ -225,6 +228,7 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
|
|||||||
existing.setVideoDuration(request.getVideoDuration());
|
existing.setVideoDuration(request.getVideoDuration());
|
||||||
existing.setVideoSize(request.getVideoSize());
|
existing.setVideoSize(request.getVideoSize());
|
||||||
existing.setPdfSize(request.getPdfSize());
|
existing.setPdfSize(request.getPdfSize());
|
||||||
|
existing.setPortfolioUrl(request.getPortfolioUrl());
|
||||||
existing.setUpdatedAt(now);
|
existing.setUpdatedAt(now);
|
||||||
contestantMapper.updateById(existing);
|
contestantMapper.updateById(existing);
|
||||||
resp.put("success", true);
|
resp.put("success", true);
|
||||||
@@ -242,7 +246,7 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
|
|||||||
String[] headers = new String[] {
|
String[] headers = new String[] {
|
||||||
"contestantNumber", "email", "firstName", "lastName", "gender", "occupation",
|
"contestantNumber", "email", "firstName", "lastName", "gender", "occupation",
|
||||||
"age", "countryRegionCity", "phoneNumber", "designTitle", "designDescription",
|
"age", "countryRegionCity", "phoneNumber", "designTitle", "designDescription",
|
||||||
"pdfPath", "videoPath", "videoDuration", "videoSizeMB", "pdfSizeMB", "createdAt", "updatedAt"
|
"pdfPath", "videoPath", "videoDuration", "videoSizeMB", "pdfSizeMB", "portfolioUrl", "createdAt", "updatedAt"
|
||||||
};
|
};
|
||||||
for (int i = 0; i < headers.length; i++) {
|
for (int i = 0; i < headers.length; i++) {
|
||||||
Cell c = header.createCell(i);
|
Cell c = header.createCell(i);
|
||||||
@@ -278,6 +282,7 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
|
|||||||
double pMb = cst.getPdfSize() / 1024.0 / 1024.0;
|
double pMb = cst.getPdfSize() / 1024.0 / 1024.0;
|
||||||
r.createCell(ci++).setCellValue(String.format("%.2f", pMb));
|
r.createCell(ci++).setCellValue(String.format("%.2f", pMb));
|
||||||
}
|
}
|
||||||
|
r.createCell(ci++).setCellValue(cst.getPortfolioUrl() == null ? "" : cst.getPortfolioUrl());
|
||||||
r.createCell(ci++).setCellValue(cst.getCreatedAt() == null ? "" : cst.getCreatedAt().toString());
|
r.createCell(ci++).setCellValue(cst.getCreatedAt() == null ? "" : cst.getCreatedAt().toString());
|
||||||
r.createCell(ci++).setCellValue(cst.getUpdatedAt() == null ? "" : cst.getUpdatedAt().toString());
|
r.createCell(ci++).setCellValue(cst.getUpdatedAt() == null ? "" : cst.getUpdatedAt().toString());
|
||||||
}
|
}
|
||||||
@@ -307,7 +312,7 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
|
|||||||
String[] headers = new String[] {
|
String[] headers = new String[] {
|
||||||
"contestantNumber", "email", "firstName", "lastName", "gender", "occupation",
|
"contestantNumber", "email", "firstName", "lastName", "gender", "occupation",
|
||||||
"age", "countryRegionCity", "phoneNumber", "designTitle", "designDescription",
|
"age", "countryRegionCity", "phoneNumber", "designTitle", "designDescription",
|
||||||
"pdfPath", "videoPath", "videoDuration", "videoSizeMB", "pdfSizeMB", "createdAt", "updatedAt"
|
"pdfPath", "videoPath", "videoDuration", "videoSizeMB", "pdfSizeMB", "portfolioUrl", "createdAt", "updatedAt"
|
||||||
};
|
};
|
||||||
for (int i = 0; i < headers.length; i++) {
|
for (int i = 0; i < headers.length; i++) {
|
||||||
Cell c = header.createCell(i);
|
Cell c = header.createCell(i);
|
||||||
@@ -343,6 +348,7 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
|
|||||||
double pMb = cst.getPdfSize() / 1024.0 / 1024.0;
|
double pMb = cst.getPdfSize() / 1024.0 / 1024.0;
|
||||||
r.createCell(ci++).setCellValue(String.format("%.2f", pMb));
|
r.createCell(ci++).setCellValue(String.format("%.2f", pMb));
|
||||||
}
|
}
|
||||||
|
r.createCell(ci++).setCellValue(cst.getPortfolioUrl() == null ? "" : cst.getPortfolioUrl());
|
||||||
r.createCell(ci++).setCellValue(cst.getCreatedAt() == null ? "" : cst.getCreatedAt().toString());
|
r.createCell(ci++).setCellValue(cst.getCreatedAt() == null ? "" : cst.getCreatedAt().toString());
|
||||||
r.createCell(ci++).setCellValue(cst.getUpdatedAt() == null ? "" : cst.getUpdatedAt().toString());
|
r.createCell(ci++).setCellValue(cst.getUpdatedAt() == null ? "" : cst.getUpdatedAt().toString());
|
||||||
}
|
}
|
||||||
@@ -381,6 +387,7 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
|
|||||||
dto.setVideoDuration(existing.getVideoDuration());
|
dto.setVideoDuration(existing.getVideoDuration());
|
||||||
dto.setPdfSize(existing.getPdfSize());
|
dto.setPdfSize(existing.getPdfSize());
|
||||||
dto.setVideoSize(existing.getVideoSize());
|
dto.setVideoSize(existing.getVideoSize());
|
||||||
|
dto.setPortfolioUrl(existing.getPortfolioUrl());
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -542,6 +549,7 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
|
|||||||
sb.append("Video Path: ").append(nullSafe(videoPath)).append("\n");
|
sb.append("Video Path: ").append(nullSafe(videoPath)).append("\n");
|
||||||
sb.append("Video Duration (seconds): ").append(contestant.getVideoDuration() != null ? contestant.getVideoDuration() : "N/A").append("\n");
|
sb.append("Video Duration (seconds): ").append(contestant.getVideoDuration() != null ? contestant.getVideoDuration() : "N/A").append("\n");
|
||||||
sb.append("Video Size (bytes): ").append(contestant.getVideoSize() != null ? contestant.getVideoSize() : "N/A").append("\n");
|
sb.append("Video Size (bytes): ").append(contestant.getVideoSize() != null ? contestant.getVideoSize() : "N/A").append("\n");
|
||||||
|
sb.append("Portfolio URL: ").append(nullSafe(contestant.getPortfolioUrl())).append("\n");
|
||||||
sb.append("Created At: ").append(contestant.getCreatedAt() != null ? contestant.getCreatedAt() : "N/A").append("\n");
|
sb.append("Created At: ").append(contestant.getCreatedAt() != null ? contestant.getCreatedAt() : "N/A").append("\n");
|
||||||
sb.append("Updated At: ").append(contestant.getUpdatedAt() != null ? contestant.getUpdatedAt() : "N/A").append("\n");
|
sb.append("Updated At: ").append(contestant.getUpdatedAt() != null ? contestant.getUpdatedAt() : "N/A").append("\n");
|
||||||
|
|
||||||
@@ -592,13 +600,57 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getContestantCount() {
|
public ContestantCountVO getContestantCount() {
|
||||||
return contestantMapper.selectCount(null);
|
long count = contestantMapper.selectCount(null);
|
||||||
|
Integer maxContestantNumber = null;
|
||||||
|
QueryWrapper<Contestant> qMax = new QueryWrapper<>();
|
||||||
|
qMax.isNotNull("contestant_number");
|
||||||
|
qMax.orderByDesc("contestant_number");
|
||||||
|
qMax.last("LIMIT 1");
|
||||||
|
Contestant last = contestantMapper.selectOne(qMax);
|
||||||
|
if (last != null) {
|
||||||
|
maxContestantNumber = last.getContestantNumber();
|
||||||
|
}
|
||||||
|
return ContestantCountVO.builder()
|
||||||
|
.count(count)
|
||||||
|
.maxContestantNumber(maxContestantNumber)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String nullSafe(String value) {
|
private String nullSafe(String value) {
|
||||||
return value != null ? value : "N/A";
|
return value != null ? value : "N/A";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String RAW_VISIT_COUNT_KEY = "GLOBAL_AWARD:visit:raw";
|
||||||
|
private static final String UNIQUE_VISIT_SET_KEY = "GLOBAL_AWARD:visit:unique";
|
||||||
|
private static final String SESSION_VISIT_KEY_PREFIX = "GLOBAL_AWARD:visit:session:";
|
||||||
|
private static final long SESSION_DEDUP_SECONDS = 5L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recordPageVisit(String sessionId) {
|
||||||
|
redisUtil.increaseCount(RAW_VISIT_COUNT_KEY);
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(sessionId)) {
|
||||||
|
String sessionKey = SESSION_VISIT_KEY_PREFIX + sessionId;
|
||||||
|
if (!redisUtil.hasKey(sessionKey)) {
|
||||||
|
redisUtil.increaseCount(UNIQUE_VISIT_SET_KEY);
|
||||||
|
redisUtil.addToString(sessionKey, "1", SESSION_DEDUP_SECONDS);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
redisUtil.increaseCount(UNIQUE_VISIT_SET_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageVisitCountVO getPageVisitCount() {
|
||||||
|
Long raw = redisUtil.getIncrementCount(RAW_VISIT_COUNT_KEY);
|
||||||
|
Long unique = redisUtil.getIncrementCount(UNIQUE_VISIT_SET_KEY);
|
||||||
|
return PageVisitCountVO.builder()
|
||||||
|
.rawVisitCount(raw != null ? raw : 0L)
|
||||||
|
.uniqueVisitCount(unique != null ? unique : 0L)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理结束时间(只能延长)
|
* 处理结束时间,不允许订阅结束时间早于当前时间和订阅开始时间
|
||||||
*/
|
*/
|
||||||
private void handlePeriodEnd(UpdateSubscriptionPlanDTO dto, SubscriptionPlan plan) {
|
private void handlePeriodEnd(UpdateSubscriptionPlanDTO dto, SubscriptionPlan plan) {
|
||||||
Long newEnd = dto.getCurrentPeriodEnd();
|
Long newEnd = dto.getCurrentPeriodEnd();
|
||||||
@@ -177,15 +177,25 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newEnd < plan.getCurrentPeriodEnd()) {
|
long currentTimeSec = System.currentTimeMillis() / 1000;
|
||||||
|
long startTime = plan.getCurrentPeriodStart();
|
||||||
|
|
||||||
|
// 检查是否早于开始时间(不能等于,否则周期长度为0)
|
||||||
|
if (newEnd <= startTime) {
|
||||||
throw new BusinessException(
|
throw new BusinessException(
|
||||||
"the.subscription.end.date.can.be.extended.only.not.reduced"
|
"end.time.cannot.be.earlier.than.or.equal.to.start.time"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否早于当前时间(不能等于,否则立即过期)
|
||||||
|
if (newEnd <= currentTimeSec) {
|
||||||
|
throw new BusinessException(
|
||||||
|
"end.time.cannot.be.earlier.than.or.equal.to.the.current.time"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
plan.setCurrentPeriodEnd(newEnd);
|
plan.setCurrentPeriodEnd(newEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理账号数量
|
* 处理账号数量
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -210,6 +210,8 @@ please.specify.the.organizationId=Please specify the organizationId.
|
|||||||
switch.failed.sub-account.not.under.your.active.subscription=Switch failed. Sub-account not under your active subscription.
|
switch.failed.sub-account.not.under.your.active.subscription=Switch failed. Sub-account not under your active subscription.
|
||||||
Sub-accounts.cannot.be.admins=Sub-accounts in a subscription cannot be designated as admins.
|
Sub-accounts.cannot.be.admins=Sub-accounts in a subscription cannot be designated as admins.
|
||||||
only.subscription.plans.with.a.PENDING.status.can.have.their.start.time.modified=Only subscription plans with a PENDING status can have their start time modified.
|
only.subscription.plans.with.a.PENDING.status.can.have.their.start.time.modified=Only subscription plans with a PENDING status can have their start time modified.
|
||||||
|
end.time.cannot.be.earlier.than.or.equal.to.start.time=End time cannot be earlier than or equal to start time.
|
||||||
|
end.time.cannot.be.earlier.than.or.equal.to.the.current.time=End time cannot be earlier than or equal to the current time.
|
||||||
the.subscription.end.date.can.be.extended.only.not.reduced=The subscription end date can be extended only, not reduced.
|
the.subscription.end.date.can.be.extended.only.not.reduced=The subscription end date can be extended only, not reduced.
|
||||||
total.sub-account.quota.cannot.be.lower.than.existing.sub-accounts=Total sub-account quota cannot be lower than existing sub-accounts.
|
total.sub-account.quota.cannot.be.lower.than.existing.sub-accounts=Total sub-account quota cannot be lower than existing sub-accounts.
|
||||||
the.credit.limit.set.cannot.be.lower.than.the.amount.of.credits.already.used=The credit limit set cannot be lower than the amount of credits already used.
|
the.credit.limit.set.cannot.be.lower.than.the.amount.of.credits.already.used=The credit limit set cannot be lower than the amount of credits already used.
|
||||||
|
|||||||
@@ -206,6 +206,8 @@ please.specify.the.organizationId=请指定organizationId
|
|||||||
switch.failed.sub-account.not.under.your.active.subscription=切换失败,该子账号不属于您当前管理的订阅计划
|
switch.failed.sub-account.not.under.your.active.subscription=切换失败,该子账号不属于您当前管理的订阅计划
|
||||||
Sub-accounts.cannot.be.admins=在订阅中的子账号不能被指定为管理员
|
Sub-accounts.cannot.be.admins=在订阅中的子账号不能被指定为管理员
|
||||||
only.subscription.plans.with.a.PENDING.status.can.have.their.start.time.modified=只有PENDING状态的订阅计划可以修改订阅开始时间
|
only.subscription.plans.with.a.PENDING.status.can.have.their.start.time.modified=只有PENDING状态的订阅计划可以修改订阅开始时间
|
||||||
|
end.time.cannot.be.earlier.than.or.equal.to.start.time=订阅结束时间不能早于或等于开始时间
|
||||||
|
end.time.cannot.be.earlier.than.or.equal.to.the.current.time=结束时间不能早于或等于当前时间
|
||||||
the.subscription.end.date.can.be.extended.only.not.reduced=订阅的到期时间不能缩短,只能延长
|
the.subscription.end.date.can.be.extended.only.not.reduced=订阅的到期时间不能缩短,只能延长
|
||||||
total.sub-account.quota.cannot.be.lower.than.existing.sub-accounts=设置的子账号总数量不能低于现存已添加的子账号数量
|
total.sub-account.quota.cannot.be.lower.than.existing.sub-accounts=设置的子账号总数量不能低于现存已添加的子账号数量
|
||||||
the.credit.limit.set.cannot.be.lower.than.the.amount.of.credits.already.used=设置的积分上限不能低于已使用的积分量
|
the.credit.limit.set.cannot.be.lower.than.the.amount.of.credits.already.used=设置的积分上限不能低于已使用的积分量
|
||||||
|
|||||||
Reference in New Issue
Block a user