刘帅
2026-09-29 b55cd9aad0835a96a790e61f9f89edc2fae1be9f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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.beans.factory.annotation.Autowired;
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 javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
 
/** 对外下载引导页与 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<Map<String, Object>> guideConfig(String code) {
        AppGuideConfig config = appGuideConfigMapper.selectOne(new QueryWrapper<AppGuideConfig>()
                .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<String, Object> 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<AppGuideBanner>()
                .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<Map<String, Object>> 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<QrLink>()
                .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<String, Object> target(QrLink link) {
        Map<String, Object> target = new HashMap<>();
        target.put("pageName", link.getPageName());
        Map<String, Object> 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();
        }
    }
}