admin
2021-12-04 c79b1ebed5a42a4cbb2f824232da2a51ff22a9a1
功能完善
14个文件已修改
19个文件已添加
1998 ■■■■■ 已修改文件
app/pom.xml 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/Application.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/config/CrossConfig.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/controller/admin/feedback/AdviceAdminController.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/controller/admin/feedback/PrivacyComplainAdminController.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/controller/client/api/ConfigController.java 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/controller/client/api/FeedBackController.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/controller/client/api/LocationController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/controller/client/api/SOSController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/controller/client/api/UserController.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/dao/feedback/AdviceDao.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/dao/feedback/PrivacyComplainDao.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/entity/config/SystemConfigKey.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/entity/feedback/Advice.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/entity/feedback/PrivacyComplain.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/service/impl/feedback/AdviceServiceImpl.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/service/impl/feedback/PrivacyComplainServiceImpl.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/service/inter/feedback/AdviceService.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/service/inter/feedback/PrivacyComplainService.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/service/manager/VerifyCodeManager.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/service/query/feedback/AdviceQuery.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/service/query/feedback/PrivacyComplainQuery.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/utils/ThreadUtil.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/vo/AcceptData.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/yeshi/location/app/vo/sos/SOSRecordVO.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/resources/application-dev.yml 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/resources/cos.properties 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/resources/static/feedback/advice_list.html 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/resources/static/feedback/privacy_complain_list.html 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/resources/static/index.html 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/test/java/test/ConfigTest.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/test/java/test/GeneratorTest.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pom.xml
@@ -221,6 +221,30 @@
            <version>1.0.2</version>
        </dependency>
        <!-- 推送 -->
        <dependency>
            <groupId>com.ks</groupId>
            <artifactId>facade-push</artifactId>
            <version>0.0.2</version>
        </dependency>
        <dependency>
            <groupId>com.qcloud</groupId>
            <artifactId>cos_api</artifactId>
            <version>5.2.4</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
app/src/main/java/com/yeshi/location/app/Application.java
@@ -9,6 +9,11 @@
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.yeshi.utils.mq.JobThreadExecutorServiceImpl;
import org.yeshi.utils.tencentcloud.COSManager;
import org.yeshi.utils.tencentcloud.entity.COSInitParams;
import java.util.Properties;
//不引入数据库
//@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class,DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class
//        , DruidDataSourceAutoConfigure.class, HibernateJpaAutoConfiguration.class})
@@ -28,6 +33,7 @@
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        logger.info("容器加载完毕");
        initCOS();
        initMQMsgConsumer();
    }
@@ -45,4 +51,23 @@
        }
    }
    /**
     * 对象存储初始化
     */
    public static void initCOS() {
        // 载入cos参数
        Properties ps = org.yeshi.utils.PropertiesUtil
                .getProperties(Application.class.getClassLoader().getResourceAsStream("cos.properties"));
        COSInitParams params = new COSInitParams();
        params.setAppId(Long.parseLong(ps.getProperty("appId")));
        params.setBucketName(ps.getProperty("bucketName"));
        params.setRegion(ps.getProperty("region"));
        params.setSecretId(ps.getProperty("secretId"));
        params.setSecretKey(ps.getProperty("secretKey"));
        // 初始化
        COSManager.getInstance().init(params);
    }
}
app/src/main/java/com/yeshi/location/app/config/CrossConfig.java
New file
@@ -0,0 +1,19 @@
package com.yeshi.location.app.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CrossConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                .allowCredentials(true)
                .maxAge(3600)
                .allowedHeaders("*");
    }
}
app/src/main/java/com/yeshi/location/app/controller/admin/feedback/AdviceAdminController.java
New file
@@ -0,0 +1,69 @@
package com.yeshi.location.app.controller.admin.feedback;
import com.google.gson.*;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.TimeUtil;
import com.google.gson.reflect.TypeToken;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.List;
import com.yeshi.location.app.entity.feedback.Advice;
import com.yeshi.location.app.service.inter.feedback.AdviceService;
import com.yeshi.location.app.service.query.feedback.AdviceQuery;
@Controller
@RequestMapping("/admin/api/feedback/advice")
public class AdviceAdminController {
    @Resource
    private AdviceService adviceService;
    private String loadPrint(String callback, String root){
          return root;
    }
    @ResponseBody
    @RequestMapping("list")
    public String list(AdviceQuery query, int page, int limit, String callback) {
        List<Advice> list = adviceService.list(query,page,limit);
        long count = adviceService.count(query);
        JSONObject data = new JSONObject();
        Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new JsonSerializer<Date>() {
            @Override
            public JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) {
                return date == null ? new JsonPrimitive("") : new JsonPrimitive(TimeUtil.getGernalTime(date.getTime(), "yyyy.MM.dd HH:mm"));
            }
        }).create();
        data.put("list", gson.toJson(list));
        data.put("count", count);
        return loadPrint(callback,JsonUtil.loadTrueResult(data));
    }
    @ResponseBody
    @RequestMapping("get")
    public String get(String id, HttpSession session, String callback) {
        Advice entity = adviceService.get(id);
        if (entity !=null){
            return loadPrint(callback,JsonUtil.loadTrueResult(entity));
        } else {
            return loadPrint(callback,JsonUtil.loadFalseResult("ID不存在"));
        }
    }
}
app/src/main/java/com/yeshi/location/app/controller/admin/feedback/PrivacyComplainAdminController.java
New file
@@ -0,0 +1,69 @@
package com.yeshi.location.app.controller.admin.feedback;
import com.google.gson.*;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.TimeUtil;
import com.google.gson.reflect.TypeToken;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.List;
import com.yeshi.location.app.entity.feedback.PrivacyComplain;
import com.yeshi.location.app.service.inter.feedback.PrivacyComplainService;
import com.yeshi.location.app.service.query.feedback.PrivacyComplainQuery;
@Controller
@RequestMapping("/admin/api/feedback/privacy")
public class PrivacyComplainAdminController {
    @Resource
    private PrivacyComplainService privacyComplainService;
    private String loadPrint(String callback, String root){
          return root;
    }
    @ResponseBody
    @RequestMapping("list")
    public String list(PrivacyComplainQuery query, int page, int limit, String callback) {
        List<PrivacyComplain> list = privacyComplainService.list(query,page,limit);
        long count = privacyComplainService.count(query);
        JSONObject data = new JSONObject();
        Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new JsonSerializer<Date>() {
            @Override
            public JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) {
                return date == null ? new JsonPrimitive("") : new JsonPrimitive(TimeUtil.getGernalTime(date.getTime(), "yyyy.MM.dd HH:mm"));
            }
        }).create();
        data.put("list", gson.toJson(list));
        data.put("count", count);
        return loadPrint(callback,JsonUtil.loadTrueResult(data));
    }
    @ResponseBody
    @RequestMapping("get")
    public String get(String id, HttpSession session, String callback) {
        PrivacyComplain entity = privacyComplainService.get(id);
        if (entity !=null){
            return loadPrint(callback,JsonUtil.loadTrueResult(entity));
        } else {
            return loadPrint(callback,JsonUtil.loadFalseResult("ID不存在"));
        }
    }
}
app/src/main/java/com/yeshi/location/app/controller/client/api/ConfigController.java
New file
@@ -0,0 +1,103 @@
package com.yeshi.location.app.controller.client.api;
import com.yeshi.location.app.entity.config.SystemConfigKey;
import com.yeshi.location.app.entity.feedback.Advice;
import com.yeshi.location.app.entity.feedback.PrivacyComplain;
import com.yeshi.location.app.service.inter.config.SystemConfigService;
import com.yeshi.location.app.service.inter.feedback.AdviceService;
import com.yeshi.location.app.service.inter.feedback.PrivacyComplainService;
import com.yeshi.location.app.vo.AcceptData;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.StringUtil;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
 * @author hxh
 * @title: ConfigController
 * @description: 配置信息接口
 * @date 2021/11/16 17:37
 */
@Controller
@RequestMapping("api/v1/config")
public class ConfigController {
    @Resource
    private SystemConfigService systemConfigService;
    /**
     * @return java.lang.String
     * @author hxh
     * @description 建议
     * @date 13:15 2021/12/2
     * @param: acceptData
     **/
    @RequestMapping("getConfig")
    @ResponseBody
    public String getConfig(AcceptData acceptData) {
        com.alibaba.fastjson.JSONObject data = new  com.alibaba.fastjson.JSONObject();
        SystemConfigKey[] configs = new SystemConfigKey[]{
                SystemConfigKey.kefu,
                SystemConfigKey.course,
                SystemConfigKey.unRegister,
                SystemConfigKey.privacyComplain,
                SystemConfigKey.vipLink,
                SystemConfigKey.sdkList
        };
        for (SystemConfigKey config : configs) {
            String value = systemConfigService.getValueCache(acceptData.getSystem(), config);
            data.put(config.name(), value);
        }
        SystemConfigKey[] ads = new SystemConfigKey[]{
                SystemConfigKey.ad_homeInterstitial,
                SystemConfigKey.ad_mineExpress,
                SystemConfigKey.ad_searchExpress,
                SystemConfigKey.ad_searchResultBanner,
                SystemConfigKey.ad_splash,
                SystemConfigKey.ad_travelShareInterstitial,
                SystemConfigKey.ad_vipReward
        };
        for (SystemConfigKey ad : ads) {
            String value = systemConfigService.getValueCache(acceptData.getSystem(), ad);
            JSONObject valueJSON = JSONObject.fromObject(value);
            String channel = acceptData.getChannel();
            if (StringUtil.isNullOrEmpty(channel) || valueJSON.optJSONObject(channel) == null) {
                channel = "qq";
            }
            valueJSON = valueJSON.optJSONObject(channel.toLowerCase());
            if (valueJSON != null) {
                if (acceptData.getVersion() <= valueJSON.optInt("version")) {
                    String pid = valueJSON.optString("pid");
                    String type = valueJSON.optString("type");
                    valueJSON = new JSONObject();
                    valueJSON.put("pid", pid);
                    valueJSON.put("type", type);
                } else {
                    valueJSON = null;
                }
            }
            if (valueJSON != null) {
                data.put(ad.name().replace("ad_", ""), valueJSON.toString());
            }
        }
        return JsonUtil.loadTrueResult(data);
    }
}
app/src/main/java/com/yeshi/location/app/controller/client/api/FeedBackController.java
New file
@@ -0,0 +1,121 @@
package com.yeshi.location.app.controller.client.api;
import com.yeshi.location.app.entity.feedback.Advice;
import com.yeshi.location.app.entity.feedback.PrivacyComplain;
import com.yeshi.location.app.service.inter.feedback.AdviceService;
import com.yeshi.location.app.service.inter.feedback.PrivacyComplainService;
import com.yeshi.location.app.vo.AcceptData;
import net.sf.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.TimeUtil;
import org.yeshi.utils.annotation.RequestSerializableByKey;
import org.yeshi.utils.entity.FileUploadResult;
import org.yeshi.utils.tencentcloud.COSManager;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
 * @author hxh
 * @title: UserController
 * @description: 用户反馈接口
 * @date 2021/11/16 17:37
 */
@Controller
@RequestMapping("api/v1/feedback")
public class FeedBackController {
    Logger logger = LoggerFactory.getLogger(FeedBackController.class);
    @Resource
    private AdviceService adviceService;
    @Resource
    private PrivacyComplainService privacyComplainService;
    /**
     * @return java.lang.String
     * @author hxh
     * @description 建议
     * @date 13:15 2021/12/2
     * @param: acceptData
     * @param: uid
     * @param: type
     * @param: content
     **/
    @RequestMapping("advice")
    @ResponseBody
    public String advice(AcceptData acceptData, Long uid, String type, String content) {
        Advice advice = new Advice();
        advice.setContent(content);
        advice.setType(type);
        advice.setDevice(acceptData.getUtdId());
        advice.setUid(uid);
        try {
            adviceService.add(advice);
            return JsonUtil.loadTrueResult("");
        } catch (Exception e) {
            return JsonUtil.loadFalseResult(e.getMessage());
        }
    }
    /**
     * @return java.lang.String
     * @author hxh
     * @description 隐私投诉
     * @date 19:14 2021/10/15
     * @param: acceptData
     * @param: loginUid
     **/
    @RequestSerializableByKey(key = "#acceptData.utdId")
    @RequestMapping("privacyComplain")
    @ResponseBody
    public String privacyComplain(AcceptData acceptData, HttpServletRequest request, MultipartFile[] images) {
        String content = request.getParameter("content");
        String urlList = "";
        if (images != null && images.length > 0) {
            for (MultipartFile f : images) {
                try {
                    String name = TimeUtil.getGernalTime(System.currentTimeMillis(), "yyyyMMddHHmmssSSS") + "_" + ((int) (Math.random() * 100000)) + ".jpg";
                    FileUploadResult result = COSManager.getInstance().uploadFile(f.getInputStream(), "privacy/report/" + name);
                    if (result != null) {
                        urlList += result.getUrl() + " , ";
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
//        String title = "隐私投诉:" + content;
        StringBuffer buffer = new StringBuffer();
        buffer.append("包名:" + acceptData.getPackages());
        buffer.append("\n\r");
        buffer.append("UTDID:" + acceptData.getUtdId());
        buffer.append("\n\r");
        buffer.append("投诉内容:");
        buffer.append(content);
        buffer.append("\n\r");
        buffer.append("提供的截图为:" + urlList);
        logger.info("隐私投诉:" + buffer.toString());
//        MailSenderUtil.sendEmail("yesbd@qq.com", "buwanysdq@163.com", "weikou2014", title, buffer.toString());
        return JsonUtil.loadTrueResult("");
    }
}
app/src/main/java/com/yeshi/location/app/controller/client/api/LocationController.java
@@ -392,7 +392,7 @@
        }
        //获取轨迹记录
        List<LocationTravel> locationTravelList = locationTravelService.getTravelList(targetUid, startTime == null ? null : new Date(startTime), endTime == null ? null : new Date(endTime), page, 1);
        List<LocationTravel> locationTravelList = locationTravelService.getTravelList(targetUid, startTime == null ? null : new Date(startTime), endTime == null ? null : new Date(endTime), page, 100);
        List<UserLatestLocation> simpleLocationInfoList = new ArrayList<>();
        if (locationTravelList != null) {
            for (LocationTravel lt : locationTravelList) {
app/src/main/java/com/yeshi/location/app/controller/client/api/SOSController.java
@@ -274,6 +274,7 @@
                vo.setPhone(null);
                vo.setPortrait(user.getPortrait());
                vo.setTargetDesc(SOSRecordVO.getTargetDesc(record.getTargetList(), nickNameMap));
                vo.setTargetUid(record.getUid() + "");
                voList.add(vo);
            }
        }
@@ -313,6 +314,7 @@
                vo.setLocation(recordMap.get(targetInfo.getSosId()).getLocation());
                vo.setPhone(userInfoMap.get(recordMap.get(targetInfo.getSosId()).getUid()).getPhone());
                vo.setPortrait(userInfoMap.get(recordMap.get(targetInfo.getSosId()).getUid()).getPortrait());
                vo.setTargetUid(recordMap.get(targetInfo.getSosId()).getUid() + "");
                vo.setTargetDesc(null);
                voList.add(vo);
            }
app/src/main/java/com/yeshi/location/app/controller/client/api/UserController.java
@@ -1,6 +1,12 @@
package com.yeshi.location.app.controller.client.api;
import com.ks.lib.common.exception.ParamsException;
import com.ks.push.exception.BPushDeviceTokenException;
import com.ks.push.pojo.DO.BPushDeviceToken;
import com.ks.push.pojo.DO.PushPlatform;
import com.ks.push.service.BDeviceTokenService;
import com.yeshi.location.app.dto.user.LoginInfoDTO;
import com.yeshi.location.app.entity.SystemEnum;
import com.yeshi.location.app.entity.user.UserInfo;
import com.yeshi.location.app.entity.user.UserLoginRecord;
import com.yeshi.location.app.entity.vip.UserVIPInfo;
@@ -9,10 +15,13 @@
import com.yeshi.location.app.service.inter.user.UserInfoService;
import com.yeshi.location.app.service.inter.vip.VIPService;
import com.yeshi.location.app.utils.ApiCodeConstant;
import com.yeshi.location.app.utils.ThreadUtil;
import com.yeshi.location.app.utils.annotation.UserLogin;
import com.yeshi.location.app.vo.AcceptData;
import com.yeshi.location.app.vo.user.UserInfoVO;
import net.sf.json.util.JSONUtils;
import org.apache.commons.lang3.ThreadUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@@ -40,6 +49,9 @@
    @Resource
    private VIPService vipService;
    @Reference(check = false)
    private BDeviceTokenService bDeviceTokenService;
    @ResponseBody
    @RequestMapping("loginPhone")
    public String loginPhone(AcceptData acceptData, String phone, String vcode, String token) {
@@ -61,6 +73,18 @@
        loginInfo.setSystem(acceptData.getSystem());
        try {
            UserInfo userInfo = userAccountService.login(loginInfo);
            ThreadUtil.run(new Runnable() {
                @Override
                public void run() {
                    try {
                        //登录成功
                        bDeviceTokenService.bindUid(acceptData.getSystem().name(), acceptData.getUtdId(), userInfo.getId() + "");
                    } catch (Exception e) {
                    }
                }
            });
            return JsonUtil.loadTrueResult(JsonUtil.getApiCommonGson().toJson(userInfo));
        } catch (LoginException e) {
            return JsonUtil.loadFalseResult(e.getMessage());
@@ -72,6 +96,13 @@
    @ResponseBody
    @RequestMapping("logout")
    public String logout(AcceptData acceptData, Long uid) {
        try {
            //解绑UID
            bDeviceTokenService.unBindUid(acceptData.getSystem().name(), acceptData.getUtdId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return JsonUtil.loadTrueResult("");
    }
@@ -106,5 +137,33 @@
        return JsonUtil.loadTrueResult(vo);
    }
    @ResponseBody
    @RequestMapping("uploadPushRegId")
    public String uploadPushRegId(AcceptData acceptData, Long uid, String regId) {
        BPushDeviceToken deviceToken = new BPushDeviceToken();
        deviceToken.setAppCode(acceptData.getSystem().name());
        deviceToken.setDeviceId(acceptData.getUtdId());
        deviceToken.setBuildModel(acceptData.getDeviceType());
        deviceToken.setBuildVersion(acceptData.getOsVersion());
        deviceToken.setToken(regId);
        deviceToken.setType(PushPlatform.jpush);
        if (uid != null) {
            deviceToken.setUid(uid + "");
        }
        deviceToken.setVersionCode(acceptData.getVersion());
        try {
            bDeviceTokenService.save(deviceToken);
            return JsonUtil.loadTrueResult("");
        } catch (BPushDeviceTokenException e) {
            return JsonUtil.loadTrueResult(e.getMessage());
        } catch (ParamsException e) {
            return JsonUtil.loadTrueResult(e.getMessage());
        }
    }
}
app/src/main/java/com/yeshi/location/app/dao/feedback/AdviceDao.java
New file
@@ -0,0 +1,96 @@
package com.yeshi.location.app.dao.feedback;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Repository;
import java.util.List;
import com.yeshi.location.app.entity.SystemEnum;
import java.lang.Long;
import java.util.Date;
import org.yeshi.utils.mongo.MongodbBaseDao;
import java.lang.String;
import com.yeshi.location.app.entity.feedback.Advice;
import java.util.ArrayList;
@Repository
public class AdviceDao extends MongodbBaseDao<Advice>{
  public void updateSelective(Advice bean) {
        Query query = new Query();
        Update update=new Update();
        query.addCriteria(Criteria.where("id").is(bean.getId()));
        if(bean.getSystem() != null) {
            update.set("system", bean.getSystem());
        }
        if(bean.getUid() != null) {
            update.set("uid", bean.getUid());
        }
        if(bean.getDevice() != null) {
            update.set("device", bean.getDevice());
        }
        if(bean.getType() != null) {
            update.set("type", bean.getType());
        }
        if(bean.getContent() != null) {
            update.set("content", bean.getContent());
        }
        if(bean.getCreateTime() != null) {
            update.set("createTime", bean.getCreateTime());
        }
        update.set("updateTime", new Date());
        update(query, update);
  }
  public List<Advice> list(DaoQuery daoQuery){
        Query query = getQuery(daoQuery);
        if (daoQuery.sortList!=null && daoQuery.sortList.size()>0){
            query.with(Sort.by(daoQuery.sortList));
        }
        query.skip(daoQuery.start);
        query.limit(daoQuery.count);
        return findList(query);
  }
  public long count(DaoQuery daoQuery){
        Query query=getQuery(daoQuery);
        return count(query);
  }
  private Query getQuery(DaoQuery daoQuery){
        List<Criteria> andList=new ArrayList<>();
        if(daoQuery.system!=null){
            andList.add(Criteria.where("system").is(daoQuery.system));
        }
        if(daoQuery.uid!=null){
            andList.add(Criteria.where("uid").is(daoQuery.uid));
        }
        if(daoQuery.maxCreateTime!=null){
            andList.add(Criteria.where("createTime").lt(daoQuery.maxCreateTime));
        }
        if(daoQuery.minCreateTime!=null){
            andList.add(Criteria.where("createTime").gte(daoQuery.minCreateTime));
        }
        Query query=new Query();
        Criteria[]  ands=new Criteria[andList.size()];
        andList.toArray(ands);
        if(ands.length>0){
            query.addCriteria(new Criteria().andOperator(ands));
        }
        return query;
  }
  public static class DaoQuery{
        public SystemEnum system;
        public Long uid;
        public Date maxCreateTime;
        public Date minCreateTime;
        public int start;
        public int count;
        public List<Sort.Order> sortList;
  }
}
app/src/main/java/com/yeshi/location/app/dao/feedback/PrivacyComplainDao.java
New file
@@ -0,0 +1,94 @@
package com.yeshi.location.app.dao.feedback;
import com.yeshi.location.app.entity.SystemEnum;
import com.yeshi.location.app.entity.feedback.PrivacyComplain;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;
import org.yeshi.utils.mongo.MongodbBaseDao;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Repository
public class PrivacyComplainDao extends MongodbBaseDao<PrivacyComplain>{
  public void updateSelective(PrivacyComplain bean) {
        Query query = new Query();
        Update update=new Update();
        query.addCriteria(Criteria.where("id").is(bean.getId()));
        if(bean.getSystem() != null) {
            update.set("system", bean.getSystem());
        }
        if(bean.getUid() != null) {
            update.set("uid", bean.getUid());
        }
        if(bean.getDevice() != null) {
            update.set("device", bean.getDevice());
        }
        if(bean.getContent() != null) {
            update.set("content", bean.getContent());
        }
        if(bean.getImgList() != null) {
            update.set("imgList", bean.getImgList());
        }
        if(bean.getCreateTime() != null) {
            update.set("createTime", bean.getCreateTime());
        }
        update.set("updateTime", new Date());
        update(query, update);
  }
  public List<PrivacyComplain> list(DaoQuery daoQuery){
        Query query = getQuery(daoQuery);
        if (daoQuery.sortList!=null && daoQuery.sortList.size()>0){
            query.with(Sort.by(daoQuery.sortList));
        }
        query.skip(daoQuery.start);
        query.limit(daoQuery.count);
        return findList(query);
  }
  public long count(DaoQuery daoQuery){
        Query query=getQuery(daoQuery);
        return count(query);
  }
  private Query getQuery(DaoQuery daoQuery){
        List<Criteria> andList=new ArrayList<>();
        if(daoQuery.system!=null){
            andList.add(Criteria.where("system").is(daoQuery.system));
        }
        if(daoQuery.uid!=null){
            andList.add(Criteria.where("uid").is(daoQuery.uid));
        }
        if(daoQuery.maxCreateTime!=null){
            andList.add(Criteria.where("createTime").lt(daoQuery.maxCreateTime));
        }
        if(daoQuery.minCreateTime!=null){
            andList.add(Criteria.where("createTime").gte(daoQuery.minCreateTime));
        }
        Query query=new Query();
        Criteria[]  ands=new Criteria[andList.size()];
        andList.toArray(ands);
        if(ands.length>0){
            query.addCriteria(new Criteria().andOperator(ands));
        }
        return query;
  }
  public static class DaoQuery{
        public SystemEnum system;
        public Long uid;
        public Date maxCreateTime;
        public Date minCreateTime;
        public int start;
        public int count;
        public List<Sort.Order> sortList;
  }
}
app/src/main/java/com/yeshi/location/app/entity/config/SystemConfigKey.java
@@ -17,7 +17,24 @@
    aliyunOneKeyAuthAcessSecret("阿里云一键登录appSecret"),
    tencentSMSAppId("腾讯云短信APPID"),
    tencentSMSAppKey("腾讯云短信APPKey"),
    tencentVerifySMSTemplate("腾讯云验证码短信模板");
    tencentVerifySMSTemplate("腾讯云验证码短信模板"),
    //返回给前端的数据
    kefu("客服链接"),
    course("教程链接"),
    unRegister("注销链接"),
    privacyComplain("隐私投诉链接"),
    vipLink("会员链接"),
    sdkList("三方SDK链接"),
    ad_splash("广告-开屏"),
    ad_homeInterstitial("广告-首页插屏"),
    ad_mineExpress("广告-我的页面原生"),
    ad_searchExpress("广告-搜索页面原生"),
    ad_searchResultBanner("广告-搜索结果banner"),
    ad_travelShareInterstitial("广告-轨迹分享页插屏"),
    ad_vipReward("广告-会员激励视频"),
    ;
    private String desc;
app/src/main/java/com/yeshi/location/app/entity/feedback/Advice.java
New file
@@ -0,0 +1,115 @@
package com.yeshi.location.app.entity.feedback;
import com.yeshi.location.app.entity.SystemEnum;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.yeshi.utils.generater.annotation.admin.AdminController;
import org.yeshi.utils.generater.annotation.admin.DaoQueryCondition;
import org.yeshi.utils.generater.annotation.admin.Show;
import org.yeshi.utils.generater.entity.CommonSearchForm;
import java.util.Date;
/**
 * @author hxh
 * @title: Advice
 * @description: 用户反馈
 * @date 2021/12/2 11:55
 */
@Document(collection = "advice")
@AdminController(mapping = "/admin/api/feedback/advice", title = "用户反馈", delete = false, edit = false, searchForm = CommonSearchForm.class)
public class Advice {
    @Id
    private String id;
    @DaoQueryCondition
    @Indexed
    private SystemEnum system;
    @Show(title = "用户ID")
    @DaoQueryCondition
    @Indexed
    private Long uid;
    @Show(title = "设备ID")
    private String device;
    @Show(title = "建议类型")
    private String type;
    @Show(title = "建议内容")
    private String content;
    @Show(title = "创建时间")
    @DaoQueryCondition
    @Indexed
    private Date createTime;
    private Date updateTime;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public SystemEnum getSystem() {
        return system;
    }
    public void setSystem(SystemEnum system) {
        this.system = system;
    }
    public Long getUid() {
        return uid;
    }
    public void setUid(Long uid) {
        this.uid = uid;
    }
    public String getDevice() {
        return device;
    }
    public void setDevice(String device) {
        this.device = device;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
}
app/src/main/java/com/yeshi/location/app/entity/feedback/PrivacyComplain.java
New file
@@ -0,0 +1,118 @@
package com.yeshi.location.app.entity.feedback;
import com.yeshi.location.app.entity.SystemEnum;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.yeshi.utils.generater.annotation.admin.AdminController;
import org.yeshi.utils.generater.annotation.admin.DaoQueryCondition;
import org.yeshi.utils.generater.annotation.admin.Show;
import org.yeshi.utils.generater.entity.CommonSearchForm;
import java.util.Date;
import java.util.List;
/**
 * @author hxh
 * @title: Advice
 * @description: 隐私投诉
 * @date 2021/12/2 11:55
 */
@Document(collection = "privacyComplain")
@AdminController(mapping = "/admin/api/feedback/privacy", title = "用户反馈", delete = false, edit = false, searchForm = CommonSearchForm.class)
public class PrivacyComplain {
    @Id
    private String id;
    @DaoQueryCondition
    @Indexed
    private SystemEnum system;
    @Show(title = "用户ID")
    @DaoQueryCondition
    @Indexed
    private Long uid;
    @Show(title = "设备ID")
    private String device;
    @Show(title = "投诉内容")
    private String content;
    @Show(title = "投诉图片")
    private List<String> imgList;
    @Show(title = "创建时间")
    @DaoQueryCondition
    @Indexed
    private Date createTime;
    private Date updateTime;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public SystemEnum getSystem() {
        return system;
    }
    public void setSystem(SystemEnum system) {
        this.system = system;
    }
    public Long getUid() {
        return uid;
    }
    public void setUid(Long uid) {
        this.uid = uid;
    }
    public String getDevice() {
        return device;
    }
    public void setDevice(String device) {
        this.device = device;
    }
    public List<String> getImgList() {
        return imgList;
    }
    public void setImgList(List<String> imgList) {
        this.imgList = imgList;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
}
app/src/main/java/com/yeshi/location/app/service/impl/feedback/AdviceServiceImpl.java
New file
@@ -0,0 +1,97 @@
package com.yeshi.location.app.service.impl.feedback;
import java.lang.Exception;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import java.util.Date;
import org.yeshi.utils.bean.BeanUtil;
import java.util.List;
import java.util.UUID;
import com.yeshi.location.app.dao.feedback.AdviceDao;
import com.yeshi.location.app.entity.feedback.Advice;
import com.yeshi.location.app.service.inter.feedback.AdviceService;
import com.yeshi.location.app.service.query.feedback.AdviceQuery;
import com.yeshi.location.app.dao.feedback.AdviceDao.DaoQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
@Service
public class AdviceServiceImpl implements AdviceService {
    @Resource
    private AdviceDao adviceDao;
    @Override
    public List<Advice> list(AdviceQuery adviceQuery, int page, int pageSize) {
        DaoQuery daoQuery = new DaoQuery();
        try {
            BeanUtil.copyProperties(adviceQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        daoQuery.start = (page - 1) * pageSize;
        daoQuery.count = pageSize;
        return adviceDao.list(daoQuery);
    }
    @Override
    public long count(AdviceQuery adviceQuery) {
        DaoQuery daoQuery = new DaoQuery();
        try {
            BeanUtil.copyProperties(adviceQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return adviceDao.count(daoQuery);
    }
    @Override
    public Advice get(String id) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(id));
        return adviceDao.findOne(query);
    }
    @Override
    public void add(Advice advice) throws Exception {
        if (advice.getId() == null) {
            advice.setId(UUID.randomUUID().toString());
        }
        //查询主键ID是否存在
        if (adviceDao.get(advice.getId()) != null) {
            throw new Exception("已存在");
        }
        if (advice.getCreateTime() == null) {
            advice.setCreateTime(new Date());
        }
        //保存
        adviceDao.save(advice);
    }
    @Override
    public void update(Advice advice) {
        if (advice.getUpdateTime() == null) {
            advice.setUpdateTime(new Date());
        }
        //更新
        adviceDao.updateSelective(advice);
    }
    @Override
    public void delete(List<String> idList) {
        for (String id : idList) {
            adviceDao.delete(id);
        }
    }
}
app/src/main/java/com/yeshi/location/app/service/impl/feedback/PrivacyComplainServiceImpl.java
New file
@@ -0,0 +1,92 @@
package com.yeshi.location.app.service.impl.feedback;
import java.lang.Exception;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import java.util.Date;
import org.yeshi.utils.bean.BeanUtil;
import java.util.List;
import java.util.UUID;
import com.yeshi.location.app.dao.feedback.PrivacyComplainDao;
import com.yeshi.location.app.entity.feedback.PrivacyComplain;
import com.yeshi.location.app.service.inter.feedback.PrivacyComplainService;
import com.yeshi.location.app.service.query.feedback.PrivacyComplainQuery;
import com.yeshi.location.app.dao.feedback.PrivacyComplainDao.DaoQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
@Service
public class PrivacyComplainServiceImpl implements PrivacyComplainService{
  @Resource
  private PrivacyComplainDao privacyComplainDao;
  @Override
  public List<PrivacyComplain> list(PrivacyComplainQuery privacyComplainQuery, int page, int pageSize)  {
    DaoQuery daoQuery = new DaoQuery();
    try {
        BeanUtil.copyProperties(privacyComplainQuery, daoQuery);
    } catch (IllegalAccessException e) {
          e.printStackTrace();
    }
    daoQuery.start=(page-1)*pageSize;
    daoQuery.count=pageSize;
    return privacyComplainDao.list(daoQuery);
  }
  @Override
  public long count(PrivacyComplainQuery privacyComplainQuery)  {
    DaoQuery daoQuery = new DaoQuery();
    try {
        BeanUtil.copyProperties(privacyComplainQuery, daoQuery);
    } catch (IllegalAccessException e) {
          e.printStackTrace();
    }
    return privacyComplainDao.count(daoQuery);
  }
  @Override
  public PrivacyComplain get(String id)  {
    Query query=new Query();
    query.addCriteria(Criteria.where("_id").is(id));
    return privacyComplainDao.findOne(query);
  }
  @Override
  public void add(PrivacyComplain privacyComplain)  throws Exception {
      if (privacyComplain.getId() == null) {
          privacyComplain.setId(UUID.randomUUID().toString());
      }
     //查询主键ID是否存在
     if(privacyComplainDao.get(privacyComplain.getId())!=null){
        throw new Exception("已存在");
     }
     if(privacyComplain.getCreateTime()==null){
        privacyComplain.setCreateTime(new Date());
     }
     //保存
     privacyComplainDao.save(privacyComplain);
  }
  @Override
  public void update(PrivacyComplain privacyComplain)  {
     if(privacyComplain.getUpdateTime()==null){
        privacyComplain.setUpdateTime(new Date());
     }
     //更新
     privacyComplainDao.updateSelective(privacyComplain);
  }
  @Override
  public void delete(List<String> idList)  {
     for (String id : idList){
        privacyComplainDao.delete(id);
     }
  }
}
app/src/main/java/com/yeshi/location/app/service/inter/feedback/AdviceService.java
New file
@@ -0,0 +1,50 @@
package com.yeshi.location.app.service.inter.feedback;
import java.lang.Exception;
import javax.annotation.Resource;
import java.util.Date;
import org.yeshi.utils.bean.BeanUtil;
import java.util.List;
import com.yeshi.location.app.entity.feedback.Advice;
import com.yeshi.location.app.service.inter.feedback.AdviceService;
import com.yeshi.location.app.service.query.feedback.AdviceQuery;
public interface AdviceService {
    /**
     * 获取列表
     * @param adviceQuery
     * @param page
     * @param pageSize
     * @return
     */
    public List<Advice> list(AdviceQuery adviceQuery, int page, int pageSize) ;
    /**
     *
     */
    public long count(AdviceQuery adviceQuery) ;
    /**
     *
     */
    public Advice get(String id) ;
    /**
     *
     */
    public void add(Advice advice)  throws Exception;
    /**
     *
     */
    public void update(Advice advice) ;
    /**
     *
     */
    public void delete(List<String> idList) ;
}
app/src/main/java/com/yeshi/location/app/service/inter/feedback/PrivacyComplainService.java
New file
@@ -0,0 +1,50 @@
package com.yeshi.location.app.service.inter.feedback;
import java.lang.Exception;
import javax.annotation.Resource;
import java.util.Date;
import org.yeshi.utils.bean.BeanUtil;
import java.util.List;
import com.yeshi.location.app.entity.feedback.PrivacyComplain;
import com.yeshi.location.app.service.inter.feedback.PrivacyComplainService;
import com.yeshi.location.app.service.query.feedback.PrivacyComplainQuery;
public interface PrivacyComplainService {
    /**
     * 获取列表
     * @param privacyComplainQuery
     * @param page
     * @param pageSize
     * @return
     */
    public List<PrivacyComplain> list(PrivacyComplainQuery privacyComplainQuery, int page, int pageSize) ;
    /**
     *
     */
    public long count(PrivacyComplainQuery privacyComplainQuery) ;
    /**
     *
     */
    public PrivacyComplain get(String id) ;
    /**
     *
     */
    public void add(PrivacyComplain privacyComplain)  throws Exception;
    /**
     *
     */
    public void update(PrivacyComplain privacyComplain) ;
    /**
     *
     */
    public void delete(List<String> idList) ;
}
app/src/main/java/com/yeshi/location/app/service/manager/VerifyCodeManager.java
@@ -58,7 +58,7 @@
     * @param: code
     **/
    public boolean isPhoneCodeRight(String phone, String code) {
        Object oldCode = redisTemplate.opsForValue().get("v-c-p-" + phone);
        Boolean hasKey  = redisTemplate.hasKey("v-c-p-" + phone);
//        return oldCode != null && oldCode.equalsIgnoreCase(code);
        return true;
    }
app/src/main/java/com/yeshi/location/app/service/query/feedback/AdviceQuery.java
New file
@@ -0,0 +1,16 @@
package com.yeshi.location.app.service.query.feedback;
public class AdviceQuery {
    //搜索关键词
    private String kw;
    private String getKw(){
        return kw;
    }
    private void setKw(String kw){
        this.kw = kw;
    }
}
app/src/main/java/com/yeshi/location/app/service/query/feedback/PrivacyComplainQuery.java
New file
@@ -0,0 +1,16 @@
package com.yeshi.location.app.service.query.feedback;
public class PrivacyComplainQuery {
    //搜索关键词
    private String kw;
    private String getKw(){
        return kw;
    }
    private void setKw(String kw){
        this.kw = kw;
    }
}
app/src/main/java/com/yeshi/location/app/utils/ThreadUtil.java
New file
@@ -0,0 +1,27 @@
package com.yeshi.location.app.utils;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
 * @author hxh
 * @title: ThreadUtil
 * @description: TODO
 * @date 2021/12/2 17:50
 */
public class ThreadUtil {
    private static LinkedBlockingQueue<Runnable> queue=new LinkedBlockingQueue<Runnable>(100);
    private static ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(30, 3000, 20, TimeUnit.SECONDS, queue);
    static{
        threadPoolExecutor.allowCoreThreadTimeOut(true);
    }
    public static void run(Runnable runnable){
        threadPoolExecutor.execute(runnable);
    }
}
app/src/main/java/com/yeshi/location/app/vo/AcceptData.java
@@ -20,7 +20,8 @@
    private String channel;
    private String osVersion;
    private String idfa;
    private String utdid;
    private String utdId;
    private String deviceType;
    public long getTimestamp() {
@@ -88,13 +89,6 @@
        this.idfa = idfa;
    }
    public String getUtdid() {
        return utdid;
    }
    public void setUtdid(String utdid) {
        this.utdid = utdid;
    }
    public APPPlatform getPlatform() {
        return platform;
@@ -103,4 +97,20 @@
    public void setPlatform(APPPlatform platform) {
        this.platform = platform;
    }
    public String getUtdId() {
        return utdId;
    }
    public void setUtdId(String utdId) {
        this.utdId = utdId;
    }
    public String getDeviceType() {
        return deviceType;
    }
    public void setDeviceType(String deviceType) {
        this.deviceType = deviceType;
    }
}
app/src/main/java/com/yeshi/location/app/vo/sos/SOSRecordVO.java
@@ -33,6 +33,9 @@
    //被求助者的信息
    private String targetDesc;
    //求助者的用户ID
    private String targetUid;
    public static String getDesc(SOSRecord record, boolean own) {
        return String.format("%s在位置:\"%s\",经纬度:\"N %s W %s\"于%s发出了一条紧急救助信息,求助信息推送成功。", own ? "你" : "他", record.getLocation().getAddress() + record.getLocation().getAddressDetail(), record.getLocation().getLatitude().toString(), record.getLocation().getLongitude().toString(), TimeUtil.getGernalTime(record.getCreateTime().getTime(), "yyyy.MM.dd HH:mm"));
    }
@@ -101,4 +104,12 @@
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public String getTargetUid() {
        return targetUid;
    }
    public void setTargetUid(String targetUid) {
        this.targetUid = targetUid;
    }
}
app/src/main/resources/application-dev.yml
@@ -85,19 +85,14 @@
      addresses: http://1.14.235.17:9000/xxl-job-admin
#buddo配置参数
#dubbo:
#  application:
#    name: push-service
#  registry:
#    protocol: zookeeper
#    address: zookeeper://193.112.35.168:2182 # 134.175.68.214   134.175.68.214:2181
#    client: curator
#  protocol:
#    name: dubbo
#    port: 20882
#    host: 192.168.3.122
#  scan:
#    base-packages: com.yeshi.location.app.service.remote
#  provider:
#    timeout: 10000
dubbo:
  application:
    name: location-consumer
  registry:
    protocol: zookeeper
    address: zookeeper://193.112.35.168:2182 # 134.175.68.214   134.175.68.214:2181
    client: curator
  protocol:
    name: dubbo
    port: 20882
app/src/main/resources/application.yml
@@ -1,3 +1,3 @@
spring:
  profiles:
    active: pro
    active: dev
app/src/main/resources/cos.properties
New file
@@ -0,0 +1,5 @@
appId =1255749512
secretId =AKIDTlpgJhLjOozvd6QI2XnpfGbgV4NQJk25
secretKey =xhCSUHo55oHUQ6XicFcmfIgspX0EEzWo
bucketName =location
region=ap-nanjing
app/src/main/resources/static/feedback/advice_list.html
New file
@@ -0,0 +1,239 @@
<!DOCTYPE html>
<html class="x-admin-sm">
<head>
    <meta charset="UTF-8">
    <title>用户反馈列表</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
          content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi"/>
    <link rel="stylesheet" href="../css/font.css">
    <link rel="stylesheet" href="../css/xadmin.css">
    <script src="../lib/layui/layui.js" charset="utf-8"></script>
    <link rel="stylesheet" href="../css/theme3049.min.css">
    <script src="../js/vue.min.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" src="../js/xadmin.js"></script>
    <script src="../js/http.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <!--[if lt IE 9]>
    <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
    <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <script src="../js/utils.js"></script>
</head>
<body>
<div class="x-nav">
            <span class="layui-breadcrumb">
                <a href="">###</a>
                <a>
                    <cite>###</cite></a>
            </span>
    <a class="layui-btn layui-btn-small" style="line-height:1.6em;margin-top:3px;float:right"
       onclick="location.reload()" title="刷新">
        <i class="layui-icon layui-icon-refresh" style="line-height:30px"></i>
    </a>
</div>
<div class="layui-fluid" id="app">
    <div class="layui-row layui-col-space15">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body">
                    <form class="layui-form layui-col-space5">
                        <div class="layui-inline layui-show-xs-block">
                          <input type="date" name="startDate"  lay-verify=""  placeholder="" autocomplete="off"
                               class="layui-input">
                        </div>
                        <div class="layui-inline layui-show-xs-block">
                          <input type="date" name="endDate"  lay-verify=""  placeholder="" autocomplete="off"
                               class="layui-input">
                        </div>
                        <div class="layui-inline layui-show-xs-block">
                          <input type="text" name="key"  lay-verify=""  placeholder="" autocomplete="off"
                               class="layui-input">
                        </div>
                        <div class="layui-inline layui-show-xs-block">
                            <button id="search" class="layui-btn" lay-submit="" lay-filter="search">
                                <i class="layui-icon">&#xe615;</i></button>
                        </div>
                    </form>
                </div>
                <div class="layui-card-body ">
                    <table class="layui-table" id="table_list" lay-filter="app">
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
<script type="text/html" id="toolbar">
    <div class="layui-btn-container">
    </div>
</script>
<script type="text/html" id="optContainer">
    <div class="layui-btn-container">
    </div>
</script>
<script type="text/html" id="statusContainer">
    <div class="layui-btn-container">
        {{# if(d.status==0){ }}
        <span class="layui-btn layui-btn-mini">
            正常
        </span>
        {{# }else{ }}
        <span class="layui-btn layui-btn-danger layui-btn-mini">
             已删除
        </span>
        {{# } }}
    </div>
</script>
<script type="text/html" id="switchTpl">
    <!-- 这里的checked的状态只是演示 -->
    <input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="女|男" lay-filter="sexDemo" {{ d.id==
           10003 ? 'checked': ''}} >
</script>
<script type="text/html" id="imgshow">
    <!-- 这里的checked的状态只是演示 -->
    <img  src="{{d.}}"/>
    <input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="女|男" lay-filter="sexDemo" {{ d.id==
           10003 ? 'checked': ''}} >
</script>
<script>
</script>
<script>
    var tableIns = null;
    $(function () {
        var app = new Vue({
            el: "#app",
            data: {
                key: '',
                start: '',
                end: '',
                appList: []
            },
            watch: {},
            created: function () {
            },
            methods: {
                init: function () {
                    //初始化
                    layui.use(['laydate', 'form', 'table'], function () {
                        var laydate = layui.laydate,
                                form = layui.form,
                                table = layui.table;
                        //渲染日期输入框
                                laydate.render({
                                    elem: "intput[name=startDate]" //指定元素
                                });
                                laydate.render({
                                    elem: "intput[name=endDate]" //指定元素
                                });
                        //搜索条件
                        form.on('submit(search)', function (data) {
                            app.search(data.field);
                            return false;
                        });
                        tableIns = table.render({
                            elem: '#table_list',
                            url: "/admin/api/feedback/advice/list",
                            toolbar: "#toolbar",
                            totalRow: true,
                            cols: [[{type: 'checkbox', title: "ID"},
                                    {field: 'uid', width: 120, sort: false, title: "用户ID"},
                                    {field: 'device', width: 220, sort: false, title: "设备ID"},
                                    {field: 'type', width: 120, sort: false, title: "建议类型"},
                                    {field: 'content', width: 300, sort: false, title: "建议内容"},
                                    {field: 'createTime', width: 150, sort: false, title: "创建时间"},
                                {fixed: 'right', width: 80, title: "操作", toolbar: '#optContainer'}]],
                            page: true,
                            parseData: function (res) { //res 即为原始返回的数据
                                if (res.code != 0)
                                    return;
                                if (res.data.list == null)
                                    return;
                                console.log(res.data.list)
                                return {
                                    "code": res.code, //解析接口状态
                                    "msg": res.msg, //解析提示文本
                                    "count": res.data.count, //解析数据长度
                                    "data": res.data.list //解析数据列表
                                };
                            },
                            error: function (e, msg) {
                                ksapp.tableError(e)
                            }
                            //,…… //其他参数
                        });
                        //头工具栏事件
                        table.on('toolbar(app)',
                                function (obj) {
                                    var checkStatus = table.checkStatus(obj.config.id);
                                    switch (obj.event) {
                                        case 'delete':
                                            var data = checkStatus.data;
                                            if (data == null || data.length == 0) {
                                                layer.msg("未选择选项");
                                                return;
                                            }
                                            var ids = new Array();
                                            for (var i = 0; i < data.length; i++)
                                                ids.push(data[i].id);
                                            layer.confirm('确认要删除吗?', function (index) {
                                                //发异步删除数据
                                                app.deleteList(ids, function () {
                                                    layer.msg("删除成功");
                                                    $("form").submit();
                                                });
                                            });
                                            break;
                                    };
                                });
                        //请求搜索表单中需要的数据
                          $('#search').trigger("click");
                    });
                },
                delete: function (obj, index, id) {
                    var ids = new Array();
                    ids.push(id);
                    app.deleteList(ids, function () {
                        $(obj).parents("tr").remove();
                        layer.msg('已删除!', {icon: 1, time: 1000});
                    });
                },
                search: function (params) {
                    //数据重载
                    tableIns.reload({
                        where: params,
                        page: {
                            curr: 1 //重新从第 1 页开始
                        }
                    });
                },
            }
    });
    app.init();
    });
</script>
<script>
</script>
</html>
app/src/main/resources/static/feedback/privacy_complain_list.html
New file
@@ -0,0 +1,239 @@
<!DOCTYPE html>
<html class="x-admin-sm">
<head>
    <meta charset="UTF-8">
    <title>用户反馈列表</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
          content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi"/>
    <link rel="stylesheet" href="../css/font.css">
    <link rel="stylesheet" href="../css/xadmin.css">
    <script src="../lib/layui/layui.js" charset="utf-8"></script>
    <link rel="stylesheet" href="../css/theme3049.min.css">
    <script src="../js/vue.min.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" src="../js/xadmin.js"></script>
    <script src="../js/http.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <!--[if lt IE 9]>
    <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
    <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <script src="../js/utils.js"></script>
</head>
<body>
<div class="x-nav">
            <span class="layui-breadcrumb">
                <a href="">###</a>
                <a>
                    <cite>###</cite></a>
            </span>
    <a class="layui-btn layui-btn-small" style="line-height:1.6em;margin-top:3px;float:right"
       onclick="location.reload()" title="刷新">
        <i class="layui-icon layui-icon-refresh" style="line-height:30px"></i>
    </a>
</div>
<div class="layui-fluid" id="app">
    <div class="layui-row layui-col-space15">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body">
                    <form class="layui-form layui-col-space5">
                        <div class="layui-inline layui-show-xs-block">
                          <input type="date" name="startDate"  lay-verify=""  placeholder="" autocomplete="off"
                               class="layui-input">
                        </div>
                        <div class="layui-inline layui-show-xs-block">
                          <input type="date" name="endDate"  lay-verify=""  placeholder="" autocomplete="off"
                               class="layui-input">
                        </div>
                        <div class="layui-inline layui-show-xs-block">
                          <input type="text" name="key"  lay-verify=""  placeholder="" autocomplete="off"
                               class="layui-input">
                        </div>
                        <div class="layui-inline layui-show-xs-block">
                            <button id="search" class="layui-btn" lay-submit="" lay-filter="search">
                                <i class="layui-icon">&#xe615;</i></button>
                        </div>
                    </form>
                </div>
                <div class="layui-card-body ">
                    <table class="layui-table" id="table_list" lay-filter="app">
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
<script type="text/html" id="toolbar">
    <div class="layui-btn-container">
    </div>
</script>
<script type="text/html" id="optContainer">
    <div class="layui-btn-container">
    </div>
</script>
<script type="text/html" id="statusContainer">
    <div class="layui-btn-container">
        {{# if(d.status==0){ }}
        <span class="layui-btn layui-btn-mini">
            正常
        </span>
        {{# }else{ }}
        <span class="layui-btn layui-btn-danger layui-btn-mini">
             已删除
        </span>
        {{# } }}
    </div>
</script>
<script type="text/html" id="switchTpl">
    <!-- 这里的checked的状态只是演示 -->
    <input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="女|男" lay-filter="sexDemo" {{ d.id==
           10003 ? 'checked': ''}} >
</script>
<script type="text/html" id="imgshow">
    <!-- 这里的checked的状态只是演示 -->
    <img  src="{{d.}}"/>
    <input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="女|男" lay-filter="sexDemo" {{ d.id==
           10003 ? 'checked': ''}} >
</script>
<script>
</script>
<script>
    var tableIns = null;
    $(function () {
        var app = new Vue({
            el: "#app",
            data: {
                key: '',
                start: '',
                end: '',
                appList: []
            },
            watch: {},
            created: function () {
            },
            methods: {
                init: function () {
                    //初始化
                    layui.use(['laydate', 'form', 'table'], function () {
                        var laydate = layui.laydate,
                                form = layui.form,
                                table = layui.table;
                        //渲染日期输入框
                                laydate.render({
                                    elem: "intput[name=startDate]" //指定元素
                                });
                                laydate.render({
                                    elem: "intput[name=endDate]" //指定元素
                                });
                        //搜索条件
                        form.on('submit(search)', function (data) {
                            app.search(data.field);
                            return false;
                        });
                        tableIns = table.render({
                            elem: '#table_list',
                            url: "/admin/api/feedback/privacy/list",
                            toolbar: "#toolbar",
                            totalRow: true,
                            cols: [[{type: 'checkbox', title: "ID"},
                                    {field: 'uid', width: 120, sort: false, title: "用户ID"},
                                    {field: 'device', width: 120, sort: false, title: "设备ID"},
                                    {field: 'content', width: 120, sort: false, title: "投诉内容"},
                                    {field: 'imgList', width: 120, sort: false, title: "投诉图片"},
                                    {field: 'createTime', width: 120, sort: false, title: "创建时间"},
                                {fixed: 'right', width: 80, title: "操作", toolbar: '#optContainer'}]],
                            page: true,
                            parseData: function (res) { //res 即为原始返回的数据
                                if (res.code != 0)
                                    return;
                                if (res.data.list == null)
                                    return;
                                console.log(res.data.list)
                                return {
                                    "code": res.code, //解析接口状态
                                    "msg": res.msg, //解析提示文本
                                    "count": res.data.count, //解析数据长度
                                    "data": res.data.list //解析数据列表
                                };
                            },
                            error: function (e, msg) {
                                ksapp.tableError(e)
                            }
                            //,…… //其他参数
                        });
                        //头工具栏事件
                        table.on('toolbar(app)',
                                function (obj) {
                                    var checkStatus = table.checkStatus(obj.config.id);
                                    switch (obj.event) {
                                        case 'delete':
                                            var data = checkStatus.data;
                                            if (data == null || data.length == 0) {
                                                layer.msg("未选择选项");
                                                return;
                                            }
                                            var ids = new Array();
                                            for (var i = 0; i < data.length; i++)
                                                ids.push(data[i].id);
                                            layer.confirm('确认要删除吗?', function (index) {
                                                //发异步删除数据
                                                app.deleteList(ids, function () {
                                                    layer.msg("删除成功");
                                                    $("form").submit();
                                                });
                                            });
                                            break;
                                    };
                                });
                        //请求搜索表单中需要的数据
                          $('#search').trigger("click");
                    });
                },
                delete: function (obj, index, id) {
                    var ids = new Array();
                    ids.push(id);
                    app.deleteList(ids, function () {
                        $(obj).parents("tr").remove();
                        layer.msg('已删除!', {icon: 1, time: 1000});
                    });
                },
                search: function (params) {
                    //数据重载
                    tableIns.reload({
                        where: params,
                        page: {
                            curr: 1 //重新从第 1 页开始
                        }
                    });
                },
            }
    });
    app.init();
    });
</script>
<script>
</script>
</html>
app/src/main/resources/static/index.html
@@ -159,6 +159,39 @@
                </ul>
            </li>
            <li>
                <a href="javascript:;">
                    <i class="layui-icon left-nav-li" lay-tips="用户反馈">&#xe6b2;</i>
                    <cite>用户反馈</cite>
                    <i class="iconfont nav_right">&#xe697;</i></a>
                <ul class="sub-menu">
                    <li>
                        <a onclick="xadmin.add_tab('用户建议','feedback/advice_list.html')">
                            <i class="iconfont">&#xe6a7;</i>
                            <cite>用户建议</cite></a>
                    </li>
                    <li>
                        <a onclick="xadmin.add_tab('隐私投诉','feedback/privacy_complain_list.html')">
                            <i class="iconfont">&#xe6a7;</i>
                            <cite>隐私投诉</cite></a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="javascript:;">
                    <i class="layui-icon left-nav-li" lay-tips="设置">&#xe716;</i>
                    <cite>设置</cite>
                    <i class="iconfont nav_right">&#xe697;</i></a>
                <ul class="sub-menu">
                </ul>
            </li>
        </ul>
    </div>
</div>
app/src/test/java/test/ConfigTest.java
@@ -5,6 +5,7 @@
import com.yeshi.location.app.entity.config.SystemConfig;
import com.yeshi.location.app.entity.config.SystemConfigKey;
import com.yeshi.location.app.service.inter.config.SystemConfigService;
import net.sf.json.JSONObject;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@@ -69,7 +70,6 @@
        systemConfigService.save(config);
        config = new SystemConfig();
        config.setKey(SystemConfigKey.signKey);
        config.setName(config.getKey().getDesc());
@@ -87,4 +87,116 @@
    }
    @Test
    public void addClientConfig() {
        SystemConfigKey[] keys = new SystemConfigKey[]{
                SystemConfigKey.kefu,
                SystemConfigKey.course,
                SystemConfigKey.unRegister,
                SystemConfigKey.privacyComplain,
                SystemConfigKey.vipLink,
                SystemConfigKey.sdkList,
        };
        for (SystemConfigKey key : keys) {
            SystemConfig config = new SystemConfig();
            config.setKey(key);
            config.setName(config.getKey().getDesc());
            config.setSystem(SystemEnum.location);
            config.setValue("https://www.baidu.com");
            systemConfigService.save(config);
        }
    }
    private String getGDT(String pid) {
        JSONObject root = new JSONObject();
        JSONObject channel = new JSONObject();
        channel.put("version", 1);
        channel.put("type", "gdt");
        channel.put("pid", pid);
        root.put("qq", channel.toString());
        return root.toString();
    }
    private String getCSJ(String pid) {
        JSONObject root = new JSONObject();
        JSONObject channel = new JSONObject();
        channel.put("version", 1);
        channel.put("type", "csj");
        channel.put("pid", pid);
        root.put("qq", channel.toString());
        return root.toString();
    }
    @Test
    public void addADPosition() {
        SystemConfig config = new SystemConfig();
        config.setKey(SystemConfigKey.ad_splash);
        config.setName(config.getKey().getDesc());
        config.setSystem(SystemEnum.location);
        config.setValue(getGDT("5002860910157654"));
        config.setValue(getCSJ("887634894"));
        systemConfigService.save(config);
        config = new SystemConfig();
        config.setKey(SystemConfigKey.ad_homeInterstitial);
        config.setName(config.getKey().getDesc());
        config.setSystem(SystemEnum.location);
        config.setValue(getGDT("1012267980852677"));
        config.setValue(getCSJ("947240112"));
        systemConfigService.save(config);
        config = new SystemConfig();
        config.setKey(SystemConfigKey.ad_mineExpress);
        config.setName(config.getKey().getDesc());
        config.setSystem(SystemEnum.location);
        config.setValue(getGDT("8082461920451628"));
        config.setValue(getCSJ("947239180"));
        systemConfigService.save(config);
        config = new SystemConfig();
        config.setKey(SystemConfigKey.ad_searchExpress);
        config.setName(config.getKey().getDesc());
        config.setSystem(SystemEnum.location);
        config.setValue(getGDT("8082461920451628"));
        config.setValue(getCSJ("947239180"));
        systemConfigService.save(config);
        config = new SystemConfig();
        config.setKey(SystemConfigKey.ad_searchResultBanner);
        config.setName(config.getKey().getDesc());
        config.setSystem(SystemEnum.location);
        config.setValue(getGDT("4022361930756639"));
        config.setValue(getCSJ("947242084"));
        systemConfigService.save(config);
        config = new SystemConfig();
        config.setKey(SystemConfigKey.ad_travelShareInterstitial);
        config.setName(config.getKey().getDesc());
        config.setSystem(SystemEnum.location);
        config.setValue(getGDT("1012267980852677"));
        config.setValue(getCSJ("947240112"));
        systemConfigService.save(config);
        config = new SystemConfig();
        config.setKey(SystemConfigKey.ad_vipReward);
        config.setName(config.getKey().getDesc());
        config.setSystem(SystemEnum.location);
        config.setValue(getGDT("9012462980758616"));
        config.setValue(getCSJ("947239184"));
        systemConfigService.save(config);
    }
}
app/src/test/java/test/GeneratorTest.java
@@ -1,5 +1,7 @@
package test;
import com.yeshi.location.app.entity.feedback.Advice;
import com.yeshi.location.app.entity.feedback.PrivacyComplain;
import com.yeshi.location.app.entity.location.LocationTravel;
import com.yeshi.location.app.entity.location.LocationUsers;
import com.yeshi.location.app.entity.location.UserLatestLocation;
@@ -58,6 +60,20 @@
        GeneraterManager.getInstance().createWholeFunction(daoGeneraterParams, serviceGeneraterParams, adminGeneraterParams);
    }
    private static void createFeedBack() throws  Exception{
        GeneraterManager.getInstance().init("D:\\workspace\\server\\location\\app\\src\\main\\java", Advice.class);
        DaoGeneraterParams daoGeneraterParams = new DaoGeneraterParams().setDaoPackage("com.yeshi.location.app.dao.feedback");
        ServiceGeneraterParams serviceGeneraterParams = new ServiceGeneraterParams().setServiceInterPackage("com.yeshi.location.app.service.inter.feedback").setServiceImplPackage("com.yeshi.location.app.service.impl.feedback").setQueryPackage("com.yeshi.location.app.service.query.feedback");
        AdminGeneraterParams adminGeneraterParams = new AdminGeneraterParams().setControllerPackage("com.yeshi.location.app.controller.admin.feedback").setHtmlDir("D:\\workspace\\server\\location\\app\\src\\main\\resources\\static\\feedback");
        GeneraterManager.getInstance().createWholeFunction(daoGeneraterParams, serviceGeneraterParams, adminGeneraterParams);
        GeneraterManager.getInstance().init("D:\\workspace\\server\\location\\app\\src\\main\\java", PrivacyComplain.class);
        GeneraterManager.getInstance().createWholeFunction(daoGeneraterParams, serviceGeneraterParams, adminGeneraterParams);
    }
    private static void createVIPPrice() throws Exception {
        GeneraterManager.getInstance().init("D:\\workspace\\server\\location\\app\\src\\main\\java", VIPPrice.class);
@@ -67,7 +83,8 @@
    public static void main(String[] args) throws Exception {
        createSOS();
        createFeedBack();
//        createSOS();
//        createSystemConfig();
//        GeneraterManager.getInstance().init("D:\\workspace\\server\\location\\app\\src\\main\\java", UserInfo.class);
//        AdminGeneraterParams adminGeneraterParams = new AdminGeneraterParams("com.yeshi.location.app.controller.admin.user", "D:\\workspace\\server\\location\\app\\src\\main\\resources\\static\\user");