shinnosuke
2026-08-24 aedb037a68b925ef5f0229de1484d63db7e19da9
fix: expose admin approval window pdf
2个文件已修改
68 ■■■■■ 已修改文件
rencaika/pages/admin-approval/admin-approval.uvue 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
talent-card-server/src/main/java/com/talentcard/server/business/portal/AdminApprovalPortalService.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rencaika/pages/admin-approval/admin-approval.uvue
@@ -54,6 +54,32 @@
    const listLoaded = ref(false)
    const listError = ref(false)
    const uploadUrl = (value: any): string => {
        if (value == null) return ''
        if (typeof value == 'object') {
            const keys = ['url', 'path', 'fileUrl', 'file_url', 'downloadUrl', 'download_url']
            for (const key of keys) {
                if (value[key] != null && String(value[key]).trim() != '') return String(value[key]).trim()
            }
            return ''
        }
        return String(value).trim()
    }
    const normalizeOrganization = (source: any): any => {
        const item = source != null ? source : {}
        const keys = ['windowInfoUrl', 'window_info_url', 'pdfFile', 'pdf_file', 'windowInfo', 'window_info', 'windowFile', 'window_file', 'fileUrl', 'file_url']
        let windowInfoUrl = ''
        for (const key of keys) {
            const candidate = uploadUrl(item[key])
            if (candidate != '') { windowInfoUrl = candidate; break }
        }
        const normalized: any = { ...item }
        normalized.windowInfoUrl = windowInfoUrl
        normalized.hasWindowInfo = windowInfoUrl != ''
        if (normalized.phone == null) normalized.phone = ''
        return normalized
    }
    onLoad((options: any) => {
        // #ifdef MP-WEIXIN
        const capsule = uni.getMenuButtonBoundingClientRect()
@@ -77,7 +103,7 @@
            heroImage.value = data.heroImage != null && data.heroImage != '' ? resolveApiUrl(data.heroImage as string) : ''
            benefitAvailable.value = data.available === true
            unavailableReason.value = data.unavailableReason || '该权益暂未开放'
            orgs.value = data.organizations instanceof Array ? data.organizations as any[] : []
            orgs.value = data.organizations instanceof Array ? (data.organizations as any[]).map(normalizeOrganization) : []
            listLoading.value = false
            listLoaded.value = true
        }, () => { listLoading.value = false; listError.value = true })
@@ -86,12 +112,13 @@
    const replaceHero = () => { heroImage.value = '' }
    const callOrg = (item: any) => { if (item.phone == null || item.phone == '') { uni.showToast({ title: '机构暂未提供咨询电话', icon: 'none' }); return }; uni.makePhoneCall({ phoneNumber: item.phone, fail: () => uni.showToast({ title: '暂时无法拨打电话', icon: 'none' }) }) }
    const openWindowInfo = (item: any) => {
        const source = item != null && item.windowInfoUrl != null ? String(item.windowInfoUrl) : ''
        const normalized = normalizeOrganization(item)
        const source = normalized.windowInfoUrl
        if (source == '') {
            uni.showToast({ title: '窗口信息文件暂未配置', icon: 'none' })
            return
        }
        const url = resolveApiUrl(source)
        const url = resolveApiUrl(source.indexOf('/') == 0 || source.indexOf('http://') == 0 || source.indexOf('https://') == 0 ? source : '/' + source)
        uni.showLoading({ title: '正在打开文件', mask: true })
        uni.downloadFile({
            url: url,
talent-card-server/src/main/java/com/talentcard/server/business/portal/AdminApprovalPortalService.java
@@ -67,7 +67,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 +160,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();
    }
}