|
|
@@ -12,6 +12,8 @@ import org.springframework.util.DigestUtils;
|
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+
|
|
|
import io.swagger.v3.oas.annotations.Operation;
|
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
|
|
@@ -71,6 +73,13 @@ public class AdminController {
|
|
|
@Resource
|
|
|
private AssessmentOrderMapper assessmentOrderMapper;
|
|
|
|
|
|
+ @Resource
|
|
|
+ private LifetimeStatsMapper lifetimeStatsMapper;
|
|
|
+
|
|
|
+ // 终身会员达标阈值(分)
|
|
|
+ private static final long LIFETIME_CONSUME_THRESHOLD = 100_000_000L; // 消费 ≥ 100万元
|
|
|
+ private static final long LIFETIME_SALES_THRESHOLD = 200_000_000L; // 销售 ≥ 200万元
|
|
|
+
|
|
|
// 用户管理
|
|
|
@PostMapping("/users")
|
|
|
public Result<Page<User>> getUsers(@RequestBody Map<String, Object> params) {
|
|
|
@@ -1059,6 +1068,10 @@ public class AdminController {
|
|
|
Long totalFamilyMemberships = familyMembershipMapper.selectCount(null);
|
|
|
overview.put("totalFamilyMemberships", totalFamilyMemberships);
|
|
|
|
|
|
+ // 终身会员数
|
|
|
+ Long lifetimeCount = userMapper.selectCount(new LambdaQueryWrapper<User>().eq(User::getMemberLevel, "LIFETIME"));
|
|
|
+ overview.put("lifetimeCount", lifetimeCount);
|
|
|
+
|
|
|
return Result.success(overview);
|
|
|
}
|
|
|
|
|
|
@@ -1066,14 +1079,138 @@ public class AdminController {
|
|
|
public Result<Page<MemberUpgradeRecord>> getUpgradeRecords(@RequestBody Map<String, Object> params) {
|
|
|
int page = params.get("page") != null ? ((Number) params.get("page")).intValue() : 1;
|
|
|
int size = params.get("size") != null ? ((Number) params.get("size")).intValue() : 10;
|
|
|
+ String toLevel = params.get("toLevel") != null ? params.get("toLevel").toString() : null;
|
|
|
+
|
|
|
+ LambdaQueryWrapper<MemberUpgradeRecord> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ if (toLevel != null && !toLevel.isEmpty()) {
|
|
|
+ wrapper.eq(MemberUpgradeRecord::getToLevel, toLevel);
|
|
|
+ }
|
|
|
+ wrapper.orderByDesc(MemberUpgradeRecord::getCreatedAt);
|
|
|
|
|
|
Page<MemberUpgradeRecord> pageParam = new Page<>(page, size);
|
|
|
- Page<MemberUpgradeRecord> result = memberUpgradeRecordMapper.selectPage(pageParam,
|
|
|
- new LambdaQueryWrapper<MemberUpgradeRecord>()
|
|
|
- .orderByDesc(MemberUpgradeRecord::getCreatedAt));
|
|
|
+ Page<MemberUpgradeRecord> result = memberUpgradeRecordMapper.selectPage(pageParam, wrapper);
|
|
|
return Result.success(result);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 终身会员候选人列表:365天滚动消费/销售额,返回达标用户
|
|
|
+ */
|
|
|
+ @PostMapping("/membership/lifetime-candidates")
|
|
|
+ public Result<Map<String, Object>> getLifetimeCandidates(@RequestBody(required = false) Map<String, Object> params) {
|
|
|
+ String cutoff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
|
|
|
+ .format(new Date(System.currentTimeMillis() - 365L * 24 * 60 * 60 * 1000));
|
|
|
+
|
|
|
+ List<Map<String, Object>> consumption = lifetimeStatsMapper.selectConsumptionSummary(cutoff);
|
|
|
+ List<Map<String, Object>> sales = lifetimeStatsMapper.selectSalesSummary(cutoff);
|
|
|
+
|
|
|
+ Map<Long, Long> consumeMap = new HashMap<>();
|
|
|
+ for (Map<String, Object> row : consumption) {
|
|
|
+ Number uid = (Number) row.get("userId");
|
|
|
+ Number amt = (Number) row.get("totalAmount");
|
|
|
+ if (uid != null) consumeMap.put(uid.longValue(), amt == null ? 0L : amt.longValue());
|
|
|
+ }
|
|
|
+ Map<Long, Long> salesMap = new HashMap<>();
|
|
|
+ for (Map<String, Object> row : sales) {
|
|
|
+ Number uid = (Number) row.get("userId");
|
|
|
+ Number amt = (Number) row.get("totalAmount");
|
|
|
+ if (uid != null) salesMap.put(uid.longValue(), amt == null ? 0L : amt.longValue());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 达标类型:consumption | sales | both
|
|
|
+ Map<Long, String> typeMap = new HashMap<>();
|
|
|
+ for (Long uid : consumeMap.keySet()) {
|
|
|
+ if (consumeMap.get(uid) >= LIFETIME_CONSUME_THRESHOLD) {
|
|
|
+ typeMap.put(uid, "consumption");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (Long uid : salesMap.keySet()) {
|
|
|
+ if (salesMap.get(uid) >= LIFETIME_SALES_THRESHOLD) {
|
|
|
+ String prev = typeMap.get(uid);
|
|
|
+ typeMap.put(uid, prev == null ? "sales" : "both");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Map<String, Object>> candidates = new ArrayList<>();
|
|
|
+ for (Map.Entry<Long, String> entry : typeMap.entrySet()) {
|
|
|
+ User user = userMapper.selectById(entry.getKey());
|
|
|
+ if (user == null || "LIFETIME".equals(user.getMemberLevel())) {
|
|
|
+ continue; // 已授予或用户不存在,跳过
|
|
|
+ }
|
|
|
+ Map<String, Object> item = new HashMap<>();
|
|
|
+ item.put("userId", entry.getKey());
|
|
|
+ item.put("nickname", user.getNickname());
|
|
|
+ item.put("consumptionAmount", consumeMap.getOrDefault(entry.getKey(), 0L));
|
|
|
+ item.put("salesAmount", salesMap.getOrDefault(entry.getKey(), 0L));
|
|
|
+ item.put("qualifiedType", entry.getValue());
|
|
|
+ candidates.add(item);
|
|
|
+ }
|
|
|
+ // 按消费额降序
|
|
|
+ candidates.sort((a, b) -> Long.compare(
|
|
|
+ ((Number) b.get("consumptionAmount")).longValue(),
|
|
|
+ ((Number) a.get("consumptionAmount")).longValue()));
|
|
|
+
|
|
|
+ // 分页(overall 量可控,内存分页即可)
|
|
|
+ int current = params != null && params.get("page") != null ? ((Number) params.get("page")).intValue() : 1;
|
|
|
+ int size = params != null && params.get("size") != null ? ((Number) params.get("size")).intValue() : 20;
|
|
|
+ int from = Math.min((current - 1) * size, candidates.size());
|
|
|
+ int to = Math.min(from + size, candidates.size());
|
|
|
+
|
|
|
+ Map<String, Object> data = new HashMap<>();
|
|
|
+ data.put("records", candidates.subList(from, to));
|
|
|
+ data.put("total", (long) candidates.size());
|
|
|
+ data.put("page", current);
|
|
|
+ data.put("size", size);
|
|
|
+ return Result.success(data);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 审核授予终身会员
|
|
|
+ */
|
|
|
+ @PostMapping("/membership/lifetime-grant")
|
|
|
+ public Result<Void> grantLifetime(@RequestBody Map<String, Object> params,
|
|
|
+ @RequestAttribute("userId") Long adminUserId,
|
|
|
+ @RequestAttribute("role") String role) {
|
|
|
+ if (!"admin".equals(role)) {
|
|
|
+ return Result.error("无权限");
|
|
|
+ }
|
|
|
+ if (params.get("userId") == null) {
|
|
|
+ return Result.error("参数缺失: userId");
|
|
|
+ }
|
|
|
+ Long targetUserId = ((Number) params.get("userId")).longValue();
|
|
|
+ String remark = params.get("remark") != null ? params.get("remark").toString() : "";
|
|
|
+
|
|
|
+ User user = userMapper.selectById(targetUserId);
|
|
|
+ if (user == null) {
|
|
|
+ return Result.error("用户不存在");
|
|
|
+ }
|
|
|
+ if ("LIFETIME".equals(user.getMemberLevel())) {
|
|
|
+ return Result.error("该用户已是终身会员");
|
|
|
+ }
|
|
|
+ String fromLevel = user.getMemberLevel() != null ? user.getMemberLevel() : "FREE";
|
|
|
+
|
|
|
+ // 1. 升级用户为 LIFETIME(memberExpireTime=null 永久有效)
|
|
|
+ user.setMemberLevel("LIFETIME");
|
|
|
+ user.setMemberExpireTime(null);
|
|
|
+ user.setUpdatedAt(new Date());
|
|
|
+ userMapper.updateById(user);
|
|
|
+
|
|
|
+ // 2. 写入升级记录 upgradeType='lifetime'
|
|
|
+ MemberUpgradeRecord record = new MemberUpgradeRecord();
|
|
|
+ record.setUserId(targetUserId);
|
|
|
+ record.setFromLevel(fromLevel);
|
|
|
+ record.setToLevel("LIFETIME");
|
|
|
+ record.setUpgradeType("lifetime");
|
|
|
+ record.setApproveUserId(adminUserId);
|
|
|
+ record.setApproveStatus("approved");
|
|
|
+ record.setApproveTime(new Date());
|
|
|
+ record.setApproveRemark(remark != null && !remark.isEmpty()
|
|
|
+ ? remark : "平台终身会员:管理员审核授予");
|
|
|
+ record.setCreatedAt(new Date());
|
|
|
+ memberUpgradeRecordMapper.insert(record);
|
|
|
+
|
|
|
+ return Result.success();
|
|
|
+ }
|
|
|
+
|
|
|
// ========== 测评待分配规划师 ==========
|
|
|
|
|
|
@PostMapping("/assessment/pending-list")
|