chore: initialize qiming workspace repository

This commit is contained in:
Codex
2026-05-29 14:22:48 +08:00
commit bfd67a0f2c
10750 changed files with 1885711 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>app-platform-credit</artifactId>
<groupId>com.xspaceagi</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>app-platform-credit-web</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.xspaceagi</groupId>
<artifactId>app-platform-credit-application</artifactId>
</dependency>
<dependency>
<groupId>com.xspaceagi</groupId>
<artifactId>app-platform-credit-api</artifactId>
</dependency>
<dependency>
<groupId>com.xspaceagi</groupId>
<artifactId>app-platform-bill-sdk</artifactId>
</dependency>
<dependency>
<groupId>com.xspaceagi</groupId>
<artifactId>system-application</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,115 @@
package com.xspaceagi.credit.web.controller;
import com.xspaceagi.credit.app.service.CreditService;
import com.xspaceagi.credit.sdk.dto.*;
import com.xspaceagi.credit.spec.enums.CreditTypeEnum;
import com.xspaceagi.system.sdk.server.IUserRpcService;
import com.xspaceagi.system.sdk.service.dto.UserDetailDto;
import com.xspaceagi.system.spec.annotation.RequireResource;
import com.xspaceagi.system.spec.common.UserContext;
import com.xspaceagi.system.spec.dto.ReqResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.xspaceagi.system.spec.enums.ResourceEnum.SUBSCRIPTION_POINTS_MODIFY;
import static com.xspaceagi.system.spec.enums.ResourceEnum.SUBSCRIPTION_POINTS_QUERY;
@Slf4j
@RestController
@RequestMapping("/api/system/credit")
@Tag(name = "用户积分管理(管理端)")
public class CreditManController {
@Resource
private CreditService creditService;
@Resource
private IUserRpcService userRpcService;
@RequireResource(SUBSCRIPTION_POINTS_QUERY)
@GetMapping("/summary/list")
@Operation(summary = "用户积分查询")
public ReqResult<UserCreditSummaryPageDTO> getUserCreditSummary(@RequestParam(required = false) String usernamePhoneOrEmail,
@RequestParam(required = false) Long userId,
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "20") Integer pageSize) {
Long queryUserId = userId;
if (StringUtils.isNotBlank(usernamePhoneOrEmail)) {
UserDetailDto userDetailDto = userRpcService.queryUserDetailByName(usernamePhoneOrEmail);
if (userDetailDto != null) {
queryUserId = userDetailDto.getId();
} else {
UserCreditSummaryPageDTO emptyPage = new UserCreditSummaryPageDTO();
emptyPage.setRecords(List.of());
emptyPage.setTotal(0L);
emptyPage.setPageNum(pageNum);
emptyPage.setPageSize(pageSize);
return ReqResult.success(emptyPage);
}
}
UserCreditSummaryPageDTO page = creditService.queryUserCreditSummary(queryUserId, pageNum, pageSize);
if (!page.getRecords().isEmpty()) {
List<Long> userIds = page.getRecords().stream().map(UserCreditSummary::getUserId).distinct().collect(Collectors.toList());
List<UserContext> userContexts = userRpcService.queryUserListByIds(userIds);
Map<Long, UserContext> userContextMap = userContexts.stream().collect(Collectors.toMap(UserContext::getUserId, u -> u, (a, b) -> a));
page.getRecords().forEach(summary -> {
UserContext userContext = userContextMap.get(summary.getUserId());
if (userContext != null) {
summary.setUser(new CreditUser(userContext.getUserName(), userContext.getPhone(), userContext.getEmail()));
}
});
}
return ReqResult.success(page);
}
@RequireResource(SUBSCRIPTION_POINTS_QUERY)
@GetMapping("/flow/list")
@Operation(summary = "查询用户积分流水明细传入lastId翻页")
public ReqResult<List<CreditFlowDTO>> getCreditFlows(
@RequestParam(required = false) String usernamePhoneOrEmail,
@RequestParam(required = false) Long userId,
@RequestParam(required = false) CreditTypeEnum creditType,
@RequestParam(required = false) Long lastId,
@RequestParam(defaultValue = "20") Integer pageSize) {
UserDetailDto userDetailDto = null;
if (StringUtils.isNotBlank(usernamePhoneOrEmail)) {
userDetailDto = userRpcService.queryUserDetailByName(usernamePhoneOrEmail);
}
if (userId != null && userDetailDto == null) {
userDetailDto = userRpcService.queryUserDetailById(userId);
}
if (userDetailDto == null) {
return ReqResult.success(List.of());
}
List<CreditFlowDTO> creditFlows = creditService.getCreditFlows(userDetailDto.getId(), creditType, lastId == null ? Long.MAX_VALUE : lastId, pageSize);
for (CreditFlowDTO creditFlowDTO : creditFlows) {
creditFlowDTO.setUser(new CreditUser(userDetailDto.getUserName(), userDetailDto.getPhone(), userDetailDto.getEmail()));
}
return ReqResult.success(creditFlows);
}
@RequireResource(SUBSCRIPTION_POINTS_MODIFY)
@PostMapping("/add")
@Operation(summary = "积分发放")
public ReqResult<String> addCredit(@RequestBody CreditAddRequest request) {
request.setCreditType(request.getCreditType() == null || (request.getCreditType() != CreditTypeEnum.MANUAL && request.getCreditType() != CreditTypeEnum.ACTIVITY)
? CreditTypeEnum.MANUAL : request.getCreditType());//手动积分发放
return ReqResult.success(creditService.addCredit(request));
}
@RequireResource(SUBSCRIPTION_POINTS_MODIFY)
@PostMapping("/deduct")
@Operation(summary = "积分扣减")
public ReqResult<Boolean> deductCredit(@RequestBody CreditDeductRequest request) {
request.setCreditType(CreditTypeEnum.MANUAL_DEDUCT);
return ReqResult.success(creditService.deductCredit(request));
}
}

View File

@@ -0,0 +1,68 @@
package com.xspaceagi.credit.web.controller;
import com.xspaceagi.credit.app.service.CreditPackageService;
import com.xspaceagi.credit.sdk.dto.CreditPackageDTO;
import com.xspaceagi.credit.web.controller.dto.SortUpdateDTO;
import com.xspaceagi.system.spec.annotation.RequireResource;
import com.xspaceagi.system.spec.dto.ReqResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static com.xspaceagi.system.spec.enums.ResourceEnum.*;
@Slf4j
@RestController
@RequestMapping("/api/system/credit/package")
@Tag(name = "积分套餐管理(管理端)")
public class CreditPackageController {
@Resource
private CreditPackageService creditPackageService;
@RequireResource(SUBSCRIPTION_POINTS_MODIFY)
@PostMapping("/create")
@Operation(summary = "创建积分套餐")
public ReqResult<Long> createPackage(@RequestBody CreditPackageDTO dto) {
return ReqResult.success(creditPackageService.createPackage(dto));
}
@RequireResource(SUBSCRIPTION_POINTS_MODIFY)
@PostMapping("/update")
@Operation(summary = "更新积分套餐")
public ReqResult<Boolean> updatePackage(@RequestBody CreditPackageDTO dto) {
return ReqResult.success(creditPackageService.updatePackage(dto));
}
@RequireResource(SUBSCRIPTION_POINTS_MODIFY)
@PostMapping("/sort/update")
@Operation(summary = "更新积分套餐排序")
public ReqResult<Void> updatePackageSort(@RequestBody List<SortUpdateDTO> updateDTOS) {
updateDTOS.forEach(updateDTO -> {
CreditPackageDTO dto = new CreditPackageDTO();
dto.setId(updateDTO.getId());
dto.setSort(updateDTO.getSort());
creditPackageService.updatePackage(dto);
});
return ReqResult.success();
}
@RequireResource(SUBSCRIPTION_POINTS_DELETE)
@PostMapping("/{id}/delete")
@Operation(summary = "删除积分套餐")
public ReqResult<Boolean> deletePackage(@PathVariable Long id) {
return ReqResult.success(creditPackageService.deletePackage(id));
}
@RequireResource(SUBSCRIPTION_POINTS_QUERY)
@GetMapping("/list")
@Operation(summary = "查询积分套餐列表")
public ReqResult<List<CreditPackageDTO>> getPackageList(
@RequestParam(required = false) Integer status) {
return ReqResult.success(creditPackageService.getPackageList(status));
}
}

View File

@@ -0,0 +1,127 @@
package com.xspaceagi.credit.web.controller;
import com.alibaba.fastjson2.JSON;
import com.xspaceagi.bill.sdk.dto.CreateOrderRequest;
import com.xspaceagi.bill.sdk.dto.OrderDTO;
import com.xspaceagi.bill.sdk.rpc.IBillRpcService;
import com.xspaceagi.bill.spec.enums.BizTypeEnum;
import com.xspaceagi.bill.spec.enums.TargetTypeEnum;
import com.xspaceagi.credit.app.service.CreditPackageService;
import com.xspaceagi.credit.app.service.CreditService;
import com.xspaceagi.credit.sdk.dto.*;
import com.xspaceagi.credit.spec.enums.CreditTypeEnum;
import com.xspaceagi.system.application.dto.TenantConfigDto;
import com.xspaceagi.system.spec.common.RequestContext;
import com.xspaceagi.system.spec.dto.ReqResult;
import com.xspaceagi.system.spec.utils.I18nUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/api/credit")
@Tag(name = "用户积分相关接口")
public class UserCreditController {
@Resource
private CreditService creditService;
@Resource
private CreditPackageService creditPackageService;
@Resource
private IBillRpcService iBillRpcService;
@GetMapping("/summary")
@Operation(summary = "查询当前登录用户总积分")
public ReqResult<UserCreditSummary> getUserCreditSummary() {
TenantConfigDto tenantConfigDto = (TenantConfigDto) RequestContext.get().getTenantConfig();
int dailyGiftCredit = 0;
if (tenantConfigDto.getEnableDailyGiftCredit() != null && tenantConfigDto.getEnableDailyGiftCredit() == 1) {
dailyGiftCredit = tenantConfigDto.getDailyGiftCreditAmount() == null ? 0 : tenantConfigDto.getDailyGiftCreditAmount();
}
//每日积分发放bizNo一样只会发放一次
if (dailyGiftCredit > 0) {
String bizNo = "DGC" + RequestContext.get().getUserId() + "-" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
CreditAddRequest request = new CreditAddRequest();
request.setCreditType(CreditTypeEnum.ACTIVITY);
request.setUserId(RequestContext.get().getUserId());
request.setAmount(BigDecimal.valueOf(dailyGiftCredit));
request.setTenantId(RequestContext.get().getTenantId());
request.setBizNo(bizNo);
request.setExpireTime(Date.from(LocalDate.now().atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant()));
request.setRemark(I18nUtil.systemMessage("Backend.Credit.DailyGift.Remark"));
creditService.addCredit(request);
}
UserCreditSummary userCreditSummary = creditService.getUserCreditSummary(RequestContext.get().getUserId());
userCreditSummary.setDailyGiftCredit(BigDecimal.valueOf(dailyGiftCredit));
return ReqResult.success(userCreditSummary);
}
@GetMapping("/batches")
@Operation(summary = "查询用户积分批次列表")
public ReqResult<List<UserCreditBatchDTO>> getUserCreditBatches(
@RequestParam(required = false) CreditTypeEnum creditType,
@RequestParam(required = false) Boolean expired) {
return ReqResult.success(creditService.getUserCreditBatches(RequestContext.get().getUserId(), creditType, expired));
}
@GetMapping("/flows")
@Operation(summary = "查询用户积分流水明细")
public ReqResult<List<CreditFlowDTO>> getCreditFlows(
@RequestParam(required = false) CreditTypeEnum creditType,
@RequestParam(required = false) Long lastId,
@RequestParam(defaultValue = "20") Integer pageSize) {
return ReqResult.success(creditService.getCreditFlows(RequestContext.get().getUserId(), creditType, lastId == null ? Long.MAX_VALUE : lastId, pageSize));
}
@GetMapping("/package/list")
@Operation(summary = "查询可增购的积分套餐列表")
public ReqResult<List<CreditPackageDTO>> getPackageList() {
return ReqResult.success(creditPackageService.getPackageList(1));
}
@PostMapping("/order/create")
@Operation(summary = "创建积分增购订单")
public ReqResult<OrderDTO> createOrder(@RequestParam Long packageId, HttpServletRequest httpServletRequest) {
CreditPackageDTO packageById = creditPackageService.getPackageById(packageId);
if (packageById == null) {
return ReqResult.error(I18nUtil.systemMessage("Backend.Credit.Package.Error.NotFound"));
}
CreateOrderRequest request = new CreateOrderRequest();
request.setTenantId(RequestContext.get().getTenantId());
request.setUserId(RequestContext.get().getUserId());
request.setDescription(I18nUtil.systemMessage("Backend.Credit.Order.Description", packageById.getPackageName()));
request.setBizType(BizTypeEnum.CREDIT_PURCHASE);
CreateOrderRequest.CreateOrderItem item = new CreateOrderRequest.CreateOrderItem();
item.setTargetName(packageById.getPackageName());
item.setTargetType(TargetTypeEnum.CREDIT_PACKAGE.getCode());
item.setTargetId(packageById.getId());
item.setPrice(packageById.getPrice());
item.setCount(1);
item.setSnapshot(JSON.parseObject(JSON.toJSONString(packageById)));
request.setItems(List.of(item));
OrderDTO order = iBillRpcService.createOrder(request);
return ReqResult.success(order);
}
private Date addMonths(Date from, int months) {
Calendar cal = Calendar.getInstance();
cal.setTime(from);
cal.add(Calendar.MONTH, months);
return cal.getTime();
}
}

View File

@@ -0,0 +1,10 @@
package com.xspaceagi.credit.web.controller.dto;
import lombok.Data;
@Data
public class PayInfoDTO {
private Long orderId;
private String cashierUrl;
}

View File

@@ -0,0 +1,10 @@
package com.xspaceagi.credit.web.controller.dto;
import lombok.Data;
@Data
public class SortUpdateDTO {
private Long id;
private Integer sort;
}