Prechádzať zdrojové kódy

feat(service-role): 申请列表支持角色/状态过滤并补充用户信息

Xiaogang Liao 5 dní pred
rodič
commit
6c34e477c7

+ 5 - 3
cfc-backend/src/main/java/com/etotem/cfc/controller/ServiceRoleApplicationController.java

@@ -91,11 +91,13 @@ public class ServiceRoleApplicationController {
     @PostMapping("/admin/list")
     @Operation(summary = "管理端: 获取申请列表")
     public Result adminList(@RequestParam(required = false, defaultValue = "0") Integer status,
-                            @RequestAttribute("role") String role) {
-        if (!"admin".equals(role) && !"operator".equals(role)) {
+                            @RequestParam(required = false) String role,
+                            @RequestAttribute("role") String operatorRole) {
+        if (!"admin".equals(operatorRole) && !"operator".equals(operatorRole)) {
             return Result.error("无权限:仅管理员/运营可查看服务角色申请列表");
         }
-        List<ServiceRoleApplication> list = serviceRoleApplicationService.listApplications(status);
+        List<Map<String, Object>> list = serviceRoleApplicationService.listApplicationsWithUserInfo(
+                status, com.etotem.cfc.service.impl.ServiceRoleApplicationServiceImpl.parseRoleFilter(role));
         return Result.success(list);
     }
 

+ 2 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ServiceRoleApplicationService.java

@@ -6,6 +6,7 @@ import com.etotem.cfc.dto.ServiceRoleApplyDTO;
 import com.etotem.cfc.entity.ServiceRoleApplication;
 
 import java.util.List;
+import java.util.Map;
 
 public interface ServiceRoleApplicationService {
     Result submit(Long userId, ServiceRoleApplyDTO dto);
@@ -13,4 +14,5 @@ public interface ServiceRoleApplicationService {
     Result approve(Long id, Long reviewerId);
     Result reject(Long id, String reason, Long reviewerId);
     List<ServiceRoleApplication> listApplications(Integer status);
+    List<Map<String, Object>> listApplicationsWithUserInfo(Integer status, List<String> roleFilter);
 }

+ 100 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/impl/ServiceRoleApplicationServiceImpl.java

@@ -13,7 +13,15 @@ import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 @Service
 public class ServiceRoleApplicationServiceImpl
@@ -152,6 +160,98 @@ public class ServiceRoleApplicationServiceImpl
                 .orderByDesc(ServiceRoleApplication::getCreatedAt));
     }
 
+    @Override
+    public List<Map<String, Object>> listApplicationsWithUserInfo(Integer status, List<String> roleFilter) {
+        List<ServiceRoleApplication> apps = listApplications(status);
+        List<ServiceRoleApplication> filtered = new ArrayList<>();
+        boolean noFilter = roleFilter == null || roleFilter.isEmpty();
+        for (ServiceRoleApplication app : apps) {
+            if (noFilter || matchesAnyRole(app.getRoles(), roleFilter)) {
+                filtered.add(app);
+            }
+        }
+
+        Set<Long> userIds = filtered.stream()
+                .map(ServiceRoleApplication::getUserId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        Map<Long, User> userMap = new HashMap<>();
+        if (!userIds.isEmpty()) {
+            List<User> users = userMapper.selectBatchIds(userIds);
+            if (users != null) {
+                for (User u : users) {
+                    userMap.put(u.getId(), u);
+                }
+            }
+        }
+
+        List<Map<String, Object>> result = new ArrayList<>();
+        for (ServiceRoleApplication app : filtered) {
+            Map<String, Object> row = new LinkedHashMap<>();
+            row.put("id", app.getId());
+            row.put("userId", app.getUserId());
+            row.put("roles", app.getRoles());
+            row.put("idCard", app.getIdCard());
+            row.put("idCardImages", app.getIdCardImages());
+            row.put("certificateImages", app.getCertificateImages());
+            row.put("province", app.getProvince());
+            row.put("city", app.getCity());
+            row.put("district", app.getDistrict());
+            row.put("street", app.getStreet());
+            row.put("addressDetail", app.getAddressDetail());
+            row.put("status", app.getStatus());
+            row.put("rejectReason", app.getRejectReason());
+            row.put("createdAt", app.getCreatedAt());
+            row.put("reviewedAt", app.getReviewedAt());
+            User u = userMap.get(app.getUserId());
+            row.put("userName", u != null ? (u.getNickname() != null ? u.getNickname() : u.getRealName()) : null);
+            row.put("realName", u != null ? u.getRealName() : null);
+            row.put("phone", u != null ? u.getPhone() : null);
+            result.add(row);
+        }
+        return result;
+    }
+
+    /**
+     * 解析前端传入的角色过滤参数(逗号分隔),null/空白返回空列表。
+     */
+    public static List<String> parseRoleFilter(String roleParam) {
+        if (roleParam == null || roleParam.trim().isEmpty()) {
+            return Collections.emptyList();
+        }
+        List<String> roles = new ArrayList<>();
+        for (String part : roleParam.split(",")) {
+            String role = part.trim();
+            if (!role.isEmpty() && !roles.contains(role)) {
+                roles.add(role);
+            }
+        }
+        return roles;
+    }
+
+    /**
+     * 判断申请记录的角色 JSON 数组是否与目标角色有交集;解析失败按不匹配处理。
+     */
+    public static boolean matchesAnyRole(String rolesJson, List<String> targetRoles) {
+        if (rolesJson == null || targetRoles == null || targetRoles.isEmpty()) {
+            return false;
+        }
+        try {
+            List<String> roles = JSON.parseArray(rolesJson, String.class);
+            if (roles == null) {
+                return false;
+            }
+            for (String role : roles) {
+                if (targetRoles.contains(role)) {
+                    return true;
+                }
+            }
+            return false;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
     @Override
     @Transactional
     public Result reject(Long id, String reason, Long reviewerId) {

+ 34 - 0
cfc-backend/src/test/java/com/etotem/cfc/unit/ServiceRoleFilterTest.java

@@ -0,0 +1,34 @@
+package com.etotem.cfc.unit;
+
+import com.etotem.cfc.service.impl.ServiceRoleApplicationServiceImpl;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class ServiceRoleFilterTest {
+
+    @Test
+    void parseRoleFilter_null和空白返回空列表() {
+        assertEquals(Collections.emptyList(), ServiceRoleApplicationServiceImpl.parseRoleFilter(null));
+        assertEquals(Collections.emptyList(), ServiceRoleApplicationServiceImpl.parseRoleFilter("  "));
+    }
+
+    @Test
+    void parseRoleFilter_逗号分隔去空格去重() {
+        assertEquals(Arrays.asList("vendor", "activity_provider"),
+                ServiceRoleApplicationServiceImpl.parseRoleFilter(" vendor, activity_provider ,vendor "));
+    }
+
+    @Test
+    void matchesAnyRole_按JSON数组精确匹配() {
+        String json = "[\"activity_provider\"]";
+        assertTrue(ServiceRoleApplicationServiceImpl.matchesAnyRole(json, Arrays.asList("vendor", "activity_provider")));
+        assertFalse(ServiceRoleApplicationServiceImpl.matchesAnyRole(json, Arrays.asList("vendor")));
+        assertFalse(ServiceRoleApplicationServiceImpl.matchesAnyRole(json, Arrays.asList("planner")));
+        assertFalse(ServiceRoleApplicationServiceImpl.matchesAnyRole("not-json", Arrays.asList("vendor")));
+        assertFalse(ServiceRoleApplicationServiceImpl.matchesAnyRole(null, Arrays.asList("vendor")));
+    }
+}