xiexiang 2 rokov pred
rodič
commit
730a580c39
24 zmenil súbory, kde vykonal 1435 pridanie a 121 odobranie
  1. 32 17
      PCS/pom.xml
  2. 0 1
      PCS/src/main/java/cn/cslg/permission/common/config/SaTokenConfigure.java
  3. 39 0
      PCS/src/main/java/cn/cslg/permission/common/model/dto/AccessCountDTO.java
  4. 53 0
      PCS/src/main/java/cn/cslg/permission/common/model/vo/LoginRecordExportVO.java
  5. 61 0
      PCS/src/main/java/cn/cslg/permission/common/model/vo/LoginRecordVO.java
  6. 1 2
      PCS/src/main/java/cn/cslg/permission/common/model/vo/LoginVO.java
  7. 30 0
      PCS/src/main/java/cn/cslg/permission/common/model/vo/PersonnelNameVO.java
  8. 26 0
      PCS/src/main/java/cn/cslg/permission/common/model/vo/ProjectSharedTenantVO.java
  9. 35 0
      PCS/src/main/java/cn/cslg/permission/common/model/vo/ProjectUsedByTenantVO.java
  10. 28 0
      PCS/src/main/java/cn/cslg/permission/common/model/vo/ReportTenantVO.java
  11. 26 0
      PCS/src/main/java/cn/cslg/permission/common/model/vo/ReportUsedByTenantVO.java
  12. 35 0
      PCS/src/main/java/cn/cslg/permission/common/model/vo/TotalDataVO.java
  13. 9 9
      PCS/src/main/java/cn/cslg/permission/common/utils/StpAdminUtil.java
  14. 1 1
      PCS/src/main/java/cn/cslg/permission/common/utils/auth/AuthAop.java
  15. 85 0
      PCS/src/main/java/cn/cslg/permission/controller/Export2ExcelController.java
  16. 10 0
      PCS/src/main/java/cn/cslg/permission/controller/TenantController.java
  17. 51 0
      PCS/src/main/java/cn/cslg/permission/domain/AccessCount.java
  18. 12 6
      PCS/src/main/java/cn/cslg/permission/domain/LoginRecord.java
  19. 14 0
      PCS/src/main/java/cn/cslg/permission/mapper/AccessCountMapper.java
  20. 57 0
      PCS/src/main/java/cn/cslg/permission/service/AccessCountService.java
  21. 691 0
      PCS/src/main/java/cn/cslg/permission/service/Export2ExcelService.java
  22. 80 21
      PCS/src/main/java/cn/cslg/permission/service/LoginRecordService.java
  23. 41 64
      PCS/src/main/java/cn/cslg/permission/service/LoginService.java
  24. 18 0
      PCS/src/main/java/cn/cslg/permission/service/TenantService.java

+ 32 - 17
PCS/pom.xml

@@ -17,18 +17,18 @@
 
     <properties>
         <java.version>1.8</java.version>
-        <jwt.version>0.9.0</jwt.version>
+        <jwt.version>0.9.1</jwt.version>
         <commons.io.version>2.5</commons.io.version>
-        <mybatisplus.version>3.4.3.4</mybatisplus.version>
-        <google.code.gson.version>2.7</google.code.gson.version>
-        <hutool.version>5.6.5</hutool.version>
-        <okhttps.version>3.1.1</okhttps.version>
+        <mybatisplus.version>3.5.3.1</mybatisplus.version>
+        <google.code.gson.version>2.10.1</google.code.gson.version>
+        <hutool.version>5.8.18</hutool.version>
+        <okhttps.version>3.5.3</okhttps.version>
         <poi.version>4.1.2</poi.version>
-        <poi-tl.version>1.10.3</poi-tl.version>
-        <druid.version>1.1.10</druid.version>
-        <fastjson.version>2.0.0</fastjson.version>
-        <sa-token.version>1.29.0</sa-token.version>
-        <springdoc.version>1.6.6</springdoc.version>
+        <poi-tl.version>1.12.1</poi-tl.version>
+        <druid.version>1.2.16</druid.version>
+        <fastjson.version>2.0.32</fastjson.version>
+        <sa-token.version>1.34.0.temp1</sa-token.version>
+        <springdoc.version>1.6.15</springdoc.version>
     </properties>
 
     <dependencies>
@@ -74,7 +74,7 @@
         <dependency>
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
-            <version>2.6</version>
+            <version>2.11.0</version>
         </dependency>
         <dependency>
             <groupId>io.jsonwebtoken</groupId>
@@ -127,6 +127,11 @@
             <scope>runtime</scope>
         </dependency>
         <dependency>
+            <groupId>com.ejlchina</groupId>
+            <artifactId>okhttps</artifactId>
+            <version>${okhttps.version}</version>
+        </dependency>
+        <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
             <optional>true</optional>
@@ -144,11 +149,11 @@
         <!--            <artifactId>nashorn-core</artifactId>-->
         <!--            <version>15.3</version>-->
         <!--        </dependency>-->
-        <dependency>
-            <groupId>com.squareup.okhttp3</groupId>
-            <artifactId>okhttp</artifactId>
-            <version>3.9.1</version>
-        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>com.squareup.okhttp3</groupId>-->
+<!--            <artifactId>okhttp</artifactId>-->
+<!--            <version>4.10.0</version>-->
+<!--        </dependency>-->
         <!--rabbitmq-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -157,13 +162,23 @@
         <dependency>
             <groupId>com.github.pagehelper</groupId>
             <artifactId>pagehelper-spring-boot-starter</artifactId>
-            <version>1.4.0</version>
+            <version>1.4.6</version>
         </dependency>
 <!--        <dependency>-->
 <!--            <groupId>org.springframework.boot</groupId>-->
 <!--            <artifactId>spring-boot-starter-test</artifactId>-->
 <!--            <scope>test</scope>-->
 <!--        </dependency>-->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>eu.bitwalker</groupId>
+            <artifactId>UserAgentUtils</artifactId>
+            <version>1.21</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 0 - 1
PCS/src/main/java/cn/cslg/permission/common/config/SaTokenConfigure.java

@@ -4,7 +4,6 @@ import cn.cslg.permission.common.core.base.Constants;
 import cn.cslg.permission.common.utils.Response;
 import cn.cslg.permission.common.utils.ResponseEnum;
 import cn.dev33.satoken.filter.SaServletFilter;
-import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
 import cn.dev33.satoken.router.SaRouter;
 import cn.dev33.satoken.stp.StpUtil;
 import org.springframework.context.annotation.Bean;

+ 39 - 0
PCS/src/main/java/cn/cslg/permission/common/model/dto/AccessCountDTO.java

@@ -0,0 +1,39 @@
+package cn.cslg.permission.common.model.dto;
+
+import cn.cslg.permission.common.model.BaseEntity;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+/**
+ * 访问次数记录
+ * @Author xiexiang
+ * @Date 2023/7/27
+ */
+@Data
+@Accessors(chain = true)
+public class AccessCountDTO {
+    /**
+     * 访问来源(1专题库,2报告)
+     */
+    private Integer accessFrom;
+
+    /**
+     * id(抽象id)
+     */
+    private Integer rangeId;
+
+    /**
+     * 访问人员
+     */
+    private Integer createId;
+
+    /**
+     * 访问次数
+     */
+    private Integer count;
+}

+ 53 - 0
PCS/src/main/java/cn/cslg/permission/common/model/vo/LoginRecordExportVO.java

@@ -0,0 +1,53 @@
+package cn.cslg.permission.common.model.vo;
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @Author xiexiang
+ * @Date 2023/8/7
+ */
+@Data
+public class LoginRecordExportVO {
+
+    /**
+     * 租户名称
+     */
+    private String tenantName;
+
+    /**
+     * 登录人用户名
+     */
+    private String personnelUserName;
+
+    /**
+     * 登录人IP
+     */
+    private String loginIp;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 登录结果
+     */
+    private String loginResult;
+
+    /**
+     * 登录系统(0权限系统1分析系统2报告系统)
+     */
+    private String loginSystemName;
+
+    /**
+     * 登录浏览器
+     */
+    private String browser;
+
+    /**
+     * 登录操作系统
+     */
+    private String loginOs;
+}

+ 61 - 0
PCS/src/main/java/cn/cslg/permission/common/model/vo/LoginRecordVO.java

@@ -0,0 +1,61 @@
+package cn.cslg.permission.common.model.vo;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+/**
+ * @Author xiexiang
+ * @Date 2023/7/20
+ */
+@Data
+@Accessors(chain = true)
+public class LoginRecordVO {
+    /**
+     * 自增id
+     */
+    private Integer id;
+
+    /**
+     * 租户ID
+     */
+    private Integer tenantId;
+
+    /**
+     * 登录人Id
+     */
+    private Integer personnelId;
+
+    /**
+     * 登录人IP
+     */
+    private String loginIp;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 登录结果
+     */
+    private String loginResult;
+
+    /**
+     * 登录系统(0权限系统1分析系统2报告系统)
+     */
+    private Integer loginSystem;
+
+    /**
+     * 登录浏览器
+     */
+    private String browser;
+
+    /**
+     * 登录操作系统
+     */
+    private String loginOs;
+
+}

+ 1 - 2
PCS/src/main/java/cn/cslg/permission/common/model/vo/LoginVO.java

@@ -32,11 +32,10 @@ public class LoginVO {
      * 密码
      */
     private String password;
+
     /**
      * 登录系统(0权限系统1分析系统2报告系统)
      */
-
     private Integer loginSystem;
 
-
 }

+ 30 - 0
PCS/src/main/java/cn/cslg/permission/common/model/vo/PersonnelNameVO.java

@@ -0,0 +1,30 @@
+package cn.cslg.permission.common.model.vo;
+
+import lombok.Data;
+
+/**
+ * @Author xiexiang
+ * @Date 2023/8/2
+ */
+@Data
+public class PersonnelNameVO {
+    /**
+     * 租户名
+     */
+    private String tenantName;
+
+    /**
+     * 人员数量
+     */
+    private Integer personnelNum;
+
+    /**
+     * 账号
+     */
+    private String personnelUserName;
+
+    /**
+     * 姓名
+     */
+    private String personnelName;
+}

+ 26 - 0
PCS/src/main/java/cn/cslg/permission/common/model/vo/ProjectSharedTenantVO.java

@@ -0,0 +1,26 @@
+package cn.cslg.permission.common.model.vo;
+
+import lombok.Data;
+
+/**
+ * 租户被分享专题库报表
+ * @Author xiexiang
+ * @Date 2023/8/3
+ */
+@Data
+public class ProjectSharedTenantVO {
+    /**
+     * 租户名
+     */
+    private String tenantName;
+
+    /**
+     * 被分享专题库数量
+     */
+    private Integer projectNum;
+
+    /**
+     * 被分享专题库名
+     */
+    private String projectName;
+}

+ 35 - 0
PCS/src/main/java/cn/cslg/permission/common/model/vo/ProjectUsedByTenantVO.java

@@ -0,0 +1,35 @@
+package cn.cslg.permission.common.model.vo;
+
+import lombok.Data;
+
+/**
+ * @Author xiexiang
+ * @Date 2023/7/28
+ */
+@Data
+public class ProjectUsedByTenantVO {
+    /**
+     * 租户名
+     */
+    private String tenantName;
+
+    /**
+     * 专题库数量
+     */
+    private Integer projectNum;
+
+    /**
+     * 专题库id
+     */
+    private Integer projectId;
+
+    /**
+     * 专题库名
+     */
+    private String projectName;
+
+    /**
+     * 专利数量
+     */
+    private Integer patentNum;
+}

+ 28 - 0
PCS/src/main/java/cn/cslg/permission/common/model/vo/ReportTenantVO.java

@@ -0,0 +1,28 @@
+package cn.cslg.permission.common.model.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 租户报告表
+ * @Author xiexiang
+ * @Date 2023/8/2
+ */
+@Data
+public class ReportTenantVO {
+    /**
+     * 租户id
+     */
+    private Integer tenantId;
+
+    /**
+     * 租户名
+     */
+    private String tenantName;
+
+    /**
+     * 人员ids
+     */
+    private List<Integer> personnelIds;
+}

+ 26 - 0
PCS/src/main/java/cn/cslg/permission/common/model/vo/ReportUsedByTenantVO.java

@@ -0,0 +1,26 @@
+package cn.cslg.permission.common.model.vo;
+
+import lombok.Data;
+
+/**
+ * 租户报告使用情况
+ * @Author xiexiang
+ * @Date 2023/8/2
+ */
+@Data
+public class ReportUsedByTenantVO {
+    /**
+     * 租户名
+     */
+    private String tenantName;
+
+    /**
+     * 报告数量
+     */
+    private Integer reportNum;
+
+    /**
+     * 报告名称
+     */
+    private String reportName;
+}

+ 35 - 0
PCS/src/main/java/cn/cslg/permission/common/model/vo/TotalDataVO.java

@@ -0,0 +1,35 @@
+package cn.cslg.permission.common.model.vo;
+
+import lombok.Data;
+
+/**
+ * @Author xiexiang
+ * @Date 2023/8/4
+ */
+@Data
+public class TotalDataVO {
+    /**
+     * 租户
+     */
+    private String tenantName;
+
+    /**
+     * 报告数量
+     */
+    private Integer reportNum;
+
+    /**
+     * 专题库数量
+     */
+    private Integer projectNum;
+
+    /**
+     * 人员数量
+     */
+    private Integer personnelNum;
+
+    /**
+     * 专题库被分享数量
+     */
+    private Integer projectSharedNum;
+}

+ 9 - 9
PCS/src/main/java/cn/cslg/permission/common/utils/StpAdminUtil.java

@@ -716,9 +716,9 @@ public class StpAdminUtil {
      * @param size    获取数量
      * @return token集合
      */
-    public static List<String> searchTokenValue(String keyword, int start, int size) {
-        return stpLogic.searchTokenValue(keyword, start, size);
-    }
+//    public static List<String> searchTokenValue(String keyword, int start, int size) {
+//        return stpLogic.searchTokenValue(keyword, start, size);
+//    }
 
     /**
      * 根据条件查询SessionId
@@ -728,9 +728,9 @@ public class StpAdminUtil {
      * @param size    获取数量
      * @return sessionId集合
      */
-    public static List<String> searchSessionId(String keyword, int start, int size) {
-        return stpLogic.searchSessionId(keyword, start, size);
-    }
+//    public static List<String> searchSessionId(String keyword, int start, int size) {
+//        return stpLogic.searchSessionId(keyword, start, size);
+//    }
 
     /**
      * 根据条件查询Token专属Session的Id
@@ -740,9 +740,9 @@ public class StpAdminUtil {
      * @param size    获取数量
      * @return sessionId集合
      */
-    public static List<String> searchTokenSessionId(String keyword, int start, int size) {
-        return stpLogic.searchTokenSessionId(keyword, start, size);
-    }
+//    public static List<String> searchTokenSessionId(String keyword, int start, int size) {
+//        return stpLogic.searchTokenSessionId(keyword, start, size);
+//    }
 
 
     // ------------------- 账号封禁 -------------------

+ 1 - 1
PCS/src/main/java/cn/cslg/permission/common/utils/auth/AuthAop.java

@@ -71,7 +71,7 @@ public class AuthAop {
         String resBody = dataController.queryDataRule(StpUtil.getLoginIdAsInt(), functionId).toString();
         JSONArray jsonArray = JSONArray.parseArray(resBody);
         //如果获得规则的返回值为[-1]则代表登录人没有使用该功能的权限
-        if (jsonArray.get(0).toString().equals("-1")) {
+         if (jsonArray.get(0).toString().equals("-1")) {
             return Response.error("没有" + operAnnotation.summary() + "的功能");
         }
         //如果获得规则的返回值为[0],则直接通过判断

+ 85 - 0
PCS/src/main/java/cn/cslg/permission/controller/Export2ExcelController.java

@@ -0,0 +1,85 @@
+package cn.cslg.permission.controller;
+
+import cn.cslg.permission.common.core.base.Constants;
+import cn.cslg.permission.common.model.vo.PersonnelNameVO;
+import cn.cslg.permission.common.model.vo.ReportTenantVO;
+import cn.cslg.permission.common.utils.Response;
+import cn.cslg.permission.service.Export2ExcelService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * 导出报表
+ * @Author xiexiang
+ * @Date 2023/7/28
+ */
+@Slf4j
+@Tag(name = "导出报表")
+@RestController
+@RequestMapping(Constants.PERMISSION_API + "/exportExcel")
+@RequiredArgsConstructor(onConstructor_ = {@Lazy})
+public class Export2ExcelController {
+    private final Export2ExcelService export2ExcelService;
+
+    @GetMapping("/exportLoginRecord")
+    @Operation(summary = "导出登录日志")
+    public String exportLoginRecord(Integer queryType) throws IOException {
+        export2ExcelService.exportLoginRecord(queryType);
+        return Response.success();
+    }
+
+    @PostMapping("/exportTotal")
+    @Operation(summary = "导出汇总报表")
+    public String exportTotal(@RequestBody List<Integer> tenantIds) throws IOException {
+        export2ExcelService.exportTotal(tenantIds);
+        return Response.success();
+    }
+
+    @PostMapping("/exportProject")
+    @Operation(summary = "导出租户专题库使用报表")
+    public String exportProject(@RequestBody List<Integer> tenantIds) throws IOException {
+        export2ExcelService.exportProjectNameToExcel(tenantIds);
+        return Response.success();
+    }
+
+    @PostMapping("/exportPersonName")
+    @Operation(summary = "导出租户人员报表")
+    public String exportPersonName(@RequestBody List<Integer> tenantIds) throws IOException {
+        export2ExcelService.exportPersonnelNameToExcel(tenantIds);
+        return Response.success();
+    }
+
+    @PostMapping("/getTenantPerson")
+    @Operation(summary = "查出所有租户,并且查出租户下的人员")
+    public List<ReportTenantVO> getTenantPerson(@RequestBody List<Integer> tenantIds){
+        return export2ExcelService.getTenantPerson(tenantIds);
+    }
+
+    @PostMapping("/exportReport")
+    @Operation(summary = "导出租户报告使用报表")
+    public String exportReport(@RequestBody List<Integer> tenantIds) throws IOException {
+        export2ExcelService.exportReportTenant(tenantIds);
+        return Response.success();
+    }
+
+    @PostMapping("/exportProjectShared")
+    @Operation(summary = "导出租户被分享专题库报表")
+    public String exportProjectShared(@RequestBody List<Integer> tenantIds) throws IOException {
+        export2ExcelService.exportProjectShared(tenantIds);
+        return Response.success();
+    }
+
+    @PostMapping("/getPersonnelNameData")
+    @Operation(summary = "获取租户人员报表信息")
+    public List<PersonnelNameVO> getPersonnelNameData(@RequestBody List<Integer> tenantIds) {
+        return export2ExcelService.getPersonnelNameData(tenantIds);
+    }
+
+}

+ 10 - 0
PCS/src/main/java/cn/cslg/permission/controller/TenantController.java

@@ -5,6 +5,7 @@ import cn.cslg.permission.common.model.vo.TenantVO;
 import cn.cslg.permission.common.utils.Response;
 import cn.cslg.permission.common.utils.auth.checkAuth;
 import cn.cslg.permission.domain.Invitation;
+import cn.cslg.permission.domain.Tenant;
 import cn.cslg.permission.exception.XiaoShiException;
 import cn.cslg.permission.service.TenantService;
 import io.swagger.v3.oas.annotations.Operation;
@@ -14,6 +15,8 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.List;
+
 @Slf4j
 @Tag(name = "租户管理")
 @RestController
@@ -97,4 +100,11 @@ public class TenantController {
     public String getTenantList() {
         return tenantService.getTenantList();
     }
+
+    @PostMapping("/getTenantIdAndName")
+    @Operation(summary = "查询所有租户的id和名称")
+    public List<Tenant> getTenantIdAndName(@RequestBody List<Integer> tenantIds) {
+        return tenantService.getTenantIdAndName(tenantIds);
+    }
+
 }

+ 51 - 0
PCS/src/main/java/cn/cslg/permission/domain/AccessCount.java

@@ -0,0 +1,51 @@
+package cn.cslg.permission.domain;
+
+import cn.cslg.permission.common.model.BaseEntity;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+/**
+ * @Author xiexiang
+ * @Date 2023/7/27
+ */
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = true)
+@TableName(value = "LOGIN_COUNT")
+public class AccessCount extends BaseEntity<AccessCount> {
+
+    /**
+     * 访问来源(1专题库,2报告)
+     */
+    @TableField(value = "ACCESS_FROM")
+    private Integer accessFrom;
+
+    /**
+     * id(抽象id)
+     */
+    @TableField(value = "RANGE_ID")
+    private Integer rangeId;
+
+    /**
+     * 访问次数
+     */
+    @TableField(value = "COUNT")
+    private Integer count;
+
+    /**
+     * 访问人员
+     */
+    @TableField(value = "CREATE_ID")
+    private Integer createId;
+
+    /**
+     * 更新时间
+     */
+    @TableField(value = "UPDATE_TIME")
+    private Date updateTime;
+}

+ 12 - 6
PCS/src/main/java/cn/cslg/permission/domain/LoginRecord.java

@@ -31,19 +31,19 @@ public class LoginRecord extends Model {
      * 租户ID
      */
     @TableField(value = "TENANT_ID")
-    private Integer TENANT_ID;
+    private Integer tenantId;
 
     /**
      * 登录人Id
      */
     @TableField(value = "PERSONNEL_ID")
-    private Integer  personnelId;
+    private Integer personnelId;
 
     /**
      * 登录人IP
      */
     @TableField(value = "LOGIN_IP")
-    private Integer  loginIp;
+    private String loginIp;
 
     /**
      * 创建时间
@@ -55,18 +55,24 @@ public class LoginRecord extends Model {
      * 登录结果
      */
     @TableField(value = "LOGIN_RESULT")
-    private String  loginResult ;
+    private String  loginResult;
 
     /**
      * 登录系统(0权限系统1分析系统2报告系统)
      */
     @TableField(value = "LOGIN_SYSTEM")
-    private Integer  loginSystem ;
+    private Integer loginSystem;
+
+    /**
+     * 登录浏览器
+     */
+    @TableField(value = "BROWSER")
+    private String browser;
 
     /**
      * 登录操作系统
      */
     @TableField(value = "LOGIN_OS")
-    private String  loginOs ;
+    private String loginOs;
 
 }

+ 14 - 0
PCS/src/main/java/cn/cslg/permission/mapper/AccessCountMapper.java

@@ -0,0 +1,14 @@
+package cn.cslg.permission.mapper;
+
+import cn.cslg.permission.domain.AccessCount;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 访问次数记录
+ * @Author xiexiang
+ * @Date 2023/7/27
+ */
+@Mapper
+public interface AccessCountMapper extends BaseMapper<AccessCount> {
+}

+ 57 - 0
PCS/src/main/java/cn/cslg/permission/service/AccessCountService.java

@@ -0,0 +1,57 @@
+package cn.cslg.permission.service;
+
+import cn.cslg.permission.common.model.dto.AccessCountDTO;
+import cn.cslg.permission.common.model.vo.PersonnelVO;
+import cn.cslg.permission.common.utils.CacheUtils;
+import cn.cslg.permission.common.utils.LoginUtils;
+import cn.cslg.permission.domain.AccessCount;
+
+import cn.cslg.permission.domain.Personnel;
+import cn.cslg.permission.mapper.AccessCountMapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 访问次数记录
+ * @Author xiexiang
+ * @Date 2023/7/27
+ */
+@Service
+@RequiredArgsConstructor(onConstructor_ = {@Lazy})
+public class AccessCountService extends ServiceImpl<AccessCountMapper, AccessCount> {
+    private final CacheUtils cacheUtils;
+    private final LoginUtils loginUtils;
+
+    public void accessCountRecord(Integer accessFrom, Integer id){
+        //传入对象不为空
+        if(accessFrom != null && id != null && accessFrom > 0 && id > 0){
+            //获取当前登陆人信息
+            PersonnelVO personnelVO = cacheUtils.getLoginUser(loginUtils.getId());
+            Integer createId = personnelVO.getId();
+            LambdaQueryWrapper<AccessCount> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper.eq(AccessCount::getCreateId, createId);
+            queryWrapper.eq(AccessCount::getRangeId, id);
+            queryWrapper.eq(AccessCount::getAccessFrom, accessFrom);
+            AccessCount accessCount = this.getOne(queryWrapper);
+            //访问过
+            if(accessCount != null){
+                accessCount.setCount(accessCount.getCount() + 1);
+                accessCount.updateById();
+            } else {
+                //没访问过
+                AccessCount addAccessCount = new AccessCount();
+                addAccessCount.setAccessFrom(accessFrom);
+                addAccessCount.setRangeId(id);
+                addAccessCount.setCreateId(createId);
+                addAccessCount.setCount(1);
+                addAccessCount.insert();
+            }
+        }
+    }
+}

+ 691 - 0
PCS/src/main/java/cn/cslg/permission/service/Export2ExcelService.java

@@ -0,0 +1,691 @@
+package cn.cslg.permission.service;
+
+import cn.cslg.permission.common.model.vo.*;
+import cn.cslg.permission.common.utils.CacheUtils;
+import cn.cslg.permission.common.utils.FileUtils;
+import cn.cslg.permission.common.utils.LoginUtils;
+import cn.cslg.permission.domain.LoginRecord;
+import cn.cslg.permission.domain.Personnel;
+import cn.cslg.permission.domain.Tenant;
+import cn.cslg.permission.exception.XiaoShiException;
+import cn.hutool.core.util.IdUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * 导出报表
+ * @Author xiexiang
+ * @Date 2023/8/2
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class Export2ExcelService {
+    private String PASUrl = "http://localhost:8877";
+    private String RMSUrl = "http://localhost:8872";
+    private String PCSUrl = "http://localhost:8871";
+    private final FileUtils fileUtils;
+    private final CacheUtils cacheUtils;
+    private final LoginUtils loginUtils;
+    private final PersonnelService personnelService;
+    private final TenantService tenantService;
+    private final LoginRecordService loginRecordService;
+
+    /**
+     * 租户专题库使用情况报表
+     * @throws IOException
+     */
+    public void exportProjectNameToExcel(List<Integer> tenantIds) throws IOException {
+        //保存生成excel的地址
+        String fileName = IdUtil.simpleUUID() + ".xls";
+        String directoryName = fileUtils.createDirectory();
+        String outPath = fileUtils.getSavePath(directoryName) + fileName;
+        //查询数据
+        List<ProjectUsedByTenantVO> projectUsedByTenantVOS = this.getProjectData(tenantIds);
+        //配置导出excel
+        try (FileOutputStream fileOut = new FileOutputStream(outPath)){
+            //创建excel
+            Workbook workbook = new XSSFWorkbook();
+            //创建sheet页
+            Sheet sheet = workbook.createSheet("租户专题库使用报表");
+            //创建标题行
+            Row headerRow = sheet.createRow(0);
+            String[] headers = {"租户","专题库数量","专题库名称","专利数量"};
+            for(int i = 0; i < headers.length; i++){
+                Cell cell = headerRow.createCell(i);
+                cell.setCellValue(headers[i]);
+            }
+            //字体
+            Font headerFont = workbook.createFont();
+            headerFont.setBold(true);
+            CellStyle headerCellStyle = workbook.createCellStyle();
+            headerCellStyle.setFont(headerFont);
+            //开始插入数据的行数
+            int rowNum = 1;
+            //填充数据
+            for(ProjectUsedByTenantVO projectUsedByTenantVO : projectUsedByTenantVOS){
+                Row row = sheet.createRow(rowNum++);
+                row.createCell(0).setCellValue(projectUsedByTenantVO.getTenantName());
+                row.createCell(1).setCellValue(projectUsedByTenantVO.getProjectNum());
+                row.createCell(2).setCellValue(projectUsedByTenantVO.getProjectName());
+                row.createCell(3).setCellValue(projectUsedByTenantVO.getPatentNum());
+            }
+//            //自动调整列宽
+//            for(int i = 0; i < headers.length; i++){
+//                sheet.autoSizeColumn(i);
+//            }
+            sheet.setColumnWidth(0, 256 * 30);
+            sheet.setColumnWidth(1, 256 * 20);
+            sheet.setColumnWidth(2, 256 * 20);
+            sheet.setColumnWidth(3, 256 * 20);
+            workbook.write(fileOut);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+    }
+    /**
+     * 返回租户专题库使用情况对象集合
+     * @return
+     * @throws IOException
+     */
+    public List<ProjectUsedByTenantVO> getProjectData(List<Integer> tenantIds) throws IOException {
+        String data = this.getProjectUsedByTenantFromPAS(tenantIds);
+        Gson gson = new Gson();
+        Type listType = new TypeToken<List<ProjectUsedByTenantVO>>(){}.getType();
+        List<ProjectUsedByTenantVO> projectUsedByTenantVOS = gson.fromJson(data, listType);
+        return projectUsedByTenantVOS;
+    }
+    /**
+     * 调用分析系统查询接口
+     * @return
+     * @throws IOException
+     */
+    public String getProjectUsedByTenantFromPAS(List<Integer> tenantIds) throws IOException {
+        String param = new Gson().toJson(tenantIds);
+        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), param);
+        OkHttpClient okHttpClient = new OkHttpClient.Builder()
+                .connectTimeout(60, TimeUnit.SECONDS)
+                .writeTimeout(60, TimeUnit.SECONDS)
+                .readTimeout(60, TimeUnit.SECONDS)
+                .build();
+        Request request = new Request.Builder()
+                .url(PASUrl + "/api/v2/usedByTenant/query")
+                .post(requestBody)
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+
+    //---------------------------------租户专题库使用情况报表-------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //-----------------------------------------租户人员报表-------------------------------------------------------
+
+    /**
+     * 租户人员报表
+     * @throws IOException
+     */
+    public void exportPersonnelNameToExcel(List<Integer> tenantIds) throws IOException {
+        //保存生成excel的地址
+        String fileName = IdUtil.simpleUUID() + ".xls";
+        String directoryName = fileUtils.createDirectory();
+        String outPath = fileUtils.getSavePath(directoryName) + fileName;
+        //查询数据
+        List<PersonnelNameVO> personnelNameVOS = this.getPersonnelNameData(tenantIds);
+        //配置导出excel
+        try (FileOutputStream fileOut = new FileOutputStream(outPath)){
+            //创建excel
+            Workbook workbook = new XSSFWorkbook();
+            //创建sheet页
+            Sheet sheet = workbook.createSheet("租户人员表");
+            //创建标题行
+            Row headerRow = sheet.createRow(0);
+            String[] headers = {"租户","人员数量","人员名称","账号"};
+            for(int i = 0; i < headers.length; i++){
+                Cell cell = headerRow.createCell(i);
+                cell.setCellValue(headers[i]);
+            }
+            //字体
+            Font headerFont = workbook.createFont();
+            headerFont.setBold(true);
+            CellStyle headerCellStyle = workbook.createCellStyle();
+            headerCellStyle.setFont(headerFont);
+            //开始插入数据的行数
+            int rowNum = 1;
+            //填充数据
+            for(PersonnelNameVO personnelNameVO : personnelNameVOS){
+                Row row = sheet.createRow(rowNum++);
+                row.createCell(0).setCellValue(personnelNameVO.getTenantName());
+                row.createCell(1).setCellValue(personnelNameVO.getPersonnelNum());
+                row.createCell(2).setCellValue(personnelNameVO.getPersonnelName());
+                row.createCell(3).setCellValue(personnelNameVO.getPersonnelUserName());
+            }
+//            //自动调整列宽
+//            for(int i = 0; i < headers.length; i++){
+//                sheet.autoSizeColumn(i);
+//            }
+            sheet.setColumnWidth(0, 256 * 30);
+            sheet.setColumnWidth(1, 256 * 20);
+            sheet.setColumnWidth(2, 256 * 20);
+            sheet.setColumnWidth(3, 256 * 20);
+            workbook.write(fileOut);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+    }
+    /**
+     * 查询租户人员信息
+     * @param tenantIds
+     * @return
+     */
+    public List<PersonnelNameVO> getPersonnelNameData(List<Integer> tenantIds){
+        List<PersonnelNameVO> personnelNameVOS = new ArrayList<>();
+        if(tenantIds.size() == 0){
+            List<Tenant> tenants = tenantService.list();
+            tenantIds = tenants.stream().map(Tenant::getId).collect(Collectors.toList());
+            System.out.println(tenantIds);
+        }
+        for(Integer tenantId : tenantIds){
+            //租户名
+            Tenant tenant = tenantService.getById(tenantId);
+            String tenantName = tenant.getTenantName();
+            LambdaQueryWrapper<Personnel> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper.eq(Personnel::getTenantId, tenantId);
+            Long count = personnelService.count(queryWrapper);
+            if(count > 0){
+                //人员数量
+                Integer personnelNum = Long.valueOf(count).intValue();
+                List<Personnel> personnels = personnelService.list(queryWrapper);
+                for(Personnel personnel : personnels){
+                    PersonnelNameVO personnelNameVO = new PersonnelNameVO();
+                    //租户
+                    personnelNameVO.setTenantName(tenantName);
+                    //人员数量
+                    personnelNameVO.setPersonnelNum(personnelNum);
+                    //人员名称
+                    personnelNameVO.setPersonnelName(personnel.getPersonnelName());
+                    //账号
+                    personnelNameVO.setPersonnelUserName(personnel.getPersonnelUserName());
+                    personnelNameVOS.add(personnelNameVO);
+                }
+            } else {
+                PersonnelNameVO personnelNameVO = new PersonnelNameVO();
+                //租户
+                personnelNameVO.setTenantName(tenantName);
+                //人员数量
+                personnelNameVO.setPersonnelNum(0);
+                personnelNameVOS.add(personnelNameVO);
+            }
+        }
+        return personnelNameVOS;
+    }
+
+    //-----------------------------------------租户人员报表-------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //-----------------------------------租户报告使用情况报表-------------------------------------------------------
+
+    /**
+     * 租户报告使用情况报表
+     * @throws IOException
+     */
+    public void exportReportTenant(List<Integer> tenantIds) throws IOException {
+        //需要导出到excel的对象集合,查询数据
+        List<ReportUsedByTenantVO> reportUsedByTenantVOS = this.reportStr2Object(tenantIds);
+        //保存生成excel的地址
+        String fileName = IdUtil.simpleUUID() + ".xls";
+        String directoryName = fileUtils.createDirectory();
+        String outPath = fileUtils.getSavePath(directoryName) + fileName;
+        //配置导出excel
+        try (FileOutputStream fileOut = new FileOutputStream(outPath)){
+            //创建excel
+            Workbook workbook = new XSSFWorkbook();
+            //创建sheet页
+            Sheet sheet = workbook.createSheet("租户报告使用报表");
+            //创建标题行
+            Row headerRow = sheet.createRow(0);
+            String[] headers = {"租户","报告数量","报告名称"};
+            for(int i = 0; i < headers.length; i++){
+                Cell cell = headerRow.createCell(i);
+                cell.setCellValue(headers[i]);
+            }
+            //字体
+            Font headerFont = workbook.createFont();
+            headerFont.setBold(true);
+            CellStyle headerCellStyle = workbook.createCellStyle();
+            headerCellStyle.setFont(headerFont);
+            //开始插入数据的行数
+            int rowNum = 1;
+            //填充数据
+            for(ReportUsedByTenantVO reportUsedByTenantVO : reportUsedByTenantVOS){
+                Row row = sheet.createRow(rowNum++);
+                row.createCell(0).setCellValue(reportUsedByTenantVO.getTenantName());
+                row.createCell(1).setCellValue(reportUsedByTenantVO.getReportNum());
+                row.createCell(2).setCellValue(reportUsedByTenantVO.getReportName());
+            }
+//            //自动调整列宽
+//            for(int i = 0; i < headers.length; i++){
+//                sheet.autoSizeColumn(i);
+//            }
+            sheet.setColumnWidth(0, 256 * 30);
+            sheet.setColumnWidth(1, 256 * 20);
+            sheet.setColumnWidth(2, 256 * 20);
+            workbook.write(fileOut);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+    }
+    /**
+     * 租户报告报表字符串转对象集合
+     * @return
+     * @throws IOException
+     */
+    public List<ReportUsedByTenantVO> reportStr2Object(List<Integer> tenantIds) throws IOException {
+        String reData = this.getReportDataFromRMS(tenantIds);
+        Gson gson = new Gson();
+        Type listType = new TypeToken<List<ReportUsedByTenantVO>>(){}.getType();
+        List<ReportUsedByTenantVO> tenantVos = gson.fromJson(reData, listType);
+        return tenantVos;
+    }
+    /**
+     * 从报告系统获取租户报告使用情况
+     * @return
+     * @throws IOException
+     */
+    public String getReportDataFromRMS(List<Integer> tenantIds) throws IOException {
+        String param = new Gson().toJson(tenantIds);
+        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), param);
+        OkHttpClient okHttpClient = new OkHttpClient.Builder()
+                .connectTimeout(60, TimeUnit.SECONDS)
+                .writeTimeout(60, TimeUnit.SECONDS)
+                .readTimeout(60, TimeUnit.SECONDS)
+                .build();
+        Request request = new Request.Builder()
+                .url("http://localhost:8872" + "/api/report/api/report/queryReportNameUsedByTenant")
+                .post(requestBody)
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+    /**
+     * 查出所有租户,并且查出租户下的人员
+     */
+    public List<ReportTenantVO> getTenantPerson(List<Integer> tenantIds){
+        List<ReportTenantVO> reportTenantVOS = new ArrayList<>();
+        //放入空集合,查询全部
+        List<Tenant> tenants = tenantService.getTenantIdAndName(tenantIds);
+        //遍历,装载
+        for(Tenant tenant : tenants){
+            ReportTenantVO reportTenantVO = new ReportTenantVO();
+            //租户id
+            reportTenantVO.setTenantId(tenant.getId());
+            //租户名
+            reportTenantVO.setTenantName(tenant.getTenantName());
+            //人员ids
+            LambdaQueryWrapper<Personnel> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper.eq(Personnel::getTenantId, tenant.getId());
+            List<Personnel> personnels = personnelService.list(queryWrapper);
+            List<Integer> personnelIds = personnels.stream().map(Personnel::getId).collect(Collectors.toList());
+            reportTenantVO.setPersonnelIds(personnelIds);
+            reportTenantVOS.add(reportTenantVO);
+        }
+        return reportTenantVOS;
+    }
+    //-----------------------------------租户报告使用情况报表-------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //-----------------------------------租户被分享专题库报表-------------------------------------------------------
+
+    /**
+     * 租户被分享专题库报表
+     * @throws IOException
+     */
+    public void exportProjectShared(List<Integer> tenantIds) throws IOException {
+        //需要导出到excel的对象集合,查询数据
+        List<ProjectSharedTenantVO> projectSharedTenantVOS = this.getProjectSharedData(tenantIds);
+        //保存生成excel的地址
+        String fileName = IdUtil.simpleUUID() + ".xls";
+        String directoryName = fileUtils.createDirectory();
+        String outPath = fileUtils.getSavePath(directoryName) + fileName;
+        //配置导出excel
+        try (FileOutputStream fileOut = new FileOutputStream(outPath)){
+            //创建excel
+            Workbook workbook = new XSSFWorkbook();
+            //创建sheet页
+            Sheet sheet = workbook.createSheet("租户被分享专题库报表");
+            //创建标题行
+            Row headerRow = sheet.createRow(0);
+            String[] headers = {"租户","被分享专题库数量","被分享专题库"};
+            for(int i = 0; i < headers.length; i++){
+                Cell cell = headerRow.createCell(i);
+                cell.setCellValue(headers[i]);
+            }
+            //字体
+            Font headerFont = workbook.createFont();
+            headerFont.setBold(true);
+            CellStyle headerCellStyle = workbook.createCellStyle();
+            headerCellStyle.setFont(headerFont);
+            //开始插入数据的行数
+            int rowNum = 1;
+            //填充数据
+            for(ProjectSharedTenantVO projectSharedTenantVO : projectSharedTenantVOS){
+                Row row = sheet.createRow(rowNum++);
+                row.createCell(0).setCellValue(projectSharedTenantVO.getTenantName());
+                row.createCell(1).setCellValue(projectSharedTenantVO.getProjectNum());
+                row.createCell(2).setCellValue(projectSharedTenantVO.getProjectName());
+            }
+//            //自动调整列宽
+//            for(int i = 0; i < headers.length; i++){
+//                sheet.autoSizeColumn(i);
+//            }
+            sheet.setColumnWidth(0, 256 * 30);
+            sheet.setColumnWidth(1, 256 * 20);
+            sheet.setColumnWidth(2, 256 * 20);
+            workbook.write(fileOut);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 返回租户被分享专题库对象集合
+     * @return
+     * @throws IOException
+     */
+    public List<ProjectSharedTenantVO> getProjectSharedData(List<Integer> tenantIds) throws IOException {
+        String data = this.getProjectSharedTenantFromPAS(tenantIds);
+        Gson gson = new Gson();
+        Type listType = new TypeToken<List<ProjectSharedTenantVO>>(){}.getType();
+        List<ProjectSharedTenantVO> projectSharedTenantVOS = gson.fromJson(data, listType);
+        return projectSharedTenantVOS;
+    }
+    /**
+     * 调用分析系统查询接口
+     * @return
+     * @throws IOException
+     */
+    public String getProjectSharedTenantFromPAS(List<Integer> tenantIds) throws IOException {
+        String param = new Gson().toJson(tenantIds);
+        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), param);
+        OkHttpClient okHttpClient = new OkHttpClient.Builder()
+                .connectTimeout(60, TimeUnit.SECONDS)
+                .writeTimeout(60, TimeUnit.SECONDS)
+                .readTimeout(60, TimeUnit.SECONDS)
+                .build();
+        Request request = new Request.Builder()
+                .url(PASUrl + "/api/v2/usedByTenant/projectShared")
+                .post(requestBody)
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+
+    //-----------------------------------租户被分享专题库报表-------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //-----------------------------------------租户汇总报表-------------------------------------------------------
+
+    /**
+     * 导出汇总报表
+     * @param tenantIds
+     * @throws IOException
+     */
+    public void exportTotal(List<Integer> tenantIds) throws IOException {
+        List<TotalDataVO> totalDataVOS = new ArrayList<>();
+        if(tenantIds.size() > 0) {
+            for (Integer tenantId : tenantIds) {
+                TotalDataVO totalDataVO = this.getTotalData(tenantId);
+                totalDataVOS.add(totalDataVO);
+            }
+        } else {
+            List<Tenant> tenants = tenantService.getTenantIdAndName(tenantIds);
+            for(Tenant tenant : tenants){
+                TotalDataVO totalDataVO = this.getTotalData(tenant.getId());
+                totalDataVOS.add(totalDataVO);
+            }
+        }
+        //保存生成excel的地址
+        String fileName = IdUtil.simpleUUID() + ".xls";
+        String directoryName = fileUtils.createDirectory();
+        String outPath = fileUtils.getSavePath(directoryName) + fileName;
+        //配置导出excel
+        try (FileOutputStream fileOut = new FileOutputStream(outPath)){
+            //创建excel
+            Workbook workbook = new XSSFWorkbook();
+            //创建sheet页
+            Sheet sheet = workbook.createSheet("汇总报表");
+            //创建标题行
+            Row headerRow = sheet.createRow(0);
+            headerRow.setHeightInPoints(30);  //设置行高为30个点
+            String[] headers = {"租户","报告数量","专题库数量","人员数量","专题库被分享数量"};
+            for(int i = 0; i < headers.length; i++){
+                Cell cell = headerRow.createCell(i);
+                cell.setCellValue(headers[i]);
+            }
+            //开始插入数据的行数
+            int rowNum = 1;
+            //填充数据
+            for(TotalDataVO totalDataVO : totalDataVOS){
+                Row row = sheet.createRow(rowNum++);
+                row.createCell(0).setCellValue(totalDataVO.getTenantName());
+                row.createCell(1).setCellValue(totalDataVO.getReportNum());
+                row.createCell(2).setCellValue(totalDataVO.getProjectNum());
+                row.createCell(3).setCellValue(totalDataVO.getPersonnelNum());
+                row.createCell(4).setCellValue(totalDataVO.getProjectSharedNum());
+            }
+            //字体
+            Font headerFont = workbook.createFont();
+            //粗体
+            headerFont.setBold(true);
+            CellStyle headerCellStyle = workbook.createCellStyle();
+            headerCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);  //文字垂直居中
+            //将字体应用于单元格样式
+            headerCellStyle.setFont(headerFont);
+            sheet.setColumnWidth(0, 256 * 30);
+            sheet.setColumnWidth(1, 256 * 20);
+            sheet.setColumnWidth(2, 256 * 20);
+            sheet.setColumnWidth(3, 256 * 20);
+            sheet.setColumnWidth(4, 256 * 20);
+            workbook.write(fileOut);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 装载单个租户的汇总报表数据
+     * @param tenantId
+     * @return
+     * @throws IOException
+     */
+    public TotalDataVO getTotalData(Integer tenantId) throws IOException {
+        TotalDataVO totalDataVO = new TotalDataVO();
+        Tenant tenant = tenantService.getById(tenantId);
+        if(tenant != null) {
+            List<Integer> tenantIds = new ArrayList<>();
+            tenantIds.add(tenant.getId());
+            //租户名
+            totalDataVO.setTenantName(tenant.getTenantName());
+            //租户下人员数量
+            List<PersonnelNameVO> personnelNameVOS = this.getPersonnelNameData(tenantIds);
+            totalDataVO.setPersonnelNum(personnelNameVOS.get(0).getPersonnelNum());
+            //报告数量
+            String reportNumStr = this.getReportNumOfTotal(tenantId);
+            Integer reportNum = Integer.parseInt(reportNumStr);
+            totalDataVO.setReportNum(reportNum);
+            //专题库数量
+            List<ProjectUsedByTenantVO> projectUsedByTenantVOS = this.getProjectData(tenantIds);
+            Integer projectNum = projectUsedByTenantVOS.get(0).getProjectNum();
+            totalDataVO.setProjectNum(projectNum);
+            //被分享专题库数量
+            List<ProjectSharedTenantVO> projectSharedTenantVOS = this.getProjectSharedData(tenantIds);
+            Integer projectSharedNum = projectSharedTenantVOS.get(0).getProjectNum();
+            totalDataVO.setProjectSharedNum(projectSharedNum);
+        }
+        return totalDataVO;
+    }
+
+    /**
+     * 传给报告系统接口租户id 返回报告数量
+     * @return
+     * @throws IOException
+     */
+    public String getReportNumOfTotal(Integer tenantId) throws IOException {
+        OkHttpClient okHttpClient = new OkHttpClient.Builder()
+                .connectTimeout(60, TimeUnit.SECONDS)
+                .writeTimeout(60, TimeUnit.SECONDS)
+                .readTimeout(60, TimeUnit.SECONDS)
+                .build();
+        Request request = new Request.Builder()
+                .url("http://localhost:8872" + "/api/report/api/report/queryReportNumOfTotal?tenantId=" + tenantId)
+                .get()
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+    //-----------------------------------------租户汇总报表-------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------------------------------
+    //----------------------------------------登录日志导出报表------------------------------------------------------
+
+    /**
+     * 登陆日志报表导出
+     * @param queryType
+     * @throws IOException
+     */
+    public void exportLoginRecord(Integer queryType) throws IOException {
+        //需要导出到excel的对象集合,查询数据
+        List<LoginRecordExportVO> loginRecordExportVOS = this.loadLoginRecordData(queryType);
+        //保存生成excel的地址
+        String fileName = IdUtil.simpleUUID() + ".xls";
+        String directoryName = fileUtils.createDirectory();
+        String outPath = fileUtils.getSavePath(directoryName) + fileName;
+        //配置导出excel
+        try (FileOutputStream fileOut = new FileOutputStream(outPath)){
+            //创建excel
+            Workbook workbook = new XSSFWorkbook();
+            //创建sheet页
+            Sheet sheet = workbook.createSheet("登录日志报表");
+            //创建标题行
+            Row headerRow = sheet.createRow(0);
+            String[] headers = {"租户","用户名","IP","创建时间","登录结果","登录系统","浏览器","操作系统"};
+            for(int i = 0; i < headers.length; i++){
+                Cell cell = headerRow.createCell(i);
+                cell.setCellValue(headers[i]);
+            }
+            //字体
+            Font headerFont = workbook.createFont();
+            headerFont.setBold(true);
+            CellStyle headerCellStyle = workbook.createCellStyle();
+            headerCellStyle.setFont(headerFont);
+            //开始插入数据的行数
+            int rowNum = 1;
+            //填充数据
+            for(LoginRecordExportVO loginRecordExportVO : loginRecordExportVOS){
+                Row row = sheet.createRow(rowNum++);
+                row.createCell(0).setCellValue(loginRecordExportVO.getTenantName());
+                row.createCell(1).setCellValue(loginRecordExportVO.getPersonnelUserName());
+                row.createCell(2).setCellValue(loginRecordExportVO.getLoginIp());
+                row.createCell(3).setCellValue(loginRecordExportVO.getCreateTime());
+                row.createCell(4).setCellValue(loginRecordExportVO.getLoginResult());
+                row.createCell(5).setCellValue(loginRecordExportVO.getLoginSystemName());
+                row.createCell(6).setCellValue(loginRecordExportVO.getBrowser());
+                row.createCell(7).setCellValue(loginRecordExportVO.getLoginOs());
+            }
+//            //自动调整列宽
+//            for(int i = 0; i < headers.length; i++){
+//                sheet.autoSizeColumn(i);
+//            }
+            sheet.setColumnWidth(0, 256 * 30);
+            sheet.setColumnWidth(1, 256 * 20);
+            sheet.setColumnWidth(2, 256 * 20);
+            sheet.setColumnWidth(3, 256 * 20);
+            sheet.setColumnWidth(4, 256 * 20);
+            sheet.setColumnWidth(5, 256 * 20);
+            sheet.setColumnWidth(6, 256 * 20);
+            sheet.setColumnWidth(7, 256 * 20);
+            workbook.write(fileOut);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 装载登录日志Excel信息
+     * @param queryType
+     * @return
+     */
+    public List<LoginRecordExportVO> loadLoginRecordData(Integer queryType){
+        List<LoginRecordExportVO> loginRecordExportVOS = new ArrayList<>();
+        List<LoginRecord> loginRecords = new ArrayList<>();
+        //获取当前登陆人信息
+//        PersonnelVO personnelVO = cacheUtils.getLoginUser(loginUtils.getId());
+        if(queryType == null || queryType.equals(0)){
+//            Integer id = personnelVO.getId();
+            Integer id = 328;
+            loginRecords = loginRecordService.getLoginRecord(id, queryType);
+        } else if(queryType.equals(1)){
+//            Integer id = personnelVO.getTenantId();
+            Integer id = 1;
+            loginRecords = loginRecordService.getLoginRecord(id, queryType);
+        } else {
+            throw new XiaoShiException("导出失败");
+        }
+        for(LoginRecord loginRecord : loginRecords){
+            LoginRecordExportVO loginRecordExportVO = new LoginRecordExportVO();
+            BeanUtils.copyProperties(loginRecord, loginRecordExportVO);
+            Tenant tenant = tenantService.getById(loginRecord.getTenantId());
+            loginRecordExportVO.setTenantName(tenant.getTenantName());
+            Personnel personnel = personnelService.getById(loginRecord.getPersonnelId());
+            loginRecordExportVO.setPersonnelUserName(personnel.getPersonnelUserName());
+            if(loginRecord.getLoginSystem().equals(0)){
+                loginRecordExportVO.setLoginSystemName("权限系统");
+                loginRecordExportVOS.add(loginRecordExportVO);
+            } else if(loginRecord.getLoginSystem().equals(1)){
+                loginRecordExportVO.setLoginSystemName("分析系统");
+                loginRecordExportVOS.add(loginRecordExportVO);
+            } else if(loginRecord.getLoginSystem().equals(2)){
+                loginRecordExportVO.setLoginSystemName("报告系统");
+                loginRecordExportVOS.add(loginRecordExportVO);
+            }
+        }
+        return loginRecordExportVOS;
+    }
+
+}

+ 80 - 21
PCS/src/main/java/cn/cslg/permission/service/LoginRecordService.java

@@ -1,21 +1,15 @@
 package cn.cslg.permission.service;
 
-import cn.cslg.permission.common.model.vo.DataVO;
-import cn.cslg.permission.common.model.vo.LoginVO;
-import cn.cslg.permission.common.utils.Response;
-import cn.cslg.permission.domain.Data;
-import cn.cslg.permission.domain.Function;
+import cn.cslg.permission.common.model.vo.LoginRecordVO;
 import cn.cslg.permission.domain.LoginRecord;
-import cn.cslg.permission.mapper.DataMapper;
+import cn.cslg.permission.exception.XiaoShiException;
 import cn.cslg.permission.mapper.LoginRecordMapper;
-import cn.cslg.permission.service.associate.RoleFunctionDataService;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.transaction.interceptor.TransactionAspectSupport;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -30,21 +24,86 @@ import java.util.List;
 @RequiredArgsConstructor(onConstructor_ = {@Lazy})
 public class LoginRecordService extends ServiceImpl<LoginRecordMapper,LoginRecord> {
 
-public void addLoginRecord(LoginVO loginVO){
-
-
-
-}
-
-
+    /**
+     * 新增登录日志
+     * @param loginRecordVO
+     */
+    public void addLoginRecord(LoginRecordVO loginRecordVO){
+        if(loginRecordVO != null){
+            LoginRecord loginRecord = new LoginRecord();
+            BeanUtils.copyProperties(loginRecordVO, loginRecord);
+            loginRecord.insert();
+        }
+    }
 
-/*
-根据租户名称/id 人员名称/id 查询登录记录
- */
-    public void getLoginRecord(LoginVO loginVO){
+    /**
+     * 解析操作系统
+     * @param userAgentStr
+     * @return
+     */
+    public static String getOperatingSystem(String userAgentStr){
+        String os = "";
+        if (userAgentStr.contains("Windows")) {
+            os = "Windows";
+        } else if (userAgentStr.contains("Mac")) {
+            os = "Mac OSX";
+        } else if (userAgentStr.contains("Linux")) {
+            os = "Linux";
+        } else if (userAgentStr.contains("Android")) {
+            os = "Android";
+        } else if (userAgentStr.contains("iPhone")) {
+            os = "iOS";
+        }
+        return os;
+    }
 
+    /**
+     * 解析浏览器
+     * @param userAgentStr
+     * @return
+     */
+    public static String getBrowser(String userAgentStr){
+        String browser = "";
+        if (userAgentStr.contains("Chrome")) {
+            browser = "Chrome";
+        } else if (userAgentStr.contains("Safari")) {
+            browser = "Safari";
+        } else if (userAgentStr.contains("Firefox")) {
+            browser = "Firefox";
+        } else if (userAgentStr.contains("Edge")) {
+            browser = "Edge";
+        } else if (userAgentStr.contains("Opera")) {
+            browser = "Opera";
+        } else {
+            browser = "Unknown";
+        }
+        return browser;
+    }
 
 
+    /**
+     * 查询登陆记录,queryType为空或者为0,则根据人员查询,为1,则根据租户查询
+     * @param id
+     * @param queryType
+     * @return
+     */
+    public List<LoginRecord> getLoginRecord(Integer id, Integer queryType){
+        List<LoginRecord> loginRecords = new ArrayList<>();
+        if(id != null && id > 0){
+            LambdaQueryWrapper<LoginRecord> queryWrapper = new LambdaQueryWrapper<>();
+            if(queryType == null || queryType.equals(0)){
+                queryWrapper.eq(LoginRecord::getPersonnelId, id);
+                loginRecords = this.list(queryWrapper);
+                return loginRecords;
+            } else if(queryType.equals(1)){
+                queryWrapper.eq(LoginRecord::getTenantId, id);
+                loginRecords = this.list(queryWrapper);
+                return loginRecords;
+            } else {
+                throw new XiaoShiException("查询类型错误");
+            }
+        } else {
+            throw new XiaoShiException("查询条件不能为空");
+        }
     }
-
 }

+ 41 - 64
PCS/src/main/java/cn/cslg/permission/service/LoginService.java

@@ -1,13 +1,13 @@
 package cn.cslg.permission.service;
 
 import cn.cslg.permission.common.core.base.RedisConf;
+import cn.cslg.permission.common.model.vo.LoginRecordVO;
 import cn.cslg.permission.common.model.vo.LoginVO;
 import cn.cslg.permission.common.model.vo.PersonnelVO;
 import cn.cslg.permission.common.model.vo.RoleVO;
 import cn.cslg.permission.common.utils.*;
 import cn.cslg.permission.common.utils.message.MessageUtils;
 import cn.cslg.permission.domain.Personnel;
-import cn.cslg.permission.domain.ReSetPasswordDTO;
 import cn.cslg.permission.domain.Tenant;
 import cn.cslg.permission.mapper.PersonnelMapper;
 import cn.cslg.permission.service.associate.PerDpService;
@@ -18,14 +18,16 @@ import cn.hutool.captcha.CircleCaptcha;
 import cn.hutool.core.img.ImgUtil;
 import cn.hutool.core.lang.UUID;
 import cn.hutool.crypto.SecureUtil;
+import javax.servlet.http.HttpServletRequest;
+import eu.bitwalker.useragentutils.UserAgent;
+
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 
-import java.text.SimpleDateFormat;
+import javax.servlet.ServletRequest;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 
@@ -35,7 +37,6 @@ import java.util.concurrent.TimeUnit;
  * @description 登录 Service 层
  */
 
-@Slf4j
 @Service
 @RequiredArgsConstructor(onConstructor_ = {@Lazy})
 public class LoginService extends ServiceImpl<PersonnelMapper, Personnel> {
@@ -46,13 +47,17 @@ public class LoginService extends ServiceImpl<PersonnelMapper, Personnel> {
     private final PersonRoleService personRoleService;
     private final PerDpService perDpService;
     private final SystemService systemService;
-
+    private final LoginRecordService loginRecordService;
+    private final HttpServletRequest request;
+    private final ServletRequest request1;
     /**
      * @param loginVO 登录参数类
      * @return 登录成功的信息
      * @author 沈永艺
      */
     public String login(LoginVO loginVO) {
+        LoginRecordVO loginRecordVO = new LoginRecordVO();
+        loginRecordVO.setLoginSystem(loginVO.getLoginSystem());
         //获取已经存放进Redis的验证码 格式: verify-code:uuid(参数)
         String tempCode = redisUtil.get(RedisConf.VERIFY_CODE + RedisConf.SYMBOL_COLON + loginVO.getUuid());
         //为空报错 验证码错误
@@ -68,31 +73,54 @@ public class LoginService extends ServiceImpl<PersonnelMapper, Personnel> {
         if (personnel == null) {
             return Response.error(ResponseEnum.USERNAME_ERROR);
         }
+        //登录日志记录人员id
+        loginRecordVO.setPersonnelId(personnel.getId());
+        //登录日志记录租户id
+        loginRecordVO.setTenantId(personnel.getTenantId());
+        //登录日志记录ip地址
+        loginRecordVO.setLoginIp(request1.getRemoteAddr());
+        String ua = request.getHeader("User-Agent");
+        UserAgent userAgent = UserAgent.parseUserAgentString(ua);
+        System.out.println("-----------------------------------" + loginRecordVO.getLoginIp());
+        System.out.println("-----------------------------------" + userAgent);
+        // 获取客户端操作系统
+        String os = userAgent.getOperatingSystem().getName();
+        // 获取客户端浏览器
+        String browser = userAgent.getBrowser().getName();
+        //登录日志记录操作系统
+        loginRecordVO.setLoginOs(os);
+        //解析浏览器
+        loginRecordVO.setBrowser(browser);
         //校验密码是否正确
         boolean isPassword = personnel.getPersonnelPassword().equals(SecureUtil.md5(loginVO.getPassword()));
         if (!isPassword) {
+            //登录日志记录登录是否成功
+            loginRecordVO.setLoginResult("失败");
+            loginRecordService.addLoginRecord(loginRecordVO);
             return Response.error(ResponseEnum.PASSWORD_ERROR);
         }
         //判断登录人所属的租户是否启用 以及 登录人账号本身是否是启用的
         Tenant tenant = tenantService.getById(personnel.getTenantId());
-        if (tenant.getTenantStatus() != null && tenant.getTenantStatus() != 1) {
+        if (tenant.getTenantStatus() != 1) {
+            //登录日志记录登录是否成功
+            loginRecordVO.setLoginResult("失败");
+            loginRecordService.addLoginRecord(loginRecordVO);
             return Response.error(ResponseEnum.TENANT_STATUS_ERROR);
         }
-        if (personnel.getPersonnelStatus() != null && personnel.getPersonnelStatus() != 1) {
+        if (personnel.getPersonnelStatus() != 1) {
+            //登录日志记录登录是否成功
+            loginRecordVO.setLoginResult("失败");
+            loginRecordService.addLoginRecord(loginRecordVO);
             return Response.error(ResponseEnum.PERSONNEL_STATUS_ERROR);
         }
-        //判断登陆人所属的租户是否过期(截止日期与当前时间比较)
-        if (tenant.getDeadLine() != null && tenant.getDeadLine().compareTo(new Date()) < 0) {
-            return Response.error(ResponseEnum.TENANT_DEADLINE_ERROR);
-        }
-
         //Sa-token 登录方法 登录后 生成Token 如果集成了Redis的话 会自动存入Redis
         StpUtil.login(personnel.getId());
         //填充数据
         PersonnelVO personnelVO = this.pushData(personnel);
         //将用户信息数据存入Redis
         cacheUtils.setLoginUser(personnelVO);
-
+        loginRecordVO.setLoginResult("成功");
+        loginRecordService.addLoginRecord(loginRecordVO);
         return Response.success(personnelVO);
     }
 
@@ -226,55 +254,4 @@ public class LoginService extends ServiceImpl<PersonnelMapper, Personnel> {
         return Response.success(true);
     }
 
-
-    /**
-     * 登录前重置密码
-     *
-     * @param reSetPasswordDTO 人员账号和邮箱
-     */
-    public void reSetPasswordBeforeLogin(ReSetPasswordDTO reSetPasswordDTO) {
-        log.info("开始处理【登录前重置密码】的业务,参数为:{}", reSetPasswordDTO);
-
-        //若账号与邮箱未填写或格式不正确,则返回提示"请正确填写账号与邮箱"
-        if (reSetPasswordDTO.getPersonnelUserName() == null || reSetPasswordDTO.getPersonnelUserName().trim().equals("")
-                || reSetPasswordDTO.getPersonnelEmail() == null || reSetPasswordDTO.getPersonnelEmail().trim().equals("")) {
-            ThrowException.throwXiaoShiException("请正确填写账号与邮箱");
-        }
-
-        //检查账号是否存在,若不存在则返回提示"账号错误,请检查账号是否输入正确"
-        Personnel personnel = this.getOne(new LambdaQueryWrapper<Personnel>().eq(Personnel::getPersonnelUserName, reSetPasswordDTO.getPersonnelUserName()).last("LIMIT 1"));
-        if (personnel == null) {
-            ThrowException.throwXiaoShiException("账号错误,请检查账号是否输入正确");
-            return;
-        }
-
-        //检查邮箱是否存在,若没有邮箱则返回提示"该账号未绑定邮箱无法重置密码,请联系管理员"
-        String personnelEmail = personnel.getPersonnelEmail();
-        if (personnelEmail == null || personnelEmail.trim().equals("")) {
-            ThrowException.throwXiaoShiException("该账号未绑定邮箱无法重置密码,请联系管理员");
-        }
-
-        //检查邮箱是否正确,若错误则返回提示"邮箱不正确,请检查后重新填写"
-        if (!reSetPasswordDTO.getPersonnelEmail().equals(personnelEmail)) {
-            ThrowException.throwXiaoShiException("邮箱不正确,请检查后重新填写");
-        }
-
-        //重置密码,发送邮件通知
-        int tem = (int) ((Math.random() * 9 + 1) * 100000);
-        String newPassword = String.valueOf(tem);
-        personnel.setPersonnelPassword(SecureUtil.md5(newPassword));
-        if (personnel.updateById()) {
-            Map<String, Object> map = new HashMap<>();
-            map.put("title", "密码重置通知");
-            map.put("template", "mail/email.html");
-            map.put("value1", newPassword);
-            map.put("img", "/logo.png");
-            map.put("email", personnel.getPersonnelEmail());
-            map.put("value2", personnel.getPersonnelName());
-            mailUtils.sendEmailMessage(map);
-        }
-
-
-    }
-
 }

+ 18 - 0
PCS/src/main/java/cn/cslg/permission/service/TenantService.java

@@ -22,6 +22,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import io.swagger.v3.oas.models.security.SecurityScheme;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.ss.formula.functions.T;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -254,6 +255,23 @@ public class TenantService extends ServiceImpl<TenantEntityMapper, Tenant> {
         return Response.success(setTenantToVO(tenantPeople));
     }
 
+    /**
+     * 查询租户id和名称
+     * @return
+     */
+    public List<Tenant> getTenantIdAndName(List<Integer> tenantIds) {
+        List<Tenant> tenants = new ArrayList<>();
+        LambdaQueryWrapper<Tenant> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(Tenant::getTenantStatus, 1);
+        if(tenantIds.size() > 0){
+            queryWrapper.in(Tenant::getId,tenantIds);
+            tenants = this.list(queryWrapper);
+        } else {
+            tenants = this.list(queryWrapper);
+        }
+        return tenants;
+    }
+
     public String queryPageList(TenantVO tenantVO) {
         LambdaQueryWrapper<Tenant> lambdaQueryWrapper = new LambdaQueryWrapper<>();