13404089107
2026-04-24 e24c81afde61a58d297f4b378fae95fe3385984e
tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/share/service/AppShareService.java
@@ -17,6 +17,7 @@
import com.tcm.training.admin.system.service.AppVersionSettingsAppService;
import com.tcm.training.admin.system.vo.AppVersionCheckVO;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
@@ -69,6 +70,7 @@
        result.setClinicName(trimToEmpty(clinic.getName()));
        result.setInviteCode(inviteCode);
        result.setShareLandingUrl(shareLandingUrl);
        result.setQrCodeImageUrl(buildQrCodeImageUrl(inviteCode));
        result.setQrCodeDataUrl(buildQrCodeDataUrl(shareLandingUrl));
        result.setBoundUsers(listBoundUsers(doctorUser));
        return result;
@@ -200,6 +202,46 @@
    }
    /**
     * 构建二维码图片公开访问地址。
     */
    private String buildQrCodeImageUrl(String inviteCode) {
        String landingBaseUrl = trimToNull(appShareProperties.getLandingBaseUrl());
        if (landingBaseUrl == null) {
            throw new IllegalArgumentException("邀请下载页地址暂未配置");
        }
        int schemeIndex = landingBaseUrl.indexOf("://");
        if (schemeIndex < 0) {
            throw new IllegalArgumentException("邀请下载页地址格式不正确");
        }
        int hostEndIndex = landingBaseUrl.indexOf('/', schemeIndex + 3);
        String origin = hostEndIndex >= 0 ? landingBaseUrl.substring(0, hostEndIndex) : landingBaseUrl;
        String normalizedInviteCode = trimToNull(inviteCode);
        if (!StringUtils.hasText(normalizedInviteCode)) {
            throw new IllegalArgumentException("邀请码不能为空");
        }
        return origin + "/api/open/app-share/qrcode-image?inviteCode=" + normalizedInviteCode;
    }
    /**
     * 生成二维码 PNG 图片字节流。
     */
    public byte[] generateQrcodeImage(String inviteCode) {
        Clinic clinic = findClinicByInviteCode(inviteCode);
        if (clinic == null) {
            throw new IllegalArgumentException("邀请码无效");
        }
        String shareLandingUrl = buildShareLandingUrl(requireInviteCode(clinic));
        try {
            BufferedImage image = QrCodeUtil.generate(shareLandingUrl, 400, 400);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImgUtil.write(image, "png", outputStream);
            return outputStream.toByteArray();
        } catch (Exception ex) {
            throw new IllegalArgumentException("生成分享二维码失败");
        }
    }
    /**
     * 构建绑定用户展示项。
     */
    private AppShareBoundUserItemVO toBoundUserItem(AppUser user) {