2026-04-21 22:07:29 +08:00
|
|
|
package com.xuqm.update.controller;
|
|
|
|
|
|
|
|
|
|
import com.xuqm.common.model.ApiResponse;
|
|
|
|
|
import com.xuqm.update.entity.AppVersionEntity;
|
|
|
|
|
import com.xuqm.update.repository.AppVersionRepository;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
|
|
import org.springframework.http.ResponseEntity;
|
2026-04-24 16:16:33 +08:00
|
|
|
import org.springframework.web.bind.annotation.*;
|
2026-04-21 22:07:29 +08:00
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.nio.file.Files;
|
|
|
|
|
import java.nio.file.Path;
|
|
|
|
|
import java.nio.file.Paths;
|
|
|
|
|
import java.time.LocalDateTime;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Optional;
|
|
|
|
|
import java.util.UUID;
|
|
|
|
|
|
|
|
|
|
@RestController
|
|
|
|
|
@RequestMapping("/api/v1/updates")
|
|
|
|
|
public class AppVersionController {
|
|
|
|
|
|
|
|
|
|
private final AppVersionRepository versionRepository;
|
|
|
|
|
|
|
|
|
|
@Value("${update.upload-dir:/tmp/xuqm-update}")
|
|
|
|
|
private String uploadDir;
|
|
|
|
|
|
|
|
|
|
@Value("${update.base-url:http://localhost:8084}")
|
|
|
|
|
private String baseUrl;
|
|
|
|
|
|
|
|
|
|
public AppVersionController(AppVersionRepository versionRepository) {
|
|
|
|
|
this.versionRepository = versionRepository;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@GetMapping("/app/check")
|
|
|
|
|
public ResponseEntity<ApiResponse<Map<String, Object>>> checkUpdate(
|
|
|
|
|
@RequestParam String appId,
|
|
|
|
|
@RequestParam AppVersionEntity.Platform platform,
|
|
|
|
|
@RequestParam int currentVersionCode) {
|
|
|
|
|
|
|
|
|
|
Optional<AppVersionEntity> latest = versionRepository
|
|
|
|
|
.findTopByAppIdAndPlatformAndPublishStatusOrderByVersionCodeDesc(
|
|
|
|
|
appId, platform, AppVersionEntity.PublishStatus.PUBLISHED);
|
|
|
|
|
|
|
|
|
|
if (latest.isEmpty() || latest.get().getVersionCode() <= currentVersionCode) {
|
|
|
|
|
return ResponseEntity.ok(ApiResponse.success(Map.of("needsUpdate", false)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AppVersionEntity v = latest.get();
|
|
|
|
|
return ResponseEntity.ok(ApiResponse.success(Map.of(
|
|
|
|
|
"needsUpdate", true,
|
|
|
|
|
"versionName", v.getVersionName(),
|
|
|
|
|
"versionCode", v.getVersionCode(),
|
|
|
|
|
"downloadUrl", v.getDownloadUrl() != null ? v.getDownloadUrl() : "",
|
|
|
|
|
"changeLog", v.getChangeLog() != null ? v.getChangeLog() : "",
|
|
|
|
|
"forceUpdate", v.isForceUpdate(),
|
|
|
|
|
"appStoreUrl", v.getAppStoreUrl() != null ? v.getAppStoreUrl() : "",
|
|
|
|
|
"marketUrl", v.getMarketUrl() != null ? v.getMarketUrl() : ""
|
|
|
|
|
)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@PostMapping("/app/upload")
|
|
|
|
|
public ResponseEntity<ApiResponse<AppVersionEntity>> upload(
|
|
|
|
|
@RequestParam String appId,
|
|
|
|
|
@RequestParam AppVersionEntity.Platform platform,
|
|
|
|
|
@RequestParam String versionName,
|
|
|
|
|
@RequestParam int versionCode,
|
|
|
|
|
@RequestParam(required = false) String changeLog,
|
|
|
|
|
@RequestParam(defaultValue = "false") boolean forceUpdate,
|
|
|
|
|
@RequestParam(required = false) MultipartFile apkFile) throws IOException {
|
|
|
|
|
|
|
|
|
|
String downloadUrl = null;
|
|
|
|
|
if (apkFile != null && !apkFile.isEmpty()) {
|
|
|
|
|
String filename = UUID.randomUUID() + "_" + apkFile.getOriginalFilename();
|
|
|
|
|
Path dir = Paths.get(uploadDir, "apk");
|
|
|
|
|
Files.createDirectories(dir);
|
|
|
|
|
Path dest = dir.resolve(filename);
|
|
|
|
|
apkFile.transferTo(dest.toFile());
|
|
|
|
|
downloadUrl = baseUrl + "/files/apk/" + filename;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AppVersionEntity entity = new AppVersionEntity();
|
|
|
|
|
entity.setId(UUID.randomUUID().toString());
|
|
|
|
|
entity.setAppId(appId);
|
|
|
|
|
entity.setPlatform(platform);
|
|
|
|
|
entity.setVersionName(versionName);
|
|
|
|
|
entity.setVersionCode(versionCode);
|
|
|
|
|
entity.setDownloadUrl(downloadUrl);
|
|
|
|
|
entity.setChangeLog(changeLog);
|
|
|
|
|
entity.setForceUpdate(forceUpdate);
|
|
|
|
|
entity.setPublishStatus(AppVersionEntity.PublishStatus.DRAFT);
|
|
|
|
|
entity.setCreatedAt(LocalDateTime.now());
|
|
|
|
|
return ResponseEntity.ok(ApiResponse.success(versionRepository.save(entity)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@PostMapping("/app/{id}/publish")
|
|
|
|
|
public ResponseEntity<ApiResponse<AppVersionEntity>> publish(@PathVariable String id) {
|
|
|
|
|
AppVersionEntity entity = versionRepository.findById(id).orElseThrow();
|
|
|
|
|
entity.setPublishStatus(AppVersionEntity.PublishStatus.PUBLISHED);
|
2026-04-24 16:16:33 +08:00
|
|
|
entity.setGrayEnabled(false);
|
|
|
|
|
entity.setGrayPercent(0);
|
|
|
|
|
return ResponseEntity.ok(ApiResponse.success(versionRepository.save(entity)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@PostMapping("/app/{id}/unpublish")
|
|
|
|
|
public ResponseEntity<ApiResponse<AppVersionEntity>> unpublish(@PathVariable String id) {
|
|
|
|
|
AppVersionEntity entity = versionRepository.findById(id).orElseThrow();
|
|
|
|
|
entity.setPublishStatus(AppVersionEntity.PublishStatus.DEPRECATED);
|
|
|
|
|
return ResponseEntity.ok(ApiResponse.success(versionRepository.save(entity)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@PostMapping("/app/{id}/gray")
|
|
|
|
|
public ResponseEntity<ApiResponse<AppVersionEntity>> gray(
|
|
|
|
|
@PathVariable String id,
|
|
|
|
|
@RequestBody Map<String, Object> body) {
|
|
|
|
|
AppVersionEntity entity = versionRepository.findById(id).orElseThrow();
|
|
|
|
|
entity.setGrayEnabled(Boolean.TRUE.equals(body.get("enabled")));
|
|
|
|
|
entity.setGrayPercent(body.get("percent") instanceof Number n ? n.intValue() : 0);
|
|
|
|
|
entity.setPublishStatus(AppVersionEntity.PublishStatus.PUBLISHED);
|
2026-04-21 22:07:29 +08:00
|
|
|
return ResponseEntity.ok(ApiResponse.success(versionRepository.save(entity)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@GetMapping("/app/list")
|
|
|
|
|
public ResponseEntity<ApiResponse<List<AppVersionEntity>>> list(
|
|
|
|
|
@RequestParam String appId, @RequestParam AppVersionEntity.Platform platform) {
|
|
|
|
|
return ResponseEntity.ok(ApiResponse.success(
|
|
|
|
|
versionRepository.findByAppIdAndPlatformOrderByVersionCodeDesc(appId, platform)));
|
|
|
|
|
}
|
|
|
|
|
}
|