From c79b1ebed5a42a4cbb2f824232da2a51ff22a9a1 Mon Sep 17 00:00:00 2001
From: admin <weikou2014>
Date: 星期六, 04 十二月 2021 18:25:08 +0800
Subject: [PATCH] 功能完善

---
 app/pom.xml                                                                                            |   24 
 app/src/main/java/com/yeshi/location/app/controller/client/api/LocationController.java                 |    2 
 app/src/main/java/com/yeshi/location/app/dao/feedback/AdviceDao.java                                   |   96 ++
 app/src/main/java/com/yeshi/location/app/vo/sos/SOSRecordVO.java                                       |   11 
 app/src/main/java/com/yeshi/location/app/controller/client/api/ConfigController.java                   |  103 +++
 app/src/main/java/com/yeshi/location/app/config/CrossConfig.java                                       |   19 
 app/src/main/java/com/yeshi/location/app/service/inter/feedback/PrivacyComplainService.java            |   50 +
 app/src/main/resources/static/index.html                                                               |   33 
 app/src/main/java/com/yeshi/location/app/service/impl/feedback/PrivacyComplainServiceImpl.java         |   92 ++
 app/src/main/java/com/yeshi/location/app/service/manager/VerifyCodeManager.java                        |    2 
 app/src/main/resources/application.yml                                                                 |    2 
 app/src/main/java/com/yeshi/location/app/utils/ThreadUtil.java                                         |   27 
 app/src/main/java/com/yeshi/location/app/service/query/feedback/PrivacyComplainQuery.java              |   16 
 app/src/main/java/com/yeshi/location/app/controller/client/api/FeedBackController.java                 |  121 +++
 app/src/test/java/test/ConfigTest.java                                                                 |  114 +++
 app/src/main/java/com/yeshi/location/app/vo/AcceptData.java                                            |   26 
 app/src/main/resources/cos.properties                                                                  |    5 
 app/src/main/java/com/yeshi/location/app/controller/client/api/UserController.java                     |   59 +
 app/src/main/java/com/yeshi/location/app/controller/admin/feedback/PrivacyComplainAdminController.java |   69 ++
 app/src/test/java/test/GeneratorTest.java                                                              |   19 
 app/src/main/java/com/yeshi/location/app/entity/config/SystemConfigKey.java                            |   19 
 app/src/main/java/com/yeshi/location/app/Application.java                                              |   25 
 app/src/main/resources/application-dev.yml                                                             |   25 
 app/src/main/java/com/yeshi/location/app/controller/admin/feedback/AdviceAdminController.java          |   69 ++
 app/src/main/java/com/yeshi/location/app/entity/feedback/Advice.java                                   |  115 +++
 app/src/main/resources/static/feedback/privacy_complain_list.html                                      |  239 +++++++
 app/src/main/java/com/yeshi/location/app/entity/feedback/PrivacyComplain.java                          |  118 +++
 app/src/main/java/com/yeshi/location/app/service/query/feedback/AdviceQuery.java                       |   16 
 app/src/main/java/com/yeshi/location/app/service/inter/feedback/AdviceService.java                     |   50 +
 app/src/main/resources/static/feedback/advice_list.html                                                |  239 +++++++
 app/src/main/java/com/yeshi/location/app/dao/feedback/PrivacyComplainDao.java                          |   94 ++
 app/src/main/java/com/yeshi/location/app/service/impl/feedback/AdviceServiceImpl.java                  |   97 ++
 app/src/main/java/com/yeshi/location/app/controller/client/api/SOSController.java                      |    2 
 33 files changed, 1,969 insertions(+), 29 deletions(-)

diff --git a/app/pom.xml b/app/pom.xml
index 6e2a9e2..b0a5730 100644
--- a/app/pom.xml
+++ b/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>
 
diff --git a/app/src/main/java/com/yeshi/location/app/Application.java b/app/src/main/java/com/yeshi/location/app/Application.java
index 46c62ce..2ccf881 100644
--- a/app/src/main/java/com/yeshi/location/app/Application.java
+++ b/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);
+    }
+
+
 }
diff --git a/app/src/main/java/com/yeshi/location/app/config/CrossConfig.java b/app/src/main/java/com/yeshi/location/app/config/CrossConfig.java
new file mode 100644
index 0000000..2fcda0f
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/config/CrossConfig.java
@@ -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("*");
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/yeshi/location/app/controller/admin/feedback/AdviceAdminController.java b/app/src/main/java/com/yeshi/location/app/controller/admin/feedback/AdviceAdminController.java
new file mode 100644
index 0000000..8ba4039
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/controller/admin/feedback/AdviceAdminController.java
@@ -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涓嶅瓨鍦�"));
+        }
+    }
+
+
+
+
+}
diff --git a/app/src/main/java/com/yeshi/location/app/controller/admin/feedback/PrivacyComplainAdminController.java b/app/src/main/java/com/yeshi/location/app/controller/admin/feedback/PrivacyComplainAdminController.java
new file mode 100644
index 0000000..258a82f
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/controller/admin/feedback/PrivacyComplainAdminController.java
@@ -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涓嶅瓨鍦�"));
+        }
+    }
+
+
+
+
+}
diff --git a/app/src/main/java/com/yeshi/location/app/controller/client/api/ConfigController.java b/app/src/main/java/com/yeshi/location/app/controller/client/api/ConfigController.java
new file mode 100644
index 0000000..e20a559
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/controller/client/api/ConfigController.java
@@ -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);
+    }
+
+
+}
diff --git a/app/src/main/java/com/yeshi/location/app/controller/client/api/FeedBackController.java b/app/src/main/java/com/yeshi/location/app/controller/client/api/FeedBackController.java
new file mode 100644
index 0000000..4d53cf0
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/controller/client/api/FeedBackController.java
@@ -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("");
+    }
+
+
+}
diff --git a/app/src/main/java/com/yeshi/location/app/controller/client/api/LocationController.java b/app/src/main/java/com/yeshi/location/app/controller/client/api/LocationController.java
index f063c6c..bbaeeed 100644
--- a/app/src/main/java/com/yeshi/location/app/controller/client/api/LocationController.java
+++ b/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) {
diff --git a/app/src/main/java/com/yeshi/location/app/controller/client/api/SOSController.java b/app/src/main/java/com/yeshi/location/app/controller/client/api/SOSController.java
index f1a38a5..3c4eacf 100644
--- a/app/src/main/java/com/yeshi/location/app/controller/client/api/SOSController.java
+++ b/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);
             }
diff --git a/app/src/main/java/com/yeshi/location/app/controller/client/api/UserController.java b/app/src/main/java/com/yeshi/location/app/controller/client/api/UserController.java
index 8f946d5..fb0dbe3 100644
--- a/app/src/main/java/com/yeshi/location/app/controller/client/api/UserController.java
+++ b/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 {
+            //瑙g粦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());
+        }
+
+
+    }
+
 
 }
diff --git a/app/src/main/java/com/yeshi/location/app/dao/feedback/AdviceDao.java b/app/src/main/java/com/yeshi/location/app/dao/feedback/AdviceDao.java
new file mode 100644
index 0000000..e48b589
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/dao/feedback/AdviceDao.java
@@ -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;
+  }
+}
diff --git a/app/src/main/java/com/yeshi/location/app/dao/feedback/PrivacyComplainDao.java b/app/src/main/java/com/yeshi/location/app/dao/feedback/PrivacyComplainDao.java
new file mode 100644
index 0000000..fafabcc
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/dao/feedback/PrivacyComplainDao.java
@@ -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;
+  }
+}
diff --git a/app/src/main/java/com/yeshi/location/app/entity/config/SystemConfigKey.java b/app/src/main/java/com/yeshi/location/app/entity/config/SystemConfigKey.java
index 3a16399..ce3a023 100644
--- a/app/src/main/java/com/yeshi/location/app/entity/config/SystemConfigKey.java
+++ b/app/src/main/java/com/yeshi/location/app/entity/config/SystemConfigKey.java
@@ -17,7 +17,24 @@
     aliyunOneKeyAuthAcessSecret("闃块噷浜戜竴閿櫥褰昦ppSecret"),
     tencentSMSAppId("鑵捐浜戠煭淇PPID"),
     tencentSMSAppKey("鑵捐浜戠煭淇PPKey"),
-    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;
 
diff --git a/app/src/main/java/com/yeshi/location/app/entity/feedback/Advice.java b/app/src/main/java/com/yeshi/location/app/entity/feedback/Advice.java
new file mode 100644
index 0000000..fda1f48
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/entity/feedback/Advice.java
@@ -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;
+    }
+}
diff --git a/app/src/main/java/com/yeshi/location/app/entity/feedback/PrivacyComplain.java b/app/src/main/java/com/yeshi/location/app/entity/feedback/PrivacyComplain.java
new file mode 100644
index 0000000..cd76995
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/entity/feedback/PrivacyComplain.java
@@ -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;
+    }
+}
diff --git a/app/src/main/java/com/yeshi/location/app/service/impl/feedback/AdviceServiceImpl.java b/app/src/main/java/com/yeshi/location/app/service/impl/feedback/AdviceServiceImpl.java
new file mode 100644
index 0000000..a7a75be
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/service/impl/feedback/AdviceServiceImpl.java
@@ -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);
+        }
+    }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/yeshi/location/app/service/impl/feedback/PrivacyComplainServiceImpl.java b/app/src/main/java/com/yeshi/location/app/service/impl/feedback/PrivacyComplainServiceImpl.java
new file mode 100644
index 0000000..c2f05ae
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/service/impl/feedback/PrivacyComplainServiceImpl.java
@@ -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);
+     }
+  }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/yeshi/location/app/service/inter/feedback/AdviceService.java b/app/src/main/java/com/yeshi/location/app/service/inter/feedback/AdviceService.java
new file mode 100644
index 0000000..0e86d20
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/service/inter/feedback/AdviceService.java
@@ -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) ;
+
+
+}
diff --git a/app/src/main/java/com/yeshi/location/app/service/inter/feedback/PrivacyComplainService.java b/app/src/main/java/com/yeshi/location/app/service/inter/feedback/PrivacyComplainService.java
new file mode 100644
index 0000000..d106168
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/service/inter/feedback/PrivacyComplainService.java
@@ -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) ;
+
+
+}
diff --git a/app/src/main/java/com/yeshi/location/app/service/manager/VerifyCodeManager.java b/app/src/main/java/com/yeshi/location/app/service/manager/VerifyCodeManager.java
index ca9eb4c..ddc550c 100644
--- a/app/src/main/java/com/yeshi/location/app/service/manager/VerifyCodeManager.java
+++ b/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;
     }
diff --git a/app/src/main/java/com/yeshi/location/app/service/query/feedback/AdviceQuery.java b/app/src/main/java/com/yeshi/location/app/service/query/feedback/AdviceQuery.java
new file mode 100644
index 0000000..c70d93f
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/service/query/feedback/AdviceQuery.java
@@ -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;
+    }
+
+
+}
diff --git a/app/src/main/java/com/yeshi/location/app/service/query/feedback/PrivacyComplainQuery.java b/app/src/main/java/com/yeshi/location/app/service/query/feedback/PrivacyComplainQuery.java
new file mode 100644
index 0000000..8f8f832
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/service/query/feedback/PrivacyComplainQuery.java
@@ -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;
+    }
+
+
+}
diff --git a/app/src/main/java/com/yeshi/location/app/utils/ThreadUtil.java b/app/src/main/java/com/yeshi/location/app/utils/ThreadUtil.java
new file mode 100644
index 0000000..b486266
--- /dev/null
+++ b/app/src/main/java/com/yeshi/location/app/utils/ThreadUtil.java
@@ -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);
+    }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/yeshi/location/app/vo/AcceptData.java b/app/src/main/java/com/yeshi/location/app/vo/AcceptData.java
index 1cf04d3..1e609e8 100644
--- a/app/src/main/java/com/yeshi/location/app/vo/AcceptData.java
+++ b/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;
+    }
 }
diff --git a/app/src/main/java/com/yeshi/location/app/vo/sos/SOSRecordVO.java b/app/src/main/java/com/yeshi/location/app/vo/sos/SOSRecordVO.java
index 64e5eea..07a5103 100644
--- a/app/src/main/java/com/yeshi/location/app/vo/sos/SOSRecordVO.java
+++ b/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;
+    }
 }
diff --git a/app/src/main/resources/application-dev.yml b/app/src/main/resources/application-dev.yml
index 84c1896..3a5152e 100644
--- a/app/src/main/resources/application-dev.yml
+++ b/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
 
diff --git a/app/src/main/resources/application.yml b/app/src/main/resources/application.yml
index fc3033b..caf4dfc 100644
--- a/app/src/main/resources/application.yml
+++ b/app/src/main/resources/application.yml
@@ -1,3 +1,3 @@
 spring:
   profiles:
-    active: pro
\ No newline at end of file
+    active: dev
\ No newline at end of file
diff --git a/app/src/main/resources/cos.properties b/app/src/main/resources/cos.properties
new file mode 100644
index 0000000..ed443f0
--- /dev/null
+++ b/app/src/main/resources/cos.properties
@@ -0,0 +1,5 @@
+appId =1255749512
+secretId =AKIDTlpgJhLjOozvd6QI2XnpfGbgV4NQJk25
+secretKey =xhCSUHo55oHUQ6XicFcmfIgspX0EEzWo
+bucketName =location
+region=ap-nanjing
\ No newline at end of file
diff --git a/app/src/main/resources/static/feedback/advice_list.html b/app/src/main/resources/static/feedback/advice_list.html
new file mode 100644
index 0000000..d7ca826
--- /dev/null
+++ b/app/src/main/resources/static/feedback/advice_list.html
@@ -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">
+            姝e父
+        </span>
+        {{# }else{ }}
+        <span class="layui-btn layui-btn-danger layui-btn-mini">
+             宸插垹闄�
+        </span>
+        {{# } }}
+    </div>
+</script>
+
+<script type="text/html" id="switchTpl">
+    <!-- 杩欓噷鐨刢hecked鐨勭姸鎬佸彧鏄紨绀� -->
+    <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">
+    <!-- 杩欓噷鐨刢hecked鐨勭姸鎬佸彧鏄紨绀� -->
+    <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, //瑙f瀽鎺ュ彛鐘舵��
+                                    "msg": res.msg, //瑙f瀽鎻愮ず鏂囨湰
+                                    "count": res.data.count, //瑙f瀽鏁版嵁闀垮害
+                                    "data": res.data.list //瑙f瀽鏁版嵁鍒楄〃
+                                };
+                            },
+                            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>
\ No newline at end of file
diff --git a/app/src/main/resources/static/feedback/privacy_complain_list.html b/app/src/main/resources/static/feedback/privacy_complain_list.html
new file mode 100644
index 0000000..f09f4d5
--- /dev/null
+++ b/app/src/main/resources/static/feedback/privacy_complain_list.html
@@ -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">
+            姝e父
+        </span>
+        {{# }else{ }}
+        <span class="layui-btn layui-btn-danger layui-btn-mini">
+             宸插垹闄�
+        </span>
+        {{# } }}
+    </div>
+</script>
+
+<script type="text/html" id="switchTpl">
+    <!-- 杩欓噷鐨刢hecked鐨勭姸鎬佸彧鏄紨绀� -->
+    <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">
+    <!-- 杩欓噷鐨刢hecked鐨勭姸鎬佸彧鏄紨绀� -->
+    <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, //瑙f瀽鎺ュ彛鐘舵��
+                                    "msg": res.msg, //瑙f瀽鎻愮ず鏂囨湰
+                                    "count": res.data.count, //瑙f瀽鏁版嵁闀垮害
+                                    "data": res.data.list //瑙f瀽鏁版嵁鍒楄〃
+                                };
+                            },
+                            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>
\ No newline at end of file
diff --git a/app/src/main/resources/static/index.html b/app/src/main/resources/static/index.html
index aa067be..317eef1 100644
--- a/app/src/main/resources/static/index.html
+++ b/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>
diff --git a/app/src/test/java/test/ConfigTest.java b/app/src/test/java/test/ConfigTest.java
index 62d20b0..61e2cba 100644
--- a/app/src/test/java/test/ConfigTest.java
+++ b/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);
+    }
+
 }
diff --git a/app/src/test/java/test/GeneratorTest.java b/app/src/test/java/test/GeneratorTest.java
index 08ceec7..bf7d101 100644
--- a/app/src/test/java/test/GeneratorTest.java
+++ b/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");

--
Gitblit v1.8.0