Преглед на файлове

Merge branch 'master' into release/1.0.0

guozhaoshun преди 6 години
родител
ревизия
80c1c1742a
променени са 51 файла, в които са добавени 2012 реда и са изтрити 152 реда
  1. 6 0
      rankin-api-web/pom.xml
  2. 175 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/ApiWebMain.java
  3. 197 4
      rankin-api-web/src/main/java/cn/rankin/apiweb/controller/CallbackController.java
  4. 13 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/controller/CollectionController.java
  5. 35 1
      rankin-api-web/src/main/java/cn/rankin/apiweb/controller/CourseController.java
  6. 83 7
      rankin-api-web/src/main/java/cn/rankin/apiweb/controller/LoginController.java
  7. 1 8
      rankin-api-web/src/main/java/cn/rankin/apiweb/controller/RecommendController.java
  8. 145 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/helper/MacAddressHelper.java
  9. 51 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/service/collection/CollectionService.java
  10. 36 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/service/download/DownloadInfoClient.java
  11. 50 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/service/download/DownloadInfoService.java
  12. 8 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/service/product/ProductClient.java
  13. 8 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/service/product/ProductService.java
  14. 62 13
      rankin-api-web/src/main/java/cn/rankin/apiweb/service/user/UserClient.java
  15. 145 54
      rankin-api-web/src/main/java/cn/rankin/apiweb/service/user/UserService.java
  16. 2 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/utils/SecurityManager.java
  17. 35 0
      rankin-cms-web/src/main/java/cn/rankin/cmsweb/controller/user/UserDeviceController.java
  18. 19 0
      rankin-cms-web/src/main/java/cn/rankin/cmsweb/service/user/UserDeviceService.java
  19. 25 0
      rankin-common-utils/src/main/java/cn/rankin/common/utils/constant/DownloadStatus.java
  20. 29 0
      rankin-common-utils/src/main/java/cn/rankin/common/utils/enums/EventTypeEnum.java
  21. 1 1
      rankin-common-utils/src/main/java/cn/rankin/common/utils/enums/PlatformTypeEnum.java
  22. 7 0
      rankin-common-utils/src/main/java/cn/rankin/common/utils/exception/CommonException.java
  23. 84 0
      rankin-common-utils/src/main/java/cn/rankin/common/utils/util/HttpUtil.java
  24. 13 0
      rankin-data-api/src/main/java/cn/rankin/data/api/app/dto/LoginInfoDTO.java
  25. 2 0
      rankin-data-api/src/main/java/cn/rankin/data/api/app/vo/LessonVo.java
  26. 3 0
      rankin-data-api/src/main/java/cn/rankin/data/api/product/dto/CourseDTO.java
  27. 3 0
      rankin-data-api/src/main/java/cn/rankin/data/api/product/entity/Course.java
  28. 3 0
      rankin-data-api/src/main/java/cn/rankin/data/api/product/vo/CourseVo.java
  29. 66 0
      rankin-data-api/src/main/java/cn/rankin/data/api/user/dto/DownloadInfoDTO.java
  30. 7 0
      rankin-data-api/src/main/java/cn/rankin/data/api/user/dto/UserDeviceDTO.java
  31. 97 0
      rankin-data-api/src/main/java/cn/rankin/data/api/user/entity/DownloadInfo.java
  32. 60 0
      rankin-data-api/src/main/java/cn/rankin/data/api/user/entity/UserDevice.java
  33. 7 0
      rankin-data-api/src/main/java/cn/rankin/data/api/user/vo/UserDeviceVo.java
  34. 5 0
      rankin-product-service/src/main/java/cn/rankin/productservice/controller/app/AppTagController.java
  35. 0 41
      rankin-product-service/src/main/java/cn/rankin/productservice/controller/app/ItemControllerV0.java
  36. 2 2
      rankin-product-service/src/main/java/cn/rankin/productservice/controller/cms/MerchantProductController.java
  37. 16 2
      rankin-product-service/src/main/java/cn/rankin/productservice/controller/cms/TagController.java
  38. 5 0
      rankin-product-service/src/main/java/cn/rankin/productservice/service/TagService.java
  39. 118 0
      rankin-user-service/src/main/java/cn/rankin/userservice/controller/DownloadInfoController.java
  40. 53 0
      rankin-user-service/src/main/java/cn/rankin/userservice/controller/UserDeviceController.java
  41. 7 0
      rankin-user-service/src/main/java/cn/rankin/userservice/controller/UserTagProductRelationController.java
  42. 37 0
      rankin-user-service/src/main/java/cn/rankin/userservice/helper/RaStringHelper.java
  43. 1 0
      rankin-user-service/src/main/java/cn/rankin/userservice/proxy/RemoteUserFeign.java
  44. 37 0
      rankin-user-service/src/main/java/cn/rankin/userservice/repository/DownloadInfoRepository.java
  45. 32 0
      rankin-user-service/src/main/java/cn/rankin/userservice/repository/UserDeviceRepository.java
  46. 2 19
      rankin-user-service/src/main/java/cn/rankin/userservice/repository/UserTagProductRelationRepository.java
  47. 1 0
      rankin-user-service/src/main/java/cn/rankin/userservice/service/CollectionService.java
  48. 115 0
      rankin-user-service/src/main/java/cn/rankin/userservice/service/DownloadInfoService.java
  49. 83 0
      rankin-user-service/src/main/java/cn/rankin/userservice/service/UserDeviceService.java
  50. 14 0
      rankin-user-service/src/main/java/cn/rankin/userservice/service/UserTagProductRelationService.java
  51. 6 0
      rankin-user-service/src/main/java/cn/rankin/userservice/utils/DTOConverter.java

+ 6 - 0
rankin-api-web/pom.xml

@@ -65,6 +65,12 @@
             <artifactId>rankin-data-api</artifactId>
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
+
+        <dependency>
+        <groupId>eu.bitwalker</groupId>
+        <artifactId>UserAgentUtils</artifactId>
+        <version>1.21</version>
+         </dependency>
 	</dependencies>
 
 	<dependencyManagement>

+ 175 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/ApiWebMain.java

@@ -0,0 +1,175 @@
+package cn.rankin.apiweb;
+
+
+import eu.bitwalker.useragentutils.Browser;
+import eu.bitwalker.useragentutils.OperatingSystem;
+import eu.bitwalker.useragentutils.UserAgent;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ApiWebMain
+{
+
+    public static void main(String[] args)
+    {
+        try
+        {
+            System.out.print(getMac("47.95.197.36"));
+        }
+        catch (Exception ex)
+        {
+            ex.printStackTrace();
+        }
+    }
+
+    public static void userAgent()
+    {
+        String userAgentStr = "ser-agent=Mozilla/5.0 (Linux; Android 5.0.2; sdk_google_atv_x86 Build/LSY64) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile Safari/537.36";
+        UserAgent userAgent = UserAgent.parseUserAgentString(userAgentStr);
+        //获取浏览器对象
+        Browser browser = userAgent.getBrowser();
+        //获取操作系统对象
+        OperatingSystem operatingSystem = userAgent.getOperatingSystem();
+
+        //操作系统
+        String osName = operatingSystem.getName();
+        //操作系统设备类型
+        System.out.println("操作系统名:" + operatingSystem.getName());
+        System.out.println("访问设备类型:" + operatingSystem.getDeviceType());
+        System.out.println("操作系统家族:" + operatingSystem.getGroup());
+        System.out.println("操作系统生产厂商:" + operatingSystem.getManufacturer());
+
+        String eviceType = operatingSystem.getDeviceType().toString();
+
+        if ("MOBILE".equals(eviceType))
+        {
+            Pattern pattern = Pattern.compile(";\\s?(\\S*?\\s?\\S*?)\\s?(Build)?/");
+            Matcher matcher = pattern.matcher(userAgentStr);
+            String model = null;
+            if (matcher.find())
+            {
+                model = matcher.group(1).trim();
+                System.out.println("操作系统生产厂商:" + model);
+            }
+        }
+        else if ("WINDOWS".equals(eviceType))
+        {
+
+        }
+    }
+
+    /**
+     * 根据IP地址获取mac地址
+     *
+     * @param ipAddress 127.0.0.1
+     * @return
+     * @throws SocketException
+     * @throws UnknownHostException
+     */
+    public static String getLocalMac(String ipAddress) throws SocketException,
+            UnknownHostException
+    {
+        // TODO Auto-generated method stub
+        String str = "";
+        String macAddress = "";
+        final String LOOPBACK_ADDRESS = "127.0.0.1";
+        // 如果为127.0.0.1,则获取本地MAC地址。
+        if (LOOPBACK_ADDRESS.equals(ipAddress))
+        {
+            InetAddress inetAddress = InetAddress.getLocalHost();
+            // 貌似此方法需要JDK1.6。
+            byte[] mac = NetworkInterface.getByInetAddress(inetAddress)
+                    .getHardwareAddress();
+            // 下面代码是把mac地址拼装成String
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < mac.length; i++)
+            {
+                if (i != 0)
+                {
+                    sb.append("-");
+                }
+                // mac[i] & 0xFF 是为了把byte转化为正整数
+                String s = Integer.toHexString(mac[i] & 0xFF);
+                sb.append(s.length() == 1 ? 0 + s : s);
+            }
+            // 把字符串所有小写字母改为大写成为正规的mac地址并返回
+            macAddress = sb.toString().trim().toUpperCase();
+            return macAddress;
+        }
+        else
+        {
+            // 获取非本地IP的MAC地址
+            try
+            {
+                System.out.println(ipAddress);
+                Process p = Runtime.getRuntime().exec("nbtstat -A " + ipAddress);
+                System.out.println("===process==" + p);
+                InputStreamReader ir = new InputStreamReader(p.getInputStream());
+
+                BufferedReader br = new BufferedReader(ir);
+
+                while ((str = br.readLine()) != null)
+                {
+                    if (str.indexOf("MAC") > 1)
+                    {
+                        macAddress = str.substring(str.indexOf("MAC") + 9, str.length());
+                        macAddress = macAddress.trim();
+                        System.out.println("macAddress:" + macAddress);
+                        break;
+                    }
+                }
+                p.destroy();
+                br.close();
+                ir.close();
+            }
+            catch (IOException ex)
+            {
+                ex.printStackTrace();
+            }
+            return macAddress;
+        }
+    }
+
+
+        public static String getMac(String ip) throws IOException {
+            String mac = "not found!";
+            if (ip != null) {
+
+                try {
+                    Process process = Runtime.getRuntime().exec("arp "+ip);
+                    InputStreamReader ir = new InputStreamReader(process.getInputStream());
+                    LineNumberReader input = new LineNumberReader(ir);
+                    String line;
+                    StringBuffer s = new StringBuffer();
+                    while ((line = input.readLine()) != null) {
+                        s.append(line);
+
+                    }
+                    mac = s.toString();
+                    if (mac != null) {
+
+                        mac = mac.substring(mac.indexOf(":") - 2, mac.lastIndexOf(":") + 3);
+
+                    } else {
+                        mac = "not found!";
+                    }
+                    return mac;
+
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+            return mac;
+
+    }
+
+}

+ 197 - 4
rankin-api-web/src/main/java/cn/rankin/apiweb/controller/CallbackController.java

@@ -2,21 +2,35 @@ package cn.rankin.apiweb.controller;
 
 import cn.rankin.apiweb.assist.resolver.NeedUser;
 import cn.rankin.apiweb.code.ApiWebCode;
+import cn.rankin.apiweb.service.download.DownloadInfoService;
 import cn.rankin.apiweb.service.event.EventService;
+import cn.rankin.apiweb.service.product.ProductService;
+import cn.rankin.common.utils.api.model.APICode;
 import cn.rankin.common.utils.api.model.APIResult;
+import cn.rankin.common.utils.constant.DownloadStatus;
+import cn.rankin.common.utils.enums.BaseStatusEnum;
+import cn.rankin.common.utils.enums.EventTypeEnum;
+import cn.rankin.common.utils.util.HttpUtil;
 import cn.rankin.data.api.app.vo.DeviceUserVo;
+import cn.rankin.data.api.product.entity.Course;
+import cn.rankin.data.api.product.entity.Lesson;
+import cn.rankin.data.api.user.dto.DownloadInfoDTO;
 import cn.rankin.data.api.user.dto.EventLogDTO;
+import cn.rankin.data.api.user.entity.DownloadInfo;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
 
 
 /**
  * CallbackController
  * Created by huodongdong on 2017/10/27.
  */
+@Slf4j
 @RestController
 @RequestMapping(value = "/callback")
 public class CallbackController {
@@ -24,6 +38,12 @@ public class CallbackController {
     @Autowired
     private EventService eventService;
 
+    @Autowired
+    private DownloadInfoService downloadInfoService;
+
+    @Autowired
+    private ProductService productService;
+
     @RequestMapping(value = "/event", method = RequestMethod.POST)
     public APIResult<Boolean> addEvent(@NeedUser DeviceUserVo user, @RequestBody EventLogDTO eventLog) {
         if (eventLog.getEventType() == null ) {
@@ -36,5 +56,178 @@ public class CallbackController {
         APIResult<Boolean> result = eventService.addLog(eventLog);
         return result;
     }
+
+    @RequestMapping(value = "/download/add", method = RequestMethod.POST)
+    public APIResult<Boolean> addDownloadInfo(HttpServletRequest request, @NeedUser DeviceUserVo user ,
+                                              @RequestParam("courseId") String courseId,
+                                              @RequestParam("lessonId") String lessonId,
+                                              @RequestParam("resTotal") int resTotal,
+                                              @RequestParam("resSize") int resSize,
+                                              @RequestParam("mac") String mac) {
+
+        String ip = HttpUtil.getClientIp(request);
+        log.info("ip={}",ip);
+
+
+        log.info("mac={}",mac);
+
+        String systemInfo = HttpUtil.getSystemInfo(request);
+
+        log.info("systemInfo={}",systemInfo);
+
+        /**
+         * 1.获得客户机信息
+         */
+        String device = request.getHeader("User-Agent");
+
+        log.info("device={}",device);
+
+        DownloadInfoDTO dto = new DownloadInfoDTO();
+
+        if(StringUtils.isBlank(lessonId)){
+            return APIResult.error(ApiWebCode.PARAMETER_ERROR);
+        }else{
+            Lesson lesson = productService.getLesson(lessonId, courseId).getData();
+            if(null == lesson){
+                log.info("not found lesson by id ,lessonId={}",lessonId);
+                return APIResult.error(ApiWebCode.PARAMETER_ERROR);
+            }
+
+            dto.setLessonId(lessonId);
+            dto.setLessonName(lesson.getTitle());
+        }
+
+        if(StringUtils.isBlank(courseId)){
+            return APIResult.error(ApiWebCode.PARAMETER_ERROR);
+        }else{
+            Course course = productService.getCourse(courseId);
+            if(null == course){
+                log.info("not found course by id ,courseId={}",courseId);
+                return APIResult.error(ApiWebCode.PARAMETER_ERROR);
+            }
+
+            dto.setCourseId(courseId);
+            dto.setCourseName(course.getTitle());
+        }
+
+        dto.setMac(mac);
+        dto.setIp(ip);
+        dto.setMerchantId(user.getMerchantId());
+        dto.setUserId(user.getUid());
+        dto.setDeviceType(device);
+        dto.setDownloadStatus(DownloadStatus.PROCESS_DOWNLOAD);
+        dto.setEventType(EventTypeEnum.DOWNLOAD);
+        dto.setStatus(BaseStatusEnum.NORMAL);
+        dto.setNeedUpdate(0);
+        dto.setResTotal(resTotal);
+        dto.setResSize(resSize);
+
+
+
+        DownloadInfo downloadInfo = downloadInfoService.add(dto);
+        if(downloadInfo != null){
+            return APIResult.ok();
+        }else{
+            return APIResult.error(APICode.OPERATE_ERROR);
+        }
+
+    }
+
+    @RequestMapping(value = "/download/list", method = RequestMethod.GET)
+    public APIResult<List<DownloadInfo>> findByUserId(@NeedUser DeviceUserVo user,
+                                                      @RequestParam("mac") String mac) {
+        List<DownloadInfo> downloadInfos = downloadInfoService.findByUserId(user.getUid(), mac);
+        return APIResult.ok(downloadInfos);
+    }
+
+    @RequestMapping(value = "/download/find", method = RequestMethod.GET)
+    public APIResult<DownloadInfo> findByLessonUserId(@NeedUser DeviceUserVo user,
+                                                      @RequestParam("lessonId") String lessonId,
+                                                      @RequestParam("mac") String mac) {
+        DownloadInfo downloadInfo = downloadInfoService.findByLessonUserId(user.getUid(),lessonId, mac);
+        if(downloadInfo != null){
+            return APIResult.ok(downloadInfo);
+        }else{
+            return APIResult.error(APICode.OPERATE_ERROR);
+        }
+    }
+
+    @RequestMapping(value = "/download/status", method = RequestMethod.GET)
+    public APIResult<DownloadInfo> findDownloadStatus(@NeedUser DeviceUserVo user,
+                                                      @RequestParam("lessonId") String lessonId,
+                                                      @RequestParam("mac") String mac) {
+        DownloadInfo downloadInfo = downloadInfoService.findDownloadStatus(user.getUid(),lessonId, mac);
+        return APIResult.ok(downloadInfo);
+    }
+
+    @RequestMapping(value = "/download/delete", method = RequestMethod.DELETE)
+    public APIResult<Boolean> deleteByLessonUserId(@NeedUser DeviceUserVo user,
+                                                   @RequestParam("lessonId") String lessonId,
+                                                   @RequestParam("mac") String mac) {
+        DownloadInfo downloadInfo = downloadInfoService.deleteByLessonUserId(user.getUid(),lessonId,mac);
+        if(downloadInfo == null){
+            APIResult.error(APICode.OPERATE_ERROR);
+        }
+        return APIResult.ok();
+    }
+
+    @RequestMapping(value = "/download/fail", method = RequestMethod.GET)
+    public APIResult<Boolean> downloadFail(@NeedUser DeviceUserVo user,
+                                                   @RequestParam("mac") String mac) {
+
+        log.info("mac============,{}",mac);
+
+        boolean flag = downloadInfoService.downloadFail(user.getUid(), mac);
+        return APIResult.ok();
+    }
+
+    @RequestMapping(value = "/download/update", method = RequestMethod.PUT)
+    public APIResult<Boolean> updateByLessonUserId(@NeedUser DeviceUserVo user,
+                                                   @RequestParam("lessonId") String lessonId,
+                                                   @RequestParam("mac") String mac) {
+        DownloadInfo downloadInfo = downloadInfoService.updateByLessonUserId(user.getUid(),lessonId,mac);
+        if(downloadInfo == null){
+            APIResult.error(APICode.OPERATE_ERROR);
+        }
+        return APIResult.ok();
+    }
+
+    @RequestMapping(value = "/download/update/resource/size", method = RequestMethod.PUT)
+    public APIResult<Boolean> updateResourceByLessonUserId(@NeedUser DeviceUserVo user,
+                                                           @RequestParam("lessonId") String lessonId,
+                                                           @RequestParam("mac") String mac) {
+        return sync(user,lessonId, mac);
+    }
+
+    private synchronized APIResult<Boolean> sync(DeviceUserVo user, String lessonId, String mac) {
+
+        log.info("Thread.currentThread(),name = {}",Thread.currentThread().getName());
+
+        DownloadInfo downloadInfo = downloadInfoService.findByLessonUserId(user.getUid(),lessonId, mac);
+        if(downloadInfo == null){
+            APIResult.error(APICode.OPERATE_ERROR);
+        }else{
+            int resSize = downloadInfo.getResSize() + 1 ;
+            int resTotal = downloadInfo.getResTotal();
+            if(resSize == resTotal){
+                downloadInfo.setDownloadStatus(DownloadStatus.FINISH_DOWNLOAD);
+            }
+            downloadInfo.setResSize(resSize);
+        }
+
+        DownloadInfo update = downloadInfoService.update(downloadInfo);
+        if(update == null){
+            APIResult.error(APICode.OPERATE_ERROR);
+        }
+        try{
+
+            //Thread.sleep(3000l);
+        }catch(Exception e){
+
+        }
+
+        return APIResult.ok();
+    }
+
 }
 

+ 13 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/controller/CollectionController.java

@@ -2,11 +2,13 @@ package cn.rankin.apiweb.controller;
 
 import cn.rankin.apiweb.assist.resolver.NeedUser;
 import cn.rankin.apiweb.service.collection.CollectionService;
+import cn.rankin.apiweb.service.user.UserService;
 import cn.rankin.common.utils.api.model.APIResult;
 import cn.rankin.common.utils.api.page.Page;
 import cn.rankin.data.api.app.vo.DeviceUserVo;
 import cn.rankin.data.api.app.vo.ItemVo;
 import cn.rankin.data.api.user.dto.CollectionDTO;
+import cn.rankin.data.api.user.entity.UserTag;
 import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -18,6 +20,9 @@ public class CollectionController {
     @Autowired
     private CollectionService collectionService;
 
+    @Autowired
+    private UserService userService;
+
     @RequestMapping(method = RequestMethod.POST)
     public APIResult<Boolean> put(@NeedUser DeviceUserVo user, @RequestBody CollectionDTO collectionDTO) {
         return collectionService.put(user.getUid(), user.getMerchantId(), collectionDTO.getPid());
@@ -37,6 +42,14 @@ public class CollectionController {
         if (StringUtils.isEmpty(tagId)) {
             return collectionService.getUserCollection(userId, merchantId, pageNo, pageSize);
         }else {
+            //tagId   可能为渠道标签ID,也可能为用户标签ID,先做判断再去获取数据
+            UserTag userTag = userService.findUserTagById(tagId);
+            if(null != userTag){
+                //用户标签,
+                return collectionService.getUserConllectionByUserTag(userId, merchantId, tagId, pageNo, pageSize);
+            }
+
+            //渠道标签
             return collectionService.getUserCollection(userId, merchantId, tagId, pageNo, pageSize);
         }
     }

+ 35 - 1
rankin-api-web/src/main/java/cn/rankin/apiweb/controller/CourseController.java

@@ -3,14 +3,19 @@ package cn.rankin.apiweb.controller;
 import cn.rankin.apiweb.assist.resolver.NeedUser;
 import cn.rankin.apiweb.service.auth.AuthService;
 import cn.rankin.apiweb.service.collection.CollectionService;
+import cn.rankin.apiweb.service.download.DownloadInfoService;
 import cn.rankin.apiweb.service.product.ProductService;
 import cn.rankin.apiweb.service.shopcart.ShopCartService;
 import cn.rankin.common.utils.api.model.APIResult;
+import cn.rankin.common.utils.constant.DownloadStatus;
 import cn.rankin.data.api.app.vo.*;
 import cn.rankin.data.api.auth.vo.AuthResult;
+import cn.rankin.data.api.user.entity.DownloadInfo;
+import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.ArrayList;
 import java.util.List;
 
 @RestController
@@ -29,18 +34,47 @@ public class CourseController {
     @Autowired
     private ShopCartService shopCartService;
 
+    @Autowired
+    private DownloadInfoService downloadInfoService;
+
     @RequestMapping(value = "/{courseId}/lessons", method = RequestMethod.GET)
-    public APIResult<CourseVo> getCourseLessons(@NeedUser DeviceUserVo user, @PathVariable("courseId") String courseId) {
+    public APIResult<CourseVo> getCourseLessons(@NeedUser DeviceUserVo user,
+                                                @PathVariable("courseId") String courseId,
+                                                @RequestParam(name="mac",required =false) String mac) {
         String userId = user.getUid();
         String merchantId = user.getMerchantId();
         APIResult<CourseVo> apiResult = productService.getCourseLessons(courseId);
         if (!apiResult.getSuccess()) {
             return apiResult;
         }
+
         CourseVo courseVo = apiResult.getData();
         Boolean auth = authService.isValid(userId, merchantId, courseId);
         courseVo.setAuth(auth);
 
+
+        List<LessonVo> data = new ArrayList<>();
+        List<LessonVo> lessonVos = courseVo.getList();
+        lessonVos.forEach( vo -> {
+            try{
+                if(StringUtils.isNotBlank(mac)){
+                    DownloadInfo downloadInfo = downloadInfoService.findByLessonUserId(userId, vo.getId(), mac);
+                    if(null != downloadInfo && DownloadStatus.FINISH_DOWNLOAD == downloadInfo.getDownloadStatus()){
+                        vo.setDownloadStatus(DownloadStatus.FINISH_DOWNLOAD);
+                    }else if(null != downloadInfo && DownloadStatus.PROCESS_DOWNLOAD == downloadInfo.getDownloadStatus()){
+                        vo.setDownloadStatus(DownloadStatus.PROCESS_DOWNLOAD);
+                    }else if(null != downloadInfo && DownloadStatus.FAIL_DOWNLOAD == downloadInfo.getDownloadStatus()){
+                        vo.setDownloadStatus(DownloadStatus.FAIL_DOWNLOAD);
+                    }
+                }
+            }catch(Exception e){
+                e.printStackTrace();
+            }
+
+            data.add(vo);
+        });
+        courseVo.setList(data);
+
         Boolean isCollected = collectionService.isCollected(userId, courseId);
         courseVo.setCollected(isCollected);
         return apiResult;

+ 83 - 7
rankin-api-web/src/main/java/cn/rankin/apiweb/controller/LoginController.java

@@ -2,12 +2,16 @@ package cn.rankin.apiweb.controller;
 
 import cn.rankin.apiweb.assist.resolver.RequestHeader;
 import cn.rankin.apiweb.entity.GlobalHeader;
+import cn.rankin.apiweb.helper.MacAddressHelper;
 import cn.rankin.apiweb.service.user.UserService;
 import cn.rankin.common.utils.api.model.APIResult;
 import cn.rankin.common.utils.util.HttpUtil;
 import cn.rankin.data.api.app.dto.DeviceLoginDTO;
 import cn.rankin.data.api.app.dto.LoginInfoDTO;
 import cn.rankin.data.api.app.vo.UserInfoVo;
+import eu.bitwalker.useragentutils.Browser;
+import eu.bitwalker.useragentutils.OperatingSystem;
+import eu.bitwalker.useragentutils.UserAgent;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -17,27 +21,43 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.validation.Valid;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 @Slf4j
 @RestController
 @RequestMapping(value = "/token")
-public class LoginController {
+public class LoginController
+{
 
     @Autowired
     private UserService userService;
 
     @RequestMapping(method = RequestMethod.POST)
-    public APIResult<UserInfoVo> login(HttpServletRequest request, @Valid @RequestBody LoginInfoDTO loginInfoDTO) {
+    public APIResult<UserInfoVo> login(HttpServletRequest request, @Valid @RequestBody LoginInfoDTO loginInfoDTO)
+    {
+
+        String terminal = request.getHeader("terminal");
+        String merchant = request.getHeader("merchant");
+        String userAgent = request.getHeader("User-Agent");
+
         String ip = HttpUtil.getClientIp(request);
         loginInfoDTO.setIp(ip);
-        loginInfoDTO.setTerminal(request.getHeader("terminal"));
-        loginInfoDTO.setMerchant(request.getHeader("merchant"));
+        loginInfoDTO.setTerminal(terminal);
+        loginInfoDTO.setMerchant(merchant);
+
+        //填充设备信息
+        fillDeviceInfo(userAgent, loginInfoDTO);
+
+        log.info("login request header : ip={},terminal={},merchant={},user-agent={}", ip, terminal, merchant);
+
 
-        log.info("login request header : ip={},terminal={},merchant={}",ip , request.getHeader("terminal"), request.getHeader("merchant"));
         return userService.login(loginInfoDTO);
     }
 
     @RequestMapping(method = RequestMethod.PUT)
-    public APIResult<UserInfoVo> refresh(HttpServletRequest request, @RequestBody DeviceLoginDTO deviceLoginDTO) {
+    public APIResult<UserInfoVo> refresh(HttpServletRequest request, @RequestBody DeviceLoginDTO deviceLoginDTO)
+    {
         String deviceCode = deviceLoginDTO.getDeviceCode();
         String merchant = request.getHeader("merchant");
         log.info("refresh request header : deviceCode={}, merchant={}", deviceCode, merchant);
@@ -45,8 +65,64 @@ public class LoginController {
     }
 
     @RequestMapping(method = RequestMethod.DELETE)
-    public APIResult<Boolean> logout(@RequestHeader GlobalHeader globalHeader) {
+    public APIResult<Boolean> logout(@RequestHeader GlobalHeader globalHeader)
+    {
         String userId = globalHeader.getUid();
         return userService.logout(userId);
     }
+
+    /**
+     * Fill device info
+     * @param userAgentStr the string of user agent
+     * @param loginInfoDTO the login info
+     */
+    private void fillDeviceInfo(String userAgentStr, LoginInfoDTO loginInfoDTO)
+    {
+        if (userAgentStr == "" || userAgentStr == null)
+        {
+            return;
+        }
+        if (loginInfoDTO == null)
+        {
+            return;
+        }
+
+        UserAgent userAgent = UserAgent.parseUserAgentString(userAgentStr);
+
+        //获取浏览器对象
+        Browser browser = userAgent.getBrowser();
+
+        //获取操作系统对象
+        OperatingSystem operatingSystem = userAgent.getOperatingSystem();
+
+        //操作系统名称
+        String osName = operatingSystem.getName();
+        loginInfoDTO.setDeviceName(osName);
+
+        //获取厂商
+        String osMfrs = operatingSystem.getManufacturer().toString();
+        loginInfoDTO.setDeviceMfrs(osMfrs);
+
+        //获取设备类型
+        String deviceType = operatingSystem.getDeviceType().toString();
+        loginInfoDTO.setDeviceType(deviceType);
+
+        //获取设备型号
+        if ("MOBILE".equals(deviceType))
+        {
+            Pattern pattern = Pattern.compile(";\\s?(\\S*?\\s?\\S*?)\\s?(Build)?/");
+            Matcher matcher = pattern.matcher(userAgentStr);
+            String model = null;
+            if (matcher.find())
+            {
+                model = matcher.group(1).trim();
+                loginInfoDTO.setDeviceModel(model);
+            }
+        }
+        else
+        {
+            loginInfoDTO.setDeviceModel(osName);
+        }
+    }
+
 }

+ 1 - 8
rankin-api-web/src/main/java/cn/rankin/apiweb/controller/RecommendController.java

@@ -52,14 +52,7 @@ public class RecommendController {
             pids.forEach(pid -> {
                 if(result.size() < RECOMMEND_NUM){
                     Course course = productService.getCourse(pid);
-                    if(course != null){
-                        /*RecommendVo vo = new RecommendVo();
-                        vo.setId(course.getId());
-                        vo.setCode(course.getCode());
-                        vo.setTitle(course.getTitle());
-                        vo.setSubTitle(course.getSubTitle());
-                        vo.setBreadCrumb(course.getBreadCrumb());
-                        vo.setCoverUrl(course.getCoverUrl());*/
+                    if(course != null && course.getCourseType() == 0){
                         RecommendVo vo = courseToRecommendVo(course);
                         result.add(vo);
                     }else{

+ 145 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/helper/MacAddressHelper.java

@@ -0,0 +1,145 @@
+package cn.rankin.apiweb.helper;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class MacAddressHelper
+{
+    public static String callCmd(String[] cmd) {
+        String result = "";
+        String line = "";
+        try {
+            Process proc = Runtime.getRuntime().exec(cmd);
+            InputStreamReader is = new InputStreamReader(proc.getInputStream());
+            BufferedReader br = new BufferedReader(is);
+            while ((line = br.readLine ()) != null) {
+                result += line;
+            }
+        }catch(Exception e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+    /**
+     *
+     *
+     *
+     * @param cmd
+     *            第一个命令
+     *
+     * @param another
+     *            第二个命令
+     *
+     * @return 第二个命令的执行结果
+     *
+     */
+
+    public static String callCmd(String[] cmd,String[] another) {
+        String result = "";
+        String line = "";
+        try {
+            Runtime rt = Runtime.getRuntime();
+            Process proc = rt.exec(cmd);
+            proc.waitFor(); // 已经执行完第一个命令,准备执行第二个命令
+            proc = rt.exec(another);
+            InputStreamReader is = new InputStreamReader(proc.getInputStream());
+            BufferedReader br = new BufferedReader (is);
+            while ((line = br.readLine ()) != null) {
+                result += line;
+            }
+        }catch(Exception e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+    /**
+     *
+     *
+     *
+     * @param ip
+     *            目标ip,一般在局域网内
+     *
+     * @param sourceString
+     *            命令处理的结果字符串
+     *
+     * @param macSeparator
+     *            mac分隔符号
+     *
+     * @return mac地址,用上面的分隔符号表示
+     *
+     */
+
+    public static String filterMacAddress(final String ip, final String sourceString,final String macSeparator) {
+        String result = "";
+        String regExp = "((([0-9,A-F,a-f]{1,2}" + macSeparator + "){1,5})[0-9,A-F,a-f]{1,2})";
+        Pattern pattern = Pattern.compile(regExp);
+        Matcher matcher = pattern.matcher(sourceString);
+        while(matcher.find()){
+            result = matcher.group(1);
+            if(sourceString.indexOf(ip) <= sourceString.lastIndexOf(matcher.group(1))) {
+                break; // 如果有多个IP,只匹配本IP对应的Mac.
+            }
+        }
+        return result;
+    }
+
+    /**
+     *
+     *
+     *
+     * @param ip
+     *            目标ip
+     *
+     * @return Mac Address
+     *
+     *
+     *
+     */
+
+    public static String getMacInWindows(final String ip){
+        String result = "";
+        String[] cmd = {"cmd","/c","ping " + ip};
+        String[] another = {"cmd","/c","arp -a"};
+        String cmdResult = callCmd(cmd,another);
+        result = filterMacAddress(ip,cmdResult,"-");
+        return result;
+    }
+    /**
+     *
+     * @param ip
+     *            目标ip
+     * @return Mac Address
+     *
+     */
+    public static String getMacInLinux(final String ip){
+        String result = "";
+        String[] cmd = {"/bin/sh","-c","ping " +  ip + " -c 2 && arp -a" };
+        String cmdResult = callCmd(cmd);
+        result = filterMacAddress(ip,cmdResult,":");
+        return result;
+    }
+
+    /**
+     * 获取MAC地址
+     *
+     * @return 返回MAC地址
+     */
+    public static String getMacAddress(String ip){
+        String macAddress = "";
+        macAddress = getMacInWindows(ip).trim();
+        if(macAddress==null||"".equals(macAddress)){
+            macAddress = getMacInLinux(ip).trim();
+        }
+        return macAddress;
+    }
+    public static void main(String[] args) {
+
+
+        String mac1=getMacInLinux("127.0.0.1");
+        System.out.println("mac:"+mac1);
+    }
+
+}

+ 51 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/service/collection/CollectionService.java

@@ -1,7 +1,9 @@
 package cn.rankin.apiweb.service.collection;
 
 import cn.rankin.apiweb.code.ApiWebCode;
+import cn.rankin.apiweb.service.product.ProductClient;
 import cn.rankin.apiweb.service.product.ProductService;
+import cn.rankin.apiweb.service.user.UserService;
 import cn.rankin.common.utils.api.model.APIResult;
 import cn.rankin.common.utils.api.model.BaseCode;
 import cn.rankin.common.utils.api.page.Page;
@@ -11,6 +13,7 @@ import cn.rankin.data.api.app.vo.ItemVo;
 import cn.rankin.data.api.product.entity.MerchantProduct;
 import cn.rankin.data.api.user.dto.CollectionDTO;
 import cn.rankin.data.api.user.entity.Collection;
+import cn.rankin.data.api.user.entity.UserTagProductRelation;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -30,8 +33,14 @@ public class CollectionService {
     private CollectionClient collectionClient;
 
     @Autowired
+    private ProductClient productClient;
+
+    @Autowired
     private ProductService productService;
 
+    @Autowired
+    private UserService userService;
+
     public Boolean isCollected(String userId, String productId) {
         APIResult<Collection> apiResult = collectionClient.getCollection(userId, productId);
         if (apiResult.getSuccess() && apiResult.getData() != null) {
@@ -115,4 +124,46 @@ public class CollectionService {
         return productService.findItemPageByIds(itemSearchDTO);
     }
 
+    public APIResult<Page<ItemVo>> getUserConllectionByUserTag(String userId, String merchantId, String userTagId,
+                                                               Integer pageNo, Integer pageSize) {
+        APIResult<List<Collection>> collectionApiResult = collectionClient.getUserCollections(userId, MAX_SIZE);
+        if (!collectionApiResult.getSuccess()) {
+            return APIResult.error(new BaseCode(collectionApiResult.getCode(), collectionApiResult.getMessage()));
+        }
+        List<Collection> collectionList = collectionApiResult.getData();
+        if (CollectionUtils.isEmpty(collectionList)) {
+            return APIResult.ok(new ArrayList<>());
+        }
+        List<String> productIdList = new ArrayList<>();
+        for (Collection collection : collectionList) {
+            String productId = collection.getPid();
+            productIdList.add(productId);
+        }
+
+        Page<UserTagProductRelation> resultPage = userService.findRelations(userTagId, productIdList, pageNo, pageSize);
+
+        if(resultPage == null){
+            return APIResult.ok(new ArrayList());
+        }
+
+        List<ItemVo> itemVos = new ArrayList<>();
+        List<UserTagProductRelation> userTagProductRelations = resultPage.getList();
+        userTagProductRelations.forEach(userTagProductRelation -> {
+            String pid = userTagProductRelation.getPid();
+            ItemVo itemVo = productClient.findItemByPid(merchantId, pid);
+            if(itemVo == null){
+                log.info("not found item by pid , pid={}",pid);
+            }else{
+                itemVos.add(itemVo);
+            }
+        });
+
+        Page<ItemVo> page = new Page<>();
+        page.setPageSize(pageSize);
+        page.setPageNo(pageNo);
+        page.setTotalSize((int)resultPage.getTotalSize());
+        page.setList(itemVos);
+
+        return APIResult.ok(page);
+    }
 }

+ 36 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/service/download/DownloadInfoClient.java

@@ -0,0 +1,36 @@
+package cn.rankin.apiweb.service.download;
+
+import cn.rankin.data.api.user.dto.DownloadInfoDTO;
+import cn.rankin.data.api.user.entity.DownloadInfo;
+import org.springframework.cloud.netflix.feign.FeignClient;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@FeignClient(name = "${service.user.name}")
+public interface DownloadInfoClient {
+
+    @RequestMapping(value = "/download", method = RequestMethod.POST)
+    DownloadInfo add(@RequestBody DownloadInfoDTO dto);
+
+    @RequestMapping(value = "/download/list", method = RequestMethod.GET)
+    List<DownloadInfo> findByUserId(@RequestParam("uid") String uid , @RequestParam("mac") String mac);
+
+    @RequestMapping(value = "/download", method = RequestMethod.GET)
+    DownloadInfo findByLessonUserId(@RequestParam("uid") String uid, @RequestParam("lessonId") String lessonId, @RequestParam("mac") String mac);
+
+    @RequestMapping(value = "/download/delete", method = RequestMethod.DELETE)
+    DownloadInfo deleteByLessonUserId(@RequestParam("uid") String uid, @RequestParam("lessonId") String lessonId, @RequestParam("mac") String mac);
+
+    @RequestMapping(value = "/download/update/resource", method = RequestMethod.PUT)
+    DownloadInfo updateByLessonUserId(@RequestParam("uid") String uid, @RequestParam("lessonId") String lessonId, @RequestParam("mac") String mac);
+
+    @RequestMapping(value = "/download/update", method = RequestMethod.PUT)
+    DownloadInfo update(@RequestBody DownloadInfo downloadInfo);
+
+    @RequestMapping(value = "/download/fail", method = RequestMethod.PUT)
+    boolean downloadFail(@RequestParam("uid") String uid, @RequestParam("mac") String mac);
+
+    @RequestMapping(value = "/download/status", method = RequestMethod.GET)
+    DownloadInfo findDownloadStatus(@RequestParam("uid")String uid, @RequestParam("lessonId") String lessonId, @RequestParam("mac") String mac);
+}

+ 50 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/service/download/DownloadInfoService.java

@@ -0,0 +1,50 @@
+package cn.rankin.apiweb.service.download;
+
+import cn.rankin.data.api.user.dto.DownloadInfoDTO;
+import cn.rankin.data.api.user.entity.DownloadInfo;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+@Slf4j
+public class DownloadInfoService {
+
+    @Autowired
+    private DownloadInfoClient downloadInfoClient;
+
+    public DownloadInfo add(DownloadInfoDTO dto) {
+        return downloadInfoClient.add(dto);
+    }
+
+
+    public List<DownloadInfo> findByUserId(String uid , String mac) {
+        return downloadInfoClient.findByUserId(uid, mac);
+    }
+
+    public DownloadInfo findByLessonUserId(String uid,String lessonId, String mac) {
+        return downloadInfoClient.findByLessonUserId(uid,lessonId,mac);
+    }
+
+    public DownloadInfo deleteByLessonUserId(String uid, String lessonId, String mac) {
+        return downloadInfoClient.deleteByLessonUserId(uid,lessonId,mac);
+    }
+
+    public DownloadInfo updateByLessonUserId(String uid, String lessonId, String mac) {
+        return downloadInfoClient.updateByLessonUserId(uid,lessonId,mac);
+    }
+
+    public synchronized DownloadInfo update(DownloadInfo downloadInfo) {
+        return downloadInfoClient.update(downloadInfo);
+    }
+
+    public boolean downloadFail(String uid, String mac) {
+        return downloadInfoClient.downloadFail(uid, mac);
+    }
+
+    public DownloadInfo findDownloadStatus(String uid, String lessonId, String mac) {
+        return downloadInfoClient.findDownloadStatus(uid,lessonId,mac);
+    }
+}

+ 8 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/service/product/ProductClient.java

@@ -89,6 +89,9 @@ public interface ProductClient {
     @RequestMapping(value = "/item/pid", method = RequestMethod.POST)
     ItemVo findItemByPid(@RequestParam("merchantId") String merchantId, @RequestParam("pid") String pid);
 
+    @RequestMapping(value = "/app/tag/{tagId}", method = RequestMethod.GET)
+    Tag findTagById(@PathVariable("tagId") String tagId);
+
 
     @Component
     class ProductClientHystrix implements ProductClient {
@@ -197,5 +200,10 @@ public interface ProductClient {
             return null;
         }
 
+        @Override
+        public Tag findTagById(String tagId) {
+            return null;
+        }
+
     }
 }

+ 8 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/service/product/ProductService.java

@@ -102,6 +102,14 @@ public class ProductService {
         return APIResult.error(ApiWebCode.ACCESS_DENIED);
     }
 
+    public APIResult<Lesson> getLesson(String lessonId, String courseId) {
+        APIResult<Lesson> apiResult = productClient.getLesson(lessonId, courseId);
+        if (!apiResult.getSuccess()) {
+            return APIResult.error(new BaseCode(apiResult.getCode(), apiResult.getMessage()));
+        }
+        return apiResult;
+    }
+
     public List<Poster> getPosters(String merchantId){
         return productClient.getPosters(merchantId, 0L, 10, "sort", Sort.Direction.ASC);
     }

+ 62 - 13
rankin-api-web/src/main/java/cn/rankin/apiweb/service/user/UserClient.java

@@ -4,6 +4,7 @@ import cn.rankin.apiweb.code.ApiWebCode;
 import cn.rankin.common.utils.api.model.APIResult;
 import cn.rankin.common.utils.api.page.Page;
 import cn.rankin.data.api.user.dto.TerminalDeviceDTO;
+import cn.rankin.data.api.user.dto.UserDeviceDTO;
 import cn.rankin.data.api.user.entity.UserRecommend;
 import cn.rankin.data.api.user.entity.UserTag;
 import cn.rankin.data.api.user.entity.UserTagProductRelation;
@@ -17,7 +18,8 @@ import org.springframework.web.bind.annotation.*;
 import java.util.List;
 
 @FeignClient(name = "${service.user.name}", fallback = UserClient.UserServiceHystrix.class)
-public interface UserClient {
+public interface UserClient
+{
 
     @RequestMapping(value = "/user/code/{code}", method = RequestMethod.GET)
     APIResult<TerminalUserVo> loadUserByEid(@PathVariable("code") String code);
@@ -54,62 +56,109 @@ public interface UserClient {
                                                      @RequestParam("pageNo") Integer pageNo,
                                                      @RequestParam("pageSize") Integer pageSize);
 
+    @RequestMapping(value = "/userTag/{tagId}", method = RequestMethod.GET)
+    UserTag findUserTagById(@PathVariable("tagId") String tagId);
+
+
+    @RequestMapping(value = "/userDevice/op/{uid}", method = RequestMethod.GET)
+    int opUserDevice(@PathVariable("uid") String uid,
+                     @RequestBody UserDeviceDTO userDeviceDTO);
+
+
+    @RequestMapping(value = "/userTagProductRelation/page/pids", method = RequestMethod.POST)
+    Page<UserTagProductRelation> findRelations(@RequestParam("userTagId") String userTagId,
+                                               @RequestBody List<String> productIdList,
+                                               @RequestParam("pageNo") Integer pageNo,
+                                               @RequestParam("pageSize") Integer pageSize);
 
     @Component
-    class UserServiceHystrix implements UserClient {
+    class UserServiceHystrix implements UserClient
+    {
 
         @Override
-        public APIResult loadUserByEid(String code) {
+        public APIResult loadUserByEid(String code)
+        {
             return APIResult.error(ApiWebCode.SERVER_ERROR);
         }
 
         @Override
-        public APIResult deviceBind(TerminalDeviceDTO terminalDeviceDTO) {
+        public APIResult deviceBind(TerminalDeviceDTO terminalDeviceDTO)
+        {
             return APIResult.error(ApiWebCode.SERVER_ERROR);
         }
 
         @Override
-        public APIResult deviceUnbind(String userId) {
+        public APIResult deviceUnbind(String userId)
+        {
             return APIResult.error(ApiWebCode.SERVER_ERROR);
         }
 
         @Override
-        public APIResult findDeviceByUid(String uid) {
+        public APIResult findDeviceByUid(String uid)
+        {
             return APIResult.error(ApiWebCode.SERVER_ERROR);
         }
 
         @Override
-        public APIResult findUserById(String id) {
+        public APIResult findUserById(String id)
+        {
             return APIResult.error(ApiWebCode.SERVER_ERROR);
         }
 
         @Override
-        public List<TerminalDeviceVo> findByDeviceCode(String deviceCode) {
+        public List<TerminalDeviceVo> findByDeviceCode(String deviceCode)
+        {
             return null;
         }
 
         @Override
-        public APIResult<WhiteUserVo> findWhiteUserById(String userId) {
+        public APIResult<WhiteUserVo> findWhiteUserById(String userId)
+        {
             return APIResult.error(ApiWebCode.SERVER_ERROR);
         }
 
         @Override
-        public List<UserRecommend> getUserRecommendCourses(String uid) {
+        public List<UserRecommend> getUserRecommendCourses(String uid)
+        {
             return null;
         }
 
         @Override
-        public List<UserTag> findUserTagByCodeUid(String code, String uid) {
+        public List<UserTag> findUserTagByCodeUid(String code, String uid)
+        {
             return null;
         }
 
         @Override
-        public APIResult updateDeviceBind(TerminalDeviceDTO deviceDTO) {
+        public APIResult updateDeviceBind(TerminalDeviceDTO deviceDTO)
+        {
             return APIResult.error(ApiWebCode.SERVER_ERROR);
         }
 
         @Override
-        public Page<UserTagProductRelation> findPageByUserTagId(String userTagId, Integer pageNo, Integer pageSize) {
+        public Page<UserTagProductRelation> findPageByUserTagId(String userTagId, Integer pageNo, Integer pageSize)
+        {
+            return null;
+        }
+
+        @Override
+        public UserTag findUserTagById(String tagId)
+        {
+            return null;
+        }
+
+        @Override
+        public int opUserDevice(String uid, UserDeviceDTO userDeviceDTO)
+        {
+            return 0;
+        }
+
+        @Override
+        public Page<UserTagProductRelation> findRelations(String userTagId,
+                                                          List<String> productIdList,
+                                                          Integer pageNo,
+                                                          Integer pageSize)
+        {
             return null;
         }
 

+ 145 - 54
rankin-api-web/src/main/java/cn/rankin/apiweb/service/user/UserService.java

@@ -14,6 +14,7 @@ import cn.rankin.data.api.app.vo.DeviceUserVo;
 import cn.rankin.data.api.app.vo.ItemVo;
 import cn.rankin.data.api.app.vo.UserInfoVo;
 import cn.rankin.data.api.user.dto.TerminalDeviceDTO;
+import cn.rankin.data.api.user.dto.UserDeviceDTO;
 import cn.rankin.data.api.user.entity.UserRecommend;
 import cn.rankin.data.api.user.entity.UserTag;
 import cn.rankin.data.api.user.entity.UserTagProductRelation;
@@ -37,7 +38,8 @@ import java.util.Map;
 
 @Service
 @Slf4j
-public class UserService {
+public class UserService
+{
 
     public final static String USER_FORMAT_KEY = RedisKey.USER_FORMAT_KEY;
 
@@ -56,8 +58,14 @@ public class UserService {
     @Autowired
     private RedisService redisService;
 
-    public APIResult<UserInfoVo> login(LoginInfoDTO loginInfoDTO) {
+    public APIResult<UserInfoVo> login(LoginInfoDTO loginInfoDTO)
+    {
         String deviceCode = loginInfoDTO.getDeviceCode();
+        String deviceModel = loginInfoDTO.getDeviceModel();
+        String deviceMfrs = loginInfoDTO.getDeviceMfrs();
+        String deviceName = loginInfoDTO.getDeviceName();
+        String deviceType = loginInfoDTO.getDeviceType();
+
         String merchant = loginInfoDTO.getMerchant();
         String eid = loginInfoDTO.getEid();
         String loginPassword = loginInfoDTO.getPassword();
@@ -65,15 +73,37 @@ public class UserService {
 
         APIResult<TerminalUserVo> userVoAPIResult = userClient.loadUserByEid(eid);
         TerminalUserVo userVo = userVoAPIResult.getData();
-        if (!userVoAPIResult.getSuccess()) {
+        if (!userVoAPIResult.getSuccess())
+        {
             log.error("load user api error");
             return APIResult.error(ApiWebCode.LOGIN_ERROR);
         }
 
-
+        //操作用户登录设备信息
+        if (deviceName != null && !"".equals(deviceName.trim()))
+        {
+            String uid = userVo.getId();
+            UserDeviceDTO dto = new UserDeviceDTO();
+            dto.setDeviceCode(deviceCode);
+            dto.setDeviceModel(deviceModel);
+            dto.setDeviceType(deviceType);
+            dto.setDeviceMfrs(deviceMfrs);
+            dto.setDeviceName(deviceName);
+
+            int opRet = userClient.opUserDevice(uid,dto);
+            if (opRet == 0)
+            {
+                log.error("Failed to operated user device with[uid={},deviceCode={},deviceModel={},deviceName={}]", uid, deviceCode, deviceModel, deviceName);
+            }
+            else
+            {
+                log.info("Succeed to operating user device with[uid={},deviceCode={},deviceModel={},deviceName={}]", uid, deviceCode, deviceModel, deviceName);
+            }
+        }
 
         String storePassword = userVo.getPassword();
-        if (!SecurityManager.validate(loginPassword, storePassword)) {
+        if (!SecurityManager.validate(loginPassword, storePassword))
+        {
             log.error("密码校验错误, loginPassword={}, storePassword={}", loginPassword, storePassword);
             return APIResult.error(ApiWebCode.PASSWORD_ERROR);
         }
@@ -89,16 +119,20 @@ public class UserService {
         String terminal = loginInfoDTO.getTerminal();
 
         // 网页端登陆在40分钟后可以踢掉对方网页登陆
-        if (PlatForm.WEB.equals(terminal)) {
+        if (PlatForm.WEB.equals(terminal))
+        {
             String key = getUserFormatKey(userId);
             DeviceUserVo deviceUserVo = (DeviceUserVo) redisService.get(key);
-            if (deviceUserVo != null ) {
+            if (deviceUserVo != null)
+            {
                 Date refreshAt = deviceUserVo.getRefreshAt();
                 String lastTerminal = deviceUserVo.getTerminal();
-                if (DateUtils.addSeconds(refreshAt, forceLoginInterval).before(new Date()) && PlatForm.WEB.equals(lastTerminal)) {
+                if (DateUtils.addSeconds(refreshAt, forceLoginInterval).before(new Date()) && PlatForm.WEB.equals(lastTerminal))
+                {
                     log.info("网页端强制登陆, deviceCode={}, eid={}", deviceCode, eid);
                     APIResult<Boolean> forceLogoutResult = this.logout(userId);
-                    if (!forceLogoutResult.getSuccess()) {
+                    if (!forceLogoutResult.getSuccess())
+                    {
                         return APIResult.error(new BaseCode(forceLogoutResult.getCode(), forceLogoutResult.getMessage()));
                     }
                 }
@@ -106,7 +140,8 @@ public class UserService {
         }
 
         TerminalDeviceVo deviceVo = this.bind(userId, deviceCode, merchant, ip, terminal);
-        if (deviceVo == null) {
+        if (deviceVo == null)
+        {
             return APIResult.error(ApiWebCode.DEVICE_BOUND_ERROR);
         }
 
@@ -121,9 +156,11 @@ public class UserService {
         return APIResult.ok(userInfoVo);
     }
 
-    public APIResult<Boolean> logout(String userId) {
+    public APIResult<Boolean> logout(String userId)
+    {
         APIResult<Boolean> unbindResult = userClient.deviceUnbind(userId);
-        if (!unbindResult.getSuccess()) {
+        if (!unbindResult.getSuccess())
+        {
             return APIResult.error(ApiWebCode.LOGOUT_ERROR);
         }
 
@@ -133,7 +170,8 @@ public class UserService {
         return APIResult.ok();
     }
 
-    public TerminalDeviceVo bind(String userId, String deviceCode, String merchant, String ip, String terminal) {
+    public TerminalDeviceVo bind(String userId, String deviceCode, String merchant, String ip, String terminal)
+    {
         TerminalDeviceDTO deviceDTO = new TerminalDeviceDTO();
         deviceDTO.setUserId(userId);
         deviceDTO.setDeviceCode(deviceCode);
@@ -141,41 +179,49 @@ public class UserService {
         deviceDTO.setIp(ip);
         deviceDTO.setTerminal(terminal);
         APIResult<TerminalDeviceVo> apiResult = userClient.deviceBind(deviceDTO);
-        if (!apiResult.getSuccess()) {
+        if (!apiResult.getSuccess())
+        {
             log.error("bind user api error");
-            throw new RuntimeException(apiResult.getMessage());
+            return null;
         }
         return apiResult.getData();
     }
 
     // load user and device info
-    public DeviceUserVo load(String uid) {
+    public DeviceUserVo load(String uid)
+    {
         String key = getUserFormatKey(uid);
         DeviceUserVo deviceUserVo = (DeviceUserVo) redisService.get(key);
-        if (deviceUserVo == null) {
+        if (deviceUserVo == null)
+        {
             deviceUserVo = getDeviceUserVo(uid);
         }
-        if (deviceUserVo != null) {
+        if (deviceUserVo != null)
+        {
             this.save(deviceUserVo);
         }
         return deviceUserVo;
     }
 
-    public UserInfoVo getUserInfo(String uid) {
+    public UserInfoVo getUserInfo(String uid)
+    {
         DeviceUserVo deviceUserVo = this.load(uid);
         return toUserInfoVo(deviceUserVo, false);
     }
 
-    public DeviceUserVo getDeviceUserVo(String uid) {
+    public DeviceUserVo getDeviceUserVo(String uid)
+    {
         APIResult<TerminalDeviceVo> deviceAPIResult = userClient.findDeviceByUid(uid);
-        if (!deviceAPIResult.getSuccess()) {
+        if (!deviceAPIResult.getSuccess())
+        {
             log.error("load device api error, {}", deviceAPIResult.getMessage());
             return null;
         }
         TerminalDeviceVo deviceVo = deviceAPIResult.getData();
         // load user info
         APIResult<TerminalUserVo> userAPIResult = userClient.findUserById(uid);
-        if (!userAPIResult.getSuccess()) {
+        if (!userAPIResult.getSuccess())
+        {
             log.error("load user api error, {}", userAPIResult.getMessage());
             return null;
         }
@@ -184,30 +230,44 @@ public class UserService {
         return toDeviceUserVo(userVo, deviceVo);
     }
 
-    public APIResult<UserInfoVo> refresh(String deviceCode, String merchant, Boolean force) {
+    public APIResult<UserInfoVo> refresh(String deviceCode, String merchant, Boolean force)
+    {
 
         List<TerminalDeviceVo> deviceVoList = userClient.findByDeviceCode(deviceCode);
-        if (CollectionUtils.isEmpty(deviceVoList)) {
+        if (CollectionUtils.isEmpty(deviceVoList))
+        {
             log.error("device code not bind any eid! deviceCode={}", deviceCode);
-            return APIResult.error(ApiWebCode.NOT_EXISTS);
+            return APIResult.error(ApiWebCode.INVALID_TOKEN);
         }
 
         TerminalDeviceVo deviceVo = null;
 
-        for (TerminalDeviceVo dv : deviceVoList) {
+        for (TerminalDeviceVo dv : deviceVoList)
+        {
             //判断当前鉴权账号
-            if(StringUtils.isBlank(dv.getMerchant())){
+            if (StringUtils.isBlank(dv.getMerchant()))
+            {
                 //如果设备渠道code为空,则设置为当前渠道code
                 dv.setMerchant(merchant);
-                //更新数据库
-                updateDeviceBind(dv);
+                try
+                {
+                    //更新数据库
+                    updateDeviceBind(dv);
+                }
+                catch (Exception e)
+                {
+                    return APIResult.error(ApiWebCode.DEVICE_BOUND_ERROR);
+                }
                 deviceVo = dv;
-            }else if(StringUtils.isNotBlank(merchant) && merchant.equals(dv.getMerchant())) {
+            }
+            else if (StringUtils.isNotBlank(merchant) && merchant.equals(dv.getMerchant()))
+            {
                 deviceVo = dv;
             }
         }
 
-        if(null == deviceVo){
+        if (null == deviceVo)
+        {
             log.error("by device code not find this merchant! deviceCode={},merchant={}", deviceCode, merchant);
             return APIResult.error(ApiWebCode.INVALID_TOKEN);
         }
@@ -215,21 +275,26 @@ public class UserService {
         String uid = deviceVo.getUserId();
 
         DeviceUserVo deviceUserVo;
-        if (force) {
+        if (force)
+        {
             APIResult<TerminalUserVo> userAPIResult = userClient.findUserById(uid);
-            if (!userAPIResult.getSuccess()) {
+            if (!userAPIResult.getSuccess())
+            {
                 log.error("load user api error, {}", userAPIResult.getMessage());
-                return APIResult.error(ApiWebCode.NOT_EXISTS);
+                return APIResult.error(ApiWebCode.INVALID_TOKEN);
             }
             TerminalUserVo userVo = userAPIResult.getData();
             deviceUserVo = toDeviceUserVo(userVo, deviceVo);
-        }else {
+        }
+        else
+        {
             String key = getUserFormatKey(uid);
             deviceUserVo = (DeviceUserVo) redisService.get(key);
         }
 
         // 无论怎样都能成功刷新
-        if (deviceUserVo == null) {
+        if (deviceUserVo == null)
+        {
             deviceUserVo = getDeviceUserVo(uid);
         }
 
@@ -240,30 +305,35 @@ public class UserService {
         return APIResult.ok(userInfoVo);
     }
 
-    private void updateDeviceBind(TerminalDeviceVo terminalDeviceVo) {
+    private void updateDeviceBind(TerminalDeviceVo terminalDeviceVo)
+    {
         TerminalDeviceDTO deviceDTO = new TerminalDeviceDTO();
         deviceDTO.setId(terminalDeviceVo.getId());
         deviceDTO.setMerchant(terminalDeviceVo.getMerchant());
         deviceDTO.setDeviceCode(terminalDeviceVo.getDeviceCode());
         deviceDTO.setUserId(terminalDeviceVo.getUserId());
         APIResult apiResult = userClient.updateDeviceBind(deviceDTO);
-        if (!apiResult.getSuccess()) {
+        if (!apiResult.getSuccess())
+        {
             log.error("update bind user api error");
             throw new RuntimeException("update bind user api error");
         }
     }
 
     // cache user and device info
-    public void save(DeviceUserVo deviceUserVo) {
+    public void save(DeviceUserVo deviceUserVo)
+    {
         String key = getUserFormatKey(deviceUserVo.getUid());
         redisService.set(key, deviceUserVo);
     }
 
-    public static String getUserFormatKey(String uid) {
+    public static String getUserFormatKey(String uid)
+    {
         return String.format(USER_FORMAT_KEY, uid);
     }
 
-    public static UserInfoVo toUserInfoVo(DeviceUserVo deviceUserVo, Boolean withToken) {
+    public static UserInfoVo toUserInfoVo(DeviceUserVo deviceUserVo, Boolean withToken)
+    {
         UserInfoVo userInfoVo = new UserInfoVo();
         userInfoVo.setUid(deviceUserVo.getUid());
         userInfoVo.setEid(deviceUserVo.getEid());
@@ -271,13 +341,15 @@ public class UserService {
         userInfoVo.setMerchantName(deviceUserVo.getMerchantName());
         userInfoVo.setMerchantContactName(deviceUserVo.getMerchantContactName());
         userInfoVo.setMerchantContactMobile(deviceUserVo.getMerchantContactMobile());
-        if (withToken) {
+        if (withToken)
+        {
             userInfoVo.setToken(deviceUserVo.getToken());
         }
         return userInfoVo;
     }
 
-    public DeviceUserVo toDeviceUserVo(TerminalUserVo userVo, TerminalDeviceVo deviceVo) {
+    public DeviceUserVo toDeviceUserVo(TerminalUserVo userVo, TerminalDeviceVo deviceVo)
+    {
         DeviceUserVo deviceUserVo = new DeviceUserVo();
         deviceUserVo.setUid(userVo.getId());
         deviceUserVo.setEid(userVo.getCode());
@@ -293,8 +365,10 @@ public class UserService {
         return deviceUserVo;
     }
 
-    public void refreshToken(DeviceUserVo deviceUserVo) {
+    public void refreshToken(DeviceUserVo deviceUserVo)
+    {
         String token = SecurityManager.generateToken(deviceUserVo.getPassword());
+        log.info("token ======================= ,{}", token);
         Date nowTime = new Date();
         Date expireAt = DateUtils.addSeconds(nowTime, this.expiration);
         deviceUserVo.setToken(token);
@@ -302,34 +376,43 @@ public class UserService {
         deviceUserVo.setRefreshAt(nowTime);
     }
 
-    public List<Map<String, Object>> getProductValid(String uid){
+    public List<Map<String, Object>> getProductValid(String uid)
+    {
         //TODO: move this method to userCient
         return productClient.getProductValid(uid, 0L, 50, "endTime", Sort.Direction.ASC);
     }
 
-    public List<UserTag> findUserTagByCodeUid(String code, String uid) {
+    public List<UserTag> findUserTagByCodeUid(String code, String uid)
+    {
         return userClient.findUserTagByCodeUid(code, uid);
     }
 
-    public List<UserRecommend> getUserRecommendCourses(String uid) {
+    public List<UserRecommend> getUserRecommendCourses(String uid)
+    {
         return userClient.getUserRecommendCourses(uid);
     }
 
-    public APIResult<Page<ItemVo>> findPageByUserTagId(String userTagId,  String merchantId, Integer pageNo, Integer pageSize) {
+    public APIResult<Page<ItemVo>> findPageByUserTagId(String userTagId, String merchantId, Integer pageNo, Integer pageSize)
+    {
         Page<UserTagProductRelation> resultPage = userClient.findPageByUserTagId(userTagId, pageNo, pageSize);
 
-        if(resultPage == null){
+        if (resultPage == null)
+        {
             throw new RuntimeException("请求失败!");
         }
 
         List<ItemVo> itemVos = new ArrayList<>();
         List<UserTagProductRelation> userTagProductRelations = resultPage.getList();
-        userTagProductRelations.forEach(userTagProductRelation -> {
+        userTagProductRelations.forEach(userTagProductRelation ->
+        {
             String pid = userTagProductRelation.getPid();
             ItemVo itemVo = productClient.findItemByPid(merchantId, pid);
-            if(itemVo == null){
-                log.info("not found item by pid , pid={}",pid);
-            }else{
+            if (itemVo == null)
+            {
+                log.info("not found item by pid , pid={}", pid);
+            }
+            else
+            {
                 itemVos.add(itemVo);
             }
         });
@@ -337,12 +420,20 @@ public class UserService {
         Page<ItemVo> page = new Page<>();
         page.setPageSize(pageSize);
         page.setPageNo(pageNo);
-        page.setTotalSize((int)resultPage.getTotalSize());
+        page.setTotalSize((int) resultPage.getTotalSize());
         page.setList(itemVos);
 
         return APIResult.ok(page);
     }
 
 
+    public UserTag findUserTagById(String tagId)
+    {
+        return userClient.findUserTagById(tagId);
+    }
 
+    public Page<UserTagProductRelation> findRelations(String userTagId, List<String> productIdList, Integer pageNo, Integer pageSize)
+    {
+        return userClient.findRelations(userTagId, productIdList, pageNo, pageSize);
+    }
 }

+ 2 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/utils/SecurityManager.java

@@ -44,6 +44,8 @@ public class SecurityManager {
         sb.append("eid=" + globalHeader.getEid() + "&");
         String computeSign = SecurityUtil.MD5(sb.toString(), token);
 
+        log.info("--------------sb.toString()={},token={}",sb.toString(),token  );
+        log.info("computeSign  sign ,computeSign={},sign={}",computeSign,sign);
         return computeSign.equals(sign);
     }
 }

+ 35 - 0
rankin-cms-web/src/main/java/cn/rankin/cmsweb/controller/user/UserDeviceController.java

@@ -0,0 +1,35 @@
+package cn.rankin.cmsweb.controller.user;
+
+
+import cn.rankin.cmsweb.service.user.UserDeviceService;
+import cn.rankin.common.utils.api.model.APIResult;
+import cn.rankin.data.api.user.entity.DownloadInfo;
+import cn.rankin.data.api.user.entity.UserDevice;
+import com.alibaba.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+
+/**
+ * The controller of user device
+ */
+@Slf4j
+@RestController
+@RequestMapping(value = "/userDevice")
+public class UserDeviceController
+{
+    @Autowired
+    private UserDeviceService userDeviceService;
+
+    @RequestMapping(value = "/list/{uid}", method = RequestMethod.GET)
+    public APIResult<List<UserDevice>> findByUserId(@PathVariable("uid") String uid)
+    {
+        List<UserDevice> list = userDeviceService.findByCondition(uid);
+
+        return APIResult.ok(list);
+    }
+}
+

+ 19 - 0
rankin-cms-web/src/main/java/cn/rankin/cmsweb/service/user/UserDeviceService.java

@@ -0,0 +1,19 @@
+package cn.rankin.cmsweb.service.user;
+
+import cn.rankin.common.utils.api.model.APIResult;
+import cn.rankin.common.utils.api.page.Page;
+import cn.rankin.data.api.user.dto.CampusDTO;
+import cn.rankin.data.api.user.entity.UserDevice;
+import cn.rankin.data.api.user.vo.CampusVo;
+import org.springframework.cloud.netflix.feign.FeignClient;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+
+@FeignClient(name = "${service.user.name}")
+public interface UserDeviceService
+{
+    @RequestMapping(value = "/userDevice/list/{uid}", method = RequestMethod.GET)
+    List<UserDevice> findByCondition(@PathVariable("uid") String uid);
+}

+ 25 - 0
rankin-common-utils/src/main/java/cn/rankin/common/utils/constant/DownloadStatus.java

@@ -0,0 +1,25 @@
+package cn.rankin.common.utils.constant;
+
+public class DownloadStatus {
+
+    /**
+     * 未下载
+     */
+    public final static int UN_DOWNLOAD = 0;
+
+    /**
+     * 已下载
+     */
+    public final static int FINISH_DOWNLOAD = 1;
+
+    /**
+     * 下载中
+     */
+    public final static int PROCESS_DOWNLOAD = 2;
+
+    /**
+     * 下载失败
+     */
+    public final static int FAIL_DOWNLOAD = 3;
+
+}

+ 29 - 0
rankin-common-utils/src/main/java/cn/rankin/common/utils/enums/EventTypeEnum.java

@@ -0,0 +1,29 @@
+package cn.rankin.common.utils.enums;
+
+public enum EventTypeEnum {
+
+    DOWNLOAD("DOWNLOAD"), DELETE("DELETE"), UPDATE("UPDATE");
+
+    private String desc;
+
+    EventTypeEnum(String desc) {
+        this.desc = desc;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public static EventTypeEnum getByName(String name) {
+        if (name == null) {
+            return null;
+        }
+        for (EventTypeEnum favoritesType : values()) {
+            if (favoritesType.name().equals(name)) {
+                return favoritesType;
+            }
+        }
+        return null;
+    }
+}
+

+ 1 - 1
rankin-common-utils/src/main/java/cn/rankin/common/utils/enums/PlatformTypeEnum.java

@@ -2,7 +2,7 @@ package cn.rankin.common.utils.enums;
 
 public enum PlatformTypeEnum {
 
-    APP("app"), TV("TV"), WEIXIN("微信");
+    APP("app"), TV("TV"), WEIXIN("微信"), WINDOWS("windows");
 
     private String desc;
 

+ 7 - 0
rankin-common-utils/src/main/java/cn/rankin/common/utils/exception/CommonException.java

@@ -0,0 +1,7 @@
+package cn.rankin.common.utils.exception;
+
+public class CommonException extends ServiceException {
+    public CommonException (int code , String message){
+        super(message);
+    }
+}

+ 84 - 0
rankin-common-utils/src/main/java/cn/rankin/common/utils/util/HttpUtil.java

@@ -14,10 +14,14 @@ import org.springframework.util.StringUtils;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedReader;
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Created by tomas on 2017/6/4.
@@ -152,4 +156,84 @@ public class HttpUtil {
         return ip.split(",")[0];
     }
 
+
+    /**
+     * 根据IP获取MAC地址
+     * @param request
+     * @return
+     */
+    public static String getMacAddrByIp(HttpServletRequest request) {
+        String ip = getClientIp(request);
+        String macAddr = null;
+        try {
+            Process process = Runtime.getRuntime().exec("nbtstat -a " + ip);
+            BufferedReader br = new BufferedReader(
+                    new InputStreamReader(process.getInputStream()));
+            Pattern pattern = Pattern.compile("([A-F0-9]{2}-){5}[A-F0-9]{2}");
+            Matcher matcher;
+            for (String strLine = br.readLine(); strLine != null;
+                 strLine = br.readLine()) {
+                matcher = pattern.matcher(strLine);
+                if (matcher.find()) {
+                    macAddr = matcher.group();
+                    break;
+                }
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return macAddr;
+    }
+
+    /**
+     * 获取系统版本信息
+     * @param request
+     * @return
+     */
+    public static String getSystemInfo(HttpServletRequest request){
+        String systenInfo = null;
+        String header = request.getHeader("user-agent");
+        logger.info("获取系统版本信息:"+header);
+        if(header == null || header.equals("")){
+            return "";
+        }
+
+
+        //得到用户的操作系统
+        if (header.indexOf("NT 6.0") > 0){
+            systenInfo = "Windows Vista/Server 2008";
+        } else if (header.indexOf("NT 5.2") > 0){
+            systenInfo = "Windows Server 2003";
+        } else if (header.indexOf("NT 5.1") > 0){
+            systenInfo = "Windows XP";
+        } else if (header.indexOf("NT 6.0") > 0){
+            systenInfo = "Windows Vista";
+        } else if (header.indexOf("NT 6.1") > 0){
+            systenInfo = "Windows 7";
+        } else if (header.indexOf("NT 6.2") > 0){
+            systenInfo = "Windows Slate";
+        } else if (header.indexOf("NT 6.3") > 0){
+            systenInfo = "Windows 9";
+        } else if (header.indexOf("NT 5") > 0){
+            systenInfo = "Windows 2000";
+        } else if (header.indexOf("NT 4") > 0){
+            systenInfo = "Windows NT4";
+        } else if (header.indexOf("Me") > 0){
+            systenInfo = "Windows Me";
+        } else if (header.indexOf("98") > 0){
+            systenInfo = "Windows 98";
+        } else if (header.indexOf("95") > 0){
+            systenInfo = "Windows 95";
+        } else if (header.indexOf("Mac") > 0){
+            systenInfo = "Mac";
+        } else if (header.indexOf("Unix") > 0){
+            systenInfo = "UNIX";
+        } else if (header.indexOf("Linux") > 0){
+            systenInfo = "Linux";
+        } else if (header.indexOf("SunOS") > 0){
+            systenInfo = "SunOS";
+        }
+        return systenInfo;
+    }
+
 }

+ 13 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/app/dto/LoginInfoDTO.java

@@ -24,4 +24,17 @@ public class LoginInfoDTO implements Serializable {
     private String ip;
 
     private String terminal;
+
+    //设备名称
+    private String deviceName;
+
+    //设备型号
+    private String deviceModel;
+
+    //设备厂商
+    private String deviceMfrs;
+
+    //设备类型
+    private String deviceType;
+
 }

+ 2 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/app/vo/LessonVo.java

@@ -16,5 +16,7 @@ public class LessonVo implements Serializable {
 
     private String title;
 
+    private int downloadStatus;
+
     private List<CourseWareVo> list;
 }

+ 3 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/product/dto/CourseDTO.java

@@ -15,6 +15,9 @@ public class CourseDTO implements Serializable {
 
     private String name;
 
+    //0课程 || 1导学
+    private int courseType;
+
     private String title;
 
     private String subTitle;

+ 3 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/product/entity/Course.java

@@ -30,6 +30,9 @@ public class Course implements Serializable{
     @Column
     private String name;
 
+    @Column(name = "course_type",nullable=false)
+    private int courseType;    //0课程   1导学
+
     @Column
     private String title;
 

+ 3 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/product/vo/CourseVo.java

@@ -15,6 +15,9 @@ public class CourseVo implements Serializable {
 
     private String name;
 
+    //0课程 || 1导学
+    private int courseType;
+
     private String title;
 
     private String subTitle;

+ 66 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/user/dto/DownloadInfoDTO.java

@@ -0,0 +1,66 @@
+package cn.rankin.data.api.user.dto;
+
+import cn.rankin.common.utils.enums.BaseStatusEnum;
+import cn.rankin.common.utils.enums.EventTypeEnum;
+import cn.rankin.common.utils.enums.PlatformTypeEnum;
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Date;
+
+
+@Data
+@ToString
+public class DownloadInfoDTO implements Serializable {
+
+    private String id;
+
+    private String userId;
+
+    private String merchantId;
+
+    private String lessonId;
+
+    private String lessonName;
+
+    private String courseId;
+
+    private String courseName;
+
+    private EventTypeEnum eventType;
+
+    private String deviceType;
+
+    private String mac;
+
+    private String ip;
+
+    private String deviceVersion;
+
+    //资源总数
+    private int resTotal;
+
+    //已转码资源数
+    private int resSize;
+
+    private String data;
+
+    private Integer needUpdate;
+
+    private int downloadStatus;
+
+    private PlatformTypeEnum platformType;
+
+    private BaseStatusEnum status;
+
+    private Date gmtCreated;
+
+    private Date gmtModified;
+
+
+
+}
+
+
+

+ 7 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/user/dto/UserDeviceDTO.java

@@ -0,0 +1,7 @@
+package cn.rankin.data.api.user.dto;
+
+import cn.rankin.data.api.user.entity.UserDevice;
+
+public class UserDeviceDTO extends UserDevice
+{
+}

+ 97 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/user/entity/DownloadInfo.java

@@ -0,0 +1,97 @@
+package cn.rankin.data.api.user.entity;
+
+import cn.rankin.common.utils.enums.BaseStatusEnum;
+import cn.rankin.common.utils.enums.EventTypeEnum;
+import cn.rankin.common.utils.enums.PlatformTypeEnum;
+import lombok.Data;
+import lombok.ToString;
+import org.hibernate.annotations.DynamicInsert;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+
+@Data
+@ToString
+@Entity
+@Table(name = "u_download_info")
+@DynamicInsert
+@DynamicUpdate
+public class DownloadInfo implements Serializable {
+    @Id
+    @Column(name="id")
+    private String id;
+
+    @Column(name="user_id")
+    private String userId;
+
+    @Column(name="merchant_id")
+    private String merchantId;
+
+    @Column(name="lesson_id")
+    private String lessonId;
+
+    @Column(name="lesson_name")
+    private String lessonName;
+
+    @Column(name="course_id")
+    private String courseId;
+
+    @Column(name="course_name")
+    private String courseName;
+
+    @Column(name="download_status", nullable = false)
+    private int downloadStatus;
+
+    @Enumerated(EnumType.ORDINAL)
+    @Column(name="event_type", nullable = false)
+    private EventTypeEnum eventType;
+
+    @Column(name="device_type")
+    private String deviceType;
+
+    @Column(name="mac")
+    private String mac;
+
+    @Column(name="ip")
+    private String ip;
+
+    @Column(name="device_version")
+    private String deviceVersion;
+
+    //资源总数
+    @Column(name="res_total")
+    private int resTotal;
+
+    //已转码资源数
+    @Column(name="res_size")
+    private int resSize;
+
+    @Column(name="data")
+    private String data;
+
+    @Column(name="need_update")
+    private Integer needUpdate;
+
+    @Enumerated(EnumType.ORDINAL)
+    @Column(name="platform_type")
+    private PlatformTypeEnum platformType;
+
+    @Enumerated(EnumType.ORDINAL)
+    @Column(name="status")
+    private BaseStatusEnum status;
+
+    @Column(name = "gmt_created", updatable = false, insertable = false, columnDefinition = "timestamp NULL DEFAULT CURRENT_TIMESTAMP")
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date gmtCreated;
+
+    @Column(name = "gmt_modified", updatable = false, insertable = false, columnDefinition = "timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date gmtModified;
+
+}
+
+
+

+ 60 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/user/entity/UserDevice.java

@@ -0,0 +1,60 @@
+package cn.rankin.data.api.user.entity;
+
+import lombok.Data;
+import lombok.ToString;
+import org.hibernate.annotations.DynamicInsert;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+
+@Data
+@ToString
+@Entity
+@Table(name = "u_user_device")
+@DynamicInsert
+@DynamicUpdate
+public class UserDevice implements Serializable {
+    @Id
+    @Column(name="id")
+    private String id;
+
+    @Column(name="user_id")
+    private String userId;
+
+    @Column(name="device_code")
+    private String deviceCode;
+
+    //设备型号
+    @Column(name="device_model")
+    private String deviceModel;
+
+    //设备厂商
+    @Column(name="device_mfrs")
+    private String deviceMfrs;
+
+    //设备名称
+    @Column(name="device_name")
+    private String deviceName;
+
+    //设备类型
+    @Column(name="device_type")
+    private String deviceType;
+
+    @Column(name="num")
+    private int num;
+
+    @Column(name = "gmt_created", updatable = false, insertable = false, columnDefinition = "timestamp NULL DEFAULT CURRENT_TIMESTAMP")
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date gmtCreated;
+
+    @Column(name = "gmt_modified", updatable = false, insertable = false, columnDefinition = "timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date gmtModified;
+
+}
+
+
+

+ 7 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/user/vo/UserDeviceVo.java

@@ -0,0 +1,7 @@
+package cn.rankin.data.api.user.vo;
+
+import cn.rankin.data.api.user.entity.UserDevice;
+
+public class UserDeviceVo extends UserDevice
+{
+}

+ 5 - 0
rankin-product-service/src/main/java/cn/rankin/productservice/controller/app/AppTagController.java

@@ -51,4 +51,9 @@ public class AppTagController {
         });
         return APIResult.ok(tagList);
     }
+
+    @RequestMapping(value = "/tag/{tagId}", method = RequestMethod.GET)
+    public Tag getTag(@PathVariable("tagId") String tagId) {
+        return tagService.find(tagId);
+    }
 }

+ 0 - 41
rankin-product-service/src/main/java/cn/rankin/productservice/controller/app/ItemControllerV0.java

@@ -1,41 +0,0 @@
-package cn.rankin.productservice.controller.app;
-
-import cn.rankin.common.utils.api.model.APIResult;
-import cn.rankin.common.utils.api.page.Page;
-import cn.rankin.data.api.app.dto.ItemSearchDTO;
-import cn.rankin.data.api.app.vo.ItemVo;
-import cn.rankin.productservice.service.app.ItemService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 已弃用,
- *
- * 以 cn.rankin.productservice.controller.ItemController 替代
- */
-@RestController
-@RequestMapping(value = "/v0/app/item")
-public class ItemControllerV0 {
-
-    @Autowired
-    private ItemService itemService;
-
-    @RequestMapping(value = "/ids", method = RequestMethod.POST)
-    public APIResult<List<ItemVo>> findByIds(@RequestBody List<String> productIdList, @RequestParam("merchantId") String merchantId) {
-        List<ItemVo> itemVoList = itemService.findByPids(merchantId, productIdList);
-        return APIResult.ok(itemVoList);
-    }
-
-    @RequestMapping(value = "/ids/page", method = RequestMethod.POST)
-    public APIResult<Page<ItemVo>> findPage(@RequestBody ItemSearchDTO itemSearchDTO) {
-        String merchantId = itemSearchDTO.getMerchantId();
-        String tagId = itemSearchDTO.getTagId();
-        List<String> productIdList = itemSearchDTO.getProductIdList();
-        Integer pageNo = itemSearchDTO.getPageNo();
-        Integer pageSize = itemSearchDTO.getPageSize();
-        return itemService.findPageByTagIdAndPids(merchantId, tagId, productIdList, pageNo, pageSize);
-    }
-
-}

+ 2 - 2
rankin-product-service/src/main/java/cn/rankin/productservice/controller/cms/MerchantProductController.java

@@ -87,12 +87,12 @@ public class MerchantProductController {
     }
 
     @RequestMapping(value = "/list2", method = RequestMethod.POST)
-    public APIResult<List<MerchantProduct>> getList(@RequestBody List<String> productIdList, @RequestParam("merchantId") String merchantId) {
+    public APIResult<List<MerchantProduct>> getList2(@RequestBody List<String> productIdList, @RequestParam("merchantId") String merchantId) {
         return merchantProductService.findByPidList_bak(productIdList, merchantId);
     }
 
     @RequestMapping(value = "/list", method = RequestMethod.POST)
-    public APIResult<List<MerchantProduct>> getList2(@RequestBody List<String> productIdList, @RequestParam("merchantId") String merchantId) {
+    public APIResult<List<MerchantProduct>> getList(@RequestBody List<String> productIdList, @RequestParam("merchantId") String merchantId) {
         List<MerchantProduct> merchantProductList = merchantProductService.findByPidList(productIdList, merchantId);
         return APIResult.ok(merchantProductList);
     }

+ 16 - 2
rankin-product-service/src/main/java/cn/rankin/productservice/controller/cms/TagController.java

@@ -5,13 +5,16 @@ import cn.rankin.common.utils.api.page.Page;
 import cn.rankin.common.utils.dto.search.TagSearchDTO;
 import cn.rankin.common.utils.enums.BaseOrderEnum;
 import cn.rankin.data.api.product.dto.TagDTO;
+import cn.rankin.data.api.product.entity.MerchantProduct;
 import cn.rankin.data.api.product.entity.Tag;
 import cn.rankin.productservice.service.TagService;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.LinkedHashMap;
+import java.util.List;
 
 @Slf4j
 @RestController
@@ -23,7 +26,6 @@ public class TagController {
 
     @RequestMapping(value = "/{tagId}", method = RequestMethod.GET)
     public APIResult<Tag> getTag(@PathVariable("tagId") String tagId) {
-
         return tagService.getTag(tagId);
     }
 
@@ -59,7 +61,19 @@ public class TagController {
 
     @RequestMapping(value = "/v2/{tagId}", method = RequestMethod.GET)
     public Tag getTagInfo(@PathVariable("tagId") String tagId) {
-        return tagService.getTagInfo(tagId);
+        if(StringUtils.isBlank(tagId)){
+            log.info("error! id is empty!");
+            return null;
+        }
+        Tag tag = tagService.find(tagId);
+        if(null == tag){
+            log.info("not found tag by id ,id={}",tagId);
+        }else{
+            String merchantId = tag.getMerchantId();
+            List<MerchantProduct> merchantProductList = tagService.getMerchantProductList(tagId, merchantId);
+            tag.setProductList(merchantProductList);
+        }
+        return tag;
     }
 
 }

+ 5 - 0
rankin-product-service/src/main/java/cn/rankin/productservice/service/TagService.java

@@ -210,4 +210,9 @@ public class TagService {
         tag.setProductList(merchantProductList);
         return tag;
     }
+
+    public Tag find(String tagId) {
+        Tag tag = tagRepository.find(tagId);
+        return tag;
+    }
 }

+ 118 - 0
rankin-user-service/src/main/java/cn/rankin/userservice/controller/DownloadInfoController.java

@@ -0,0 +1,118 @@
+package cn.rankin.userservice.controller;
+
+import cn.rankin.common.utils.api.model.APIResult;
+import cn.rankin.common.utils.enums.BaseStatusEnum;
+import cn.rankin.common.utils.enums.EventTypeEnum;
+import cn.rankin.data.api.user.dto.DownloadInfoDTO;
+import cn.rankin.data.api.user.entity.DownloadInfo;
+import cn.rankin.userservice.service.DownloadInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping(value = "/download")
+public class DownloadInfoController {
+
+    @Autowired
+    private DownloadInfoService downloadInfoService;
+
+    /**
+     * 添加下载
+     * @param dto
+     * @return
+     */
+    @RequestMapping(method = RequestMethod.POST)
+    public DownloadInfo add(@RequestBody DownloadInfoDTO dto) {
+        //TODO
+        //addEventLog();
+
+        return downloadInfoService.add(dto);
+    }
+
+    /**
+     * 下载列表
+     * @param uid
+     * @param mac
+     * @return
+     */
+    @RequestMapping(value = "/list", method = RequestMethod.GET)
+    public List<DownloadInfo> findByUserId(@RequestParam("uid") String uid,
+                                           @RequestParam("mac") String mac){
+        return downloadInfoService.findByUserId(uid,mac,EventTypeEnum.DOWNLOAD,BaseStatusEnum.NORMAL);
+    }
+
+    /**
+     * 查询下载
+     * @param uid
+     * @param lessonId
+     * @param mac
+     * @return
+     */
+    @RequestMapping(value = "", method = RequestMethod.GET)
+    public DownloadInfo findByLessonUserId(@RequestParam("uid") String uid,
+                                           @RequestParam("lessonId") String lessonId,
+                                           @RequestParam("mac") String mac){
+        return downloadInfoService.findByLessonUserId(uid, lessonId, mac, EventTypeEnum.DOWNLOAD, BaseStatusEnum.NORMAL);
+    }
+
+    /**
+     * 删除下载
+     * @param uid
+     * @param lessonId
+     * @param mac
+     * @return
+     */
+    @RequestMapping(value = "/delete", method = RequestMethod.DELETE)
+    public DownloadInfo deleteByLessonUserId(@RequestParam("uid") String uid,
+                                             @RequestParam("lessonId") String lessonId,
+                                             @RequestParam("mac") String mac){
+        return downloadInfoService.deleteByLessonUserId(uid, lessonId, mac);
+    }
+
+    /**
+     * 更新下载内容
+     * @param uid
+     * @param lessonId
+     * @param mac
+     * @return
+     */
+    @RequestMapping(value = "/update/resource", method = RequestMethod.PUT)
+    public DownloadInfo updateByLessonUserId(@RequestParam("uid") String uid,
+                                             @RequestParam("lessonId") String lessonId,
+                                             @RequestParam("mac") String mac){
+        return downloadInfoService.updateByLessonUserId(uid, lessonId, mac);
+    }
+
+    @RequestMapping(value = "/fail", method = RequestMethod.PUT)
+    public boolean updateDownloadFail(@RequestParam("uid") String uid,
+                                @RequestParam("mac") String mac){
+        return downloadInfoService.updateDownloadFail(uid, mac);
+    }
+
+    @RequestMapping(value = "/update", method = RequestMethod.PUT)
+    public DownloadInfo update(@RequestBody DownloadInfo downloadInfo){
+        return downloadInfoService.update(downloadInfo);
+    }
+
+    @RequestMapping(value = "/set/update/{lessonId}", method = RequestMethod.PUT)
+    public int setUpdateByLessonId(@PathVariable("lessonId") String lessonId){
+        return downloadInfoService.setUpdateByLessonId(lessonId);
+    }
+
+    /**
+     * 查询下载进度
+     * @param uid
+     * @param lessonId
+     * @param mac
+     * @return
+     */
+    @RequestMapping(value = "/status", method = RequestMethod.GET)
+    public DownloadInfo findDownloadStatus(@RequestParam("uid") String uid,
+                                           @RequestParam("lessonId") String lessonId,
+                                           @RequestParam("mac") String mac){
+        return downloadInfoService.findDownloadStatus(uid, lessonId, mac);
+    }
+
+}

+ 53 - 0
rankin-user-service/src/main/java/cn/rankin/userservice/controller/UserDeviceController.java

@@ -0,0 +1,53 @@
+package cn.rankin.userservice.controller;
+
+import cn.rankin.data.api.user.dto.UserDeviceDTO;
+import cn.rankin.data.api.user.entity.UserDevice;
+import cn.rankin.userservice.helper.RaStringHelper;
+import cn.rankin.userservice.service.UserDeviceService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+
+@RestController
+@RequestMapping(value = "/userDevice")
+public class UserDeviceController
+{
+
+    @Autowired
+    private UserDeviceService userDeviceService;
+
+    @RequestMapping(value = "/op/{uid}", method = RequestMethod.POST)
+    public int bindingDevice(@PathVariable("uid") String uid,
+                             @Valid @RequestBody UserDeviceDTO userDeviceDTO)
+    {
+
+        if (RaStringHelper.isNull(uid))
+        {
+            return 0;
+        }
+        if (RaStringHelper.isNull(userDeviceDTO.getDeviceCode()))
+        {
+            return 0;
+        }
+
+
+        userDeviceDTO.setUserId(uid);
+
+        return userDeviceService.opUserDevice(userDeviceDTO);
+
+    }
+
+    @RequestMapping(value = "/list/{uid}", method = RequestMethod.GET)
+    public List<UserDevice> bindingDevice(@PathVariable("uid") String uid)
+    {
+        if(uid == null || uid == "")
+        {
+            return null;
+        }
+        return userDeviceService.findByUserId(uid);
+    }
+
+}

+ 7 - 0
rankin-user-service/src/main/java/cn/rankin/userservice/controller/UserTagProductRelationController.java

@@ -29,4 +29,11 @@ public class UserTagProductRelationController {
     }
 
 
+    @RequestMapping(value = "/page/pids",method = RequestMethod.POST)
+    public Page<UserTagProductRelation> findPageByPidsUserTagId(@RequestParam("userTagId") String userTagId,
+                                                            @RequestBody List<String> pids,
+                                                            @RequestParam("pageNo") Integer pageNo,
+                                                            @RequestParam("pageSize") Integer pageSize) {
+        return userTagProductRelationService.findPageByPidsUserTagId(userTagId, pids,  pageNo, pageSize);
+    }
 }

+ 37 - 0
rankin-user-service/src/main/java/cn/rankin/userservice/helper/RaStringHelper.java

@@ -0,0 +1,37 @@
+package cn.rankin.userservice.helper;
+
+/**
+ * The helper of string
+ */
+public class RaStringHelper
+{
+    /**
+     * Is null
+     * @param str the string
+     * @return true or false
+     */
+    public static boolean isNull(String str)
+    {
+        if(str == null || str.trim() == "")
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Is null
+     * @param str the string
+     * @return true or false
+     */
+    public static boolean isNotNull(String str)
+    {
+        if(str != null && str.trim() == "")
+        {
+            return true;
+        }
+
+        return false;
+    }
+}

+ 1 - 0
rankin-user-service/src/main/java/cn/rankin/userservice/proxy/RemoteUserFeign.java

@@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.*;
 import java.util.List;
 
 @FeignClient(name = "user-remote", url = "${remote.user.url}")
+//@FeignClient(name = "${iaas.user.url}")
 public interface RemoteUserFeign {
 
     @RequestMapping(value = "/ucenter/v1/users", method = RequestMethod.POST)

+ 37 - 0
rankin-user-service/src/main/java/cn/rankin/userservice/repository/DownloadInfoRepository.java

@@ -0,0 +1,37 @@
+package cn.rankin.userservice.repository;
+
+import cn.rankin.common.utils.enums.BaseStatusEnum;
+import cn.rankin.common.utils.enums.EventTypeEnum;
+import cn.rankin.common.utils.jpa.BasicJpaRepository;
+import cn.rankin.data.api.user.entity.DownloadInfo;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+import java.util.List;
+
+public interface DownloadInfoRepository extends BasicJpaRepository<DownloadInfo, String> {
+
+    @Query(value = "select info from DownloadInfo info where info.userId = ?1 AND info.mac = ?2 AND info.eventType= ?3 AND info.status = ?4 ORDER BY info.gmtModified DESC ")
+    List<DownloadInfo> findByUserId(String uid, String mac, EventTypeEnum eventType, BaseStatusEnum status);
+
+    @Query(value = "select info from DownloadInfo info where info.userId = ?1 AND info.lessonId = ?2 AND info.mac = ?3 AND info.eventType = ?4  AND info.status = ?5 ORDER BY info.gmtCreated DESC ")
+    DownloadInfo findByLessonUserId(String uid, String lessonId, String mac, EventTypeEnum eventType, BaseStatusEnum status);
+
+    @Query(value = "select info from DownloadInfo info where info.userId = ?1 AND info.lessonId = ?2  AND info.mac = ?3 ORDER BY info.gmtCreated DESC ")
+    DownloadInfo findByLessonUserId(String uid, String lessonId, String mac);
+
+    @Modifying
+    @Query(value = "update DownloadInfo info set info.status = ?4 where info.userId = ?1 and info.lessonId = ?2   AND info.mac = ?3 ")
+    int updateByLessonUserId(String uid, String lessonId, String mac, BaseStatusEnum status);
+
+    @Modifying
+    @Query(value = "update DownloadInfo info set info.needUpdate = 1 where info.lessonId = ?1 AND info.status = ?2")
+    int setUpdateByLessonId(String lessonId, BaseStatusEnum status);
+
+    @Modifying
+    @Query(value = "update DownloadInfo info set info.downloadStatus = ?3 where info.userId = ?1 AND info.mac = ?2 AND info.downloadStatus = 2")
+    int updateDownloadFail(String uid, String mac, int failDownload);
+
+    @Query(value = "select info from DownloadInfo info where info.userId = ?1 AND info.lessonId = ?2  AND info.mac = ?3 AND info.downloadStatus = 2 ORDER BY info.gmtCreated DESC ")
+    DownloadInfo findDownloadStatus(String uid, String lessonId, String mac);
+}

+ 32 - 0
rankin-user-service/src/main/java/cn/rankin/userservice/repository/UserDeviceRepository.java

@@ -0,0 +1,32 @@
+package cn.rankin.userservice.repository;
+
+import cn.rankin.common.utils.enums.BaseStatusEnum;
+import cn.rankin.common.utils.enums.EventTypeEnum;
+import cn.rankin.common.utils.jpa.BasicJpaRepository;
+import cn.rankin.data.api.user.entity.DownloadInfo;
+import cn.rankin.data.api.user.entity.Resource;
+import cn.rankin.data.api.user.entity.UserDevice;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+public interface UserDeviceRepository extends BasicJpaRepository<UserDevice, String> {
+
+    @Query(value = "select device from UserDevice device where device.userId = ?1 AND device.deviceName= ?2 AND device.deviceModel = ?3")
+    UserDevice findUserDevice(String uid, String deviceName,String deviceModel);
+
+    @Transactional
+    @Modifying
+    @Query(value = "update UserDevice device set device.num = ?4 where device.userId = ?1 AND device.deviceName= ?2 AND device.deviceModel = ?3")
+    int updateDevice(String uid, String deviceName,String deviceModel,int num);
+
+    /**
+     * 根据用户编号查询设备信息
+     * @param userId the id of user
+     * @return
+     */
+    @Query(value = "select u from  UserDevice  u where u.userId = ?1 order by u.gmtModified desc")
+    List<UserDevice> findByUserId(String userId);
+}

+ 2 - 19
rankin-user-service/src/main/java/cn/rankin/userservice/repository/UserTagProductRelationRepository.java

@@ -20,23 +20,6 @@ public interface UserTagProductRelationRepository extends BasicJpaRepository<Use
     @Query(value = "update UserTagProductRelation r set r.status = 1 where r.tagId = :tagId")
     Integer deleteByTagId(@Param("tagId") String tagId);
 
-/*
-    @Modifying
-    @Query(value = "update UserTagProductRelation r set r.status = 1 where r.pid = :productId and r.tagId = :tagId")
-    Integer deleteByPidAndTagId(@Param("productId") String productId, @Param("tagId") String tagId);
-
-    List<UserTagProductRelation> findByTagIdIn(List<String> tagIds);
-
-    @Query(value = "select r from UserTagProductRelation r where r.pid in (?1) and r.tagId in (?2) and r.status = 0")
-    List<UserTagProductRelation> findByPidsAndTagIds(List<String> pids, List<String> tagIds);
-
-    @Query(value = "select r from UserTagProductRelation r where r.pid = ?1 and r.tagId = ?2 and r.status = ?3")
-    List<UserTagProductRelation> findByPidAndTagId(String pid, String tagId, BaseStatusEnum status);
-
-    List<UserTagProductRelation> findByPidAndTagId(String pid, String merchantId);
-
-    @Query(value = "select r from UserTagProductRelation r where r.tagId = ?1 and r.pid in (?2) and r.status = 0 order by r.sort limit ?3, ?4", nativeQuery = true)
-    List<UserTagProductRelation> findByTagIdAndPids(String tagId, List<String> productIdList, Long start, Integer size);
-*/
-
+    @Query(value = "select * from u_user_tag_product_relation r where r.tag_id = ?1 and r.pid in (?2) and r.status = 0 order by r.sort limit ?3, ?4  ", nativeQuery = true)
+    List<UserTagProductRelation> findByUserTagIdAndPids(String tagId, List<String> productIdList, Long start, Integer size);
 }

+ 1 - 0
rankin-user-service/src/main/java/cn/rankin/userservice/service/CollectionService.java

@@ -71,6 +71,7 @@ public class CollectionService {
     public APIResult<List<Collection>> gets(String userId, Integer size) {
         Collection sample = new Collection();
         sample.setUserId(userId);
+        sample.setStatus(BaseStatusEnum.NORMAL);
         List<Collection> list = collectionRepository.find(sample, 0L, size);
         return APIResult.ok(list);
     }

+ 115 - 0
rankin-user-service/src/main/java/cn/rankin/userservice/service/DownloadInfoService.java

@@ -0,0 +1,115 @@
+package cn.rankin.userservice.service;
+
+import cn.rankin.common.utils.constant.DownloadStatus;
+import cn.rankin.common.utils.enums.BaseStatusEnum;
+import cn.rankin.common.utils.enums.EventTypeEnum;
+import cn.rankin.data.api.user.dto.DownloadInfoDTO;
+import cn.rankin.data.api.user.entity.DownloadInfo;
+import cn.rankin.userservice.repository.DownloadInfoRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.transaction.Transactional;
+import java.util.List;
+
+import static cn.rankin.userservice.utils.DTOConverter.convert;
+
+@Service
+public class DownloadInfoService {
+
+    @Autowired
+    private DownloadInfoRepository downloadInfoRepository;
+
+    /**
+     * 增加下载信息,
+     * 若已存在,更改状态
+     * @param dto
+     * @return
+     */
+    public DownloadInfo add(DownloadInfoDTO dto) {
+        DownloadInfo entity = downloadInfoRepository.findByLessonUserId(dto.getUserId(), dto.getLessonId(), dto.getMac());
+        if(entity != null){
+            DownloadInfo downloadInfo = convert(dto);
+            downloadInfo.setId(entity.getId());
+            return downloadInfoRepository.update(downloadInfo);
+        }else{
+            DownloadInfo downloadInfo = convert(dto);
+            return downloadInfoRepository.save(downloadInfo);
+        }
+
+    }
+
+    /**
+     * 用户所有下载列表    不包含已删除
+     * @param uid
+     * @param eventType
+     * @param status
+     * @return
+     */
+    public List<DownloadInfo> findByUserId(String uid, String mac, EventTypeEnum eventType, BaseStatusEnum status) {
+        return downloadInfoRepository.findByUserId(uid, mac, eventType, status);
+    }
+
+    /**
+     * 查询下载信息
+     * 根据用户ID   课程ID
+     * @param uid
+     * @param lessonId
+     * @param eventType
+     * @param status
+     * @return
+     */
+    public DownloadInfo findByLessonUserId(String uid, String lessonId, String mac, EventTypeEnum eventType, BaseStatusEnum status) {
+        return downloadInfoRepository.findByLessonUserId(uid, lessonId, mac, eventType, status);
+    }
+
+    /**
+     * 删除下载   (数据库逻辑删除)
+     * @param uid
+     * @param lessonId
+     * @return
+     */
+    public DownloadInfo deleteByLessonUserId(String uid, String lessonId, String mac) {
+        DownloadInfo entity = downloadInfoRepository.findByLessonUserId(uid, lessonId, mac);
+        if(entity != null){
+            entity.setStatus(BaseStatusEnum.DEL);
+            return downloadInfoRepository.update(entity);
+        }else{
+            return null;
+        }
+    }
+
+    /**
+     * 更新下载
+     * @param uid
+     * @param lessonId
+     * @return
+     */
+    public DownloadInfo updateByLessonUserId(String uid, String lessonId, String mac) {
+        DownloadInfo entity = downloadInfoRepository.findByLessonUserId(uid, lessonId, mac);
+        if(entity != null){
+            entity.setNeedUpdate(0);
+            return downloadInfoRepository.update(entity);
+        }else{
+            return null;
+        }
+    }
+
+    public int setUpdateByLessonId(String lessonId) {
+        return downloadInfoRepository.setUpdateByLessonId(lessonId,BaseStatusEnum.NORMAL);
+    }
+
+    public DownloadInfo update(DownloadInfo downloadInfo) {
+        return downloadInfoRepository.update(downloadInfo);
+    }
+
+    @Transactional
+    public boolean updateDownloadFail(String uid, String mac) {
+        downloadInfoRepository.updateDownloadFail(uid, mac, DownloadStatus.FAIL_DOWNLOAD);
+        return true;
+    }
+
+    public DownloadInfo findDownloadStatus(String uid, String lessonId, String mac) {
+        return downloadInfoRepository.findDownloadStatus(uid, lessonId, mac);
+    }
+}

+ 83 - 0
rankin-user-service/src/main/java/cn/rankin/userservice/service/UserDeviceService.java

@@ -0,0 +1,83 @@
+package cn.rankin.userservice.service;
+
+import cn.rankin.data.api.user.dto.UserDeviceDTO;
+import cn.rankin.data.api.user.entity.UserDevice;
+import cn.rankin.data.api.user.vo.UserDeviceVo;
+import cn.rankin.userservice.helper.RaStringHelper;
+import cn.rankin.userservice.repository.UserDeviceRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+
+@Service
+public class UserDeviceService
+{
+    @Autowired
+    private UserDeviceRepository userDeviceRepository;
+
+    /**
+     * Find
+     *
+     * @param userDeviceVo
+     * @return
+     */
+    public int opUserDevice(UserDeviceDTO uerDeviceDTO)
+    {
+        if (uerDeviceDTO == null)
+        {
+            return 0;
+        }
+
+        String uid = uerDeviceDTO.getUserId();
+        String deviceCode = uerDeviceDTO.getDeviceCode();
+        String deviceModel = uerDeviceDTO.getDeviceModel();
+        String deviceName = uerDeviceDTO.getDeviceName();
+        String deviceType = uerDeviceDTO.getDeviceType();
+        String deviceMfrs = uerDeviceDTO.getDeviceMfrs();
+
+        //查询用户设备信息
+        UserDevice userDevice = userDeviceRepository.findUserDevice(uid, deviceName, deviceModel);
+        if (userDevice != null)
+        {
+            //更新访问量
+            int num = userDevice.getNum() + 1;
+            int updateRet = userDeviceRepository.updateDevice(uid, deviceName, deviceModel, num);
+
+            return updateRet;
+        }
+        else
+        {
+            //添加用户设备信息
+            userDevice = new UserDevice();
+            userDevice.setUserId(uid);
+            userDevice.setGmtCreated(new Date());
+            userDevice.setDeviceCode(deviceCode);
+            userDevice.setDeviceModel(deviceModel);
+            userDevice.setDeviceMfrs(deviceMfrs);
+            userDevice.setDeviceName(deviceName);
+            userDevice.setDeviceType(deviceType);
+            userDevice.setNum(1);
+
+            UserDevice userDeviceRet = userDeviceRepository.save(userDevice);
+            if (userDeviceRet != null)
+            {
+                return 1;
+            }
+            return 0;
+        }
+    }
+
+    /**
+     *Find by user id
+     * @param uid the user id
+     * @return the list of user device
+     */
+    public List<UserDevice> findByUserId(String uid)
+    {
+        List<UserDevice> list = userDeviceRepository.findByUserId(uid);
+        return list;
+    }
+
+}

+ 14 - 0
rankin-user-service/src/main/java/cn/rankin/userservice/service/UserTagProductRelationService.java

@@ -105,4 +105,18 @@ public class UserTagProductRelationService {
         page.setList(relationList);
         return page;
     }
+
+    public Page<UserTagProductRelation> findPageByPidsUserTagId(String userTagId, List<String> pids, Integer pageNo, Integer pageSize) {
+        Page<UserTagProductRelation> page = new Page();
+        page.setPageNo(pageNo);
+        page.setPageSize(pageSize);
+
+        List<UserTagProductRelation> relationList = relationRepository.findByUserTagIdAndPids(userTagId, pids, page.getStart(), pageSize);
+        if (CollectionUtils.isEmpty(relationList)) {
+            return page;
+        }
+        page.setList(relationList);
+        page.setTotalSize(relationList.size());
+        return page;
+    }
 }

+ 6 - 0
rankin-user-service/src/main/java/cn/rankin/userservice/utils/DTOConverter.java

@@ -70,4 +70,10 @@ public class DTOConverter {
         BeanUtils.copyProperties(userTagDTO, userTag);
         return userTag;
     }
+
+    public static DownloadInfo convert(DownloadInfoDTO downloadInfoDTO) {
+        DownloadInfo downloadInfo = new DownloadInfo();
+        BeanUtils.copyProperties(downloadInfoDTO, downloadInfo);
+        return downloadInfo;
+    }
 }