package com.dsh.other.controller; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.dsh.other.entity.AppGuideBanner; import com.dsh.other.entity.AppGuideConfig; import com.dsh.other.entity.QrLink; import com.dsh.other.enums.EnableStatusEnum; import com.dsh.other.enums.QrLinkTypeEnum; import com.dsh.other.mapper.AppGuideBannerMapper; import com.dsh.other.mapper.AppGuideConfigMapper; import com.dsh.other.mapper.QrLinkMapper; import com.dsh.other.util.ResultUtil; import com.dsh.other.util.TokenUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.apache.commons.lang3.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.beans.factory.annotation.Autowired; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import javax.annotation.Resource; import java.util.*; /** 对外下载引导页与 App 扫码解析接口。 */ @RestController @Api(tags = "APP下载引导与场地二维码") public class AppGuideController { @Autowired private AppGuideConfigMapper appGuideConfigMapper; @Autowired private AppGuideBannerMapper appGuideBannerMapper; @Autowired private QrLinkMapper qrLinkMapper; @Autowired private TokenUtil tokenUtil; // @GetMapping("/q/{shortCode}") // public void guidePage(@PathVariable String shortCode, HttpServletRequest request, // HttpServletResponse response) throws IOException { // // 仅重定向到静态 H5;避免 String 被 MVC 当作视图名并触发 LocaleResolver。 // String code = shortCode.replaceAll("[^A-Za-z0-9]", ""); // response.sendRedirect(request.getContextPath() + "/app-guide.html?code=" + code); // } @RequestMapping("/public/app-guide/config") @ApiOperation("获取下载引导页配置(无需登录)") public ResultUtil> guideConfig(String code) { AppGuideConfig config = appGuideConfigMapper.selectOne(new QueryWrapper() .eq("enabled", EnableStatusEnum.ENABLED.getCode()).orderByDesc("updateTime").last("limit 1")); if (config == null) return ResultUtil.error("下载引导页尚未配置"); QrLink link = validLink(code); if (code != null && !code.isEmpty() && link == null) return ResultUtil.error("二维码无效或已失效"); Map data = new HashMap<>(); data.put("appName", StringUtils.isNotBlank(config.getAppName()) ? config.getAppName() : "玩湃生活"); data.put("androidPackage", StringUtils.isNotBlank(config.getAndroidPackage()) ? config.getAndroidPackage() : "com.sinata.wepark"); data.put("iosPackage", StringUtils.isNotBlank(config.getIosPackage()) ? config.getIosPackage() : "com.sinata.WeParkLife"); data.put("iosStoreUrl", config.getIosStoreUrl()); data.put("apkUrl", config.getApkUrl()); data.put("androidDeepLink", config.getAndroidDeepLink() + (StringUtils.isNotBlank(code) ? "?route=" + code : "")); data.put("iosDeepLink", "weparklife://app" + (StringUtils.isNotBlank(code) ? "?code=" + code : "")); data.put("banners", appGuideBannerMapper.selectList(new QueryWrapper() .eq("enabled", EnableStatusEnum.ENABLED.getCode()).orderByAsc("sort").orderByDesc("id"))); // if (link != null) data.put("target", target(link)); return ResultUtil.success(data); } @RequestMapping("/api/qr/resolve") @ApiOperation("App扫码解析二维码") public ResultUtil> resolve(String code) { QrLink link = validLink(code); if (link == null) return ResultUtil.error("二维码无效或已失效"); return ResultUtil.success(target(link)); } private QrLink validLink(String code) { if (code == null || !code.matches("[A-Za-z0-9]{6,32}")) return null; QrLink link = qrLinkMapper.selectOne(new QueryWrapper().eq("shortCode", code).last("limit 1")); if (link == null || !Integer.valueOf(1).equals(link.getEnabled()) || (link.getExpiresAt() != null && link.getExpiresAt().before(new Date()))) return null; return link; } private Map target(QrLink link) { Map target = new HashMap<>(); target.put("pageName", link.getPageName()); Map params = new HashMap<>(); params.put("id", link.getSiteId().toString()); target.put("params", JSON.toJSONString(params)); return target; } private Object parseJson(String text) { if (text == null || text.trim().isEmpty()) return Collections.emptyMap(); try { return JSON.parseObject(text); } catch (Exception ignored) { return Collections.emptyMap(); } } }