shinnosuke
2026-09-21 7844f5af457ff3b7d3f8eeac8799e8d281e635a1
talent-card-server/src/main/java/com/talentcard/server/business/portal/AdminApprovalPortalService.java
@@ -34,7 +34,10 @@
        result.put("serviceId", serviceId);
        result.put("title", benefit.get("title"));
        result.put("freeLabel", benefit.get("freeLabel"));
        // 行政审批详情页顶部直接用商家封面图(后台不再单独配置「详情页图片」);
        // 商家没配封面时再回落服务权益里的全局图。
        result.put("heroImage", text(merchant.get("coverUrl"), text(benefit.get("heroImage"))));
        result.put("heroImages", List.of());
        result.put("available", number(benefit.get("enabled")) == 1 && number(merchant.get("status")) == 1);
        result.put("unavailableReason", text(benefit.get("unavailableReason"), "该权益暂未开放"));
        List<Map<String, Object>> configuredOrganizations = configuredOrganizations(merchant);
@@ -67,7 +70,10 @@
            organization.put("description", text(item.get("content"), text(merchant.get("rightsText"), "暂无权益说明")));
            organization.put("phone", text(item.get("phone"), text(merchant.get("contactMobile"))));
            organization.put("officeHours", "");
            String windowInfoUrl = text(item.get("windowInfoUrl"), text(item.get("pdfFile"), text(item.get("pdf_file"))));
            String windowInfoUrl = firstText(item,
                    "windowInfoUrl", "window_info_url", "pdfFile", "pdf_file",
                    "windowInfo", "window_info", "windowFile", "window_file",
                    "fileUrl", "file_url");
            organization.put("windowInfoUrl", windowInfoUrl);
            organization.put("windows", List.of());
            organization.put("hasWindowInfo", !windowInfoUrl.isBlank());
@@ -157,4 +163,34 @@
        String valueText = text(value).trim();
        return valueText.isBlank() ? fallback : valueText;
    }
    /**
     * Window PDFs were stored under several names while the admin form was
     * being rolled out. Keep the portal contract stable by resolving the
     * first non-empty URL from all supported names (including nested upload
     * response objects).
     */
    private String firstText(Map<String, Object> source, String... keys) {
        for (String key : keys) {
            Object value = source.get(key);
            String resolved = uploadUrl(value);
            if (!resolved.isBlank()) return resolved;
        }
        return "";
    }
    @SuppressWarnings("unchecked")
    private String uploadUrl(Object value) {
        if (value instanceof Map<?, ?> map) {
            for (String key : List.of("url", "path", "fileUrl", "file_url", "downloadUrl", "download_url")) {
                Object nested = map.get(key);
                if (nested != null) {
                    String resolved = text(nested).trim();
                    if (!resolved.isBlank()) return resolved;
                }
            }
            return "";
        }
        return text(value).trim();
    }
}