zx 2 ay önce
işleme
df977ac307
100 değiştirilmiş dosya ile 10707 ekleme ve 0 silme
  1. 56 0
      .gitignore
  2. 36 0
      README.en.md
  3. 37 0
      README.md
  4. 199 0
      fs-admin/pom.xml
  5. 33 0
      fs-admin/src/main/java/com/fs/FSAdminApplication.java
  6. 16 0
      fs-admin/src/main/java/com/fs/FSServletInitializer.java
  7. 71 0
      fs-admin/src/main/java/com/fs/api/controller/CompanyAPIController.java
  8. 250 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyController.java
  9. 158 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyDeductController.java
  10. 112 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyDeptController.java
  11. 103 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyLogininforController.java
  12. 103 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyMenuController.java
  13. 147 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyMoneyLogsController.java
  14. 103 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyOperLogController.java
  15. 103 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyPostController.java
  16. 285 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyProfitController.java
  17. 150 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyRechargeController.java
  18. 103 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyRoleController.java
  19. 103 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyRoleDeptController.java
  20. 103 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyRoleMenuController.java
  21. 105 0
      fs-admin/src/main/java/com/fs/company/controller/CompanySmsController.java
  22. 124 0
      fs-admin/src/main/java/com/fs/company/controller/CompanySmsLogsController.java
  23. 106 0
      fs-admin/src/main/java/com/fs/company/controller/CompanySmsOrderController.java
  24. 103 0
      fs-admin/src/main/java/com/fs/company/controller/CompanySmsPackageController.java
  25. 122 0
      fs-admin/src/main/java/com/fs/company/controller/CompanySmsTempController.java
  26. 246 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyStatisticsController.java
  27. 261 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyTcmReportController.java
  28. 130 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyTcmScheduleController.java
  29. 122 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyUserController.java
  30. 103 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyUserPostController.java
  31. 103 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyUserRoleController.java
  32. 106 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceApiController.java
  33. 111 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceBlacklistController.java
  34. 153 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceCallerController.java
  35. 175 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceConfigController.java
  36. 108 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceController.java
  37. 133 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceLogsController.java
  38. 134 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceMobileController.java
  39. 103 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoicePackageController.java
  40. 106 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoicePackageOrderController.java
  41. 66 0
      fs-admin/src/main/java/com/fs/company/controller/IndexController.java
  42. 172 0
      fs-admin/src/main/java/com/fs/core/aspectj/DataScopeAspect.java
  43. 73 0
      fs-admin/src/main/java/com/fs/core/aspectj/DataSourceAspect.java
  44. 218 0
      fs-admin/src/main/java/com/fs/core/aspectj/LogAspect.java
  45. 30 0
      fs-admin/src/main/java/com/fs/core/config/ApplicationConfig.java
  46. 58 0
      fs-admin/src/main/java/com/fs/core/config/ArrayStringTypeHandler.java
  47. 83 0
      fs-admin/src/main/java/com/fs/core/config/CaptchaConfig.java
  48. 103 0
      fs-admin/src/main/java/com/fs/core/config/DataSourceConfig.java
  49. 127 0
      fs-admin/src/main/java/com/fs/core/config/DruidConfig.java
  50. 71 0
      fs-admin/src/main/java/com/fs/core/config/FastJson2JsonRedisSerializer.java
  51. 60 0
      fs-admin/src/main/java/com/fs/core/config/FilterConfig.java
  52. 75 0
      fs-admin/src/main/java/com/fs/core/config/KaptchaTextCreator.java
  53. 107 0
      fs-admin/src/main/java/com/fs/core/config/MyBatisConfig.java
  54. 88 0
      fs-admin/src/main/java/com/fs/core/config/RedisConfig.java
  55. 66 0
      fs-admin/src/main/java/com/fs/core/config/ResourcesConfig.java
  56. 160 0
      fs-admin/src/main/java/com/fs/core/config/SecurityConfig.java
  57. 32 0
      fs-admin/src/main/java/com/fs/core/config/ServerConfig.java
  58. 125 0
      fs-admin/src/main/java/com/fs/core/config/SwaggerConfig.java
  59. 62 0
      fs-admin/src/main/java/com/fs/core/config/ThreadPoolConfig.java
  60. 77 0
      fs-admin/src/main/java/com/fs/core/config/properties/DruidProperties.java
  61. 26 0
      fs-admin/src/main/java/com/fs/core/datasource/DynamicDataSource.java
  62. 45 0
      fs-admin/src/main/java/com/fs/core/datasource/DynamicDataSourceContextHolder.java
  63. 51 0
      fs-admin/src/main/java/com/fs/core/exception/FSException.java
  64. 80 0
      fs-admin/src/main/java/com/fs/core/exception/FSExceptionHandler.java
  65. 55 0
      fs-admin/src/main/java/com/fs/core/interceptor/RepeatSubmitInterceptor.java
  66. 124 0
      fs-admin/src/main/java/com/fs/core/interceptor/impl/SameUrlDataInterceptor.java
  67. 55 0
      fs-admin/src/main/java/com/fs/core/manager/AsyncManager.java
  68. 39 0
      fs-admin/src/main/java/com/fs/core/manager/ShutdownManager.java
  69. 101 0
      fs-admin/src/main/java/com/fs/core/manager/factory/AsyncFactory.java
  70. 69 0
      fs-admin/src/main/java/com/fs/core/security/LoginBody.java
  71. 229 0
      fs-admin/src/main/java/com/fs/core/security/LoginUser.java
  72. 90 0
      fs-admin/src/main/java/com/fs/core/security/SecurityUtils.java
  73. 55 0
      fs-admin/src/main/java/com/fs/core/security/filter/JwtAuthenticationTokenFilter.java
  74. 34 0
      fs-admin/src/main/java/com/fs/core/security/handle/AuthenticationEntryPointImpl.java
  75. 54 0
      fs-admin/src/main/java/com/fs/core/security/handle/LogoutSuccessHandlerImpl.java
  76. 240 0
      fs-admin/src/main/java/com/fs/core/web/domain/Server.java
  77. 101 0
      fs-admin/src/main/java/com/fs/core/web/domain/server/Cpu.java
  78. 122 0
      fs-admin/src/main/java/com/fs/core/web/domain/server/Jvm.java
  79. 61 0
      fs-admin/src/main/java/com/fs/core/web/domain/server/Mem.java
  80. 84 0
      fs-admin/src/main/java/com/fs/core/web/domain/server/Sys.java
  81. 114 0
      fs-admin/src/main/java/com/fs/core/web/domain/server/SysFile.java
  82. 117 0
      fs-admin/src/main/java/com/fs/core/web/exception/GlobalExceptionHandler.java
  83. 170 0
      fs-admin/src/main/java/com/fs/core/web/service/PermissionService.java
  84. 90 0
      fs-admin/src/main/java/com/fs/core/web/service/SysLoginService.java
  85. 66 0
      fs-admin/src/main/java/com/fs/core/web/service/SysPermissionService.java
  86. 240 0
      fs-admin/src/main/java/com/fs/core/web/service/TokenService.java
  87. 60 0
      fs-admin/src/main/java/com/fs/core/web/service/UserDetailsServiceImpl.java
  88. 97 0
      fs-admin/src/main/java/com/fs/course/controller/FsCourseAnswerLogsController.java
  89. 97 0
      fs-admin/src/main/java/com/fs/course/controller/FsCourseDomainNameController.java
  90. 108 0
      fs-admin/src/main/java/com/fs/course/controller/FsCourseLinkController.java
  91. 109 0
      fs-admin/src/main/java/com/fs/course/controller/FsCourseQuestionBankController.java
  92. 123 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseCategoryController.java
  93. 110 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseCommentController.java
  94. 97 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseCommentLikeController.java
  95. 131 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseController.java
  96. 97 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseFavoriteController.java
  97. 97 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseNoteController.java
  98. 97 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseNoteLikeController.java
  99. 97 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseStudyController.java
  100. 97 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseStudyLogController.java

+ 56 - 0
.gitignore

@@ -0,0 +1,56 @@
+# Compiled class file
+
+target/
+#resources/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+#*.yml
+logback.xml
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+*.DS_Store
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+
+#1.配置语法: 以斜杠“/”开头表示目录: 以星号“*”通配多个字符: 以问号“?”通配单个字符 以方括号“[]”包含单个字符的匹配列表: 以叹号“!”表示不忽略(跟踪)匹配到的文件或目录:
+#此外,git 对于 .ignore 配置文件是按行从上到下进行规则匹配的,意味着如果前面的规则匹配的范围更大,则后面的规则将不会生效

+ 36 - 0
README.en.md

@@ -0,0 +1,36 @@
+# yunl_java
+
+#### Description
+yunl_java
+
+#### Software Architecture
+Software architecture description
+
+#### Installation
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### Instructions
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### Contribution
+
+1.  Fork the repository
+2.  Create Feat_xxx branch
+3.  Commit your code
+4.  Create Pull Request
+
+
+#### Gitee Feature
+
+1.  You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
+2.  Gitee blog [blog.gitee.com](https://blog.gitee.com)
+3.  Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
+4.  The most valuable open source project [GVP](https://gitee.com/gvp)
+5.  The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
+6.  The most popular members  [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

+ 37 - 0
README.md

@@ -0,0 +1,37 @@
+# yunl_java
+
+#### 介绍
+yunl_java
+
+#### 软件架构
+软件架构说明
+
+
+#### 安装教程
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### 使用说明
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### 参与贡献
+
+1.  Fork 本仓库
+2.  新建 Feat_xxx 分支
+3.  提交代码
+4.  新建 Pull Request
+
+
+#### 特技
+
+1.  使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
+2.  Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
+3.  你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
+4.  [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
+5.  Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
+6.  Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

+ 199 - 0
fs-admin/pom.xml

@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>fs</artifactId>
+        <groupId>com.fs</groupId>
+        <version>1.1.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>jar</packaging>
+    <artifactId>fs-admin</artifactId>
+    <version>1.1.16</version>
+    <description>
+        后台入口
+    </description>
+
+
+    <dependencies>
+
+        <!-- spring-boot-devtools -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <optional>true</optional> <!-- 表示依赖不会传递 -->
+        </dependency>
+
+        <!-- swagger2-->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+        </dependency>
+
+        <!--防止进入swagger页面报类型转换错误,排除2.9.2中的引用,手动增加1.5.21版本-->
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-annotations</artifactId>
+            <version>1.5.21</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-models</artifactId>
+            <version>1.5.21</version>
+        </dependency>
+
+        <!-- swagger2-UI-->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+        </dependency>
+
+         <!-- Mysql驱动包 -->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+
+        <!-- SpringBoot Web容器 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <!-- SpringBoot 拦截器 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+        <!-- spring security 安全认证 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+        </dependency>
+
+        <!-- 阿里数据库连接池 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+        </dependency>
+
+        <!-- 验证码 -->
+        <dependency>
+            <groupId>com.github.penggle</groupId>
+            <artifactId>kaptcha</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>javax.servlet-api</artifactId>
+                    <groupId>javax.servlet</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- 获取系统信息 -->
+        <dependency>
+            <groupId>com.github.oshi</groupId>
+            <artifactId>oshi-core</artifactId>
+        </dependency>
+
+        <!-- 系统模块-->
+        <dependency>
+            <groupId>com.fs</groupId>
+            <artifactId>fs-service-system</artifactId>
+        </dependency>
+
+        <!-- 定时任务-->
+        <dependency>
+            <groupId>com.fs</groupId>
+            <artifactId>fs-service-quartz</artifactId>
+        </dependency>
+
+        <!-- 代码生成-->
+        <dependency>
+            <groupId>com.fs</groupId>
+            <artifactId>fs-service-generator</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.github.javen205</groupId>
+            <artifactId>IJPay-All</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alipay.sdk</groupId>
+            <artifactId>alipay-sdk-java</artifactId>
+            <version>4.8.62.ALL</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+            <version>3.4.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.30</version>
+            <scope>provided</scope>
+        </dependency>
+
+
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.1.1.RELEASE</version>
+                <configuration>
+                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-war-plugin</artifactId>
+                <version>3.1.0</version>
+                <configuration>
+                    <failOnMissingWebXml>false</failOnMissingWebXml>
+                    <warName>${project.artifactId}</warName>
+                </configuration>
+           </plugin>
+            <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+                <version>1.0.0</version>
+                <configuration>
+                    <imageName>${project.artifactId}:${project.version}</imageName>
+                    <baseImage>kdvolder/jdk8</baseImage>
+                    <maintainer>docker_maven docker_maven@email.com</maintainer>
+                    <workdir>/</workdir>
+                    <cmd>["java", "-version"]</cmd>
+                    <entryPoint>["java", "-jar", "${project.build.finalName}.jar"]</entryPoint>
+                    <!-- 这里是复制 jar 包到 docker 容器指定目录配置 -->
+                    <resources>
+                        <resource>
+                            <targetPath>/</targetPath>
+                            <directory>${project.build.directory}</directory>
+                            <include>${project.build.finalName}.jar</include>
+                        </resource>
+                    </resources>
+                    <dockerHost>http://8.140.143.122:2375</dockerHost>
+                </configuration>
+            </plugin>
+
+        </plugins>
+        <finalName>${project.artifactId}</finalName>
+    </build>
+
+</project>

+ 33 - 0
fs-admin/src/main/java/com/fs/FSAdminApplication.java

@@ -0,0 +1,33 @@
+package com.fs;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+import org.springframework.web.multipart.commons.CommonsMultipartResolver;
+
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * 启动程序
+ */
+@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
+@EnableTransactionManagement
+@EnableAsync
+@EnableCaching
+public class FSAdminApplication
+{
+    public static void main(String[] args)
+    {
+        // System.setProperty("spring.devtools.restart.enabled", "false");
+        SpringApplication.run(FSAdminApplication.class, args);
+        System.out.println("Admin启动成功 \n" );
+    }
+}

+ 16 - 0
fs-admin/src/main/java/com/fs/FSServletInitializer.java

@@ -0,0 +1,16 @@
+package com.fs;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+/**
+ * web容器中进行部署
+ */
+public class FSServletInitializer extends SpringBootServletInitializer
+{
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
+    {
+        return application.sources(FSAdminApplication.class);
+    }
+}

+ 71 - 0
fs-admin/src/main/java/com/fs/api/controller/CompanyAPIController.java

@@ -0,0 +1,71 @@
+package com.fs.api.controller;
+
+import com.fs.api.param.ExpressParam;
+import com.fs.api.param.OrderListParam;
+import com.fs.api.vo.ExpressVO;
+import com.fs.api.vo.OrderListVO;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.common.exception.CustomException;
+import com.fs.company.domain.Company;
+import com.fs.company.service.ICompanyService;
+import com.fs.store.service.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * 订单Controller
+ *
+ * @author fs
+ * @date 2022-03-15
+ */
+@RestController
+@RequestMapping("/api")
+public class CompanyAPIController extends BaseController
+{
+    @Autowired
+    private ICompanyService companyService;
+    @Autowired
+    private IFsStoreOrderService storeOrderService;
+    @Autowired
+    private IFsExpressService expressService;
+
+    private Company checkCompany(HttpServletRequest request){
+        String appId=request.getHeader("appId");
+        String appKey=request.getHeader("appKey");
+        if(appId==null){
+            throw new CustomException("appId不能为空");
+        }
+        if(appKey==null){
+            throw new CustomException("appKey不能为空");
+        }
+        Company company=companyService.selectCompanyByAppId(appId);
+        if(company==null){
+            throw new CustomException("appId不存在");
+        }
+        return company;
+    }
+
+    @GetMapping("/getOrderList")
+    public R getOrderList(OrderListParam param, HttpServletRequest request)
+    {
+        Company company=checkCompany(request);
+        param.setCompanyId(company.getCompanyId());
+        List<OrderListVO> list = storeOrderService.selectCompanyStoreOrderListAPI(param);
+        return R.ok().put("data",list);
+    }
+
+
+    @GetMapping("/getExpressInfo")
+    public R getExpressInfo(ExpressParam param, HttpServletRequest request) {
+        Company company=checkCompany(request);
+        List<ExpressVO> list = expressService.getExpressInfoAPI(param);
+        return R.ok().put("data",list);
+    }
+
+
+
+}

+ 250 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyController.java

@@ -0,0 +1,250 @@
+package com.fs.company.controller;
+
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+import cn.hutool.core.util.IdUtil;
+import com.fs.common.annotation.RepeatSubmit;
+import com.fs.common.core.domain.R;
+import com.fs.common.utils.OrderUtils;
+import com.fs.common.utils.ParseUtils;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.sign.Md5Utils;
+import com.fs.company.domain.*;
+import com.fs.company.param.CompanyDeductParam;
+import com.fs.company.param.CompanyParam;
+import com.fs.company.param.CompanyRechargeParam;
+import com.fs.company.param.CompanyVoiceCallerParam;
+import com.fs.company.service.*;
+import com.fs.company.vo.CompanyCrmVO;
+import com.fs.company.vo.CompanyVO;
+import com.fs.company.vo.CompanyVoiceCallerListVO;
+import com.fs.core.security.LoginUser;
+import com.fs.core.security.SecurityUtils;
+import com.fs.core.web.service.TokenService;
+import lombok.Synchronized;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+import javax.swing.*;
+
+/**
+ * 企业Controller
+ *
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/company")
+public class CompanyController extends BaseController
+{
+    @Autowired
+    private TokenService tokenService;
+    @Autowired
+    private ICompanyService companyService;
+    @Autowired
+    private ICompanyUserService userService;
+    @Autowired
+    private ICompanyRechargeService rechargeService;
+    @Autowired
+    private ICompanyDeductService deductService;
+    @Autowired
+    private ICompanyVoiceCallerService callerService;
+    /**
+     * 查询企业列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:company:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyParam param) throws ParseException {
+        startPage();
+        List<CompanyVO> list = companyService.selectCompanyVOList(param);
+        for (CompanyVO vo : list){
+            vo.setCompanyMobile(ParseUtils.parsePhone(vo.getCompanyMobile()));
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出企业列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:company:export')")
+    @Log(title = "企业", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyParam company)
+    {
+        List<CompanyVO> list = companyService.selectCompanyVOList(company);
+        ExcelUtil<CompanyVO> util = new ExcelUtil<CompanyVO>(CompanyVO.class);
+        return util.exportExcel(list, "company");
+    }
+
+    /**
+     * 获取企业详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:company:query')")
+    @GetMapping(value = "/{companyId}")
+    public AjaxResult getInfo(@PathVariable("companyId") Long companyId)
+    {
+        return AjaxResult.success(companyService.selectCompanyById(companyId));
+    }
+
+    /**
+     * 新增企业
+     */
+    @PreAuthorize("@ss.hasPermi('company:company:add')")
+    @Log(title = "企业", businessType = BusinessType.INSERT)
+    @PostMapping
+    public R add(@RequestBody Company company)
+    {
+        company.setPassword(SecurityUtils.encryptPassword(company.getPassword()));
+        company.setAppId(Md5Utils.hash(company.getUserName()));
+        company.setAppKey(Md5Utils.hash(company.getPassword()));
+        return companyService.insertCompany(company);
+    }
+
+    /**
+     * 修改企业
+     */
+    @PreAuthorize("@ss.hasPermi('company:company:edit')")
+    @Log(title = "企业", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody Company company)
+    {
+        CompanyUser companyUser = new CompanyUser();
+        if (company.getStatus()==0){
+            companyUser.setStatus("1");
+            companyUser.setCompanyId(company.getCompanyId());
+//            companyUser.setUserType("00");
+            userService.updateAllCompanyUser(companyUser);
+            CompanyVoiceCallerParam param = new CompanyVoiceCallerParam();
+            param.setCompanyId(company.getCompanyId());
+            List<CompanyVoiceCallerListVO> list = callerService.selectCompanyVoiceCallerListVO(param);
+            for (CompanyVoiceCallerListVO vo : list){
+                CompanyVoiceCaller caller=callerService.selectCompanyVoiceCallerById(vo.getCallerId());
+                caller.setCompanyId(0L);
+                caller.setCompanyUserId(0L);
+                caller.setMobile("");
+                caller.setStatus(1);
+                callerService.updateCompanyVoiceCaller(caller);
+            }
+        }else {
+            CompanyUser companyUser1 = userService.selectCompanyUserAdminByCompanyId(company.getCompanyId());
+            companyUser1.setStatus("0");
+            userService.updateCompanyUser(companyUser1);
+        }
+        return toAjax(companyService.updateCompany(company));
+    }
+
+
+
+    /**
+     * 删除企业
+     */
+    @PreAuthorize("@ss.hasPermi('company:company:remove')")
+    @Log(title = "企业", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{companyIds}")
+    public AjaxResult remove(@PathVariable Long[] companyIds)
+    {
+        return toAjax(companyService.deleteCompanyByIds(companyIds));
+    }
+
+    @GetMapping("/getCompanyList")
+    public R getCompanyList()
+    {
+        Company map=new Company();
+        map.setIsDel(0);
+        List<Company> list = companyService.selectCompanyList(map);
+        return R.ok().put("data",list);
+    }
+
+//  @PreAuthorize("@ss.hasPermi('company:company:crmDayCountlist')")
+    @GetMapping("/crmDayCountlist")
+    public TableDataInfo companyCrmDayCountList(CompanyParam param)
+    {
+        startPage();
+        List<CompanyCrmVO> list = companyService.selectCompanyCrmDayCountList(param);
+        return getDataTable(list);
+    }
+
+
+
+    @PreAuthorize("@ss.hasPermi('company:company:resetPwd')")
+    @PostMapping("/resetPwd/{companyId}")
+    public AjaxResult resetPwd(@PathVariable Long companyId)
+    {
+        Company company=companyService.selectCompanyById(companyId);
+        return toAjax(userService.resetUserPwdByUserId(company.getUserId(),SecurityUtils.encryptPassword("123456")));
+    }
+
+//    @PreAuthorize("@ss.hasPermi('company:company:resetMoney')")
+//    @PostMapping("/resetMoney/{companyId}")
+//    public R resetMoney(@PathVariable Long companyId)
+//    {
+//        //companyService.resetMoney(companyId);
+//        return R.ok("功能已停用");
+//    }
+
+
+    @PreAuthorize("@ss.hasPermi('company:company:recharge')")
+    @Log(title = "企业转账", businessType = BusinessType.INSERT)
+    @PostMapping(value = "/recharge")
+    @Transactional
+    @RepeatSubmit
+    public R recharge(@RequestBody CompanyRechargeParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        CompanyRecharge recharge=new CompanyRecharge();
+        String orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();
+        recharge.setRechargeNo(orderSn);
+        recharge.setCompanyId(param.getCompanyId());
+        recharge.setMoney(param.getMoney());
+        recharge.setCreateUserId(loginUser.getUser().getUserId());
+        recharge.setIsAudit(0);
+        recharge.setStatus(0);
+        recharge.setRemark(param.getRemark());
+        recharge.setPayType(3);
+        rechargeService.insertCompanyRecharge(recharge);
+        return R.ok("提交成功,等待审核");
+
+    }
+
+    @PreAuthorize("@ss.hasPermi('company:company:deduct')")
+    @Log(title = "企业扣款", businessType = BusinessType.INSERT)
+    @PostMapping(value = "/deduct")
+    @Transactional
+    @RepeatSubmit
+    public R deduct(@RequestBody CompanyDeductParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        CompanyDeduct deduct=new CompanyDeduct();
+        String orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();
+        deduct.setDeductNo(orderSn);
+        deduct.setCompanyId(param.getCompanyId());
+        deduct.setMoney(param.getMoney());
+        deduct.setCreateUserId(loginUser.getUser().getUserId());
+        deduct.setIsAudit(0);
+        deduct.setRemark(param.getRemark());
+        deductService.insertCompanyDeduct(deduct);
+        return R.ok("提交成功,等待审核");
+    }
+
+
+}

+ 158 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyDeductController.java

@@ -0,0 +1,158 @@
+package com.fs.company.controller;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+import com.fs.common.core.domain.R;
+import com.fs.common.utils.ServletUtils;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyMoneyLogs;
+import com.fs.company.domain.CompanyRecharge;
+import com.fs.company.service.ICompanyMoneyLogsService;
+import com.fs.company.service.ICompanyService;
+import com.fs.company.vo.CompanyDeductExportVO;
+import com.fs.company.vo.CompanyDeductVO;
+import com.fs.company.vo.CompanyRechargeVO;
+import com.fs.core.security.LoginUser;
+import com.fs.core.web.service.TokenService;
+import lombok.Synchronized;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyDeduct;
+import com.fs.company.service.ICompanyDeductService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 扣款Controller
+ *
+ * @author fs
+ * @date 2023-02-27
+ */
+@RestController
+@RequestMapping("/company/companyDeduct")
+public class CompanyDeductController extends BaseController
+{
+    @Autowired
+    private ICompanyDeductService companyDeductService;
+    @Autowired
+    private TokenService tokenService;
+    @Autowired
+    private ICompanyService companyService;
+    @Autowired
+    private ICompanyMoneyLogsService moneyLogsService;
+    /**
+     * 查询扣款列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyDeduct:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyDeduct companyDeduct)
+    {
+        startPage();
+        List<CompanyDeductVO> list = companyDeductService.selectCompanyDeductVOList(companyDeduct);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出扣款列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyDeduct:export')")
+    @Log(title = "扣款", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyDeduct companyDeduct)
+    {
+        List<CompanyDeductExportVO> list = companyDeductService.selectCompanyExportDeductList(companyDeduct);
+        ExcelUtil<CompanyDeductExportVO> util = new ExcelUtil<CompanyDeductExportVO>(CompanyDeductExportVO.class);
+        return util.exportExcel(list, "companyDeduct");
+    }
+
+    /**
+     * 获取扣款详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyDeduct:query')")
+    @GetMapping(value = "/{deductId}")
+    public AjaxResult getInfo(@PathVariable("deductId") Long deductId)
+    {
+        return AjaxResult.success(companyDeductService.selectCompanyDeductById(deductId));
+    }
+
+    /**
+     * 新增扣款
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyDeduct:add')")
+    @Log(title = "扣款", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyDeduct companyDeduct)
+    {
+        return toAjax(companyDeductService.insertCompanyDeduct(companyDeduct));
+    }
+
+    /**
+     * 修改扣款
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyDeduct:edit')")
+    @Log(title = "扣款", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyDeduct companyDeduct)
+    {
+        return toAjax(companyDeductService.updateCompanyDeduct(companyDeduct));
+    }
+
+    /**
+     * 删除扣款
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyDeduct:remove')")
+    @Log(title = "扣款", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{deductIds}")
+    public AjaxResult remove(@PathVariable Long[] deductIds)
+    {
+        return toAjax(companyDeductService.deleteCompanyDeductByIds(deductIds));
+    }
+
+
+    @PreAuthorize("@ss.hasPermi('company:companyDeduct:audit')")
+    @PostMapping("/audit")
+    @Transactional
+    public R audit(@RequestBody CompanyDeduct param)
+    {
+        CompanyDeduct deduct=companyDeductService.selectCompanyDeductById(param.getDeductId());
+        if(deduct.getIsAudit()!=0){
+            return R.error("非法操作");
+        }
+        deduct.setIsAudit(param.getIsAudit());
+        deduct.setRemark(param.getRemark());
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if(deduct.getIsAudit()==1){
+            Company company=companyService.selectCompanyByIdForUpdate(deduct.getCompanyId());
+            company.setMoney(company.getMoney().subtract(deduct.getMoney()));
+            companyService.updateCompany(company);
+            CompanyMoneyLogs log=new CompanyMoneyLogs();
+            log.setCompanyId(deduct.getCompanyId());
+            log.setMoney(deduct.getMoney().multiply(new BigDecimal(-1)));
+            log.setRemark(deduct.getRemark());
+            log.setLogsType(2);
+            log.setBalance(company.getMoney());
+            log.setCreateTime(new Date());
+            moneyLogsService.insertCompanyMoneyLogs(log);
+        }
+        deduct.setAuditTime(new Date());
+        deduct.setAuditUserId(loginUser.getUser().getUserId());
+        companyDeductService.updateCompanyDeduct(deduct);
+        return R.ok("操作成功");
+
+    }
+}

+ 112 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyDeptController.java

@@ -0,0 +1,112 @@
+package com.fs.company.controller;
+
+import java.util.List;
+
+import com.fs.common.utils.ServletUtils;
+import com.fs.core.security.LoginUser;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyDept;
+import com.fs.company.service.ICompanyDeptService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+
+@RestController
+@RequestMapping("/company/companyDept")
+public class CompanyDeptController extends BaseController
+{
+    @Autowired
+    private ICompanyDeptService companyDeptService;
+
+    /**
+     * 查询部门列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyDept:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyDept companyDept)
+    {
+        startPage();
+        List<CompanyDept> list = companyDeptService.selectCompanyDeptList(companyDept);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出部门列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyDept:export')")
+    @Log(title = "部门", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyDept companyDept)
+    {
+        List<CompanyDept> list = companyDeptService.selectCompanyDeptList(companyDept);
+        ExcelUtil<CompanyDept> util = new ExcelUtil<CompanyDept>(CompanyDept.class);
+        return util.exportExcel(list, "companyDept");
+    }
+
+    /**
+     * 获取部门详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyDept:query')")
+    @GetMapping(value = "/{deptId}")
+    public AjaxResult getInfo(@PathVariable("deptId") Long deptId)
+    {
+        return AjaxResult.success(companyDeptService.selectCompanyDeptById(deptId));
+    }
+
+    /**
+     * 新增部门
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyDept:add')")
+    @Log(title = "部门", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyDept companyDept)
+    {
+        return toAjax(companyDeptService.insertCompanyDept(companyDept));
+    }
+
+    /**
+     * 修改部门
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyDept:edit')")
+    @Log(title = "部门", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyDept companyDept)
+    {
+        return toAjax(companyDeptService.updateCompanyDept(companyDept));
+    }
+
+    /**
+     * 删除部门
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyDept:remove')")
+    @Log(title = "部门", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{deptIds}")
+    public AjaxResult remove(@PathVariable Long[] deptIds)
+    {
+        return toAjax(companyDeptService.deleteCompanyDeptByIds(deptIds));
+    }
+
+    /**
+     * 获取部门下拉树列表
+     */
+    @GetMapping("/treeselect")
+    public AjaxResult treeselect(CompanyDept dept)
+    {
+        dept.setStatus("0");
+        List<CompanyDept> depts = companyDeptService.selectCompanyDeptList(dept);
+        return AjaxResult.success(companyDeptService.buildDeptTreeSelect(depts));
+    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyLogininforController.java

@@ -0,0 +1,103 @@
+package com.fs.company.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyLogininfor;
+import com.fs.company.service.ICompanyLogininforService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 系统访问记录Controller
+ * 
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/companyLogininfor")
+public class CompanyLogininforController extends BaseController
+{
+    @Autowired
+    private ICompanyLogininforService companyLogininforService;
+
+    /**
+     * 查询系统访问记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyLogininfor:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyLogininfor companyLogininfor)
+    {
+        startPage();
+        List<CompanyLogininfor> list = companyLogininforService.selectCompanyLogininforList(companyLogininfor);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出系统访问记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyLogininfor:export')")
+    @Log(title = "系统访问记录", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyLogininfor companyLogininfor)
+    {
+        List<CompanyLogininfor> list = companyLogininforService.selectCompanyLogininforList(companyLogininfor);
+        ExcelUtil<CompanyLogininfor> util = new ExcelUtil<CompanyLogininfor>(CompanyLogininfor.class);
+        return util.exportExcel(list, "companyLogininfor");
+    }
+
+    /**
+     * 获取系统访问记录详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyLogininfor:query')")
+    @GetMapping(value = "/{infoId}")
+    public AjaxResult getInfo(@PathVariable("infoId") Long infoId)
+    {
+        return AjaxResult.success(companyLogininforService.selectCompanyLogininforById(infoId));
+    }
+
+    /**
+     * 新增系统访问记录
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyLogininfor:add')")
+    @Log(title = "系统访问记录", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyLogininfor companyLogininfor)
+    {
+        return toAjax(companyLogininforService.insertCompanyLogininfor(companyLogininfor));
+    }
+
+    /**
+     * 修改系统访问记录
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyLogininfor:edit')")
+    @Log(title = "系统访问记录", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyLogininfor companyLogininfor)
+    {
+        return toAjax(companyLogininforService.updateCompanyLogininfor(companyLogininfor));
+    }
+
+    /**
+     * 删除系统访问记录
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyLogininfor:remove')")
+    @Log(title = "系统访问记录", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{infoIds}")
+    public AjaxResult remove(@PathVariable Long[] infoIds)
+    {
+        return toAjax(companyLogininforService.deleteCompanyLogininforByIds(infoIds));
+    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyMenuController.java

@@ -0,0 +1,103 @@
+package com.fs.company.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyMenu;
+import com.fs.company.service.ICompanyMenuService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 菜单权限Controller
+ * 
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/companyMenu")
+public class CompanyMenuController extends BaseController
+{
+    @Autowired
+    private ICompanyMenuService companyMenuService;
+
+    /**
+     * 查询菜单权限列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyMenu:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyMenu companyMenu)
+    {
+        startPage();
+        List<CompanyMenu> list = companyMenuService.selectCompanyMenuList(companyMenu);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出菜单权限列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyMenu:export')")
+    @Log(title = "菜单权限", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyMenu companyMenu)
+    {
+        List<CompanyMenu> list = companyMenuService.selectCompanyMenuList(companyMenu);
+        ExcelUtil<CompanyMenu> util = new ExcelUtil<CompanyMenu>(CompanyMenu.class);
+        return util.exportExcel(list, "companyMenu");
+    }
+
+    /**
+     * 获取菜单权限详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyMenu:query')")
+    @GetMapping(value = "/{menuId}")
+    public AjaxResult getInfo(@PathVariable("menuId") Long menuId)
+    {
+        return AjaxResult.success(companyMenuService.selectCompanyMenuById(menuId));
+    }
+
+    /**
+     * 新增菜单权限
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyMenu:add')")
+    @Log(title = "菜单权限", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyMenu companyMenu)
+    {
+        return toAjax(companyMenuService.insertCompanyMenu(companyMenu));
+    }
+
+    /**
+     * 修改菜单权限
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyMenu:edit')")
+    @Log(title = "菜单权限", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyMenu companyMenu)
+    {
+        return toAjax(companyMenuService.updateCompanyMenu(companyMenu));
+    }
+
+    /**
+     * 删除菜单权限
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyMenu:remove')")
+    @Log(title = "菜单权限", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{menuIds}")
+    public AjaxResult remove(@PathVariable Long[] menuIds)
+    {
+        return toAjax(companyMenuService.deleteCompanyMenuByIds(menuIds));
+    }
+}

+ 147 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyMoneyLogsController.java

@@ -0,0 +1,147 @@
+package com.fs.company.controller;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+import com.fs.common.annotation.RepeatSubmit;
+import com.fs.common.core.domain.R;
+import com.fs.common.utils.ParseUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.company.domain.Company;
+
+import com.fs.company.param.CompanyMoneyLogsParam;
+import com.fs.company.service.ICompanyService;
+import com.fs.company.vo.CompanyMoneyLogsExport1VO;
+import com.fs.company.vo.CompanyMoneyLogsExport2VO;
+import com.fs.company.vo.CompanyMoneyLogsExportVO;
+import com.fs.company.vo.CompanyMoneyLogsVO;
+import com.fs.voice.utils.StringUtil;
+import org.aspectj.weaver.loadtime.Aj;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyMoneyLogs;
+import com.fs.company.service.ICompanyMoneyLogsService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 企业账户记录Controller
+ *
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/companyMoneyLogs")
+public class CompanyMoneyLogsController extends BaseController
+{
+    @Autowired
+    private ICompanyMoneyLogsService companyMoneyLogsService;
+    @Autowired
+    private ICompanyService companyService;
+    /**
+     * 查询企业账户记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogs:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyMoneyLogsParam companyMoneyLogs)
+    {
+        startPage();
+        if(companyMoneyLogs.getLogsType()!=null){
+            if(companyMoneyLogs.getLogsType()==4 || companyMoneyLogs.getLogsType()==5){
+                List<CompanyMoneyLogsVO> list = companyMoneyLogsService.selectCompanyMoneyLogsMallVOList(companyMoneyLogs);
+                return getDataTable(list);
+            }
+            if(companyMoneyLogs.getLogsType()==8 || companyMoneyLogs.getLogsType()==9){
+                List<CompanyMoneyLogsVO> list = companyMoneyLogsService.selectCompanyMoneyLogsMallVO1List(companyMoneyLogs);
+                return getDataTable(list);
+            }
+        }
+        List<CompanyMoneyLogsVO> list = companyMoneyLogsService.selectCompanyMoneyLogsVOList(companyMoneyLogs);
+        return getDataTable(list);
+    }
+
+
+    //转账记录
+    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogs:list1')")
+    @GetMapping("/list1")
+
+    public TableDataInfo list1(CompanyMoneyLogsParam companyMoneyLogs)
+    {
+        startPage();
+        companyMoneyLogs.setLogsType(1);
+        List<CompanyMoneyLogsVO> list = companyMoneyLogsService.selectCompanyMoneyLogsVOList(companyMoneyLogs);
+        return getDataTable(list);
+    }
+    //转账记录
+    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogs:list2')")
+    @GetMapping("/list2")
+
+    public TableDataInfo list2(CompanyMoneyLogsParam companyMoneyLogs) {
+        startPage();
+        companyMoneyLogs.setLogsType(2);
+        List<CompanyMoneyLogsVO> list = companyMoneyLogsService.selectCompanyMoneyLogsVOList(companyMoneyLogs);
+        return getDataTable(list);
+    }
+    //扣款
+    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogs:list3')")
+    @GetMapping("/list3")
+    public TableDataInfo list3(CompanyMoneyLogsParam companyMoneyLogs) {
+        startPage();
+        companyMoneyLogs.setLogsType(3);
+        List<CompanyMoneyLogsVO> list = companyMoneyLogsService.selectCompanyMoneyLogsVOList(companyMoneyLogs);
+        return getDataTable(list);
+    }
+    /**
+     * 导出企业账户记录列表
+     */
+    @PreAuthorize("@ss.hasAnyPermi('company:companyMoneyLogs:export,company:companyMoneyLogs:export1,company:companyMoneyLogs:export2')")
+    @Log(title = "企业账户记录", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyMoneyLogs companyMoneyLogs)
+    {
+        if(companyMoneyLogs.getType()==0){
+            List<CompanyMoneyLogsExportVO> list = companyMoneyLogsService.selectCompanyMoneyLogsExportVOList(companyMoneyLogs);
+            ExcelUtil<CompanyMoneyLogsExportVO> util = new ExcelUtil<CompanyMoneyLogsExportVO>(CompanyMoneyLogsExportVO.class);
+            return util.exportExcel(list, "全部流水");
+        }
+        else if(companyMoneyLogs.getType()==1){
+            List<CompanyMoneyLogsExport1VO> list = companyMoneyLogsService.selectCompanyMoneyLogsExport1VOList(companyMoneyLogs);
+            for (CompanyMoneyLogsExport1VO vo : list){
+                vo.setUserPhone(ParseUtils.parsePhone(vo.getUserPhone()));
+                vo.setUserAddress(ParseUtils.parseAddress(vo.getUserAddress()));
+            }
+            ExcelUtil<CompanyMoneyLogsExport1VO> util = new ExcelUtil<CompanyMoneyLogsExport1VO>(CompanyMoneyLogsExport1VO.class);
+            return util.exportExcel(list, "商城订单");
+        }
+        else if(companyMoneyLogs.getType()==2){
+            List<CompanyMoneyLogsExport2VO> list = companyMoneyLogsService.selectCompanyMoneyLogsExport2VOList(companyMoneyLogs);
+            ExcelUtil<CompanyMoneyLogsExport2VO> util = new ExcelUtil<CompanyMoneyLogsExport2VO>(CompanyMoneyLogsExport2VO.class);
+            return util.exportExcel(list, "收款订单");
+        }
+        return new AjaxResult(500,"操作失败");
+    }
+
+    /**
+     * 获取企业账户记录详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogs:query')")
+    @GetMapping(value = "/{logsId}")
+    public AjaxResult getInfo(@PathVariable("logsId") Long logsId) {
+        return AjaxResult.success(companyMoneyLogsService.selectCompanyMoneyLogsById(logsId));
+    }
+
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyOperLogController.java

@@ -0,0 +1,103 @@
+package com.fs.company.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyOperLog;
+import com.fs.company.service.ICompanyOperLogService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 操作日志记录Controller
+ * 
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/companyOperLog")
+public class CompanyOperLogController extends BaseController
+{
+    @Autowired
+    private ICompanyOperLogService companyOperLogService;
+
+    /**
+     * 查询操作日志记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyOperLog:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyOperLog companyOperLog)
+    {
+        startPage();
+        List<CompanyOperLog> list = companyOperLogService.selectCompanyOperLogList(companyOperLog);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出操作日志记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyOperLog:export')")
+    @Log(title = "操作日志记录", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyOperLog companyOperLog)
+    {
+        List<CompanyOperLog> list = companyOperLogService.selectCompanyOperLogList(companyOperLog);
+        ExcelUtil<CompanyOperLog> util = new ExcelUtil<CompanyOperLog>(CompanyOperLog.class);
+        return util.exportExcel(list, "companyOperLog");
+    }
+
+    /**
+     * 获取操作日志记录详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyOperLog:query')")
+    @GetMapping(value = "/{operId}")
+    public AjaxResult getInfo(@PathVariable("operId") Long operId)
+    {
+        return AjaxResult.success(companyOperLogService.selectCompanyOperLogById(operId));
+    }
+
+    /**
+     * 新增操作日志记录
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyOperLog:add')")
+    @Log(title = "操作日志记录", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyOperLog companyOperLog)
+    {
+        return toAjax(companyOperLogService.insertCompanyOperLog(companyOperLog));
+    }
+
+    /**
+     * 修改操作日志记录
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyOperLog:edit')")
+    @Log(title = "操作日志记录", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyOperLog companyOperLog)
+    {
+        return toAjax(companyOperLogService.updateCompanyOperLog(companyOperLog));
+    }
+
+    /**
+     * 删除操作日志记录
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyOperLog:remove')")
+    @Log(title = "操作日志记录", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{operIds}")
+    public AjaxResult remove(@PathVariable Long[] operIds)
+    {
+        return toAjax(companyOperLogService.deleteCompanyOperLogByIds(operIds));
+    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyPostController.java

@@ -0,0 +1,103 @@
+package com.fs.company.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyPost;
+import com.fs.company.service.ICompanyPostService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 岗位信息Controller
+ * 
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/companyPost")
+public class CompanyPostController extends BaseController
+{
+    @Autowired
+    private ICompanyPostService companyPostService;
+
+    /**
+     * 查询岗位信息列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyPost:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyPost companyPost)
+    {
+        startPage();
+        List<CompanyPost> list = companyPostService.selectCompanyPostList(companyPost);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出岗位信息列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyPost:export')")
+    @Log(title = "岗位信息", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyPost companyPost)
+    {
+        List<CompanyPost> list = companyPostService.selectCompanyPostList(companyPost);
+        ExcelUtil<CompanyPost> util = new ExcelUtil<CompanyPost>(CompanyPost.class);
+        return util.exportExcel(list, "companyPost");
+    }
+
+    /**
+     * 获取岗位信息详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyPost:query')")
+    @GetMapping(value = "/{postId}")
+    public AjaxResult getInfo(@PathVariable("postId") Long postId)
+    {
+        return AjaxResult.success(companyPostService.selectCompanyPostById(postId));
+    }
+
+    /**
+     * 新增岗位信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyPost:add')")
+    @Log(title = "岗位信息", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyPost companyPost)
+    {
+        return toAjax(companyPostService.insertCompanyPost(companyPost));
+    }
+
+    /**
+     * 修改岗位信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyPost:edit')")
+    @Log(title = "岗位信息", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyPost companyPost)
+    {
+        return toAjax(companyPostService.updateCompanyPost(companyPost));
+    }
+
+    /**
+     * 删除岗位信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyPost:remove')")
+    @Log(title = "岗位信息", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{postIds}")
+    public AjaxResult remove(@PathVariable Long[] postIds)
+    {
+        return toAjax(companyPostService.deleteCompanyPostByIds(postIds));
+    }
+}

+ 285 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyProfitController.java

@@ -0,0 +1,285 @@
+package com.fs.company.controller;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.fs.common.core.domain.R;
+import com.fs.common.utils.ServletUtils;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyMoneyLogs;
+import com.fs.company.domain.CompanyProfitLogs;
+import com.fs.company.param.CompanyProfitAuditParam;
+import com.fs.company.service.ICompanyMoneyLogsService;
+import com.fs.company.service.ICompanyProfitLogsService;
+import com.fs.company.service.ICompanyService;
+import com.fs.company.vo.CompanyProfitVO;
+import com.fs.core.security.LoginUser;
+import com.fs.core.web.service.TokenService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.parameters.P;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyProfit;
+import com.fs.company.service.ICompanyProfitService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 提现Controller
+ *
+ * @author fs
+ * @date 2022-07-04
+ */
+@RestController
+@RequestMapping("/company/companyProfit")
+public class CompanyProfitController extends BaseController
+{
+    @Autowired
+    private ICompanyProfitService companyProfitService;
+    @Autowired
+    private ICompanyService companyService;
+    @Autowired
+    private ICompanyMoneyLogsService moneyLogsService;
+    @Autowired
+    private ICompanyProfitLogsService logsService;
+    @Autowired
+    private TokenService tokenService;
+    /**
+     * 查询提现列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyProfit:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyProfit companyProfit)
+    {
+        startPage();
+        List<CompanyProfitVO> list = companyProfitService.selectCompanyProfitListVO(companyProfit);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出提现列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyProfit:export')")
+    @Log(title = "提现", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyProfit companyProfit)
+    {
+        List<CompanyProfitVO> list = companyProfitService.selectCompanyProfitListVO(companyProfit);
+        ExcelUtil<CompanyProfitVO> util = new ExcelUtil<CompanyProfitVO>(CompanyProfitVO.class);
+        return util.exportExcel(list, "公司提现记录");
+    }
+
+    /**
+     * 获取提现详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyProfit:query')")
+    @GetMapping(value = "/{profitId}")
+    public R getInfo(@PathVariable("profitId") Long profitId)
+    {
+        CompanyProfit profit=companyProfitService.selectCompanyProfitById(profitId);
+        CompanyProfitLogs map=new CompanyProfitLogs();
+        map.setProfitId(profitId);
+        List<CompanyProfitLogs> logs= logsService.selectCompanyProfitLogsList(map);
+        return R.ok().put("profit",profit).put("logs",logs);
+    }
+
+    /**
+     * 新增提现
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyProfit:add')")
+    @Log(title = "提现", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyProfit companyProfit)
+    {
+        return toAjax(companyProfitService.insertCompanyProfit(companyProfit));
+    }
+
+    /**
+     * 修改提现
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyProfit:edit')")
+    @Log(title = "提现", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyProfit companyProfit)
+    {
+        return toAjax(companyProfitService.updateCompanyProfit(companyProfit));
+    }
+
+    /**
+     * 删除提现
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyProfit:remove')")
+    @Log(title = "提现", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{profitIds}")
+    public AjaxResult remove(@PathVariable Long[] profitIds)
+    {
+        return toAjax(companyProfitService.deleteCompanyProfitByIds(profitIds));
+    }
+
+    @PreAuthorize("@ss.hasPermi('company:companyProfit:audit1')")
+    @PostMapping("/audit1")
+    @Transactional
+    public R audit1(@RequestBody CompanyProfitAuditParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        CompanyProfit profit=companyProfitService.selectCompanyProfitById(param.getProfitId());
+        if(profit.getProfitStatus()!=1){
+            return R.error("非法操作");
+        }
+        Company company=companyService.selectCompanyByIdForUpdate(profit.getCompanyId());
+        if(param.getStatus()==1){
+            profit.setRemark(param.getRemark());
+            profit.setProfitStatus(2);
+            profit.setUpdateTime(new Date());
+            companyProfitService.updateCompanyProfit(profit);
+            CompanyProfitLogs logs=new CompanyProfitLogs();
+            logs.setProfitId(profit.getProfitId());
+            logs.setReason(param.getRemark());
+            logs.setCreateTime(new Date());
+            logs.setTitle(loginUser.getUser().getNickName()+"审核通过");
+            logsService.insertCompanyProfitLogs(logs);
+        }
+        else if(param.getStatus()==0){
+            //驳回退款
+            profit.setRemark(param.getRemark());
+            profit.setProfitStatus(0);
+            profit.setUpdateTime(new Date());
+            companyProfitService.updateCompanyProfit(profit);
+            company.setMoney(company.getMoney().add(profit.getMoney()));
+            companyService.updateCompany(company);
+            CompanyMoneyLogs logs=new CompanyMoneyLogs();
+            logs.setCompanyId(company.getCompanyId());
+            logs.setMoney(profit.getMoney());
+            logs.setLogsType(7);
+            logs.setBalance(company.getMoney());
+            logs.setRemark("驳回退款:"+profit.getMoney());
+            logs.setCreateTime(new Date());
+            moneyLogsService.insertCompanyMoneyLogs(logs);
+
+            CompanyProfitLogs profitLogs=new CompanyProfitLogs();
+            profitLogs.setProfitId(profit.getProfitId());
+            profitLogs.setReason(param.getRemark());
+            profitLogs.setCreateTime(new Date());
+            profitLogs.setTitle(loginUser.getUser().getNickName()+"驳回退款");
+            logsService.insertCompanyProfitLogs(profitLogs);
+        }
+        return R.ok("操作成功");
+    }
+
+    @PreAuthorize("@ss.hasPermi('company:companyProfit:audit2')")
+    @PostMapping("/audit2")
+    @Transactional
+    public R audit2(@RequestBody CompanyProfitAuditParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        CompanyProfit profit=companyProfitService.selectCompanyProfitById(param.getProfitId());
+        if(profit.getProfitStatus()!=2){
+            return R.error("非法操作");
+        }
+        Company company=companyService.selectCompanyByIdForUpdate(profit.getCompanyId());
+        if(param.getStatus()==1){
+            profit.setRemark(param.getRemark());
+            profit.setProfitStatus(3);
+            profit.setUpdateTime(new Date());
+            companyProfitService.updateCompanyProfit(profit);
+            CompanyProfitLogs logs=new CompanyProfitLogs();
+            logs.setProfitId(profit.getProfitId());
+            logs.setReason(param.getRemark());
+            logs.setCreateTime(new Date());
+            logs.setTitle(loginUser.getUser().getNickName()+"审核通过");
+            logsService.insertCompanyProfitLogs(logs);
+        }
+        else if(param.getStatus()==0){
+            //驳回退款
+            profit.setRemark(param.getRemark());
+            profit.setProfitStatus(0);
+            profit.setUpdateTime(new Date());
+            companyProfitService.updateCompanyProfit(profit);
+            company.setMoney(company.getMoney().add(profit.getMoney()));
+            companyService.updateCompany(company);
+            CompanyMoneyLogs logs=new CompanyMoneyLogs();
+            logs.setCompanyId(company.getCompanyId());
+            logs.setMoney(profit.getMoney());
+            logs.setLogsType(7);
+            logs.setBalance(company.getMoney());
+            logs.setRemark("驳回退款:"+profit.getMoney());
+            logs.setCreateTime(new Date());
+            moneyLogsService.insertCompanyMoneyLogs(logs);
+
+            CompanyProfitLogs profitLogs=new CompanyProfitLogs();
+            profitLogs.setProfitId(profit.getProfitId());
+            profitLogs.setReason(param.getRemark());
+            profitLogs.setCreateTime(new Date());
+            profitLogs.setTitle(loginUser.getUser().getNickName()+"驳回退款");
+            logsService.insertCompanyProfitLogs(profitLogs);
+        }
+        return R.ok("操作成功");
+    }
+
+    @PreAuthorize("@ss.hasPermi('company:companyProfit:audit3')")
+    @PostMapping("/audit3")
+    @Transactional
+    public R audit3(@RequestBody CompanyProfitAuditParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        CompanyProfit profit=companyProfitService.selectCompanyProfitById(param.getProfitId());
+        if(profit.getProfitStatus()!=3){
+            return R.error("非法操作");
+        }
+        Company company=companyService.selectCompanyByIdForUpdate(profit.getCompanyId());
+        if(param.getStatus()==1){
+            profit.setRemark(param.getRemark());
+            profit.setProfitStatus(4);
+            profit.setUpdateTime(new Date());
+            profit.setImgUrl(param.getImgUrl());
+            companyProfitService.updateCompanyProfit(profit);
+            CompanyProfitLogs logs=new CompanyProfitLogs();
+            logs.setProfitId(profit.getProfitId());
+            logs.setReason(param.getRemark());
+            logs.setCreateTime(new Date());
+            logs.setTitle(loginUser.getUser().getNickName()+"审核通过");
+            logsService.insertCompanyProfitLogs(logs);
+        }
+        else if(param.getStatus()==0){
+            //驳回退款
+            profit.setRemark(param.getRemark());
+            profit.setProfitStatus(0);
+            profit.setUpdateTime(new Date());
+            companyProfitService.updateCompanyProfit(profit);
+            company.setMoney(company.getMoney().add(profit.getMoney()));
+            companyService.updateCompany(company);
+            CompanyMoneyLogs logs=new CompanyMoneyLogs();
+            logs.setCompanyId(company.getCompanyId());
+            logs.setMoney(profit.getMoney());
+            logs.setLogsType(7);
+            logs.setBalance(company.getMoney());
+            logs.setRemark("驳回退款:"+profit.getMoney());
+            logs.setCreateTime(new Date());
+            moneyLogsService.insertCompanyMoneyLogs(logs);
+
+            CompanyProfitLogs profitLogs=new CompanyProfitLogs();
+            profitLogs.setProfitId(profit.getProfitId());
+            profitLogs.setReason(param.getRemark());
+            profitLogs.setCreateTime(new Date());
+            profitLogs.setTitle(loginUser.getUser().getNickName()+"驳回退款");
+            logsService.insertCompanyProfitLogs(profitLogs);
+        }
+        return R.ok("操作成功");
+    }
+
+
+}

+ 150 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyRechargeController.java

@@ -0,0 +1,150 @@
+package com.fs.company.controller;
+
+import java.util.Date;
+import java.util.List;
+
+import com.fs.common.core.domain.R;
+import com.fs.common.utils.ServletUtils;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyMoneyLogs;
+import com.fs.company.service.ICompanyMoneyLogsService;
+import com.fs.company.service.ICompanyService;
+import com.fs.company.vo.CompanyRechargeExportVO;
+import com.fs.company.vo.CompanyRechargeVO;
+import com.fs.core.security.LoginUser;
+import com.fs.core.web.service.TokenService;
+import lombok.Synchronized;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyRecharge;
+import com.fs.company.service.ICompanyRechargeService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 充值Controller
+ *
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/companyRecharge")
+public class CompanyRechargeController extends BaseController
+{
+    @Autowired
+    private TokenService tokenService;
+    @Autowired
+    private ICompanyRechargeService companyRechargeService;
+    @Autowired
+    private ICompanyService companyService;
+    @Autowired
+    private ICompanyMoneyLogsService moneyLogsService;
+    /**
+     * 查询充值列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRecharge:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyRecharge companyRecharge)
+    {
+        startPage();
+        List<CompanyRechargeVO> list = companyRechargeService.selectCompanyRechargeVOList(companyRecharge);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出充值列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRecharge:export')")
+    @Log(title = "充值", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyRecharge companyRecharge)
+    {
+        List<CompanyRechargeExportVO> list = companyRechargeService.selectCompanyRechargeExportList(companyRecharge);
+        ExcelUtil<CompanyRechargeExportVO> util = new ExcelUtil<CompanyRechargeExportVO>(CompanyRechargeExportVO.class);
+        return util.exportExcel(list, "公司充值明细");
+    }
+
+    /**
+     * 获取充值详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRecharge:query')")
+    @GetMapping(value = "/{rechargeId}")
+    public AjaxResult getInfo(@PathVariable("rechargeId") Long rechargeId)
+    {
+        return AjaxResult.success(companyRechargeService.selectCompanyRechargeById(rechargeId));
+    }
+
+    /**
+     * 新增充值
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRecharge:add')")
+    @Log(title = "充值", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyRecharge companyRecharge)
+    {
+        return toAjax(companyRechargeService.insertCompanyRecharge(companyRecharge));
+    }
+
+
+
+    /**
+     * 删除充值
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRecharge:remove')")
+    @Log(title = "充值", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{rechargeIds}")
+    public AjaxResult remove(@PathVariable Long[] rechargeIds)
+    {
+        return toAjax(companyRechargeService.deleteCompanyRechargeByIds(rechargeIds));
+    }
+
+
+
+    @PreAuthorize("@ss.hasPermi('company:companyRecharge:audit')")
+    @PostMapping("/audit")
+    @Transactional
+    @Synchronized
+    public R audit(@RequestBody CompanyRecharge param)
+    {
+        CompanyRecharge companyRecharge=companyRechargeService.selectCompanyRechargeById(param.getRechargeId());
+        if(companyRecharge.getIsAudit()!=0){
+            return R.error("非法操作");
+        }
+        companyRecharge.setIsAudit(param.getIsAudit());
+        companyRecharge.setRemark(param.getRemark());
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if(companyRecharge.getIsAudit()==1){
+            Company company=companyService.selectCompanyById(companyRecharge.getCompanyId());
+            company.setMoney(company.getMoney().add(companyRecharge.getMoney()));
+            companyService.updateCompany(company);
+            CompanyMoneyLogs log=new CompanyMoneyLogs();
+            log.setCompanyId(companyRecharge.getCompanyId());
+            log.setMoney(companyRecharge.getMoney());
+            log.setRemark(companyRecharge.getRemark());
+            log.setLogsType(1);
+            log.setBalance(company.getMoney());
+            log.setCreateTime(new Date());
+            moneyLogsService.insertCompanyMoneyLogs(log);
+            companyRecharge.setPayTime(new Date());
+            companyRecharge.setStatus(1);
+        }
+        companyRecharge.setAuditTime(new Date());
+        companyRecharge.setAuditUserId(loginUser.getUser().getUserId());
+        companyRechargeService.updateCompanyRecharge(companyRecharge);
+        return R.ok("操作成功");
+
+    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyRoleController.java

@@ -0,0 +1,103 @@
+package com.fs.company.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyRole;
+import com.fs.company.service.ICompanyRoleService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 角色信息Controller
+ * 
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/companyRole")
+public class CompanyRoleController extends BaseController
+{
+    @Autowired
+    private ICompanyRoleService companyRoleService;
+
+    /**
+     * 查询角色信息列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRole:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyRole companyRole)
+    {
+        startPage();
+        List<CompanyRole> list = companyRoleService.selectCompanyRoleList(companyRole);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出角色信息列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRole:export')")
+    @Log(title = "角色信息", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyRole companyRole)
+    {
+        List<CompanyRole> list = companyRoleService.selectCompanyRoleList(companyRole);
+        ExcelUtil<CompanyRole> util = new ExcelUtil<CompanyRole>(CompanyRole.class);
+        return util.exportExcel(list, "companyRole");
+    }
+
+    /**
+     * 获取角色信息详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRole:query')")
+    @GetMapping(value = "/{roleId}")
+    public AjaxResult getInfo(@PathVariable("roleId") Long roleId)
+    {
+        return AjaxResult.success(companyRoleService.selectCompanyRoleById(roleId));
+    }
+
+    /**
+     * 新增角色信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRole:add')")
+    @Log(title = "角色信息", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyRole companyRole)
+    {
+        return toAjax(companyRoleService.insertCompanyRole(companyRole));
+    }
+
+    /**
+     * 修改角色信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRole:edit')")
+    @Log(title = "角色信息", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyRole companyRole)
+    {
+        return toAjax(companyRoleService.updateCompanyRole(companyRole));
+    }
+
+    /**
+     * 删除角色信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRole:remove')")
+    @Log(title = "角色信息", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{roleIds}")
+    public AjaxResult remove(@PathVariable Long[] roleIds)
+    {
+        return toAjax(companyRoleService.deleteCompanyRoleByIds(roleIds));
+    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyRoleDeptController.java

@@ -0,0 +1,103 @@
+package com.fs.company.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyRoleDept;
+import com.fs.company.service.ICompanyRoleDeptService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 角色和部门关联Controller
+ * 
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/companyRoleDept")
+public class CompanyRoleDeptController extends BaseController
+{
+    @Autowired
+    private ICompanyRoleDeptService companyRoleDeptService;
+
+    /**
+     * 查询角色和部门关联列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRoleDept:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyRoleDept companyRoleDept)
+    {
+        startPage();
+        List<CompanyRoleDept> list = companyRoleDeptService.selectCompanyRoleDeptList(companyRoleDept);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出角色和部门关联列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRoleDept:export')")
+    @Log(title = "角色和部门关联", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyRoleDept companyRoleDept)
+    {
+        List<CompanyRoleDept> list = companyRoleDeptService.selectCompanyRoleDeptList(companyRoleDept);
+        ExcelUtil<CompanyRoleDept> util = new ExcelUtil<CompanyRoleDept>(CompanyRoleDept.class);
+        return util.exportExcel(list, "companyRoleDept");
+    }
+
+    /**
+     * 获取角色和部门关联详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRoleDept:query')")
+    @GetMapping(value = "/{roleId}")
+    public AjaxResult getInfo(@PathVariable("roleId") Long roleId)
+    {
+        return AjaxResult.success(companyRoleDeptService.selectCompanyRoleDeptById(roleId));
+    }
+
+    /**
+     * 新增角色和部门关联
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRoleDept:add')")
+    @Log(title = "角色和部门关联", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyRoleDept companyRoleDept)
+    {
+        return toAjax(companyRoleDeptService.insertCompanyRoleDept(companyRoleDept));
+    }
+
+    /**
+     * 修改角色和部门关联
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRoleDept:edit')")
+    @Log(title = "角色和部门关联", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyRoleDept companyRoleDept)
+    {
+        return toAjax(companyRoleDeptService.updateCompanyRoleDept(companyRoleDept));
+    }
+
+    /**
+     * 删除角色和部门关联
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRoleDept:remove')")
+    @Log(title = "角色和部门关联", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{roleIds}")
+    public AjaxResult remove(@PathVariable Long[] roleIds)
+    {
+        return toAjax(companyRoleDeptService.deleteCompanyRoleDeptByIds(roleIds));
+    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyRoleMenuController.java

@@ -0,0 +1,103 @@
+package com.fs.company.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyRoleMenu;
+import com.fs.company.service.ICompanyRoleMenuService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 角色和菜单关联Controller
+ * 
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/companyRoleMenu")
+public class CompanyRoleMenuController extends BaseController
+{
+    @Autowired
+    private ICompanyRoleMenuService companyRoleMenuService;
+
+    /**
+     * 查询角色和菜单关联列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRoleMenu:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyRoleMenu companyRoleMenu)
+    {
+        startPage();
+        List<CompanyRoleMenu> list = companyRoleMenuService.selectCompanyRoleMenuList(companyRoleMenu);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出角色和菜单关联列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRoleMenu:export')")
+    @Log(title = "角色和菜单关联", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyRoleMenu companyRoleMenu)
+    {
+        List<CompanyRoleMenu> list = companyRoleMenuService.selectCompanyRoleMenuList(companyRoleMenu);
+        ExcelUtil<CompanyRoleMenu> util = new ExcelUtil<CompanyRoleMenu>(CompanyRoleMenu.class);
+        return util.exportExcel(list, "companyRoleMenu");
+    }
+
+    /**
+     * 获取角色和菜单关联详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRoleMenu:query')")
+    @GetMapping(value = "/{roleId}")
+    public AjaxResult getInfo(@PathVariable("roleId") Long roleId)
+    {
+        return AjaxResult.success(companyRoleMenuService.selectCompanyRoleMenuById(roleId));
+    }
+
+    /**
+     * 新增角色和菜单关联
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRoleMenu:add')")
+    @Log(title = "角色和菜单关联", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyRoleMenu companyRoleMenu)
+    {
+        return toAjax(companyRoleMenuService.insertCompanyRoleMenu(companyRoleMenu));
+    }
+
+    /**
+     * 修改角色和菜单关联
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRoleMenu:edit')")
+    @Log(title = "角色和菜单关联", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyRoleMenu companyRoleMenu)
+    {
+        return toAjax(companyRoleMenuService.updateCompanyRoleMenu(companyRoleMenu));
+    }
+
+    /**
+     * 删除角色和菜单关联
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyRoleMenu:remove')")
+    @Log(title = "角色和菜单关联", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{roleIds}")
+    public AjaxResult remove(@PathVariable Long[] roleIds)
+    {
+        return toAjax(companyRoleMenuService.deleteCompanyRoleMenuByIds(roleIds));
+    }
+}

+ 105 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanySmsController.java

@@ -0,0 +1,105 @@
+package com.fs.company.controller;
+
+import java.util.List;
+
+import com.fs.company.vo.CompanySmsListVO;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanySms;
+import com.fs.company.service.ICompanySmsService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 公司短信Controller
+ * 
+ * @author fs
+ * @date 2023-01-09
+ */
+@RestController
+@RequestMapping("/company/companySms")
+public class CompanySmsController extends BaseController
+{
+    @Autowired
+    private ICompanySmsService companySmsService;
+
+    /**
+     * 查询公司短信列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySms:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanySms companySms)
+    {
+        startPage();
+        List<CompanySmsListVO> list = companySmsService.selectCompanySmsList(companySms);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出公司短信列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySms:export')")
+    @Log(title = "公司短信", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanySms companySms)
+    {
+        List<CompanySmsListVO> list = companySmsService.selectCompanySmsList(companySms);
+        ExcelUtil<CompanySmsListVO> util = new ExcelUtil<CompanySmsListVO>(CompanySmsListVO.class);
+        return util.exportExcel(list, "companySms");
+    }
+
+    /**
+     * 获取公司短信详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySms:query')")
+    @GetMapping(value = "/{smsId}")
+    public AjaxResult getInfo(@PathVariable("smsId") Long smsId)
+    {
+        return AjaxResult.success(companySmsService.selectCompanySmsById(smsId));
+    }
+
+    /**
+     * 新增公司短信
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySms:add')")
+    @Log(title = "公司短信", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanySms companySms)
+    {
+        return toAjax(companySmsService.insertCompanySms(companySms));
+    }
+
+    /**
+     * 修改公司短信
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySms:edit')")
+    @Log(title = "公司短信", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanySms companySms)
+    {
+        return toAjax(companySmsService.updateCompanySms(companySms));
+    }
+
+    /**
+     * 删除公司短信
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySms:remove')")
+    @Log(title = "公司短信", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{smsIds}")
+    public AjaxResult remove(@PathVariable Long[] smsIds)
+    {
+        return toAjax(companySmsService.deleteCompanySmsByIds(smsIds));
+    }
+}

+ 124 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanySmsLogsController.java

@@ -0,0 +1,124 @@
+package com.fs.company.controller;
+
+import java.util.List;
+
+import com.fs.company.param.CompanySmsLogsListParam;
+import com.fs.company.vo.CompanySmsLogsListVO;
+import com.fs.store.vo.FsStoreOrderVO;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanySmsLogs;
+import com.fs.company.service.ICompanySmsLogsService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 短信发送记录Controller
+ * 
+ * @author fs
+ * @date 2023-01-09
+ */
+@RestController
+@RequestMapping("/company/companySmsLogs")
+public class CompanySmsLogsController extends BaseController
+{
+    @Autowired
+    private ICompanySmsLogsService companySmsLogsService;
+
+    /**
+     * 查询短信发送记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsLogs:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanySmsLogsListParam companySmsLogs)
+    {
+        startPage();
+
+        List<CompanySmsLogsListVO> list = companySmsLogsService.selectCompanySmsLogsList(companySmsLogs);
+        if (list != null) {
+            for (CompanySmsLogsListVO vo : list) {
+                if(vo.getPhone()!=null){
+                    vo.setPhone(vo.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                }
+
+            }
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出短信发送记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsLogs:export')")
+    @Log(title = "短信发送记录", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanySmsLogsListParam companySmsLogs)
+    {
+        List<CompanySmsLogsListVO> list = companySmsLogsService.selectCompanySmsLogsList(companySmsLogs);
+        if (list != null) {
+            for (CompanySmsLogsListVO vo : list) {
+                if(vo.getPhone()!=null){
+                    vo.setPhone(vo.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                }
+
+            }
+        }
+        ExcelUtil<CompanySmsLogsListVO> util = new ExcelUtil<CompanySmsLogsListVO>(CompanySmsLogsListVO.class);
+        return util.exportExcel(list, "companySmsLogs");
+    }
+
+    /**
+     * 获取短信发送记录详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsLogs:query')")
+    @GetMapping(value = "/{logsId}")
+    public AjaxResult getInfo(@PathVariable("logsId") Long logsId)
+    {
+        return AjaxResult.success(companySmsLogsService.selectCompanySmsLogsById(logsId));
+    }
+
+    /**
+     * 新增短信发送记录
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsLogs:add')")
+    @Log(title = "短信发送记录", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanySmsLogs companySmsLogs)
+    {
+        return toAjax(companySmsLogsService.insertCompanySmsLogs(companySmsLogs));
+    }
+
+    /**
+     * 修改短信发送记录
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsLogs:edit')")
+    @Log(title = "短信发送记录", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanySmsLogs companySmsLogs)
+    {
+        return toAjax(companySmsLogsService.updateCompanySmsLogs(companySmsLogs));
+    }
+
+    /**
+     * 删除短信发送记录
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsLogs:remove')")
+    @Log(title = "短信发送记录", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{logsIds}")
+    public AjaxResult remove(@PathVariable Long[] logsIds)
+    {
+        return toAjax(companySmsLogsService.deleteCompanySmsLogsByIds(logsIds));
+    }
+}

+ 106 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanySmsOrderController.java

@@ -0,0 +1,106 @@
+package com.fs.company.controller;
+
+import java.util.List;
+
+import com.fs.company.param.CompanySmsOrderListParam;
+import com.fs.company.vo.CompanySmsOrderListVO;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanySmsOrder;
+import com.fs.company.service.ICompanySmsOrderService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 短信购买订单Controller
+ * 
+ * @author fs
+ * @date 2023-01-09
+ */
+@RestController
+@RequestMapping("/company/companySmsOrder")
+public class CompanySmsOrderController extends BaseController
+{
+    @Autowired
+    private ICompanySmsOrderService companySmsOrderService;
+
+    /**
+     * 查询短信购买订单列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsOrder:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanySmsOrderListParam param)
+    {
+        startPage();
+        List<CompanySmsOrderListVO> list = companySmsOrderService.selectCompanySmsOrderList(param);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出短信购买订单列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsOrder:export')")
+    @Log(title = "短信购买订单", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanySmsOrderListParam param)
+    {
+        List<CompanySmsOrderListVO> list = companySmsOrderService.selectCompanySmsOrderList(param);
+        ExcelUtil<CompanySmsOrderListVO> util = new ExcelUtil<CompanySmsOrderListVO>(CompanySmsOrderListVO.class);
+        return util.exportExcel(list, "companySmsOrder");
+    }
+
+    /**
+     * 获取短信购买订单详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsOrder:query')")
+    @GetMapping(value = "/{orderId}")
+    public AjaxResult getInfo(@PathVariable("orderId") Long orderId)
+    {
+        return AjaxResult.success(companySmsOrderService.selectCompanySmsOrderById(orderId));
+    }
+
+    /**
+     * 新增短信购买订单
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsOrder:add')")
+    @Log(title = "短信购买订单", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanySmsOrder companySmsOrder)
+    {
+        return toAjax(companySmsOrderService.insertCompanySmsOrder(companySmsOrder));
+    }
+
+    /**
+     * 修改短信购买订单
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsOrder:edit')")
+    @Log(title = "短信购买订单", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanySmsOrder companySmsOrder)
+    {
+        return toAjax(companySmsOrderService.updateCompanySmsOrder(companySmsOrder));
+    }
+
+    /**
+     * 删除短信购买订单
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsOrder:remove')")
+    @Log(title = "短信购买订单", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{orderIds}")
+    public AjaxResult remove(@PathVariable Long[] orderIds)
+    {
+        return toAjax(companySmsOrderService.deleteCompanySmsOrderByIds(orderIds));
+    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanySmsPackageController.java

@@ -0,0 +1,103 @@
+package com.fs.company.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanySmsPackage;
+import com.fs.company.service.ICompanySmsPackageService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 短信套餐包Controller
+ * 
+ * @author fs
+ * @date 2023-01-09
+ */
+@RestController
+@RequestMapping("/company/companySmsPackage")
+public class CompanySmsPackageController extends BaseController
+{
+    @Autowired
+    private ICompanySmsPackageService companySmsPackageService;
+
+    /**
+     * 查询短信套餐包列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsPackage:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanySmsPackage companySmsPackage)
+    {
+        startPage();
+        List<CompanySmsPackage> list = companySmsPackageService.selectCompanySmsPackageList(companySmsPackage);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出短信套餐包列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsPackage:export')")
+    @Log(title = "短信套餐包", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanySmsPackage companySmsPackage)
+    {
+        List<CompanySmsPackage> list = companySmsPackageService.selectCompanySmsPackageList(companySmsPackage);
+        ExcelUtil<CompanySmsPackage> util = new ExcelUtil<CompanySmsPackage>(CompanySmsPackage.class);
+        return util.exportExcel(list, "companySmsPackage");
+    }
+
+    /**
+     * 获取短信套餐包详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsPackage:query')")
+    @GetMapping(value = "/{packageId}")
+    public AjaxResult getInfo(@PathVariable("packageId") Long packageId)
+    {
+        return AjaxResult.success(companySmsPackageService.selectCompanySmsPackageById(packageId));
+    }
+
+    /**
+     * 新增短信套餐包
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsPackage:add')")
+    @Log(title = "短信套餐包", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanySmsPackage companySmsPackage)
+    {
+        return toAjax(companySmsPackageService.insertCompanySmsPackage(companySmsPackage));
+    }
+
+    /**
+     * 修改短信套餐包
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsPackage:edit')")
+    @Log(title = "短信套餐包", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanySmsPackage companySmsPackage)
+    {
+        return toAjax(companySmsPackageService.updateCompanySmsPackage(companySmsPackage));
+    }
+
+    /**
+     * 删除短信套餐包
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsPackage:remove')")
+    @Log(title = "短信套餐包", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{packageIds}")
+    public AjaxResult remove(@PathVariable Long[] packageIds)
+    {
+        return toAjax(companySmsPackageService.deleteCompanySmsPackageByIds(packageIds));
+    }
+}

+ 122 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanySmsTempController.java

@@ -0,0 +1,122 @@
+package com.fs.company.controller;
+
+import java.util.List;
+
+import com.fs.common.core.domain.R;
+import com.fs.company.vo.CompanySmsTempListVO;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanySmsTemp;
+import com.fs.company.service.ICompanySmsTempService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 短信模板Controller
+ * 
+ * @author fs
+ * @date 2023-01-09
+ */
+@RestController
+@RequestMapping("/company/companySmsTemp")
+public class CompanySmsTempController extends BaseController
+{
+    @Autowired
+    private ICompanySmsTempService companySmsTempService;
+
+    /**
+     * 查询短信模板列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsTemp:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanySmsTemp companySmsTemp)
+    {
+        startPage();
+        List<CompanySmsTempListVO> list = companySmsTempService.selectCompanySmsTempListVO(companySmsTemp);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出短信模板列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsTemp:export')")
+    @Log(title = "短信模板", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanySmsTemp companySmsTemp)
+    {
+        List<CompanySmsTemp> list = companySmsTempService.selectCompanySmsTempList(companySmsTemp);
+        ExcelUtil<CompanySmsTemp> util = new ExcelUtil<CompanySmsTemp>(CompanySmsTemp.class);
+        return util.exportExcel(list, "companySmsTemp");
+    }
+
+    /**
+     * 获取短信模板详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsTemp:query')")
+    @GetMapping(value = "/{tempId}")
+    public AjaxResult getInfo(@PathVariable("tempId") Long tempId)
+    {
+        return AjaxResult.success(companySmsTempService.selectCompanySmsTempById(tempId));
+    }
+
+    /**
+     * 新增短信模板
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsTemp:add')")
+    @Log(title = "短信模板", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanySmsTemp companySmsTemp)
+    {
+        return toAjax(companySmsTempService.insertCompanySmsTemp(companySmsTemp));
+    }
+
+    /**
+     * 修改短信模板
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsTemp:edit')")
+    @Log(title = "短信模板", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanySmsTemp companySmsTemp)
+    {
+        return toAjax(companySmsTempService.updateCompanySmsTemp(companySmsTemp));
+    }
+
+    /**
+     * 删除短信模板
+     */
+    @PreAuthorize("@ss.hasPermi('company:companySmsTemp:remove')")
+    @Log(title = "短信模板", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{tempIds}")
+    public AjaxResult remove(@PathVariable Long[] tempIds)
+    {
+        return toAjax(companySmsTempService.deleteCompanySmsTempByIds(tempIds));
+    }
+
+
+    @PreAuthorize("@ss.hasPermi('company:companySmsTemp:audit')")
+    @PostMapping("/audit")
+    public R audit(@RequestBody CompanySmsTemp companySmsTemp)
+    {
+        CompanySmsTemp map=new CompanySmsTemp();
+        map.setIsAudit(1);
+        map.setTempId(companySmsTemp.getTempId());
+        if(companySmsTempService.updateCompanySmsTemp(map)>0){
+            return R.ok("操作成功");
+        }
+        else{
+            return R.error("操作失败");
+        }
+    }
+}

+ 246 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyStatisticsController.java

@@ -0,0 +1,246 @@
+package com.fs.company.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.TimeUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.param.CompanyStatisticsParam;
+import com.fs.company.service.ICompanySmsLogsService;
+import com.fs.company.service.ICompanyUserService;
+import com.fs.company.service.ICompanyVoiceLogsService;
+import com.fs.company.vo.CompanyPackageOrderStatisticsVO;
+import com.fs.company.vo.CompanySmsLogsStatisticsVO;
+import com.fs.company.vo.CompanyTuiMoneyStatisticsVO;
+import com.fs.company.vo.CompanyVoiceLogsStatisticsVO;
+import com.fs.core.security.LoginUser;
+import com.fs.core.web.service.TokenService;
+import com.fs.store.domain.FsStoreOrder;
+import com.fs.store.mapper.FsStoreOrderMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 统计
+ *
+ * @author fs
+ * @date 2021-03-22
+ */
+@RestController
+@RequestMapping("/company/statistics")
+public class CompanyStatisticsController extends BaseController
+{
+
+    @Autowired
+    private ICompanyUserService userService;
+//    @Autowired
+//    private ICompanyPackageOrderService packageOrderService;
+    @Autowired
+    private ICompanyVoiceLogsService voiceLogsService;
+    @Autowired
+    private FsStoreOrderMapper fsStoreOrderMapper;
+    @Autowired
+    private ICompanySmsLogsService smsLogsService;
+    @Autowired
+    private TokenService tokenService;
+    @PreAuthorize("@ss.hasPermi('company:statistics:voiceLogs')")
+    @GetMapping("/voiceLogs")
+    public R voiceLogs(CompanyStatisticsParam param)
+    {
+        if(StringUtils.isNotEmpty(param.getUserIds())){
+            String[] userIds=param.getUserIds().split(",");
+            Long[] ids=new Long[userIds.length];
+            for(int i=0;i<ids.length; i++){
+                ids[i]=Long.parseLong(userIds[i]);
+            }
+            param.setUsers(ids);
+        }
+        else{
+            //获取部门下的所有用户
+            CompanyUser usermap=new CompanyUser();
+            usermap.setDeptId(param.getDeptId());
+            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
+            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
+            param.setUsers(userIds.toArray(new Long[userIds.size()]));
+        }
+        if(param.getUsers()!=null&&param.getUsers().length>0){
+            List<CompanyVoiceLogsStatisticsVO> list= voiceLogsService.selectVoiceLogsStatisticsList(param);
+            if(list!=null){
+                for(CompanyVoiceLogsStatisticsVO vo:list){
+                    double f1 = new BigDecimal((float)vo.getCallSuccessCount()/vo.getCallCount()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()*100;
+                    vo.setCallRate(f1);
+                }
+            }
+            TimeUtils.TimeEntity timeEntity=TimeUtils.parseTime(param.getType().toString(),param.getStartTime(),param.getEndTime());
+            timeEntity.setUserIds(param.getUsers());
+            Integer cycleNum = timeEntity.getCycleNum();
+            Integer beginTime = timeEntity.getBeginTime();
+            List<Integer> timeList = new ArrayList<>();
+            for (int i = 1; i <= cycleNum; i++) {
+                timeList.add(beginTime);
+                beginTime = TimeUtils.formatTime(beginTime);
+            }
+            List<JSONObject> jsonObjectList = voiceLogsService.selectVoiceLogsTotalCount(timeEntity.toMap());
+            List<String> dates = jsonObjectList.stream().map(jsonObject -> jsonObject.getString("type")).collect(Collectors.toList());
+            List<Integer> callCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("callCount")).collect(Collectors.toList());
+            List<Integer> callSuccessCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("callSuccessCount")).collect(Collectors.toList());
+            List<Integer> times = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("times")).collect(Collectors.toList());
+            List<Integer> billingTime = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("billingTime")).collect(Collectors.toList());
+            return R.ok().put("list",list).put("dates",dates).put("callCount",callCount).put("callSuccessCount",callSuccessCount).put("times",times).put("billingTime",billingTime);
+        }
+        else {
+            return R.ok("未查找到数据");
+        }
+    }
+    @PreAuthorize("@ss.hasPermi('company:statistics:exportVoiceLogs')")
+    @GetMapping("/exportVoiceLogs")
+    public AjaxResult exportVoiceLogs(CompanyStatisticsParam param)
+    {
+        if(StringUtils.isNotEmpty(param.getUserIds())){
+            String[] userIds=param.getUserIds().split(",");
+            Long[] ids=new Long[userIds.length];
+            for(int i=0;i<ids.length; i++){
+                ids[i]=Long.parseLong(userIds[i]);
+            }
+            param.setUsers(ids);
+        }
+        else{
+            //获取所有员工
+            List<CompanyUser> users = userService.selectCompanyUserList(new CompanyUser());
+            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
+            param.setUsers(userIds.toArray(new Long[userIds.size()]));
+        }
+
+        List<CompanyVoiceLogsStatisticsVO> list= voiceLogsService.selectVoiceLogsStatisticsList(param);
+        if(list!=null){
+            for(CompanyVoiceLogsStatisticsVO vo:list){
+                double f1 = new BigDecimal((float)vo.getCallSuccessCount()/vo.getCallCount()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()*100;
+                vo.setCallRate(f1);
+            }
+        }
+        ExcelUtil<CompanyVoiceLogsStatisticsVO> util = new ExcelUtil<CompanyVoiceLogsStatisticsVO>(CompanyVoiceLogsStatisticsVO.class);
+        return util.exportExcel(list, "voiceLogs");
+    }
+
+
+    @PreAuthorize("@ss.hasPermi('company:statistics:smsLogs')")
+    @GetMapping("/smsLogs")
+    public R smsLogs(CompanyStatisticsParam param)
+    {
+        if(StringUtils.isNotEmpty(param.getUserIds())){
+            String[] userIds=param.getUserIds().split(",");
+            Long[] ids=new Long[userIds.length];
+            for(int i=0;i<ids.length; i++){
+                ids[i]=Long.parseLong(userIds[i]);
+            }
+            param.setUsers(ids);
+        }
+        else{
+            //获取部门下的所有用户
+            CompanyUser usermap=new CompanyUser();
+            usermap.setDeptId(param.getDeptId());
+            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
+            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
+            param.setUsers(userIds.toArray(new Long[userIds.size()]));
+        }
+        if(param.getUsers()!=null&&param.getUsers().length>0){
+            List<CompanySmsLogsStatisticsVO> list= smsLogsService.selectSmsLogsStatisticsList(param);
+            TimeUtils.TimeEntity timeEntity=TimeUtils.parseTime(param.getType().toString(),param.getStartTime(),param.getEndTime());
+            timeEntity.setUserIds(param.getUsers());
+            Integer cycleNum = timeEntity.getCycleNum();
+            Integer beginTime = timeEntity.getBeginTime();
+            List<Integer> timeList = new ArrayList<>();
+            for (int i = 1; i <= cycleNum; i++) {
+                timeList.add(beginTime);
+                beginTime = TimeUtils.formatTime(beginTime);
+            }
+            List<JSONObject> jsonObjectList = smsLogsService.selectSmsLogsCounts(timeEntity.toMap());
+            List<String> dates = jsonObjectList.stream().map(jsonObject -> jsonObject.getString("type")).collect(Collectors.toList());
+            List<Integer> smsCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("smsCount")).collect(Collectors.toList());
+            List<Integer> successCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("successCount")).collect(Collectors.toList());
+            return R.ok().put("list",list).put("dates",dates).put("smsCount",smsCount).put("successCount",successCount);
+        }
+        else {
+            return R.ok("未查找到数据");
+        }
+    }
+
+    @PreAuthorize("@ss.hasPermi('company:statistics:exportTuiMoney')")
+    @GetMapping("/exportTuiMoney")
+    public AjaxResult exportTuiMoney(CompanyStatisticsParam param)
+    {
+        if(StringUtils.isNotEmpty(param.getUserIds())){
+            String[] userIds=param.getUserIds().split(",");
+            Long[] ids=new Long[userIds.length];
+            for(int i=0;i<ids.length; i++){
+                ids[i]=Long.parseLong(userIds[i]);
+            }
+            param.setUsers(ids);
+        }
+        else{
+            //获取所有员工
+            List<CompanyUser> users = userService.selectCompanyUserList(new CompanyUser());
+            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
+            param.setUsers(userIds.toArray(new Long[userIds.size()]));
+        }
+
+        List<CompanyTuiMoneyStatisticsVO> list= fsStoreOrderMapper.selectSoreTuiMoneyStatisticsList(param);
+        ExcelUtil<CompanyTuiMoneyStatisticsVO> util = new ExcelUtil<CompanyTuiMoneyStatisticsVO>(CompanyTuiMoneyStatisticsVO.class);
+        return util.exportExcel(list, "voiceLogs");
+    }
+
+
+    @PreAuthorize("@ss.hasPermi('company:statistics:tuiMoney')")
+    @GetMapping("/tuiMoney")
+    public R tuiMoney(CompanyStatisticsParam param)
+    {
+        if(StringUtils.isNotEmpty(param.getUserIds())){
+            String[] userIds=param.getUserIds().split(",");
+            Long[] ids=new Long[userIds.length];
+            for(int i=0;i<ids.length; i++){
+                ids[i]=Long.parseLong(userIds[i]);
+            }
+            param.setUsers(ids);
+        }
+        else{
+            //获取部门下的所有用户
+            CompanyUser usermap=new CompanyUser();
+            usermap.setDeptId(param.getDeptId());
+            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
+            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
+            param.setUsers(userIds.toArray(new Long[userIds.size()]));
+        }
+        if(param.getUsers()!=null&&param.getUsers().length>0){
+            List<CompanyTuiMoneyStatisticsVO> list= fsStoreOrderMapper.selectSoreTuiMoneyStatisticsList(param);
+            TimeUtils.TimeEntity timeEntity=TimeUtils.parseTime(param.getType().toString(),param.getStartTime(),param.getEndTime());
+            timeEntity.setUserIds(param.getUsers());
+            Integer cycleNum = timeEntity.getCycleNum();
+            Integer beginTime = timeEntity.getBeginTime();
+            List<Integer> timeList = new ArrayList<>();
+            for (int i = 1; i <= cycleNum; i++) {
+                timeList.add(beginTime);
+                beginTime = TimeUtils.formatTime(beginTime);
+            }
+            List<JSONObject> jsonObjectList = fsStoreOrderMapper.selectTuiMoneyCounts(timeEntity.toMap());
+            List<String> dates = jsonObjectList.stream().map(jsonObject -> jsonObject.getString("type")).collect(Collectors.toList());
+            List<Integer> tuiMoneyCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("tuiMoneyCount")).collect(Collectors.toList());
+            List<Integer> tuiMoney = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("tuiMoney")).collect(Collectors.toList());
+            return R.ok().put("list",list).put("dates",dates).put("tuiMoneyCount",tuiMoneyCount).put("tuiMoney",tuiMoney);
+        }
+        else {
+            return R.ok("未查找到数据");
+        }
+    }
+}

+ 261 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyTcmReportController.java

@@ -0,0 +1,261 @@
+package com.fs.company.controller;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.List;
+
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.company.vo.CompanyTcmReportExportVO;
+import com.fs.company.domain.CompanyTcmSchedule;
+import com.fs.company.param.CompanyTcmReportListQueryParam;
+import com.fs.company.service.ICompanyTcmScheduleService;
+import com.fs.company.vo.CompanyTcmReportListVO;
+import com.fs.company.vo.CompanyTcmStatisticsExportVO;
+import com.fs.core.security.LoginUser;
+import com.fs.core.web.service.TokenService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.service.ICompanyTcmReportService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 中医档期业绩报表Controller
+ *
+ * @author fs
+ * @date 2023-09-05
+ */
+@RestController
+@RequestMapping("/company/scheduleReport")
+public class CompanyTcmReportController extends BaseController
+{
+    @Autowired
+    private ICompanyTcmReportService companyTcmReportService;
+
+    @Autowired
+    private ICompanyTcmScheduleService companyTcmScheduleService;
+
+    @Autowired
+    private TokenService tokenService;
+
+    @PreAuthorize("@ss.hasPermi('company:scheduleReport:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyTcmReportListQueryParam param)
+    {
+        startPage();
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getDateRange())){
+            param.setStartTimeList(param.getDateRange().split("--"));
+        }
+        List<CompanyTcmReportListVO> list = companyTcmReportService.selectCompanyTcmReportListVOList(param);
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('company:scheduleReport:statistics')")
+    @GetMapping("/statistics")
+    public TableDataInfo statisticsList(CompanyTcmReportListQueryParam param)
+    {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getDateRange())){
+            param.setStartTimeList(param.getDateRange().split("--"));
+        }
+        List<CompanyTcmReportListVO> list = companyTcmReportService.selectCompanyTcmReportStatisticsVOList(param);
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('company:scheduleReport:statistics')")
+    @GetMapping("/getStatisticsByScheduleId")
+    public TableDataInfo getReportStatisticsListByScheduleId(CompanyTcmReportListQueryParam param)
+    {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getDateRange())){
+            param.setStartTimeList(param.getDateRange().split("--"));
+        }
+        List<CompanyTcmReportListVO> list = companyTcmReportService.selectReportStatisticsByScheduleId(param);
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('company:scheduleReport:export')")
+    @Log(title = "中医档期业绩报表", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyTcmReportListQueryParam param)
+    {
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getDateRange())){
+            param.setStartTimeList(param.getDateRange().split("--"));
+        }
+        List<CompanyTcmReportExportVO> list = companyTcmReportService.selectCompanyTcmReportExportVOList(param);
+        ExcelUtil<CompanyTcmReportExportVO> util = new ExcelUtil<CompanyTcmReportExportVO>(CompanyTcmReportExportVO.class);
+        return util.exportExcel(list, "companyTcmScheduleReport");
+    }
+
+    /**
+     * 导出中医档期业绩报表列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:scheduleReport:export')")
+    @Log(title = "中医档期业绩统计报表", businessType = BusinessType.EXPORT)
+    @GetMapping("/exportStatistics")
+    public AjaxResult exportStatistics(CompanyTcmReportListQueryParam param)
+    {
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getDateRange())){
+            param.setStartTimeList(param.getDateRange().split("--"));
+        }
+        List<CompanyTcmStatisticsExportVO> list = companyTcmReportService.selectCompanyTcmStatisticsExportVOList(param);
+        for(CompanyTcmStatisticsExportVO item:list){
+            if(item.getTotalNum()!=null && item.getTotalNum().doubleValue()>0){
+                item.setRegisterRate(String.format("%.3f",getLongRate(item.getRegisterNum().doubleValue(),item.getTotalNum())*100.0).toString()+"%");
+                item.setOnlineRate(String.format("%.3f",getLongRate(item.getOnlineNum().doubleValue(),item.getTotalNum())*100.0).toString()+"%");
+                item.setFinishRate(String.format("%.3f", getLongRate(item.getFinishNum().doubleValue(),item.getTotalNum())*100.0).toString()+"%");
+                item.setRLine(new BigDecimal(getLongRate(item.getTotalMoney().doubleValue(),item.getTotalNum())*1.0).setScale(3, RoundingMode.HALF_UP));
+
+            }else{
+                item.setRegisterRate("0%");
+                item.setOnlineRate("0%");
+                item.setFinishRate("0%");
+                item.setRLine(new BigDecimal(0.0));
+            }
+
+            if(item.getCuCount()!=null && item.getCuCount().doubleValue()>0){
+                item.setPersonMoney(String.format("%.3f",getLongRate(item.getTotalMoney().doubleValue(),Long.valueOf(item.getCuCount()))*1.0).toString());
+            }else{
+                item.setCuCount(0);
+            }
+
+            if(item.getTargetMoney()!=null && item.getTargetMoney().doubleValue()>0){
+                item.setTargetRate(String.format("%.3f", item.getTotalMoney().doubleValue()/item.getTargetMoney().doubleValue()*100.0).toString()+"%");
+            }else{
+                item.setTargetRate("0%");
+            }
+            if(item.getMoney()!=null && item.getMoney().doubleValue()>0){
+                item.setZroi(new BigDecimal(item.getTotalMoney().doubleValue()/item.getMoney().doubleValue()*1.0).setScale(3, RoundingMode.HALF_UP));
+            }else{
+                item.setZroi(new BigDecimal(0.0));
+            }
+            if(item.getRound1Order()!=null){
+                item.setRound1Rate(getRoundRate(item.getRound1Order(),item.getTotalNum()));
+                item.setRound1Unit(new BigDecimal(getRoundUnit(item.getRound1Money(),item.getRound1Order())).setScale(3, RoundingMode.HALF_UP));
+            }
+            if(item.getRound2Order()!=null){
+                item.setRound2Rate(getRoundRate(item.getRound2Order(),item.getTotalNum()));
+                item.setRound2Unit(new BigDecimal(getRoundUnit(item.getRound2Money(),item.getRound2Order())).setScale(3, RoundingMode.HALF_UP));
+            }
+            if(item.getRound3Order()!=null){
+                item.setRound3Rate(getRoundRate(item.getRound3Order(),item.getTotalNum()));
+                item.setRound3Unit(new BigDecimal(getRoundUnit(item.getRound3Money(),item.getRound3Order())).setScale(3, RoundingMode.HALF_UP));
+            }
+            if(item.getRound4Order()!=null){
+                item.setRound4Rate(getRoundRate(item.getRound4Order(),item.getTotalNum()));
+                item.setRound4Unit(new BigDecimal(getRoundUnit(item.getRound4Money(),item.getRound4Order())).setScale(3, RoundingMode.HALF_UP));
+            }
+            if(item.getRound5Order()!=null){
+                item.setRound5Rate(getRoundRate(item.getRound5Order(),item.getTotalNum()));
+                item.setRound5Unit(new BigDecimal(getRoundUnit(item.getRound5Money(),item.getRound5Order())).setScale(3, RoundingMode.HALF_UP));
+            }
+            if(item.getRound6Order()!=null){
+                item.setRound6Rate(getRoundRate(item.getRound6Order(),item.getTotalNum()));
+                item.setRound6Unit(new BigDecimal(getRoundUnit(item.getRound6Money(),item.getRound6Order())).setScale(3, RoundingMode.HALF_UP));
+            }
+            if(item.getRound7Order()!=null) {
+                item.setRound7Rate(getRoundRate(item.getRound7Order(), item.getTotalNum()));
+                item.setRound7Unit(new BigDecimal(getRoundUnit(item.getRound7Money(), item.getRound7Order())).setScale(3, RoundingMode.HALF_UP));
+            }
+            if (item.getRound8Order() != null) {
+                item.setRound8Rate(getRoundRate(item.getRound8Order(), item.getTotalNum()));
+                item.setRound8Unit(new BigDecimal(getRoundUnit(item.getRound8Money(), item.getRound8Order())).setScale(3, RoundingMode.HALF_UP));
+            }
+            if (item.getRound9Order() != null) {
+                item.setRound9Rate(getRoundRate(item.getRound9Order(), item.getTotalNum()));
+                item.setRound9Unit(new BigDecimal(getRoundUnit(item.getRound9Money(), item.getRound9Order())).setScale(3, RoundingMode.HALF_UP));
+            }
+
+        }
+
+        ExcelUtil<CompanyTcmStatisticsExportVO> util = new ExcelUtil<CompanyTcmStatisticsExportVO>(CompanyTcmStatisticsExportVO.class);
+        return util.exportExcel(list, "statisticsScheduleReport");
+    }
+
+
+
+    /**
+     * 查询可用中医档期列表
+     */
+    @GetMapping("/getScheduleList")
+    public TableDataInfo getScheduleList()
+    {
+        startPage();
+        List<CompanyTcmSchedule> list = companyTcmScheduleService.selectUseableScheduleList();
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询中医档期列表
+     */
+    @GetMapping("/getAllScheduleList")
+    public TableDataInfo getAllScheduleList()
+    {
+        startPage();
+        List<CompanyTcmSchedule> list = companyTcmScheduleService.selectCompanyTcmScheduleList(new CompanyTcmSchedule());
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取中医档期业绩报表详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:scheduleReport:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(companyTcmReportService.selectCompanyTcmReportById(id));
+    }
+
+    public String getRoundRate(Long roundOrder,Long totalNum){
+        String sorStr="0%";
+        if(totalNum.longValue()>0){
+            sorStr=String.format("%.3f", roundOrder.doubleValue()/totalNum*100.0).toString()+"%";
+        }
+        return sorStr;
+    }
+
+    public double getRoundUnit(BigDecimal roundMoney,Long roundOrder){
+        double sorNum=0;
+        if(roundOrder.longValue()>0){
+            sorNum=roundMoney.doubleValue()/roundOrder*1.0;
+        }
+        return sorNum;
+    }
+
+
+    public double getLongRate(double num1,Long num2){
+        double sorNum=0;
+        if(num2.longValue()>0){
+            sorNum=num1/num2*1.0;
+        }
+        return sorNum;
+    }
+
+
+}

+ 130 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyTcmScheduleController.java

@@ -0,0 +1,130 @@
+package com.fs.company.controller;
+
+import java.util.List;
+
+import cn.hutool.core.util.IdUtil;
+import com.fs.common.core.domain.R;
+import com.fs.common.utils.ServletUtils;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyRecharge;
+import com.fs.core.security.LoginUser;
+import com.fs.core.web.service.TokenService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyTcmSchedule;
+import com.fs.company.service.ICompanyTcmScheduleService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 中医档期管理Controller
+ *
+ * @author fs
+ * @date 2023-09-05
+ */
+@RestController
+@RequestMapping("/company/schedule")
+public class CompanyTcmScheduleController extends BaseController
+{
+    @Autowired
+    private ICompanyTcmScheduleService companyTcmScheduleService;
+
+    @Autowired
+    private TokenService tokenService;
+    /**
+     * 查询中医档期管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:schedule:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyTcmSchedule companyTcmSchedule)
+    {
+        startPage();
+        List<CompanyTcmSchedule> list = companyTcmScheduleService.selectCompanyTcmScheduleList(companyTcmSchedule);
+        return getDataTable(list);
+    }
+
+    @GetMapping("/getTcmScheduleList")
+    public R getCompanyTcmScheduleList()
+    {
+        CompanyTcmSchedule map = new CompanyTcmSchedule();
+        map.setStatus(1L);
+        List<CompanyTcmSchedule> list = companyTcmScheduleService.selectCompanyTcmScheduleList(map);
+        return R.ok().put("data",list);
+    }
+
+    /**
+     * 导出中医档期管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:schedule:export')")
+    @Log(title = "中医档期管理", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyTcmSchedule companyTcmSchedule)
+    {
+        List<CompanyTcmSchedule> list = companyTcmScheduleService.selectCompanyTcmScheduleList(companyTcmSchedule);
+        ExcelUtil<CompanyTcmSchedule> util = new ExcelUtil<CompanyTcmSchedule>(CompanyTcmSchedule.class);
+        return util.exportExcel(list, "schedule");
+    }
+
+    /**
+     * 获取中医档期管理详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:schedule:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(companyTcmScheduleService.selectCompanyTcmScheduleById(id));
+    }
+
+    /**
+     * 新增中医档期管理
+     */
+    @PreAuthorize("@ss.hasPermi('company:schedule:add')")
+    @Log(title = "中医档期管理", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyTcmSchedule companyTcmSchedule)
+    {
+
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        List<CompanyTcmSchedule> scheduleList=companyTcmScheduleService.selectCompanyTcmScheduleList(companyTcmSchedule);
+        if(scheduleList.size()>0){
+            return AjaxResult.error("档期名称已经存在");
+        }
+        companyTcmSchedule.setCreateUserId(loginUser.getUser().getUserId());
+        //companyTcmSchedule.setUpdateUserId(loginUser.getUser().getUserId());
+        return toAjax(companyTcmScheduleService.insertCompanyTcmSchedule(companyTcmSchedule));
+    }
+
+    /**
+     * 修改中医档期管理
+     */
+    @PreAuthorize("@ss.hasPermi('company:schedule:edit')")
+    @Log(title = "中医档期管理", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyTcmSchedule companyTcmSchedule)
+    {
+        return toAjax(companyTcmScheduleService.updateCompanyTcmSchedule(companyTcmSchedule));
+    }
+
+    /**
+     * 删除中医档期管理
+     */
+    @PreAuthorize("@ss.hasPermi('company:schedule:remove')")
+    @Log(title = "中医档期管理", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(companyTcmScheduleService.deleteCompanyTcmScheduleByIds(ids));
+    }
+}

+ 122 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyUserController.java

@@ -0,0 +1,122 @@
+package com.fs.company.controller;
+
+import java.util.List;
+
+import com.fs.common.constant.UserConstants;
+import com.fs.common.core.domain.R;
+import com.fs.common.utils.ServletUtils;
+import com.fs.core.security.LoginUser;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.service.ICompanyUserService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 企业员工信息Controller
+ * 
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/companyUser")
+public class CompanyUserController extends BaseController
+{
+    @Autowired
+    private ICompanyUserService companyUserService;
+
+    /**
+     * 查询企业员工信息列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUser:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyUser companyUser)
+    {
+        startPage();
+        List<CompanyUser> list = companyUserService.selectCompanyUserList(companyUser);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出企业员工信息列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUser:export')")
+    @Log(title = "企业员工信息", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyUser companyUser)
+    {
+        List<CompanyUser> list = companyUserService.selectCompanyUserList(companyUser);
+        ExcelUtil<CompanyUser> util = new ExcelUtil<CompanyUser>(CompanyUser.class);
+        return util.exportExcel(list, "companyUser");
+    }
+
+    /**
+     * 获取企业员工信息详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUser:query')")
+    @GetMapping(value = "/{userId}")
+    public AjaxResult getInfo(@PathVariable("userId") Long userId)
+    {
+        return AjaxResult.success(companyUserService.selectCompanyUserById(userId));
+    }
+
+    /**
+     * 新增企业员工信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUser:add')")
+    @Log(title = "企业员工信息", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyUser companyUser)
+    {
+        if (UserConstants.NOT_UNIQUE.equals(companyUserService.checkUserNameUnique(companyUser.getUserName())))
+        {
+            return AjaxResult.error("新增用户'" + companyUser.getUserName() + "'失败,登录账号已存在");
+        }
+        return toAjax(companyUserService.insertCompanyUser(companyUser));
+    }
+
+    /**
+     * 修改企业员工信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUser:edit')")
+    @Log(title = "企业员工信息", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyUser companyUser)
+    {
+        return toAjax(companyUserService.updateCompanyUser(companyUser));
+    }
+
+    /**
+     * 删除企业员工信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUser:remove')")
+    @Log(title = "企业员工信息", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{userIds}")
+    public AjaxResult remove(@PathVariable Long[] userIds)
+    {
+        return toAjax(companyUserService.deleteCompanyUserByIds(userIds));
+    }
+
+    @GetMapping("/getAllUserlist")
+    public R getAllUserlist(@RequestParam Long companyId)
+    {
+        CompanyUser map=new CompanyUser();
+        map.setCompanyId(companyId);
+        List<CompanyUser> list = companyUserService.selectCompanyUserList(map);
+        return R.ok().put("data",list);
+    }
+
+    @GetMapping("/getUserListByDeptId")
+    public R getUserListByDeptId(CompanyUser user)
+    {
+
+        List<CompanyUser> list = companyUserService.getUserListByDeptId(user);
+        return R.ok().put("data",list);
+    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyUserPostController.java

@@ -0,0 +1,103 @@
+package com.fs.company.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyUserPost;
+import com.fs.company.service.ICompanyUserPostService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 用户与岗位关联Controller
+ * 
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/companyUserPost")
+public class CompanyUserPostController extends BaseController
+{
+    @Autowired
+    private ICompanyUserPostService companyUserPostService;
+
+    /**
+     * 查询用户与岗位关联列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUserPost:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyUserPost companyUserPost)
+    {
+        startPage();
+        List<CompanyUserPost> list = companyUserPostService.selectCompanyUserPostList(companyUserPost);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出用户与岗位关联列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUserPost:export')")
+    @Log(title = "用户与岗位关联", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyUserPost companyUserPost)
+    {
+        List<CompanyUserPost> list = companyUserPostService.selectCompanyUserPostList(companyUserPost);
+        ExcelUtil<CompanyUserPost> util = new ExcelUtil<CompanyUserPost>(CompanyUserPost.class);
+        return util.exportExcel(list, "companyUserPost");
+    }
+
+    /**
+     * 获取用户与岗位关联详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUserPost:query')")
+    @GetMapping(value = "/{userId}")
+    public AjaxResult getInfo(@PathVariable("userId") Long userId)
+    {
+        return AjaxResult.success(companyUserPostService.selectCompanyUserPostById(userId));
+    }
+
+    /**
+     * 新增用户与岗位关联
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUserPost:add')")
+    @Log(title = "用户与岗位关联", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyUserPost companyUserPost)
+    {
+        return toAjax(companyUserPostService.insertCompanyUserPost(companyUserPost));
+    }
+
+    /**
+     * 修改用户与岗位关联
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUserPost:edit')")
+    @Log(title = "用户与岗位关联", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyUserPost companyUserPost)
+    {
+        return toAjax(companyUserPostService.updateCompanyUserPost(companyUserPost));
+    }
+
+    /**
+     * 删除用户与岗位关联
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUserPost:remove')")
+    @Log(title = "用户与岗位关联", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{userIds}")
+    public AjaxResult remove(@PathVariable Long[] userIds)
+    {
+        return toAjax(companyUserPostService.deleteCompanyUserPostByIds(userIds));
+    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyUserRoleController.java

@@ -0,0 +1,103 @@
+package com.fs.company.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyUserRole;
+import com.fs.company.service.ICompanyUserRoleService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 用户和角色关联Controller
+ * 
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/companyUserRole")
+public class CompanyUserRoleController extends BaseController
+{
+    @Autowired
+    private ICompanyUserRoleService companyUserRoleService;
+
+    /**
+     * 查询用户和角色关联列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUserRole:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyUserRole companyUserRole)
+    {
+        startPage();
+        List<CompanyUserRole> list = companyUserRoleService.selectCompanyUserRoleList(companyUserRole);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出用户和角色关联列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUserRole:export')")
+    @Log(title = "用户和角色关联", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyUserRole companyUserRole)
+    {
+        List<CompanyUserRole> list = companyUserRoleService.selectCompanyUserRoleList(companyUserRole);
+        ExcelUtil<CompanyUserRole> util = new ExcelUtil<CompanyUserRole>(CompanyUserRole.class);
+        return util.exportExcel(list, "companyUserRole");
+    }
+
+    /**
+     * 获取用户和角色关联详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUserRole:query')")
+    @GetMapping(value = "/{userId}")
+    public AjaxResult getInfo(@PathVariable("userId") Long userId)
+    {
+        return AjaxResult.success(companyUserRoleService.selectCompanyUserRoleById(userId));
+    }
+
+    /**
+     * 新增用户和角色关联
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUserRole:add')")
+    @Log(title = "用户和角色关联", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyUserRole companyUserRole)
+    {
+        return toAjax(companyUserRoleService.insertCompanyUserRole(companyUserRole));
+    }
+
+    /**
+     * 修改用户和角色关联
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUserRole:edit')")
+    @Log(title = "用户和角色关联", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyUserRole companyUserRole)
+    {
+        return toAjax(companyUserRoleService.updateCompanyUserRole(companyUserRole));
+    }
+
+    /**
+     * 删除用户和角色关联
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUserRole:remove')")
+    @Log(title = "用户和角色关联", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{userIds}")
+    public AjaxResult remove(@PathVariable Long[] userIds)
+    {
+        return toAjax(companyUserRoleService.deleteCompanyUserRoleByIds(userIds));
+    }
+}

+ 106 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceApiController.java

@@ -0,0 +1,106 @@
+package com.fs.company.controller;
+
+import java.util.List;
+
+import com.fs.common.core.domain.R;
+import com.fs.voice.service.IVoiceService;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyVoiceApi;
+import com.fs.company.service.ICompanyVoiceApiService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 呼叫接口Controller
+ * 
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/companyVoiceApi")
+public class CompanyVoiceApiController extends BaseController {
+    @Autowired
+    private ICompanyVoiceApiService companyVoiceApiService;
+    @Autowired
+    private IVoiceService voiceService;
+
+    /**
+     * 查询呼叫接口列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceApi:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyVoiceApi companyVoiceApi) {
+        startPage();
+        List<CompanyVoiceApi> list = companyVoiceApiService.selectCompanyVoiceApiList(companyVoiceApi);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出呼叫接口列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceApi:export')")
+    @Log(title = "呼叫接口", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyVoiceApi companyVoiceApi) {
+        List<CompanyVoiceApi> list = companyVoiceApiService.selectCompanyVoiceApiList(companyVoiceApi);
+        ExcelUtil<CompanyVoiceApi> util = new ExcelUtil<CompanyVoiceApi>(CompanyVoiceApi.class);
+        return util.exportExcel(list, "companyVoiceApi");
+    }
+
+    /**
+     * 获取呼叫接口详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceApi:query')")
+    @GetMapping(value = "/{apiId}")
+    public AjaxResult getInfo(@PathVariable("apiId") Long apiId) {
+        return AjaxResult.success(companyVoiceApiService.selectCompanyVoiceApiById(apiId));
+    }
+
+    /**
+     * 新增呼叫接口
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceApi:add')")
+    @Log(title = "呼叫接口", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyVoiceApi companyVoiceApi) {
+        return toAjax(companyVoiceApiService.insertCompanyVoiceApi(companyVoiceApi));
+    }
+
+    /**
+     * 修改呼叫接口
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceApi:edit')")
+    @Log(title = "呼叫接口", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyVoiceApi companyVoiceApi) {
+        return toAjax(companyVoiceApiService.updateCompanyVoiceApi(companyVoiceApi));
+    }
+
+    /**
+     * 删除呼叫接口
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceApi:remove')")
+    @Log(title = "呼叫接口", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{apiIds}")
+    public AjaxResult remove(@PathVariable Long[] apiIds) {
+        return toAjax(companyVoiceApiService.deleteCompanyVoiceApiByIds(apiIds));
+    }
+
+    @GetMapping("/getVoiceApiList")
+    public R getVoiceApiList() {
+        CompanyVoiceApi map = new CompanyVoiceApi();
+        map.setStatus(1);
+        List<CompanyVoiceApi> list = companyVoiceApiService.selectCompanyVoiceApiList(map);
+        return R.ok().put("data", list);
+    }
+
+
+}

+ 111 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceBlacklistController.java

@@ -0,0 +1,111 @@
+package com.fs.company.controller;
+
+import java.util.List;
+
+import com.fs.common.utils.ParseUtils;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyVoiceBlacklist;
+import com.fs.company.service.ICompanyVoiceBlacklistService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 黑名单Controller
+ *
+ * @author fs
+ * @date 2023-02-23
+ */
+@RestController
+@RequestMapping("/company/companyVoiceBlacklist")
+public class CompanyVoiceBlacklistController extends BaseController
+{
+    @Autowired
+    private ICompanyVoiceBlacklistService companyVoiceBlacklistService;
+
+    /**
+     * 查询黑名单列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceBlacklist:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyVoiceBlacklist companyVoiceBlacklist)
+    {
+        startPage();
+        List<CompanyVoiceBlacklist> list = companyVoiceBlacklistService.selectCompanyVoiceBlacklistList(companyVoiceBlacklist);
+        for (CompanyVoiceBlacklist blacklist : list){
+            blacklist.setMobile(ParseUtils.parsePhone(blacklist.getMobile()));
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出黑名单列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceBlacklist:export')")
+    @Log(title = "黑名单", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyVoiceBlacklist companyVoiceBlacklist)
+    {
+        List<CompanyVoiceBlacklist> list = companyVoiceBlacklistService.selectCompanyVoiceBlacklistList(companyVoiceBlacklist);
+        for (CompanyVoiceBlacklist blacklist : list){
+            blacklist.setMobile(ParseUtils.parsePhone(blacklist.getMobile()));
+        }
+        ExcelUtil<CompanyVoiceBlacklist> util = new ExcelUtil<CompanyVoiceBlacklist>(CompanyVoiceBlacklist.class);
+        return util.exportExcel(list, "companyVoiceBlacklist");
+    }
+
+    /**
+     * 获取黑名单详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceBlacklist:query')")
+    @GetMapping(value = "/{blacklistId}")
+    public AjaxResult getInfo(@PathVariable("blacklistId") Long blacklistId)
+    {
+        return AjaxResult.success(companyVoiceBlacklistService.selectCompanyVoiceBlacklistById(blacklistId));
+    }
+
+    /**
+     * 新增黑名单
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceBlacklist:add')")
+    @Log(title = "黑名单", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyVoiceBlacklist companyVoiceBlacklist)
+    {
+        return toAjax(companyVoiceBlacklistService.insertCompanyVoiceBlacklist(companyVoiceBlacklist));
+    }
+
+    /**
+     * 修改黑名单
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceBlacklist:edit')")
+    @Log(title = "黑名单", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyVoiceBlacklist companyVoiceBlacklist)
+    {
+        return toAjax(companyVoiceBlacklistService.updateCompanyVoiceBlacklist(companyVoiceBlacklist));
+    }
+
+    /**
+     * 删除黑名单
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceBlacklist:remove')")
+    @Log(title = "黑名单", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{blacklistIds}")
+    public AjaxResult remove(@PathVariable Long[] blacklistIds)
+    {
+        return toAjax(companyVoiceBlacklistService.deleteCompanyVoiceBlacklistByIds(blacklistIds));
+    }
+}

+ 153 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceCallerController.java

@@ -0,0 +1,153 @@
+package com.fs.company.controller;
+
+import java.util.List;
+
+import com.fs.common.core.domain.R;
+import com.fs.common.utils.ParseUtils;
+import com.fs.common.utils.ServletUtils;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.param.CompanyVoiceCallerImportParam;
+import com.fs.company.param.CompanyVoiceCallerParam;
+import com.fs.company.param.CompanyVoiceCallerRecoverParam;
+import com.fs.company.vo.CompanyVoiceCallerListVO;
+import com.fs.core.security.LoginUser;
+import com.fs.crm.param.CrmCustomeRecoverParam;
+import com.fs.crm.param.CrmLineCustomerImportParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyVoiceCaller;
+import com.fs.company.service.ICompanyVoiceCallerService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 企业用户坐席Controller
+ *
+ * @author fs
+ * @date 2023-02-23
+ */
+@RestController
+@RequestMapping("/company/companyVoiceCaller")
+public class CompanyVoiceCallerController extends BaseController
+{
+    @Autowired
+    private ICompanyVoiceCallerService companyVoiceCallerService;
+
+    /**
+     * 查询企业用户坐席列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceCaller:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyVoiceCallerParam param)
+    {
+        startPage();
+        List<CompanyVoiceCallerListVO> list = companyVoiceCallerService.selectCompanyVoiceCallerListVO(param);
+        for(CompanyVoiceCallerListVO vo :list){
+            vo.setMobile(ParseUtils.parsePhone(vo.getMobile()));
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出企业用户坐席列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceCaller:export')")
+    @Log(title = "企业用户坐席", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyVoiceCallerParam param)
+    {
+        List<CompanyVoiceCallerListVO> list = companyVoiceCallerService.selectCompanyVoiceCallerListVO(param);
+        ExcelUtil<CompanyVoiceCallerListVO> util = new ExcelUtil<CompanyVoiceCallerListVO>(CompanyVoiceCallerListVO.class);
+        return util.exportExcel(list, "companyVoiceCaller");
+    }
+
+    /**
+     * 获取企业用户坐席详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceCaller:query')")
+    @GetMapping(value = "/{callingId}")
+    public AjaxResult getInfo(@PathVariable("callingId") Long callingId)
+    {
+        return AjaxResult.success(companyVoiceCallerService.selectCompanyVoiceCallerById(callingId));
+    }
+
+    /**
+     * 新增企业用户坐席
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceCaller:add')")
+    @Log(title = "企业用户坐席", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyVoiceCaller companyVoiceCaller)
+    {
+        return toAjax(companyVoiceCallerService.insertCompanyVoiceCaller(companyVoiceCaller));
+    }
+
+    /**
+     * 修改企业用户坐席
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceCaller:edit')")
+    @Log(title = "企业用户坐席", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyVoiceCaller companyVoiceCaller)
+    {
+        return toAjax(companyVoiceCallerService.updateCompanyVoiceCaller(companyVoiceCaller));
+    }
+
+    /**
+     * 删除企业用户坐席
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceCaller:remove')")
+    @Log(title = "企业用户坐席", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{callingIds}")
+    public AjaxResult remove(@PathVariable Long[] callingIds)
+    {
+        return toAjax(companyVoiceCallerService.deleteCompanyVoiceCallerByIds(callingIds));
+    }
+
+
+    @Log(title = "导入线索客户", businessType = BusinessType.IMPORT)
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceCaller:import')")
+    @PostMapping("/importData")
+    public AjaxResult importLineData(MultipartFile file) throws Exception
+    {
+        ExcelUtil<CompanyVoiceCallerImportParam> util = new ExcelUtil<CompanyVoiceCallerImportParam>(CompanyVoiceCallerImportParam.class);
+        List<CompanyVoiceCallerImportParam> list = util.importExcel(file.getInputStream());
+        String message = companyVoiceCallerService.importCompanyVoiceCaller(list);
+        return AjaxResult.success(message);
+    }
+    //下载模板
+    @GetMapping("/importTemplate")
+    public AjaxResult importLineTemplate()
+    {
+        ExcelUtil<CompanyVoiceCallerImportParam> util = new ExcelUtil<CompanyVoiceCallerImportParam>(CompanyVoiceCallerImportParam.class);
+        return util.importTemplateExcel("分机号数据");
+    }
+
+    //回收
+    @PostMapping("/recover")
+    public R recover(@RequestBody CompanyVoiceCallerRecoverParam param)
+    {
+        CompanyVoiceCaller caller=companyVoiceCallerService.selectCompanyVoiceCallerById(param.getCallerId());
+        caller.setCompanyId(0l);
+        caller.setCompanyUserId(0l);
+        caller.setMobile("");
+        caller.setStatus(1);
+        companyVoiceCallerService.updateCompanyVoiceCaller(caller);
+        return R.ok();
+
+    }
+}

+ 175 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceConfigController.java

@@ -0,0 +1,175 @@
+package com.fs.company.controller;
+
+import java.util.List;
+
+import cn.hutool.json.JSONUtil;
+import com.fs.common.core.domain.R;
+import com.fs.company.config.CompanyVoiceCalleeConfig;
+import com.fs.company.config.CompanyVoiceCallerConfig;
+import com.fs.company.param.CompanyVoiceConfigParam;
+import com.fs.company.service.ICompanyService;
+import com.fs.company.vo.CompanyVoiceConfigListVO;
+import com.fs.company.vo.CompanyVoiceConfigVO;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyVoiceConfig;
+import com.fs.company.service.ICompanyVoiceConfigService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 呼叫频率配置Controller
+ * 
+ * @author fs
+ * @date 2021-11-13
+ */
+@RestController
+@RequestMapping("/company/companyVoiceConfig")
+public class CompanyVoiceConfigController extends BaseController
+{
+    @Autowired
+    private ICompanyVoiceConfigService companyVoiceConfigService;
+    @Autowired
+    private ICompanyService companyService;
+    /**
+     * 查询呼叫频率配置列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceConfig:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyVoiceConfig companyVoiceConfig)
+    {
+        startPage();
+        List<CompanyVoiceConfigListVO> list = companyVoiceConfigService.selectCompanyVoiceConfigListVO(companyVoiceConfig);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出呼叫频率配置列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceConfig:export')")
+    @Log(title = "呼叫频率配置", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyVoiceConfig companyVoiceConfig)
+    {
+        List<CompanyVoiceConfig> list = companyVoiceConfigService.selectCompanyVoiceConfigList(companyVoiceConfig);
+        ExcelUtil<CompanyVoiceConfig> util = new ExcelUtil<CompanyVoiceConfig>(CompanyVoiceConfig.class);
+        return util.exportExcel(list, "companyVoiceConfig");
+    }
+
+    /**
+     * 获取呼叫频率配置详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceConfig:query')")
+    @GetMapping(value = "/{configId}")
+    public AjaxResult getInfo(@PathVariable("configId") Long configId)
+    {
+        CompanyVoiceConfig config=companyVoiceConfigService.selectCompanyVoiceConfigById(configId);
+        CompanyVoiceCalleeConfig voiceCalleeConfigBO=JSONUtil.toBean(config.getCalleeJson(), CompanyVoiceCalleeConfig.class);
+        CompanyVoiceCallerConfig voiceCallerConfigBO=JSONUtil.toBean(config.getCallerJson(), CompanyVoiceCallerConfig.class);
+
+
+        CompanyVoiceConfigVO vo=new CompanyVoiceConfigVO();
+        vo.setCompanyId(config.getCompanyId());
+        vo.setConfigId(config.getConfigId());
+        vo.setCalleeDay(voiceCalleeConfigBO.getCalleeDay());
+        vo.setCalleeHour(voiceCalleeConfigBO.getCalleeHour());
+        vo.setCalleeWeek(voiceCalleeConfigBO.getCalleeWeek());
+        vo.setCalleeMinute(voiceCalleeConfigBO.getCalleeMinute());
+        vo.setCalleeMonth(voiceCalleeConfigBO.getCalleeMonth());
+
+        vo.setCallerDay(voiceCallerConfigBO.getCallerDay());
+        vo.setCallerHour(voiceCallerConfigBO.getCallerHour());
+        vo.setCallerWeek(voiceCallerConfigBO.getCallerWeek());
+        vo.setCallerMonth(voiceCallerConfigBO.getCallerMonth());
+        vo.setCallerMinute(voiceCallerConfigBO.getCallerMinute());
+
+        return AjaxResult.success(vo);
+    }
+
+    /**
+     * 新增呼叫频率配置
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceConfig:add')")
+    @Log(title = "呼叫频率配置", businessType = BusinessType.INSERT)
+    @PostMapping
+    public R add(@RequestBody CompanyVoiceConfigParam companyVoiceConfig)
+    {
+        //查询企业是否存在
+        CompanyVoiceConfig config=companyVoiceConfigService.selectCompanyVoiceConfigByCompanyId(companyVoiceConfig.getCompanyId());
+        if(config!=null){
+            return R.error("企业已存在");
+        }
+        CompanyVoiceCalleeConfig voiceCalleeConfigBO=new CompanyVoiceCalleeConfig();
+        voiceCalleeConfigBO.setCalleeDay(companyVoiceConfig.getCalleeDay());
+        voiceCalleeConfigBO.setCalleeHour(companyVoiceConfig.getCalleeHour());
+        voiceCalleeConfigBO.setCalleeMinute(companyVoiceConfig.getCalleeMinute());
+        voiceCalleeConfigBO.setCalleeMonth(companyVoiceConfig.getCalleeMonth());
+        voiceCalleeConfigBO.setCalleeWeek(companyVoiceConfig.getCalleeWeek());
+
+        CompanyVoiceCallerConfig voiceCallerConfigBO=new CompanyVoiceCallerConfig();
+        voiceCallerConfigBO.setCallerDay(companyVoiceConfig.getCallerDay());
+        voiceCallerConfigBO.setCallerHour(companyVoiceConfig.getCallerHour());
+        voiceCallerConfigBO.setCallerMinute(companyVoiceConfig.getCallerMinute());
+        voiceCallerConfigBO.setCallerWeek(companyVoiceConfig.getCallerWeek());
+        voiceCallerConfigBO.setCallerMonth(companyVoiceConfig.getCallerMonth());
+        config=new CompanyVoiceConfig();
+        config.setCompanyId(companyVoiceConfig.getCompanyId());
+        config.setCalleeJson(JSONUtil.toJsonStr(voiceCalleeConfigBO));
+        config.setCallerJson(JSONUtil.toJsonStr(voiceCallerConfigBO));
+        companyVoiceConfigService.insertCompanyVoiceConfig(config);
+        return R.ok("操作成功");
+    }
+
+    /**
+     * 修改呼叫频率配置
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceConfig:edit')")
+    @Log(title = "呼叫频率配置", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public R edit(@RequestBody CompanyVoiceConfigParam companyVoiceConfig)
+    {
+
+        CompanyVoiceCalleeConfig voiceCalleeConfigBO=new CompanyVoiceCalleeConfig();
+        voiceCalleeConfigBO.setCalleeDay(companyVoiceConfig.getCalleeDay());
+        voiceCalleeConfigBO.setCalleeHour(companyVoiceConfig.getCalleeHour());
+        voiceCalleeConfigBO.setCalleeMinute(companyVoiceConfig.getCalleeMinute());
+        voiceCalleeConfigBO.setCalleeMonth(companyVoiceConfig.getCalleeMonth());
+        voiceCalleeConfigBO.setCalleeWeek(companyVoiceConfig.getCalleeWeek());
+
+        CompanyVoiceCallerConfig voiceCallerConfigBO=new CompanyVoiceCallerConfig();
+        voiceCallerConfigBO.setCallerDay(companyVoiceConfig.getCallerDay());
+        voiceCallerConfigBO.setCallerHour(companyVoiceConfig.getCallerHour());
+        voiceCallerConfigBO.setCallerMinute(companyVoiceConfig.getCallerMinute());
+        voiceCallerConfigBO.setCallerWeek(companyVoiceConfig.getCallerWeek());
+        voiceCallerConfigBO.setCallerMonth(companyVoiceConfig.getCallerMonth());
+        CompanyVoiceConfig config=new CompanyVoiceConfig();
+        config.setConfigId(companyVoiceConfig.getConfigId());
+        config.setCalleeJson(JSONUtil.toJsonStr(voiceCalleeConfigBO));
+        config.setCallerJson(JSONUtil.toJsonStr(voiceCallerConfigBO));
+        companyVoiceConfigService.updateCompanyVoiceConfig(config);
+        return R.ok("修改成功");
+    }
+
+    /**
+     * 删除呼叫频率配置
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceConfig:remove')")
+    @Log(title = "呼叫频率配置", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{configIds}")
+    public AjaxResult remove(@PathVariable Long[] configIds)
+    {
+        return toAjax(companyVoiceConfigService.deleteCompanyVoiceConfigByIds(configIds));
+    }
+}

+ 108 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceController.java

@@ -0,0 +1,108 @@
+package com.fs.company.controller;
+
+import java.util.List;
+
+import com.fs.company.vo.CompanyVoiceListVO;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyVoice;
+import com.fs.company.service.ICompanyVoiceService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 企业通话Controller
+ *
+ * @author fs
+ * @date 2023-02-23
+ */
+@RestController
+@RequestMapping("/company/companyVoice")
+public class CompanyVoiceController extends BaseController
+{
+    @Autowired
+    private ICompanyVoiceService companyVoiceService;
+
+    /**
+     * 查询企业通话列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoice:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyVoice companyVoice)
+    {
+        startPage();
+        List<CompanyVoiceListVO> list = companyVoiceService.selectCompanyVoiceListVO(companyVoice);
+        for (CompanyVoiceListVO vo : list){
+            vo.setUseTimes(vo.getTotalTimes()-vo.getTimes());
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出企业通话列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoice:export')")
+    @Log(title = "企业通话", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyVoice companyVoice)
+    {
+        List<CompanyVoice> list = companyVoiceService.selectCompanyVoiceList(companyVoice);
+        ExcelUtil<CompanyVoice> util = new ExcelUtil<CompanyVoice>(CompanyVoice.class);
+        return util.exportExcel(list, "companyVoice");
+    }
+
+    /**
+     * 获取企业通话详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoice:query')")
+    @GetMapping(value = "/{voiceId}")
+    public AjaxResult getInfo(@PathVariable("voiceId") Long voiceId)
+    {
+        return AjaxResult.success(companyVoiceService.selectCompanyVoiceById(voiceId));
+    }
+
+    /**
+     * 新增企业通话
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoice:add')")
+    @Log(title = "企业通话", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyVoice companyVoice)
+    {
+        return toAjax(companyVoiceService.insertCompanyVoice(companyVoice));
+    }
+
+    /**
+     * 修改企业通话
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoice:edit')")
+    @Log(title = "企业通话", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyVoice companyVoice)
+    {
+        return toAjax(companyVoiceService.updateCompanyVoice(companyVoice));
+    }
+
+    /**
+     * 删除企业通话
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoice:remove')")
+    @Log(title = "企业通话", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{voiceIds}")
+    public AjaxResult remove(@PathVariable Long[] voiceIds)
+    {
+        return toAjax(companyVoiceService.deleteCompanyVoiceByIds(voiceIds));
+    }
+}

+ 133 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceLogsController.java

@@ -0,0 +1,133 @@
+package com.fs.company.controller;
+
+import java.util.List;
+
+import com.fs.common.utils.ParseUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.company.param.CompanyVoiceLogsParam;
+import com.fs.company.vo.CompanyVoiceLogsExportVO;
+import com.fs.company.vo.CompanyVoiceLogsVO;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyVoiceLogs;
+import com.fs.company.service.ICompanyVoiceLogsService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 通话记录Controller
+ *
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/companyVoiceLogs")
+public class CompanyVoiceLogsController extends BaseController
+{
+    @Autowired
+    private ICompanyVoiceLogsService companyVoiceLogsService;
+
+    /**
+     * 查询通话记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceLogs:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyVoiceLogsParam param)
+    {
+        startPage();
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getDateRange())){
+            param.setStartTimeList(param.getDateRange().split("--"));
+        }
+        List<CompanyVoiceLogsVO> list = companyVoiceLogsService.selectCompanyVoiceLogsVOList(param);
+        for(CompanyVoiceLogsVO vo : list){
+            vo.setCalleePhone(ParseUtils.parsePhone(vo.getCalleePhone()));
+            vo.setCallerPhone(ParseUtils.parsePhone(vo.getCallerPhone()));
+            vo.setDisplayCalleeNumber(ParseUtils.parsePhone(vo.getDisplayCalleeNumber()));
+            vo.setDisplayCallerNumber(ParseUtils.parsePhone(vo.getDisplayCallerNumber()));
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出通话记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceLogs:export')")
+    @Log(title = "通话记录", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyVoiceLogsParam param)
+    {
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getDateRange())){
+            param.setStartTimeList(param.getDateRange().split("--"));
+        }
+        List<CompanyVoiceLogsExportVO> list = companyVoiceLogsService.selectCompanyVoiceLogsExportVOList(param);
+        for(CompanyVoiceLogsExportVO vo : list){
+            vo.setCalleePhone(ParseUtils.parsePhone(vo.getCalleePhone()));
+            vo.setCallerPhone(ParseUtils.parsePhone(vo.getCallerPhone()));
+            vo.setDisplayCalleeNumber(ParseUtils.parsePhone(vo.getDisplayCalleeNumber()));
+            vo.setDisplayCallerNumber(ParseUtils.parsePhone(vo.getDisplayCallerNumber()));
+        }
+        ExcelUtil<CompanyVoiceLogsExportVO> util = new ExcelUtil<CompanyVoiceLogsExportVO>(CompanyVoiceLogsExportVO.class);
+        return util.exportExcel(list, "通话记录");
+    }
+
+    /**
+     * 获取通话记录详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceLogs:query')")
+    @GetMapping(value = "/{voiceId}")
+    public AjaxResult getInfo(@PathVariable("voiceId") Long voiceId)
+    {
+        return AjaxResult.success(companyVoiceLogsService.selectCompanyVoiceLogsById(voiceId));
+    }
+
+    /**
+     * 新增通话记录
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceLogs:add')")
+    @Log(title = "通话记录", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyVoiceLogs companyVoiceLogs)
+    {
+        return toAjax(companyVoiceLogsService.insertCompanyVoiceLogs(companyVoiceLogs));
+    }
+
+    /**
+     * 修改通话记录
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceLogs:edit')")
+    @Log(title = "通话记录", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyVoiceLogs companyVoiceLogs)
+    {
+        return toAjax(companyVoiceLogsService.updateCompanyVoiceLogs(companyVoiceLogs));
+    }
+
+    /**
+     * 删除通话记录
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceLogs:remove')")
+    @Log(title = "通话记录", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{voiceIds}")
+    public AjaxResult remove(@PathVariable Long[] voiceIds)
+    {
+        return toAjax(companyVoiceLogsService.deleteCompanyVoiceLogsByIds(voiceIds));
+    }
+}

+ 134 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceMobileController.java

@@ -0,0 +1,134 @@
+package com.fs.company.controller;
+
+import java.util.List;
+
+import com.fs.common.utils.ServletUtils;
+import com.fs.company.vo.CompanyVoiceMobileVO;
+import com.fs.core.security.LoginUser;
+import com.fs.crm.param.CrmLineCustomerImportParam;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyVoiceMobile;
+import com.fs.company.service.ICompanyVoiceMobileService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 中间号Controller
+ * 
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/companyVoiceMobile")
+public class CompanyVoiceMobileController extends BaseController
+{
+    @Autowired
+    private ICompanyVoiceMobileService companyVoiceMobileService;
+
+    /**
+     * 查询中间号列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceMobile:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyVoiceMobile companyVoiceMobile)
+    {
+        startPage();
+        List<CompanyVoiceMobileVO> list = companyVoiceMobileService.selectCompanyVoiceMobileVOList(companyVoiceMobile);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出中间号列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceMobile:export')")
+    @Log(title = "中间号", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyVoiceMobile companyVoiceMobile)
+    {
+        List<CompanyVoiceMobile> list = companyVoiceMobileService.selectCompanyVoiceMobileList(companyVoiceMobile);
+        ExcelUtil<CompanyVoiceMobile> util = new ExcelUtil<CompanyVoiceMobile>(CompanyVoiceMobile.class);
+        return util.exportExcel(list, "companyVoiceMobile");
+    }
+
+    /**
+     * 获取中间号详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceMobile:query')")
+    @GetMapping(value = "/{mobileId}")
+    public AjaxResult getInfo(@PathVariable("mobileId") Long mobileId)
+    {
+        return AjaxResult.success(companyVoiceMobileService.selectCompanyVoiceMobileById(mobileId));
+    }
+
+    /**
+     * 新增中间号
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceMobile:add')")
+    @Log(title = "中间号", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyVoiceMobile companyVoiceMobile)
+    {
+        if(companyVoiceMobile.getMobileType().equals(1)){
+            companyVoiceMobile.setCompanyId(0l);
+        }
+        return toAjax(companyVoiceMobileService.insertCompanyVoiceMobile(companyVoiceMobile));
+    }
+
+    /**
+     * 修改中间号
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceMobile:edit')")
+    @Log(title = "中间号", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyVoiceMobile companyVoiceMobile)
+    {
+        if(companyVoiceMobile.getMobileType().equals(1)){
+            companyVoiceMobile.setCompanyId(0l);
+        }
+
+        return toAjax(companyVoiceMobileService.updateCompanyVoiceMobile(companyVoiceMobile));
+    }
+
+    /**
+     * 删除中间号
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceMobile:remove')")
+    @Log(title = "中间号", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{mobileIds}")
+    public AjaxResult remove(@PathVariable Long[] mobileIds)
+    {
+        return toAjax(companyVoiceMobileService.deleteCompanyVoiceMobileByIds(mobileIds));
+    }
+
+    @Log(title = "导入线索客户", businessType = BusinessType.IMPORT)
+    @PreAuthorize("@ss.hasPermi('company:companyVoiceMobile:import')")
+    @PostMapping("/importData")
+    public AjaxResult importLineData(MultipartFile file) throws Exception
+    {
+        ExcelUtil<CompanyVoiceMobile> util = new ExcelUtil<CompanyVoiceMobile>(CompanyVoiceMobile.class);
+        List<CompanyVoiceMobile> list = util.importExcel(file.getInputStream());
+        String message = companyVoiceMobileService.importMobile(list);
+        return AjaxResult.success(message);
+    }
+    //下载模板
+    @GetMapping("/importTemplate")
+    public AjaxResult importLineTemplate()
+    {
+        ExcelUtil<CompanyVoiceMobile> util = new ExcelUtil<CompanyVoiceMobile>(CompanyVoiceMobile.class);
+        return util.importTemplateExcel("号码数据");
+    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyVoicePackageController.java

@@ -0,0 +1,103 @@
+package com.fs.company.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyVoicePackage;
+import com.fs.company.service.ICompanyVoicePackageService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 套餐Controller
+ * 
+ * @author fs
+ * @date 2023-02-23
+ */
+@RestController
+@RequestMapping("/company/companyVoicePackage")
+public class CompanyVoicePackageController extends BaseController
+{
+    @Autowired
+    private ICompanyVoicePackageService companyVoicePackageService;
+
+    /**
+     * 查询套餐列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoicePackage:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyVoicePackage companyVoicePackage)
+    {
+        startPage();
+        List<CompanyVoicePackage> list = companyVoicePackageService.selectCompanyVoicePackageList(companyVoicePackage);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出套餐列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoicePackage:export')")
+    @Log(title = "套餐", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyVoicePackage companyVoicePackage)
+    {
+        List<CompanyVoicePackage> list = companyVoicePackageService.selectCompanyVoicePackageList(companyVoicePackage);
+        ExcelUtil<CompanyVoicePackage> util = new ExcelUtil<CompanyVoicePackage>(CompanyVoicePackage.class);
+        return util.exportExcel(list, "companyVoicePackage");
+    }
+
+    /**
+     * 获取套餐详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoicePackage:query')")
+    @GetMapping(value = "/{packageId}")
+    public AjaxResult getInfo(@PathVariable("packageId") Long packageId)
+    {
+        return AjaxResult.success(companyVoicePackageService.selectCompanyVoicePackageById(packageId));
+    }
+
+    /**
+     * 新增套餐
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoicePackage:add')")
+    @Log(title = "套餐", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyVoicePackage companyVoicePackage)
+    {
+        return toAjax(companyVoicePackageService.insertCompanyVoicePackage(companyVoicePackage));
+    }
+
+    /**
+     * 修改套餐
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoicePackage:edit')")
+    @Log(title = "套餐", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyVoicePackage companyVoicePackage)
+    {
+        return toAjax(companyVoicePackageService.updateCompanyVoicePackage(companyVoicePackage));
+    }
+
+    /**
+     * 删除套餐
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoicePackage:remove')")
+    @Log(title = "套餐", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{packageIds}")
+    public AjaxResult remove(@PathVariable Long[] packageIds)
+    {
+        return toAjax(companyVoicePackageService.deleteCompanyVoicePackageByIds(packageIds));
+    }
+}

+ 106 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyVoicePackageOrderController.java

@@ -0,0 +1,106 @@
+package com.fs.company.controller;
+
+import java.util.List;
+
+import com.fs.company.param.CompanyVoicePackageOrderListParam;
+import com.fs.company.vo.CompanyVoicePackageOrderListVO;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyVoicePackageOrder;
+import com.fs.company.service.ICompanyVoicePackageOrderService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 套餐订单Controller
+ * 
+ * @author fs
+ * @date 2023-02-23
+ */
+@RestController
+@RequestMapping("/company/companyVoicePackageOrder")
+public class CompanyVoicePackageOrderController extends BaseController
+{
+    @Autowired
+    private ICompanyVoicePackageOrderService companyVoicePackageOrderService;
+
+    /**
+     * 查询套餐订单列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoicePackageOrder:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyVoicePackageOrderListParam param)
+    {
+        startPage();
+        List<CompanyVoicePackageOrderListVO> list = companyVoicePackageOrderService.selectCompanyVoicePackageOrderListVO(param);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出套餐订单列表
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoicePackageOrder:export')")
+    @Log(title = "套餐订单", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyVoicePackageOrderListParam param)
+    {
+        List<CompanyVoicePackageOrderListVO> list = companyVoicePackageOrderService.selectCompanyVoicePackageOrderListVO(param);
+        ExcelUtil<CompanyVoicePackageOrderListVO> util = new ExcelUtil<CompanyVoicePackageOrderListVO>(CompanyVoicePackageOrderListVO.class);
+        return util.exportExcel(list, "companyVoicePackageOrder");
+    }
+
+    /**
+     * 获取套餐订单详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoicePackageOrder:query')")
+    @GetMapping(value = "/{orderId}")
+    public AjaxResult getInfo(@PathVariable("orderId") Long orderId)
+    {
+        return AjaxResult.success(companyVoicePackageOrderService.selectCompanyVoicePackageOrderById(orderId));
+    }
+
+    /**
+     * 新增套餐订单
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoicePackageOrder:add')")
+    @Log(title = "套餐订单", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyVoicePackageOrder companyVoicePackageOrder)
+    {
+        return toAjax(companyVoicePackageOrderService.insertCompanyVoicePackageOrder(companyVoicePackageOrder));
+    }
+
+    /**
+     * 修改套餐订单
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoicePackageOrder:edit')")
+    @Log(title = "套餐订单", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyVoicePackageOrder companyVoicePackageOrder)
+    {
+        return toAjax(companyVoicePackageOrderService.updateCompanyVoicePackageOrder(companyVoicePackageOrder));
+    }
+
+    /**
+     * 删除套餐订单
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyVoicePackageOrder:remove')")
+    @Log(title = "套餐订单", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{orderIds}")
+    public AjaxResult remove(@PathVariable Long[] orderIds)
+    {
+        return toAjax(companyVoicePackageOrderService.deleteCompanyVoicePackageOrderByIds(orderIds));
+    }
+}

+ 66 - 0
fs-admin/src/main/java/com/fs/company/controller/IndexController.java

@@ -0,0 +1,66 @@
+package com.fs.company.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.utils.sign.Md5Utils;
+import com.fs.company.domain.Company;
+import com.fs.company.service.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 企业Controller
+ *
+ * @author fs
+ * @date 2021-10-04
+ */
+@RestController
+@RequestMapping("/company/index")
+public class IndexController extends BaseController
+{
+    @Autowired
+    private ICompanyService companyService;
+//    @Autowired
+//    private ICompanyPackageOrderService packageOrderService;
+    @Autowired
+    private ICompanyRechargeService rechargeService;
+    @Autowired
+    private ICompanyVoiceLogsService voiceLogsService;
+    @Autowired
+    private ICompanyVoiceApiService voiceApiService;
+    @Autowired
+    private ICompanyVoiceMobileService mobileService;
+    /**
+     * 查询企业列表
+     */
+    @GetMapping("/getCount")
+    public R getCount()
+    {
+//        Integer companyCount=companyService.selectCompanyCount();
+//        BigDecimal rechargeMoney=rechargeService.selectCompanyRechargeMoney();
+//        BigDecimal packageOrderMoney=packageOrderService.selectCompanyPackageOrderMoney();
+//        Integer voiceLogsCount=voiceLogsService.selectCompanyVoiceLogsCount();
+//        Integer voiceApiCount=voiceApiService.selectCompanyVoiceApiCount();
+//        Integer mobileCount=mobileService.selectCompanyVoiceMobileCount();
+//        Map<String,Object> map=new HashMap<>();
+//        map.put("companyCount",companyCount);
+//        map.put("rechargeMoney",rechargeMoney);
+//        map.put("packageOrderMoney",packageOrderMoney);
+//        map.put("voiceLogsCount",voiceLogsCount);
+//        map.put("voiceApiCount",voiceApiCount);
+//        map.put("mobileCount",mobileCount);
+
+//        return R.ok().put("data",map);
+        return R.ok();
+    }
+}

+ 172 - 0
fs-admin/src/main/java/com/fs/core/aspectj/DataScopeAspect.java

@@ -0,0 +1,172 @@
+package com.fs.core.aspectj;
+
+import java.lang.reflect.Method;
+
+import com.fs.core.security.LoginUser;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.Signature;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.stereotype.Component;
+import com.fs.common.annotation.DataScope;
+import com.fs.common.core.domain.BaseEntity;
+import com.fs.common.core.domain.entity.SysRole;
+import com.fs.common.core.domain.entity.SysUser;
+
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.spring.SpringUtils;
+import com.fs.core.web.service.TokenService;
+
+/**
+ * 数据过滤处理
+ *
+
+ */
+@Aspect
+@Component
+public class DataScopeAspect
+{
+    /**
+     * 全部数据权限
+     */
+    public static final String DATA_SCOPE_ALL = "1";
+
+    /**
+     * 自定数据权限
+     */
+    public static final String DATA_SCOPE_CUSTOM = "2";
+
+    /**
+     * 部门数据权限
+     */
+    public static final String DATA_SCOPE_DEPT = "3";
+
+    /**
+     * 部门及以下数据权限
+     */
+    public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
+
+    /**
+     * 仅本人数据权限
+     */
+    public static final String DATA_SCOPE_SELF = "5";
+
+    /**
+     * 数据权限过滤关键字
+     */
+    public static final String DATA_SCOPE = "dataScope";
+
+    // 配置织入点
+    @Pointcut("@annotation(com.fs.common.annotation.DataScope)")
+    public void dataScopePointCut()
+    {
+    }
+
+    @Before("dataScopePointCut()")
+    public void doBefore(JoinPoint point) throws Throwable
+    {
+        handleDataScope(point);
+    }
+
+    protected void handleDataScope(final JoinPoint joinPoint)
+    {
+        // 获得注解
+        DataScope controllerDataScope = getAnnotationLog(joinPoint);
+        if (controllerDataScope == null)
+        {
+            return;
+        }
+        // 获取当前的用户
+        LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
+        if (StringUtils.isNotNull(loginUser))
+        {
+            SysUser currentUser = loginUser.getUser();
+            // 如果是超级管理员,则不过滤数据
+            if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
+            {
+                dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
+                        controllerDataScope.userAlias());
+            }
+        }
+    }
+
+    /**
+     * 数据范围过滤
+     *
+     * @param joinPoint 切点
+     * @param user 用户
+     * @param userAlias 别名
+     */
+    public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
+    {
+        StringBuilder sqlString = new StringBuilder();
+
+        for (SysRole role : user.getRoles())
+        {
+            String dataScope = role.getDataScope();
+            if (DATA_SCOPE_ALL.equals(dataScope))
+            {
+                sqlString = new StringBuilder();
+                break;
+            }
+            else if (DATA_SCOPE_CUSTOM.equals(dataScope))
+            {
+                sqlString.append(StringUtils.format(
+                        " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
+                        role.getRoleId()));
+            }
+            else if (DATA_SCOPE_DEPT.equals(dataScope))
+            {
+                sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
+            }
+            else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
+            {
+                sqlString.append(StringUtils.format(
+                        " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
+                        deptAlias, user.getDeptId(), user.getDeptId()));
+            }
+            else if (DATA_SCOPE_SELF.equals(dataScope))
+            {
+                if (StringUtils.isNotBlank(userAlias))
+                {
+                    sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
+                }
+                else
+                {
+                    // 数据权限为仅本人且没有userAlias别名不查询任何数据
+                    //sqlString.append(" OR 1=0 ");
+                    sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
+                }
+            }
+        }
+
+        if (StringUtils.isNotBlank(sqlString.toString()))
+        {
+            Object params = joinPoint.getArgs()[0];
+            if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
+            {
+                BaseEntity baseEntity = (BaseEntity) params;
+                baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
+            }
+        }
+    }
+
+    /**
+     * 是否存在注解,如果存在就获取
+     */
+    private DataScope getAnnotationLog(JoinPoint joinPoint)
+    {
+        Signature signature = joinPoint.getSignature();
+        MethodSignature methodSignature = (MethodSignature) signature;
+        Method method = methodSignature.getMethod();
+
+        if (method != null)
+        {
+            return method.getAnnotation(DataScope.class);
+        }
+        return null;
+    }
+}

+ 73 - 0
fs-admin/src/main/java/com/fs/core/aspectj/DataSourceAspect.java

@@ -0,0 +1,73 @@
+package com.fs.core.aspectj;
+
+import java.util.Objects;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+import com.fs.common.annotation.DataSource;
+import com.fs.common.utils.StringUtils;
+import com.fs.core.datasource.DynamicDataSourceContextHolder;
+
+
+/**
+ * 多数据源处理
+ *
+
+ */
+@Aspect
+@Order(1)
+@Component
+public class DataSourceAspect
+{
+    protected Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Pointcut("@annotation(com.fs.common.annotation.DataSource)"
+            + "|| @within(com.fs.common.annotation.DataSource)")
+    public void dsPointCut()
+    {
+
+    }
+
+    @Around("dsPointCut()")
+    public Object around(ProceedingJoinPoint point) throws Throwable
+    {
+        DataSource dataSource = getDataSource(point);
+
+        if (StringUtils.isNotNull(dataSource))
+        {
+            DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
+        }
+
+        try
+        {
+            return point.proceed();
+        }
+        finally
+        {
+            // 销毁数据源 在执行方法之后
+            DynamicDataSourceContextHolder.clearDataSourceType();
+        }
+    }
+
+    /**
+     * 获取需要切换的数据源
+     */
+    public DataSource getDataSource(ProceedingJoinPoint point)
+    {
+        MethodSignature signature = (MethodSignature) point.getSignature();
+        DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
+        if (Objects.nonNull(dataSource))
+        {
+            return dataSource;
+        }
+
+        return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
+    }
+}

+ 218 - 0
fs-admin/src/main/java/com/fs/core/aspectj/LogAspect.java

@@ -0,0 +1,218 @@
+package com.fs.core.aspectj;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.fs.core.security.LoginUser;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.Signature;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.servlet.HandlerMapping;
+import com.alibaba.fastjson.JSON;
+import com.fs.common.annotation.Log;
+import com.fs.common.enums.BusinessStatus;
+import com.fs.common.enums.HttpMethod;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.ip.IpUtils;
+import com.fs.common.utils.spring.SpringUtils;
+import com.fs.core.manager.AsyncManager;
+import com.fs.core.manager.factory.AsyncFactory;
+import com.fs.core.web.service.TokenService;
+import com.fs.system.domain.SysOperLog;
+
+/**
+ * 操作日志记录处理
+ * 
+
+ */
+@Aspect
+@Component
+public class LogAspect
+{
+    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
+
+    // 配置织入点
+    @Pointcut("@annotation(com.fs.common.annotation.Log)")
+    public void logPointCut()
+    {
+    }
+
+    /**
+     * 处理完请求后执行
+     *
+     * @param joinPoint 切点
+     */
+    @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
+    public void doAfterReturning(JoinPoint joinPoint, Object jsonResult)
+    {
+        handleLog(joinPoint, null, jsonResult);
+    }
+
+    /**
+     * 拦截异常操作
+     * 
+     * @param joinPoint 切点
+     * @param e 异常
+     */
+    @AfterThrowing(value = "logPointCut()", throwing = "e")
+    public void doAfterThrowing(JoinPoint joinPoint, Exception e)
+    {
+        handleLog(joinPoint, e, null);
+    }
+
+    protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult)
+    {
+        try
+        {
+            // 获得注解
+            Log controllerLog = getAnnotationLog(joinPoint);
+            if (controllerLog == null)
+            {
+                return;
+            }
+
+            // 获取当前的用户
+            LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
+
+            // *========数据库日志=========*//
+            SysOperLog operLog = new SysOperLog();
+            operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
+            // 请求的地址
+            String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
+            operLog.setOperIp(ip);
+            // 返回参数
+            operLog.setJsonResult(JSON.toJSONString(jsonResult));
+
+            operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
+            if (loginUser != null)
+            {
+                operLog.setOperName(loginUser.getUsername());
+            }
+
+            if (e != null)
+            {
+                operLog.setStatus(BusinessStatus.FAIL.ordinal());
+                operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
+            }
+            // 设置方法名称
+            String className = joinPoint.getTarget().getClass().getName();
+            String methodName = joinPoint.getSignature().getName();
+            operLog.setMethod(className + "." + methodName + "()");
+            // 设置请求方式
+            operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
+            // 处理设置注解上的参数
+            getControllerMethodDescription(joinPoint, controllerLog, operLog);
+            // 保存数据库
+            AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
+        }
+        catch (Exception exp)
+        {
+            // 记录本地异常日志
+            log.error("==前置通知异常==");
+            log.error("异常信息:{}", exp.getMessage());
+            exp.printStackTrace();
+        }
+    }
+
+    /**
+     * 获取注解中对方法的描述信息 用于Controller层注解
+     * 
+     * @param log 日志
+     * @param operLog 操作日志
+     * @throws Exception
+     */
+    public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog) throws Exception
+    {
+        // 设置action动作
+        operLog.setBusinessType(log.businessType().ordinal());
+        // 设置标题
+        operLog.setTitle(log.title());
+        // 设置操作人类别
+        operLog.setOperatorType(log.operatorType().ordinal());
+        // 是否需要保存request,参数和值
+        if (log.isSaveRequestData())
+        {
+            // 获取参数的信息,传入到数据库中。
+            setRequestValue(joinPoint, operLog);
+        }
+    }
+
+    /**
+     * 获取请求的参数,放到log中
+     * 
+     * @param operLog 操作日志
+     * @throws Exception 异常
+     */
+    private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception
+    {
+        String requestMethod = operLog.getRequestMethod();
+        if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod))
+        {
+            String params = argsArrayToString(joinPoint.getArgs());
+            operLog.setOperParam(StringUtils.substring(params, 0, 2000));
+        }
+        else
+        {
+            Map<?, ?> paramsMap = (Map<?, ?>) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
+            operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000));
+        }
+    }
+
+    /**
+     * 是否存在注解,如果存在就获取
+     */
+    private Log getAnnotationLog(JoinPoint joinPoint) throws Exception
+    {
+        Signature signature = joinPoint.getSignature();
+        MethodSignature methodSignature = (MethodSignature) signature;
+        Method method = methodSignature.getMethod();
+
+        if (method != null)
+        {
+            return method.getAnnotation(Log.class);
+        }
+        return null;
+    }
+
+    /**
+     * 参数拼装
+     */
+    private String argsArrayToString(Object[] paramsArray)
+    {
+        String params = "";
+        if (paramsArray != null && paramsArray.length > 0)
+        {
+            for (int i = 0; i < paramsArray.length; i++)
+            {
+                if (!isFilterObject(paramsArray[i]))
+                {
+                    Object jsonObj = JSON.toJSON(paramsArray[i]);
+                    params += jsonObj.toString() + " ";
+                }
+            }
+        }
+        return params.trim();
+    }
+
+    /**
+     * 判断是否需要过滤的对象。
+     * 
+     * @param o 对象信息。
+     * @return 如果是需要过滤的对象,则返回true;否则返回false。
+     */
+    public boolean isFilterObject(final Object o)
+    {
+        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse;
+    }
+}

+ 30 - 0
fs-admin/src/main/java/com/fs/core/config/ApplicationConfig.java

@@ -0,0 +1,30 @@
+package com.fs.core.config;
+
+import java.util.TimeZone;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+
+/**
+ * 程序注解配置
+ *
+ 
+ */
+@Configuration
+// 表示通过aop框架暴露该代理对象,AopContext能够访问
+@EnableAspectJAutoProxy(exposeProxy = true)
+// 指定要扫描的Mapper类的包的路径
+@MapperScan("com.fs.**.mapper")
+public class ApplicationConfig
+{
+    /**
+     * 时区配置
+     */
+    @Bean
+    public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization()
+    {
+        return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault());
+    }
+}

+ 58 - 0
fs-admin/src/main/java/com/fs/core/config/ArrayStringTypeHandler.java

@@ -0,0 +1,58 @@
+package com.fs.core.config;
+
+import org.apache.ibatis.type.BaseTypeHandler;
+import org.apache.ibatis.type.JdbcType;
+import org.springframework.context.annotation.Configuration;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+
+@Configuration
+public class ArrayStringTypeHandler extends BaseTypeHandler<List<String>> {
+
+    @Override
+    public void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {
+        // 将 List<String> 转换为字符串,ClickHouse 支持的格式为 "['item1', 'item2']"
+        StringBuilder sb = new StringBuilder();
+        sb.append("[");
+        for (int j = 0; j < parameter.size(); j++) {
+            sb.append("'").append(parameter.get(j)).append("'");
+            if (j < parameter.size() - 1) {
+                sb.append(",");
+            }
+        }
+        sb.append("]");
+        ps.setString(i, sb.toString());
+    }
+
+    @Override
+    public List<String> getNullableResult(ResultSet rs, String columnName) throws SQLException {
+        // 处理查询结果,将其转换为 List<String>
+        String result = rs.getString(columnName);
+        return parseArray(result);
+    }
+
+    @Override
+    public List<String> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
+        String result = rs.getString(columnIndex);
+        return parseArray(result);
+    }
+
+    @Override
+    public List<String> getNullableResult(java.sql.CallableStatement cs, int columnIndex) throws SQLException {
+        String result = cs.getString(columnIndex);
+        return parseArray(result);
+    }
+
+    private List<String> parseArray(String arrayStr) {
+        // 将 ClickHouse 的 Array 字符串转换为 List<String>
+        if (arrayStr == null || arrayStr.isEmpty()) {
+            return null;
+        }
+        arrayStr = arrayStr.substring(1, arrayStr.length() - 1);  // 去掉 "[" 和 "]"
+        String[] elements = arrayStr.split(",");
+        return java.util.Arrays.asList(elements);
+    }
+}

+ 83 - 0
fs-admin/src/main/java/com/fs/core/config/CaptchaConfig.java

@@ -0,0 +1,83 @@
+package com.fs.core.config;
+
+import java.util.Properties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.google.code.kaptcha.impl.DefaultKaptcha;
+import com.google.code.kaptcha.util.Config;
+import static com.google.code.kaptcha.Constants.*;
+
+/**
+ * 验证码配置
+ * 
+
+ */
+@Configuration
+public class CaptchaConfig
+{
+    @Bean(name = "captchaProducer")
+    public DefaultKaptcha getKaptchaBean()
+    {
+        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
+        Properties properties = new Properties();
+        // 是否有边框 默认为true 我们可以自己设置yes,no
+        properties.setProperty(KAPTCHA_BORDER, "no");
+        // 验证码文本字符颜色 默认为Color.BLACK
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
+        // 验证码图片宽度 默认为200
+        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
+        // 验证码图片高度 默认为50
+        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
+        // 验证码文本字符大小 默认为40
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
+        // KAPTCHA_SESSION_KEY
+        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
+        // 验证码文本字符长度 默认为5
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
+        // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
+        // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
+//        properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
+        Config config = new Config(properties);
+        defaultKaptcha.setConfig(config);
+        return defaultKaptcha;
+    }
+
+    @Bean(name = "captchaProducerMath")
+    public DefaultKaptcha getKaptchaBeanMath()
+    {
+        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
+        Properties properties = new Properties();
+        // 是否有边框 默认为true 我们可以自己设置yes,no
+        properties.setProperty(KAPTCHA_BORDER, "yes");
+        // 边框颜色 默认为Color.BLACK
+        properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
+        // 验证码文本字符颜色 默认为Color.BLACK
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
+        // 验证码图片宽度 默认为200
+        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
+        // 验证码图片高度 默认为50
+        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
+        // 验证码文本字符大小 默认为40
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
+        // KAPTCHA_SESSION_KEY
+        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
+        // 验证码文本生成器
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.fs.core.config.KaptchaTextCreator");
+        // 验证码文本字符间距 默认为2
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
+        // 验证码文本字符长度 默认为5
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
+        // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
+        // 验证码噪点颜色 默认为Color.BLACK
+        properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
+        // 干扰实现类
+        properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
+        // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
+        properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
+        Config config = new Config(properties);
+        defaultKaptcha.setConfig(config);
+        return defaultKaptcha;
+    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/core/config/DataSourceConfig.java

@@ -0,0 +1,103 @@
+package com.fs.core.config;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
+import com.alibaba.druid.util.Utils;
+import com.fs.common.enums.DataSourceType;
+import com.fs.core.datasource.DynamicDataSource;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.*;
+import javax.sql.DataSource;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+@Configuration
+public class DataSourceConfig {
+    @Bean
+    @ConfigurationProperties(prefix = "spring.datasource.sop.druid.master")
+    public DataSource sopDataSource() {
+        return new DruidDataSource();
+    }
+
+    @Bean
+    @ConfigurationProperties(prefix = "spring.datasource.mysql.druid.master")
+    public DataSource masterDataSource() {
+        return new DruidDataSource();
+    }
+
+    @Bean
+    @ConfigurationProperties(prefix = "spring.datasource.mysql.druid.slave")
+    public DataSource slaveDataSource() {
+        return new DruidDataSource();
+    }
+
+
+
+    @Bean
+    @Primary
+    public DynamicDataSource dataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
+                                        @Qualifier("sopDataSource") DataSource sopDataSource,
+                                        @Qualifier("slaveDataSource") DataSource slaveDataSource) {
+        Map<Object, Object> targetDataSources = new HashMap<>();
+        targetDataSources.put(DataSourceType.MASTER, masterDataSource);
+
+        targetDataSources.put(DataSourceType.SLAVE, slaveDataSource);
+        targetDataSources.put(DataSourceType.SOP.name(), sopDataSource);
+        return new DynamicDataSource(masterDataSource, targetDataSources);
+    }
+
+    /**
+     * 去除监控页面底部的广告
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Bean
+    @ConditionalOnProperty(name = "spring.datasource.mysql.druid.statViewServlet.enabled", havingValue = "true")
+    public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
+    {
+        // 获取web监控页面的参数
+        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
+        // 提取common.js的配置路径
+        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
+        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
+        final String filePath = "support/http/resources/js/common.js";
+        // 创建filter进行过滤
+        Filter filter = new Filter()
+        {
+            @Override
+            public void init(FilterConfig filterConfig) throws ServletException
+            {
+            }
+            @Override
+            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+                    throws IOException, ServletException
+            {
+                chain.doFilter(request, response);
+                // 重置缓冲区,响应头不会被重置
+                response.resetBuffer();
+                // 获取common.js
+                String text = Utils.readFromResource(filePath);
+                // 正则替换banner, 除去底部的广告信息
+                text = text.replaceAll("<a.*?banner\"></a><br/>", "");
+                text = text.replaceAll("powered.*?shrek.wang</a>", "");
+                response.getWriter().write(text);
+            }
+            @Override
+            public void destroy()
+            {
+            }
+        };
+        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
+        registrationBean.setFilter(filter);
+        registrationBean.addUrlPatterns(commonJsPattern);
+        return registrationBean;
+    }
+}

+ 127 - 0
fs-admin/src/main/java/com/fs/core/config/DruidConfig.java

@@ -0,0 +1,127 @@
+//package com.fs.core.config;
+//
+//import java.io.IOException;
+//import java.util.HashMap;
+//import java.util.Map;
+//import javax.servlet.Filter;
+//import javax.servlet.FilterChain;
+//import javax.servlet.ServletException;
+//import javax.servlet.ServletRequest;
+//import javax.servlet.ServletResponse;
+//import javax.sql.DataSource;
+//import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+//import org.springframework.boot.context.properties.ConfigurationProperties;
+//import org.springframework.boot.web.servlet.FilterRegistrationBean;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.context.annotation.Primary;
+//import com.alibaba.druid.pool.DruidDataSource;
+//import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
+//import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
+//import com.alibaba.druid.util.Utils;
+//import com.fs.common.enums.DataSourceType;
+//import com.fs.common.utils.spring.SpringUtils;
+//import com.fs.core.config.properties.DruidProperties;
+//import com.fs.core.datasource.DynamicDataSource;
+//
+//
+///**
+// * druid 配置多数据源
+// *
+//
+// */
+//@Configuration
+//public class DruidConfig
+//{
+//    @Bean
+//    @ConfigurationProperties("spring.datasource.mysql.druid.master")
+//    public DataSource masterDataSource(DruidProperties druidProperties)
+//    {
+//        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
+//        return druidProperties.dataSource(dataSource);
+//    }
+//
+//    @Bean
+//    @ConfigurationProperties("spring.datasource.mysql.druid.slave")
+//    @ConditionalOnProperty(prefix = "spring.datasource.mysql.druid.slave", name = "enabled", havingValue = "true")
+//    public DataSource slaveDataSource(DruidProperties druidProperties)
+//    {
+//        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
+//        return druidProperties.dataSource(dataSource);
+//    }
+//
+//    @Bean(name = "dynamicDataSource")
+//    @Primary
+//    public DynamicDataSource dataSource(DataSource masterDataSource)
+//    {
+//        Map<Object, Object> targetDataSources = new HashMap<>();
+//        targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
+//        setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
+//        return new DynamicDataSource(masterDataSource, targetDataSources);
+//    }
+//
+//    /**
+//     * 设置数据源
+//     *
+//     * @param targetDataSources 备选数据源集合
+//     * @param sourceName 数据源名称
+//     * @param beanName bean名称
+//     */
+//    public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName)
+//    {
+//        try
+//        {
+//            DataSource dataSource = SpringUtils.getBean(beanName);
+//            targetDataSources.put(sourceName, dataSource);
+//        }
+//        catch (Exception e)
+//        {
+//        }
+//    }
+//
+//    /**
+//     * 去除监控页面底部的广告
+//     */
+//    @SuppressWarnings({ "rawtypes", "unchecked" })
+//    @Bean
+//    @ConditionalOnProperty(name = "spring.datasource.mysql.druid.statViewServlet.enabled", havingValue = "true")
+//    public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
+//    {
+//        // 获取web监控页面的参数
+//        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
+//        // 提取common.js的配置路径
+//        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
+//        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
+//        final String filePath = "support/http/resources/js/common.js";
+//        // 创建filter进行过滤
+//        Filter filter = new Filter()
+//        {
+//            @Override
+//            public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
+//            {
+//            }
+//            @Override
+//            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+//                    throws IOException, ServletException
+//            {
+//                chain.doFilter(request, response);
+//                // 重置缓冲区,响应头不会被重置
+//                response.resetBuffer();
+//                // 获取common.js
+//                String text = Utils.readFromResource(filePath);
+//                // 正则替换banner, 除去底部的广告信息
+//                text = text.replaceAll("<a.*?banner\"></a><br/>", "");
+//                text = text.replaceAll("powered.*?shrek.wang</a>", "");
+//                response.getWriter().write(text);
+//            }
+//            @Override
+//            public void destroy()
+//            {
+//            }
+//        };
+//        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
+//        registrationBean.setFilter(filter);
+//        registrationBean.addUrlPatterns(commonJsPattern);
+//        return registrationBean;
+//    }
+//}

+ 71 - 0
fs-admin/src/main/java/com/fs/core/config/FastJson2JsonRedisSerializer.java

@@ -0,0 +1,71 @@
+package com.fs.core.config;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.SerializationException;
+import com.alibaba.fastjson.parser.ParserConfig;
+import org.springframework.util.Assert;
+import java.nio.charset.Charset;
+
+/**
+ * Redis使用FastJson序列化
+ * 
+ 
+ */
+public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
+{
+    @SuppressWarnings("unused")
+    private ObjectMapper objectMapper = new ObjectMapper();
+
+    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
+
+    private Class<T> clazz;
+
+    static
+    {
+        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
+    }
+
+    public FastJson2JsonRedisSerializer(Class<T> clazz)
+    {
+        super();
+        this.clazz = clazz;
+    }
+
+    @Override
+    public byte[] serialize(T t) throws SerializationException
+    {
+        if (t == null)
+        {
+            return new byte[0];
+        }
+        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
+    }
+
+    @Override
+    public T deserialize(byte[] bytes) throws SerializationException
+    {
+        if (bytes == null || bytes.length <= 0)
+        {
+            return null;
+        }
+        String str = new String(bytes, DEFAULT_CHARSET);
+
+        return JSON.parseObject(str, clazz);
+    }
+
+    public void setObjectMapper(ObjectMapper objectMapper)
+    {
+        Assert.notNull(objectMapper, "'objectMapper' must not be null");
+        this.objectMapper = objectMapper;
+    }
+
+    protected JavaType getJavaType(Class<?> clazz)
+    {
+        return TypeFactory.defaultInstance().constructType(clazz);
+    }
+}

+ 60 - 0
fs-admin/src/main/java/com/fs/core/config/FilterConfig.java

@@ -0,0 +1,60 @@
+package com.fs.core.config;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.DispatcherType;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.fs.common.filter.RepeatableFilter;
+import com.fs.common.filter.XssFilter;
+import com.fs.common.utils.StringUtils;
+
+/**
+ * Filter配置
+ *
+ 
+ */
+@Configuration
+public class FilterConfig
+{
+    @Value("${xss.enabled}")
+    private String enabled;
+
+    @Value("${xss.excludes}")
+    private String excludes;
+
+    @Value("${xss.urlPatterns}")
+    private String urlPatterns;
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Bean
+    public FilterRegistrationBean xssFilterRegistration()
+    {
+        FilterRegistrationBean registration = new FilterRegistrationBean();
+        registration.setDispatcherTypes(DispatcherType.REQUEST);
+        registration.setFilter(new XssFilter());
+        registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
+        registration.setName("xssFilter");
+        registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
+        Map<String, String> initParameters = new HashMap<String, String>();
+        initParameters.put("excludes", excludes);
+        initParameters.put("enabled", enabled);
+        registration.setInitParameters(initParameters);
+        return registration;
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Bean
+    public FilterRegistrationBean someFilterRegistration()
+    {
+        FilterRegistrationBean registration = new FilterRegistrationBean();
+        registration.setFilter(new RepeatableFilter());
+        registration.addUrlPatterns("/*");
+        registration.setName("repeatableFilter");
+        registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
+        return registration;
+    }
+
+}

+ 75 - 0
fs-admin/src/main/java/com/fs/core/config/KaptchaTextCreator.java

@@ -0,0 +1,75 @@
+package com.fs.core.config;
+
+import java.util.Random;
+import com.google.code.kaptcha.text.impl.DefaultTextCreator;
+
+/**
+ * 验证码文本生成器
+ * 
+ 
+ */
+public class KaptchaTextCreator extends DefaultTextCreator
+{
+    private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
+
+    @Override
+    public String getText()
+    {
+        Integer result = 0;
+        Random random = new Random();
+        int x = random.nextInt(10);
+        int y = random.nextInt(10);
+        StringBuilder suChinese = new StringBuilder();
+        int randomoperands = (int) Math.round(Math.random() * 2);
+        if (randomoperands == 0)
+        {
+            result = x * y;
+            suChinese.append(CNUMBERS[x]);
+            suChinese.append("*");
+            suChinese.append(CNUMBERS[y]);
+        }
+        else if (randomoperands == 1)
+        {
+            if (!(x == 0) && y % x == 0)
+            {
+                result = y / x;
+                suChinese.append(CNUMBERS[y]);
+                suChinese.append("/");
+                suChinese.append(CNUMBERS[x]);
+            }
+            else
+            {
+                result = x + y;
+                suChinese.append(CNUMBERS[x]);
+                suChinese.append("+");
+                suChinese.append(CNUMBERS[y]);
+            }
+        }
+        else if (randomoperands == 2)
+        {
+            if (x >= y)
+            {
+                result = x - y;
+                suChinese.append(CNUMBERS[x]);
+                suChinese.append("-");
+                suChinese.append(CNUMBERS[y]);
+            }
+            else
+            {
+                result = y - x;
+                suChinese.append(CNUMBERS[y]);
+                suChinese.append("-");
+                suChinese.append(CNUMBERS[x]);
+            }
+        }
+        else
+        {
+            result = x + y;
+            suChinese.append(CNUMBERS[x]);
+            suChinese.append("+");
+            suChinese.append(CNUMBERS[y]);
+        }
+        suChinese.append("=?@" + result);
+        return suChinese.toString();
+    }
+}

+ 107 - 0
fs-admin/src/main/java/com/fs/core/config/MyBatisConfig.java

@@ -0,0 +1,107 @@
+package com.fs.core.config;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import javax.sql.DataSource;
+
+import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
+import org.apache.ibatis.io.VFS;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.core.io.DefaultResourceLoader;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.core.io.support.ResourcePatternResolver;
+import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.util.ClassUtils;
+
+/**
+ * Mybatis支持*匹配扫描包
+ */
+@Configuration
+public class MyBatisConfig {
+    @Autowired
+    private Environment env;
+
+    static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
+
+    public static String setTypeAliasesPackage(String typeAliasesPackage) {
+        ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
+        MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
+        List<String> allResult = new ArrayList<String>();
+        try {
+            for (String aliasesPackage : typeAliasesPackage.split(",")) {
+                List<String> result = new ArrayList<String>();
+                aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+                        + ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;
+                Resource[] resources = resolver.getResources(aliasesPackage);
+                if (resources != null && resources.length > 0) {
+                    MetadataReader metadataReader = null;
+                    for (Resource resource : resources) {
+                        if (resource.isReadable()) {
+                            metadataReader = metadataReaderFactory.getMetadataReader(resource);
+                            try {
+                                result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
+                            } catch (ClassNotFoundException e) {
+                                e.printStackTrace();
+                            }
+                        }
+                    }
+                }
+                if (result.size() > 0) {
+                    HashSet<String> hashResult = new HashSet<String>(result);
+                    allResult.addAll(hashResult);
+                }
+            }
+            if (allResult.size() > 0) {
+                typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0]));
+            } else {
+                throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包");
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return typeAliasesPackage;
+    }
+
+    //    @Bean
+//    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
+//    {
+//        String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
+//        String mapperLocations = env.getProperty("mybatis.mapperLocations");
+//        String configLocation = env.getProperty("mybatis.configLocation");
+//        typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
+//        VFS.addImplClass(SpringBootVFS.class);
+//
+//        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
+//        sessionFactory.setDataSource(dataSource);
+//        sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
+//        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
+//        sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
+//        return sessionFactory.getObject();
+//    }
+    @Bean
+    public SqlSessionFactory sqlSessionFactorys(DataSource dataSource) throws Exception {
+        String typeAliasesPackage = env.getProperty("mybatis-plus.typeAliasesPackage");
+        String mapperLocations = env.getProperty("mybatis-plus.mapperLocations");
+        String configLocation = env.getProperty("mybatis-plus.configLocation");
+        typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
+        VFS.addImplClass(SpringBootVFS.class);
+
+        final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
+        sessionFactory.setDataSource(dataSource);
+        sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
+        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
+        sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
+        return sessionFactory.getObject();
+    }
+}

+ 88 - 0
fs-admin/src/main/java/com/fs/core/config/RedisConfig.java

@@ -0,0 +1,88 @@
+package com.fs.core.config;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.GenericToStringSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * redis配置
+ *
+
+ */
+@Configuration
+@EnableCaching
+public class RedisConfig extends CachingConfigurerSupport
+{
+    @Bean
+    @SuppressWarnings(value = { "unchecked", "rawtypes" })
+    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
+    {
+        RedisTemplate<Object, Object> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        serializer.setObjectMapper(mapper);
+
+        template.setValueSerializer(serializer);
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+        template.afterPropertiesSet();
+        return template;
+    }
+
+    @Bean
+    public RedisTemplate<String, Boolean> redisTemplateForBoolean(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Boolean> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+        template.setValueSerializer(new GenericToStringSerializer<>(Boolean.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Boolean.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
+
+    @Bean
+    @SuppressWarnings(value = { "unchecked", "rawtypes" })
+    public RedisTemplate<String, Object> redisTemplateForObject(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Object> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        serializer.setObjectMapper(mapper);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+        template.setValueSerializer(serializer);
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(serializer);
+
+        template.afterPropertiesSet();
+        return template;
+    }
+}

+ 66 - 0
fs-admin/src/main/java/com/fs/core/config/ResourcesConfig.java

@@ -0,0 +1,66 @@
+package com.fs.core.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import com.fs.common.config.FSConfig;
+import com.fs.common.constant.Constants;
+import com.fs.core.interceptor.RepeatSubmitInterceptor;
+
+/**
+ * 通用配置
+ * 
+
+ */
+@Configuration
+public class ResourcesConfig implements WebMvcConfigurer
+{
+    @Autowired
+    private RepeatSubmitInterceptor repeatSubmitInterceptor;
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry)
+    {
+        /** 本地文件上传路径 */
+        registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + FSConfig.getProfile() + "/");
+
+        /** swagger配置 */
+        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
+        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
+    }
+
+    /**
+     * 自定义拦截规则
+     */
+    @Override
+    public void addInterceptors(InterceptorRegistry registry)
+    {
+        registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
+    }
+
+    /**
+     * 跨域配置
+     */
+    @Bean
+    public CorsFilter corsFilter()
+    {
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        CorsConfiguration config = new CorsConfiguration();
+        config.setAllowCredentials(true);
+        // 设置访问源地址
+        config.addAllowedOrigin("*");
+        // 设置访问源请求头
+        config.addAllowedHeader("*");
+        // 设置访问源请求方法
+        config.addAllowedMethod("*");
+        // 对接口配置跨域设置
+        source.registerCorsConfiguration("/**", config);
+        return new CorsFilter(source);
+    }
+}

+ 160 - 0
fs-admin/src/main/java/com/fs/core/config/SecurityConfig.java

@@ -0,0 +1,160 @@
+package com.fs.core.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.security.web.authentication.logout.LogoutFilter;
+import org.springframework.web.filter.CorsFilter;
+import com.fs.core.security.filter.JwtAuthenticationTokenFilter;
+import com.fs.core.security.handle.AuthenticationEntryPointImpl;
+import com.fs.core.security.handle.LogoutSuccessHandlerImpl;
+
+/**
+ * spring security配置
+ *
+
+ */
+@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
+public class SecurityConfig extends WebSecurityConfigurerAdapter
+{
+    /**
+     * 自定义用户认证逻辑
+     */
+    @Autowired
+    private UserDetailsService userDetailsService;
+
+    /**
+     * 认证失败处理类
+     */
+    @Autowired
+    private AuthenticationEntryPointImpl unauthorizedHandler;
+
+    /**
+     * 退出处理类
+     */
+    @Autowired
+    private LogoutSuccessHandlerImpl logoutSuccessHandler;
+
+    /**
+     * token认证过滤器
+     */
+    @Autowired
+    private JwtAuthenticationTokenFilter authenticationTokenFilter;
+
+    /**
+     * 跨域过滤器
+     */
+    @Autowired
+    private CorsFilter corsFilter;
+
+    /**
+     * 解决 无法直接注入 AuthenticationManager
+     *
+     * @return
+     * @throws Exception
+     */
+    @Bean
+    @Override
+    public AuthenticationManager authenticationManagerBean() throws Exception
+    {
+        return super.authenticationManagerBean();
+    }
+
+    /**
+     * anyRequest          |   匹配所有请求路径
+     * access              |   SpringEl表达式结果为true时可以访问
+     * anonymous           |   匿名可以访问
+     * denyAll             |   用户不能访问
+     * fullyAuthenticated  |   用户完全认证可以访问(非remember-me下自动登录)
+     * hasAnyAuthority     |   如果有参数,参数表示权限,则其中任何一个权限可以访问
+     * hasAnyRole          |   如果有参数,参数表示角色,则其中任何一个角色可以访问
+     * hasAuthority        |   如果有参数,参数表示权限,则其权限可以访问
+     * hasIpAddress        |   如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
+     * hasRole             |   如果有参数,参数表示角色,则其角色可以访问
+     * permitAll           |   用户可以任意访问
+     * rememberMe          |   允许通过remember-me登录的用户访问
+     * authenticated       |   用户登录后可访问
+     */
+    @Override
+    protected void configure(HttpSecurity httpSecurity) throws Exception
+    {
+        httpSecurity
+                // CSRF禁用,因为不使用session
+                .csrf().disable()
+                // 认证失败处理类
+                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
+                // 基于token,所以不需要session
+                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
+                // 过滤请求
+                .authorizeRequests()
+                // 对于登录login 验证码captchaImage 允许匿名访问
+                .antMatchers("/login", "/captchaImage").anonymous()
+                .antMatchers(
+                        HttpMethod.GET,
+                        "/",
+                        "/*.html",
+                        "/**/*.html",
+                        "/**/*.css",
+                        "/**/*.js"
+                ).permitAll()
+                .antMatchers("/api/**").anonymous()
+                .antMatchers("/store/storeAfterSales/getStoreAfterSales**").anonymous()
+                .antMatchers("/store/storeOrder/getStoreOrder**").anonymous()
+                .antMatchers("/third/feiyu/clueNotify").anonymous() //飞鱼线索主动推送API
+                .antMatchers("/common/uploadOSS").anonymous()
+//                .antMatchers("/hwcloud/upload/progress").anonymous()
+                .antMatchers("/common/uploadHuaWeiObs").anonymous()
+//                .antMatchers("/hwcloud/upload/videoUrl").anonymous()
+                .antMatchers("/common/uploadWang").anonymous()
+                .antMatchers("/common/upload").anonymous()
+                .antMatchers("/profile/**").anonymous()
+                .antMatchers("/common/download**").anonymous()
+                .antMatchers("/common/download/resource**").anonymous()
+                .antMatchers("/swagger-ui.html").anonymous()
+                .antMatchers("/swagger-resources/**").anonymous()
+                .antMatchers("/webjars/**").anonymous()
+                .antMatchers("/*/api-docs").anonymous()
+                .antMatchers("/druid/**").anonymous()
+                .antMatchers("/expense/**").anonymous()
+                // 除上面外的所有请求全部需要鉴权认证
+                .anyRequest().authenticated()
+                .and()
+                .headers().frameOptions().disable();
+
+
+        httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
+        // 添加JWT filter
+        httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
+        // 添加CORS filter
+        httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
+        httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
+    }
+
+
+    /**
+     * 强散列哈希加密实现
+     */
+    @Bean
+    public BCryptPasswordEncoder bCryptPasswordEncoder()
+    {
+        return new BCryptPasswordEncoder();
+    }
+
+    /**
+     * 身份认证接口
+     */
+    @Override
+    protected void configure(AuthenticationManagerBuilder auth) throws Exception
+    {
+        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
+    }
+}

+ 32 - 0
fs-admin/src/main/java/com/fs/core/config/ServerConfig.java

@@ -0,0 +1,32 @@
+package com.fs.core.config;
+
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.stereotype.Component;
+import com.fs.common.utils.ServletUtils;
+
+/**
+ * 服务相关配置
+ * 
+ 
+ */
+@Component
+public class ServerConfig
+{
+    /**
+     * 获取完整的请求路径,包括:域名,端口,上下文访问路径
+     * 
+     * @return 服务地址
+     */
+    public String getUrl()
+    {
+        HttpServletRequest request = ServletUtils.getRequest();
+        return getDomain(request);
+    }
+
+    public static String getDomain(HttpServletRequest request)
+    {
+        StringBuffer url = request.getRequestURL();
+        String contextPath = request.getServletContext().getContextPath();
+        return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString();
+    }
+}

+ 125 - 0
fs-admin/src/main/java/com/fs/core/config/SwaggerConfig.java

@@ -0,0 +1,125 @@
+package com.fs.core.config;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.fs.common.config.FSConfig;
+import io.swagger.annotations.ApiOperation;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.ApiKey;
+import springfox.documentation.service.AuthorizationScope;
+import springfox.documentation.service.Contact;
+import springfox.documentation.service.SecurityReference;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.service.contexts.SecurityContext;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+/**
+ * Swagger2的接口配置
+ * 
+
+ */
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig
+{
+    /** 系统基础配置 */
+    @Autowired
+    private FSConfig fsConfig;
+
+    /** 是否开启swagger */
+    @Value("${swagger.enabled}")
+    private boolean enabled;
+
+    /** 设置请求的统一前缀 */
+    @Value("${swagger.pathMapping}")
+    private String pathMapping;
+
+    /**
+     * 创建API
+     */
+    @Bean
+    public Docket createRestApi()
+    {
+        return new Docket(DocumentationType.SWAGGER_2)
+                // 是否启用Swagger
+                .enable(enabled)
+                // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
+                .apiInfo(apiInfo())
+                // 设置哪些接口暴露给Swagger展示
+                .select()
+                // 扫描所有有注解的api,用这种方式更灵活
+                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
+                // 扫描指定包中的swagger注解
+                // .apis(RequestHandlerSelectors.basePackage("com.fs.project.tool.swagger"))
+                // 扫描所有 .apis(RequestHandlerSelectors.any())
+                .paths(PathSelectors.any())
+                .build()
+                /* 设置安全模式,swagger可以设置访问token */
+                .securitySchemes(securitySchemes())
+                .securityContexts(securityContexts())
+                .pathMapping(pathMapping);
+    }
+
+    /**
+     * 安全模式,这里指定token通过Authorization头请求头传递
+     */
+    private List<ApiKey> securitySchemes()
+    {
+        List<ApiKey> apiKeyList = new ArrayList<ApiKey>();
+        apiKeyList.add(new ApiKey("Authorization", "Authorization", "header"));
+        return apiKeyList;
+    }
+
+    /**
+     * 安全上下文
+     */
+    private List<SecurityContext> securityContexts()
+    {
+        List<SecurityContext> securityContexts = new ArrayList<>();
+        securityContexts.add(
+                SecurityContext.builder()
+                        .securityReferences(defaultAuth())
+                        .forPaths(PathSelectors.regex("^(?!auth).*$"))
+                        .build());
+        return securityContexts;
+    }
+
+    /**
+     * 默认的安全上引用
+     */
+    private List<SecurityReference> defaultAuth()
+    {
+        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
+        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
+        authorizationScopes[0] = authorizationScope;
+        List<SecurityReference> securityReferences = new ArrayList<>();
+        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
+        return securityReferences;
+    }
+
+    /**
+     * 添加摘要信息
+     */
+    private ApiInfo apiInfo()
+    {
+        // 用ApiInfoBuilder进行定制
+        return new ApiInfoBuilder()
+                // 设置标题
+                .title("标题:FS管理系统_接口文档")
+                // 描述
+                .description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
+                // 作者信息
+                .contact(new Contact(fsConfig.getName(), null, null))
+                // 版本
+                .version("版本号:" + fsConfig.getVersion())
+                .build();
+    }
+}

+ 62 - 0
fs-admin/src/main/java/com/fs/core/config/ThreadPoolConfig.java

@@ -0,0 +1,62 @@
+package com.fs.core.config;
+
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadPoolExecutor;
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import com.fs.common.utils.Threads;
+
+/**
+ * 线程池配置
+ *
+ 
+ **/
+@Configuration
+public class ThreadPoolConfig
+{
+    // 核心线程池大小
+    private int corePoolSize = 50;
+
+    // 最大可创建的线程数
+    private int maxPoolSize = 200;
+
+    // 队列最大长度
+    private int queueCapacity = 1000;
+
+    // 线程池维护线程所允许的空闲时间
+    private int keepAliveSeconds = 300;
+
+    @Bean(name = "threadPoolTaskExecutor")
+    public ThreadPoolTaskExecutor threadPoolTaskExecutor()
+    {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setMaxPoolSize(maxPoolSize);
+        executor.setCorePoolSize(corePoolSize);
+        executor.setQueueCapacity(queueCapacity);
+        executor.setKeepAliveSeconds(keepAliveSeconds);
+        // 线程池对拒绝任务(无线程可用)的处理策略
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        return executor;
+    }
+
+    /**
+     * 执行周期性或定时任务
+     */
+    @Bean(name = "scheduledExecutorService")
+    protected ScheduledExecutorService scheduledExecutorService()
+    {
+        return new ScheduledThreadPoolExecutor(corePoolSize,
+                new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build())
+        {
+            @Override
+            protected void afterExecute(Runnable r, Throwable t)
+            {
+                super.afterExecute(r, t);
+                Threads.printException(r, t);
+            }
+        };
+    }
+}

+ 77 - 0
fs-admin/src/main/java/com/fs/core/config/properties/DruidProperties.java

@@ -0,0 +1,77 @@
+package com.fs.core.config.properties;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import com.alibaba.druid.pool.DruidDataSource;
+
+/**
+ * druid 配置属性
+ * 
+
+ */
+@Configuration
+public class DruidProperties
+{
+    @Value("${spring.datasource.mysql.druid.initialSize}")
+    private int initialSize;
+
+    @Value("${spring.datasource.mysql.druid.minIdle}")
+    private int minIdle;
+
+    @Value("${spring.datasource.mysql.druid.maxActive}")
+    private int maxActive;
+
+    @Value("${spring.datasource.mysql.druid.maxWait}")
+    private int maxWait;
+
+    @Value("${spring.datasource.mysql.druid.timeBetweenEvictionRunsMillis}")
+    private int timeBetweenEvictionRunsMillis;
+
+    @Value("${spring.datasource.mysql.druid.minEvictableIdleTimeMillis}")
+    private int minEvictableIdleTimeMillis;
+
+    @Value("${spring.datasource.mysql.druid.maxEvictableIdleTimeMillis}")
+    private int maxEvictableIdleTimeMillis;
+
+    @Value("${spring.datasource.mysql.druid.validationQuery}")
+    private String validationQuery;
+
+    @Value("${spring.datasource.mysql.druid.testWhileIdle}")
+    private boolean testWhileIdle;
+
+    @Value("${spring.datasource.mysql.druid.testOnBorrow}")
+    private boolean testOnBorrow;
+
+    @Value("${spring.datasource.mysql.druid.testOnReturn}")
+    private boolean testOnReturn;
+
+    public DruidDataSource dataSource(DruidDataSource datasource)
+    {
+        /** 配置初始化大小、最小、最大 */
+        datasource.setInitialSize(initialSize);
+        datasource.setMaxActive(maxActive);
+        datasource.setMinIdle(minIdle);
+
+        /** 配置获取连接等待超时的时间 */
+        datasource.setMaxWait(maxWait);
+
+        /** 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 */
+        datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
+
+        /** 配置一个连接在池中最小、最大生存的时间,单位是毫秒 */
+        datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
+        datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
+
+        /**
+         * 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
+         */
+        datasource.setValidationQuery(validationQuery);
+        /** 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 */
+        datasource.setTestWhileIdle(testWhileIdle);
+        /** 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */
+        datasource.setTestOnBorrow(testOnBorrow);
+        /** 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */
+        datasource.setTestOnReturn(testOnReturn);
+        return datasource;
+    }
+}

+ 26 - 0
fs-admin/src/main/java/com/fs/core/datasource/DynamicDataSource.java

@@ -0,0 +1,26 @@
+package com.fs.core.datasource;
+
+import java.util.Map;
+import javax.sql.DataSource;
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+
+/**
+ * 动态数据源
+ * 
+ 
+ */
+public class DynamicDataSource extends AbstractRoutingDataSource
+{
+    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources)
+    {
+        super.setDefaultTargetDataSource(defaultTargetDataSource);
+        super.setTargetDataSources(targetDataSources);
+        super.afterPropertiesSet();
+    }
+
+    @Override
+    protected Object determineCurrentLookupKey()
+    {
+        return DynamicDataSourceContextHolder.getDataSourceType();
+    }
+}

+ 45 - 0
fs-admin/src/main/java/com/fs/core/datasource/DynamicDataSourceContextHolder.java

@@ -0,0 +1,45 @@
+package com.fs.core.datasource;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 数据源切换处理
+ * 
+ 
+ */
+public class DynamicDataSourceContextHolder
+{
+    public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);
+
+    /**
+     * 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
+     *  所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
+     */
+    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
+
+    /**
+     * 设置数据源的变量
+     */
+    public static void setDataSourceType(String dsType)
+    {
+        log.info("切换到{}数据源", dsType);
+        CONTEXT_HOLDER.set(dsType);
+    }
+
+    /**
+     * 获得数据源的变量
+     */
+    public static String getDataSourceType()
+    {
+        return CONTEXT_HOLDER.get();
+    }
+
+    /**
+     * 清空数据源变量
+     */
+    public static void clearDataSourceType()
+    {
+        CONTEXT_HOLDER.remove();
+    }
+}

+ 51 - 0
fs-admin/src/main/java/com/fs/core/exception/FSException.java

@@ -0,0 +1,51 @@
+package com.fs.core.exception;
+
+/**
+ * 自定义异常
+ */
+public class FSException extends RuntimeException {
+	private static final long serialVersionUID = 1L;
+	
+    private String msg;
+    private int code = 500;
+    
+    public FSException(String msg) {
+		super(msg);
+		this.msg = msg;
+	}
+	
+	public FSException(String msg, Throwable e) {
+		super(msg, e);
+		this.msg = msg;
+	}
+	
+	public FSException(String msg, int code) {
+		super(msg);
+		this.msg = msg;
+		this.code = code;
+	}
+	
+	public FSException(String msg, int code, Throwable e) {
+		super(msg, e);
+		this.msg = msg;
+		this.code = code;
+	}
+
+	public String getMsg() {
+		return msg;
+	}
+
+	public void setMsg(String msg) {
+		this.msg = msg;
+	}
+
+	public int getCode() {
+		return code;
+	}
+
+	public void setCode(int code) {
+		this.code = code;
+	}
+	
+	
+}

+ 80 - 0
fs-admin/src/main/java/com/fs/core/exception/FSExceptionHandler.java

@@ -0,0 +1,80 @@
+package com.fs.core.exception;
+
+
+
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.exception.CustomException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.validation.BindException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.servlet.NoHandlerFoundException;
+
+
+/**
+ * 异常处理器
+ */
+@RestControllerAdvice
+public class FSExceptionHandler {
+	private Logger logger = LoggerFactory.getLogger(getClass());
+
+	/**
+	 * 处理自定义异常
+	 */
+	@ExceptionHandler(FSException.class)
+	public R handleFSException(FSException e){
+		R r = new R();
+		r.put("code", e.getCode());
+		r.put("msg", e.getMessage());
+
+		return r;
+	}
+
+	@ExceptionHandler(NoHandlerFoundException.class)
+	public R handlerNoFoundException(Exception e) {
+		logger.error(e.getMessage(), e);
+		return R.error(404, "路径不存在,请检查路径是否正确");
+	}
+
+	@ExceptionHandler(DuplicateKeyException.class)
+	public R handleDuplicateKeyException(DuplicateKeyException e){
+		logger.error(e.getMessage(), e);
+		return R.error("数据库中已存在该记录");
+	}
+
+
+	@ExceptionHandler(Exception.class)
+	public R handleException(Exception e){
+		logger.error(e.getMessage(), e);
+		return R.error();
+	}
+	@ExceptionHandler(CustomException.class)
+	public R handleException(CustomException e){
+		return R.error(e.getMessage());
+	}
+	/**
+	 * 自定义验证异常
+	 */
+	@ExceptionHandler(BindException.class)
+	public AjaxResult validatedBindException(BindException e)
+	{
+		logger.error(e.getMessage(), e);
+		String message = e.getAllErrors().get(0).getDefaultMessage();
+		return AjaxResult.error(message);
+	}
+
+	/**
+	 * 自定义验证异常
+	 */
+	@ExceptionHandler(MethodArgumentNotValidException.class)
+	public Object validExceptionHandler(MethodArgumentNotValidException e)
+	{
+		logger.error(e.getMessage(), e);
+		String message = e.getBindingResult().getFieldError().getDefaultMessage();
+		return AjaxResult.error(message);
+	}
+}

+ 55 - 0
fs-admin/src/main/java/com/fs/core/interceptor/RepeatSubmitInterceptor.java

@@ -0,0 +1,55 @@
+package com.fs.core.interceptor;
+
+import java.lang.reflect.Method;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+import com.alibaba.fastjson.JSONObject;
+import com.fs.common.annotation.RepeatSubmit;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.utils.ServletUtils;
+
+/**
+ * 防止重复提交拦截器
+ *
+
+ */
+@Component
+public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter
+{
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
+    {
+        if (handler instanceof HandlerMethod)
+        {
+            HandlerMethod handlerMethod = (HandlerMethod) handler;
+            Method method = handlerMethod.getMethod();
+            RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
+            if (annotation != null)
+            {
+                if (this.isRepeatSubmit(request))
+                {
+                    AjaxResult ajaxResult = AjaxResult.error("不允许重复提交,请稍后再试");
+                    ServletUtils.renderString(response, JSONObject.toJSONString(ajaxResult));
+                    return false;
+                }
+            }
+            return true;
+        }
+        else
+        {
+            return super.preHandle(request, response, handler);
+        }
+    }
+
+    /**
+     * 验证是否重复提交由子类实现具体的防重复提交的规则
+     *
+     * @param request
+     * @return
+     * @throws Exception
+     */
+    public abstract boolean isRepeatSubmit(HttpServletRequest request);
+}

+ 124 - 0
fs-admin/src/main/java/com/fs/core/interceptor/impl/SameUrlDataInterceptor.java

@@ -0,0 +1,124 @@
+package com.fs.core.interceptor.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import com.alibaba.fastjson.JSONObject;
+import com.fs.common.constant.Constants;
+import com.fs.common.core.redis.RedisCache;
+import com.fs.common.filter.RepeatedlyRequestWrapper;
+import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.http.HttpHelper;
+import com.fs.core.interceptor.RepeatSubmitInterceptor;
+
+/**
+ * 判断请求url和数据是否和上一次相同,
+ * 如果和上次相同,则是重复提交表单。 有效时间为10秒内。
+ * 
+ */
+@Component
+public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
+{
+    public final String REPEAT_PARAMS = "repeatParams";
+
+    public final String REPEAT_TIME = "repeatTime";
+
+    // 令牌自定义标识
+    @Value("${token.header}")
+    private String header;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    /**
+     * 间隔时间,单位:秒 默认10秒
+     * 
+     * 两次相同参数的请求,如果间隔时间大于该参数,系统不会认定为重复提交的数据
+     */
+    private int intervalTime = 10;
+
+    public void setIntervalTime(int intervalTime)
+    {
+        this.intervalTime = intervalTime;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public boolean isRepeatSubmit(HttpServletRequest request)
+    {
+        String nowParams = "";
+        if (request instanceof RepeatedlyRequestWrapper)
+        {
+            RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
+            nowParams = HttpHelper.getBodyString(repeatedlyRequest);
+        }
+
+        // body参数为空,获取Parameter的数据
+        if (StringUtils.isEmpty(nowParams))
+        {
+            nowParams = JSONObject.toJSONString(request.getParameterMap());
+        }
+        Map<String, Object> nowDataMap = new HashMap<String, Object>();
+        nowDataMap.put(REPEAT_PARAMS, nowParams);
+        nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
+
+        // 请求地址(作为存放cache的key值)
+        String url = request.getRequestURI();
+
+        // 唯一值(没有消息头则使用请求地址)
+        String submitKey = request.getHeader(header);
+        if (StringUtils.isEmpty(submitKey))
+        {
+            submitKey = url;
+        }
+
+        // 唯一标识(指定key + 消息头)
+        String cache_repeat_key = Constants.REPEAT_SUBMIT_KEY + submitKey;
+
+        Object sessionObj = redisCache.getCacheObject(cache_repeat_key);
+        if (sessionObj != null)
+        {
+            Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
+            if (sessionMap.containsKey(url))
+            {
+                Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
+                if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap))
+                {
+                    return true;
+                }
+            }
+        }
+        Map<String, Object> cacheMap = new HashMap<String, Object>();
+        cacheMap.put(url, nowDataMap);
+        redisCache.setCacheObject(cache_repeat_key, cacheMap, intervalTime, TimeUnit.SECONDS);
+        return false;
+    }
+
+    /**
+     * 判断参数是否相同
+     */
+    private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap)
+    {
+        String nowParams = (String) nowMap.get(REPEAT_PARAMS);
+        String preParams = (String) preMap.get(REPEAT_PARAMS);
+        return nowParams.equals(preParams);
+    }
+
+    /**
+     * 判断两次间隔时间
+     */
+    private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap)
+    {
+        long time1 = (Long) nowMap.get(REPEAT_TIME);
+        long time2 = (Long) preMap.get(REPEAT_TIME);
+        if ((time1 - time2) < (this.intervalTime * 1000))
+        {
+            return true;
+        }
+        return false;
+    }
+}

+ 55 - 0
fs-admin/src/main/java/com/fs/core/manager/AsyncManager.java

@@ -0,0 +1,55 @@
+package com.fs.core.manager;
+
+import java.util.TimerTask;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import com.fs.common.utils.Threads;
+import com.fs.common.utils.spring.SpringUtils;
+
+/**
+ * 异步任务管理器
+ * 
+ 
+ */
+public class AsyncManager
+{
+    /**
+     * 操作延迟10毫秒
+     */
+    private final int OPERATE_DELAY_TIME = 10;
+
+    /**
+     * 异步操作任务调度线程池
+     */
+    private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
+
+    /**
+     * 单例模式
+     */
+    private AsyncManager(){}
+
+    private static AsyncManager me = new AsyncManager();
+
+    public static AsyncManager me()
+    {
+        return me;
+    }
+
+    /**
+     * 执行任务
+     * 
+     * @param task 任务
+     */
+    public void execute(TimerTask task)
+    {
+        executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * 停止任务线程池
+     */
+    public void shutdown()
+    {
+        Threads.shutdownAndAwaitTermination(executor);
+    }
+}

+ 39 - 0
fs-admin/src/main/java/com/fs/core/manager/ShutdownManager.java

@@ -0,0 +1,39 @@
+package com.fs.core.manager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import javax.annotation.PreDestroy;
+
+/**
+ * 确保应用退出时能关闭后台线程
+ *
+ 
+ */
+@Component
+public class ShutdownManager
+{
+    private static final Logger logger = LoggerFactory.getLogger("sys-user");
+
+    @PreDestroy
+    public void destroy()
+    {
+        shutdownAsyncManager();
+    }
+
+    /**
+     * 停止异步执行任务
+     */
+    private void shutdownAsyncManager()
+    {
+        try
+        {
+            logger.info("====关闭后台任务任务线程池====");
+            AsyncManager.me().shutdown();
+        }
+        catch (Exception e)
+        {
+            logger.error(e.getMessage(), e);
+        }
+    }
+}

+ 101 - 0
fs-admin/src/main/java/com/fs/core/manager/factory/AsyncFactory.java

@@ -0,0 +1,101 @@
+package com.fs.core.manager.factory;
+
+import java.util.TimerTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.fs.common.constant.Constants;
+import com.fs.common.utils.LogUtils;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.ip.AddressUtils;
+import com.fs.common.utils.ip.IpUtils;
+import com.fs.common.utils.spring.SpringUtils;
+import com.fs.system.domain.SysLogininfor;
+import com.fs.system.domain.SysOperLog;
+import com.fs.system.service.ISysLogininforService;
+import com.fs.system.service.ISysOperLogService;
+import eu.bitwalker.useragentutils.UserAgent;
+
+/**
+ * 异步工厂(产生任务用)
+ * 
+
+ */
+public class AsyncFactory
+{
+    private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
+
+    /**
+     * 记录登录信息
+     * 
+     * @param username 用户名
+     * @param status 状态
+     * @param message 消息
+     * @param args 列表
+     * @return 任务task
+     */
+    public static TimerTask recordLogininfor(final String username, final String status, final String message,
+            final Object... args)
+    {
+        final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
+        final String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
+        return new TimerTask()
+        {
+            @Override
+            public void run()
+            {
+                String address = AddressUtils.getRealAddressByIP(ip);
+                StringBuilder s = new StringBuilder();
+                s.append(LogUtils.getBlock(ip));
+                s.append(address);
+                s.append(LogUtils.getBlock(username));
+                s.append(LogUtils.getBlock(status));
+                s.append(LogUtils.getBlock(message));
+                // 打印信息到日志
+                sys_user_logger.info(s.toString(), args);
+                // 获取客户端操作系统
+                String os = userAgent.getOperatingSystem().getName();
+                // 获取客户端浏览器
+                String browser = userAgent.getBrowser().getName();
+                // 封装对象
+                SysLogininfor logininfor = new SysLogininfor();
+                logininfor.setUserName(username);
+                logininfor.setIpaddr(ip);
+                logininfor.setLoginLocation(address);
+                logininfor.setBrowser(browser);
+                logininfor.setOs(os);
+                logininfor.setMsg(message);
+                // 日志状态
+                if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status))
+                {
+                    logininfor.setStatus(Constants.SUCCESS);
+                }
+                else if (Constants.LOGIN_FAIL.equals(status))
+                {
+                    logininfor.setStatus(Constants.FAIL);
+                }
+                // 插入数据
+                SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor);
+            }
+        };
+    }
+
+    /**
+     * 操作日志记录
+     * 
+     * @param operLog 操作日志信息
+     * @return 任务task
+     */
+    public static TimerTask recordOper(final SysOperLog operLog)
+    {
+        return new TimerTask()
+        {
+            @Override
+            public void run()
+            {
+                // 远程查询操作地点
+                operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
+                SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);
+            }
+        };
+    }
+}

+ 69 - 0
fs-admin/src/main/java/com/fs/core/security/LoginBody.java

@@ -0,0 +1,69 @@
+package com.fs.core.security;
+
+/**
+ * 用户登录对象
+ * 
+
+ */
+public class LoginBody
+{
+    /**
+     * 用户名
+     */
+    private String username;
+
+    /**
+     * 用户密码
+     */
+    private String password;
+
+    /**
+     * 验证码
+     */
+    private String code;
+
+    /**
+     * 唯一标识
+     */
+    private String uuid = "";
+
+    public String getUsername()
+    {
+        return username;
+    }
+
+    public void setUsername(String username)
+    {
+        this.username = username;
+    }
+
+    public String getPassword()
+    {
+        return password;
+    }
+
+    public void setPassword(String password)
+    {
+        this.password = password;
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public void setCode(String code)
+    {
+        this.code = code;
+    }
+
+    public String getUuid()
+    {
+        return uuid;
+    }
+
+    public void setUuid(String uuid)
+    {
+        this.uuid = uuid;
+    }
+}

+ 229 - 0
fs-admin/src/main/java/com/fs/core/security/LoginUser.java

@@ -0,0 +1,229 @@
+package com.fs.core.security;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fs.common.core.domain.entity.SysUser;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * 登录用户身份权限
+ * 
+
+ */
+public class LoginUser implements UserDetails
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 用户唯一标识
+     */
+    private String token;
+
+    /**
+     * 登录时间
+     */
+    private Long loginTime;
+
+    /**
+     * 过期时间
+     */
+    private Long expireTime;
+
+    /**
+     * 登录IP地址
+     */
+    private String ipaddr;
+
+    /**
+     * 登录地点
+     */
+    private String loginLocation;
+
+    /**
+     * 浏览器类型
+     */
+    private String browser;
+
+    /**
+     * 操作系统
+     */
+    private String os;
+
+    /**
+     * 权限列表
+     */
+    private Set<String> permissions;
+
+    /**
+     * 用户信息
+     */
+    private SysUser user;
+
+    public String getToken()
+    {
+        return token;
+    }
+
+    public void setToken(String token)
+    {
+        this.token = token;
+    }
+
+    public LoginUser()
+    {
+    }
+
+    public LoginUser(SysUser user, Set<String> permissions)
+    {
+        this.user = user;
+        this.permissions = permissions;
+    }
+
+    @JsonIgnore
+    @Override
+    public String getPassword()
+    {
+        return user.getPassword();
+    }
+
+    @Override
+    public String getUsername()
+    {
+        return user.getUserName();
+    }
+
+    /**
+     * 账户是否未过期,过期无法验证
+     */
+    @JsonIgnore
+    @Override
+    public boolean isAccountNonExpired()
+    {
+        return true;
+    }
+
+    /**
+     * 指定用户是否解锁,锁定的用户无法进行身份验证
+     * 
+     * @return
+     */
+    @JsonIgnore
+    @Override
+    public boolean isAccountNonLocked()
+    {
+        return true;
+    }
+
+    /**
+     * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
+     * 
+     * @return
+     */
+    @JsonIgnore
+    @Override
+    public boolean isCredentialsNonExpired()
+    {
+        return true;
+    }
+
+    /**
+     * 是否可用 ,禁用的用户不能身份验证
+     * 
+     * @return
+     */
+    @JsonIgnore
+    @Override
+    public boolean isEnabled()
+    {
+        return true;
+    }
+
+    public Long getLoginTime()
+    {
+        return loginTime;
+    }
+
+    public void setLoginTime(Long loginTime)
+    {
+        this.loginTime = loginTime;
+    }
+
+    public String getIpaddr()
+    {
+        return ipaddr;
+    }
+
+    public void setIpaddr(String ipaddr)
+    {
+        this.ipaddr = ipaddr;
+    }
+
+    public String getLoginLocation()
+    {
+        return loginLocation;
+    }
+
+    public void setLoginLocation(String loginLocation)
+    {
+        this.loginLocation = loginLocation;
+    }
+
+    public String getBrowser()
+    {
+        return browser;
+    }
+
+    public void setBrowser(String browser)
+    {
+        this.browser = browser;
+    }
+
+    public String getOs()
+    {
+        return os;
+    }
+
+    public void setOs(String os)
+    {
+        this.os = os;
+    }
+
+    public Long getExpireTime()
+    {
+        return expireTime;
+    }
+
+    public void setExpireTime(Long expireTime)
+    {
+        this.expireTime = expireTime;
+    }
+
+    public Set<String> getPermissions()
+    {
+        return permissions;
+    }
+
+    public void setPermissions(Set<String> permissions)
+    {
+        this.permissions = permissions;
+    }
+
+    public SysUser getUser()
+    {
+        return user;
+    }
+
+    public void setUser(SysUser user)
+    {
+        this.user = user;
+    }
+
+    @Override
+    public Collection<? extends GrantedAuthority> getAuthorities()
+    {
+        return null;
+    }
+}

+ 90 - 0
fs-admin/src/main/java/com/fs/core/security/SecurityUtils.java

@@ -0,0 +1,90 @@
+package com.fs.core.security;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import com.fs.common.constant.HttpStatus;
+
+import com.fs.common.exception.CustomException;
+
+/**
+ * 安全服务工具类
+ * 
+
+ */
+public class SecurityUtils
+{
+    /**
+     * 获取用户账户
+     **/
+    public static String getUsername()
+    {
+        try
+        {
+            return getLoginUser().getUsername();
+        }
+        catch (Exception e)
+        {
+            throw new CustomException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
+        }
+    }
+
+    /**
+     * 获取用户
+     **/
+    public static LoginUser getLoginUser()
+    {
+        try
+        {
+            return (LoginUser) getAuthentication().getPrincipal();
+        }
+        catch (Exception e)
+        {
+            throw new CustomException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
+        }
+    }
+
+    /**
+     * 获取Authentication
+     */
+    public static Authentication getAuthentication()
+    {
+        return SecurityContextHolder.getContext().getAuthentication();
+    }
+
+    /**
+     * 生成BCryptPasswordEncoder密码
+     *
+     * @param password 密码
+     * @return 加密字符串
+     */
+    public static String encryptPassword(String password)
+    {
+        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+        return passwordEncoder.encode(password);
+    }
+
+    /**
+     * 判断密码是否相同
+     *
+     * @param rawPassword 真实密码
+     * @param encodedPassword 加密后字符
+     * @return 结果
+     */
+    public static boolean matchesPassword(String rawPassword, String encodedPassword)
+    {
+        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+        return passwordEncoder.matches(rawPassword, encodedPassword);
+    }
+
+    /**
+     * 是否为管理员
+     * 
+     * @param userId 用户ID
+     * @return 结果
+     */
+    public static boolean isAdmin(Long userId)
+    {
+        return userId != null && 1L == userId;
+    }
+}

+ 55 - 0
fs-admin/src/main/java/com/fs/core/security/filter/JwtAuthenticationTokenFilter.java

@@ -0,0 +1,55 @@
+package com.fs.core.security.filter;
+
+import java.io.IOException;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.fs.common.core.redis.RedisCache;
+import com.fs.core.exception.FSException;
+import com.fs.core.security.LoginUser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+import com.fs.core.security.SecurityUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.core.web.service.TokenService;
+
+/**
+ * token过滤器 验证token有效性
+ *
+
+ */
+@Component
+public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
+{
+    @Autowired
+    private TokenService tokenService;
+    @Autowired
+    private RedisCache redisCache;
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+            throws ServletException, IOException
+    {
+        LoginUser loginUser = tokenService.getLoginUser(request);
+        if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
+        {
+            //如果REDIS中的TOKEN与请求的TOKEN不一致,抛出异常
+            String requestToken = tokenService.getHeaderToken(request).substring(7);
+            String token=redisCache.getCacheObject("token-pc:"+loginUser.getUsername());
+            if(!token.equals(requestToken)){
+                throw new FSException("Token失效,请重新登录", HttpStatus.UNAUTHORIZED.value());
+            }
+            tokenService.verifyToken(loginUser);
+            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
+            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+        }
+        chain.doFilter(request, response);
+    }
+}

+ 34 - 0
fs-admin/src/main/java/com/fs/core/security/handle/AuthenticationEntryPointImpl.java

@@ -0,0 +1,34 @@
+package com.fs.core.security.handle;
+
+import java.io.IOException;
+import java.io.Serializable;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+import com.alibaba.fastjson.JSON;
+import com.fs.common.constant.HttpStatus;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
+
+/**
+ * 认证失败处理类 返回未授权
+ * 
+ 
+ */
+@Component
+public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable
+{
+    private static final long serialVersionUID = -8970718410437077606L;
+
+    @Override
+    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)
+            throws IOException
+    {
+        int code = HttpStatus.UNAUTHORIZED;
+        String msg = StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI());
+        ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg)));
+    }
+}

+ 54 - 0
fs-admin/src/main/java/com/fs/core/security/handle/LogoutSuccessHandlerImpl.java

@@ -0,0 +1,54 @@
+package com.fs.core.security.handle;
+
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.fs.core.security.LoginUser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
+import com.alibaba.fastjson.JSON;
+import com.fs.common.constant.Constants;
+import com.fs.common.constant.HttpStatus;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.core.manager.AsyncManager;
+import com.fs.core.manager.factory.AsyncFactory;
+import com.fs.core.web.service.TokenService;
+
+/**
+ * 自定义退出处理类 返回成功
+ * 
+
+ */
+@Configuration
+public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler
+{
+    @Autowired
+    private TokenService tokenService;
+
+    /**
+     * 退出处理
+     * 
+     * @return
+     */
+    @Override
+    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
+            throws IOException, ServletException
+    {
+        LoginUser loginUser = tokenService.getLoginUser(request);
+        if (StringUtils.isNotNull(loginUser))
+        {
+            String userName = loginUser.getUsername();
+            // 删除用户缓存记录
+            tokenService.delLoginUser(loginUser.getToken());
+            // 记录用户退出日志
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "退出成功"));
+        }
+        ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(HttpStatus.SUCCESS, "退出成功")));
+    }
+}

+ 240 - 0
fs-admin/src/main/java/com/fs/core/web/domain/Server.java

@@ -0,0 +1,240 @@
+package com.fs.core.web.domain;
+
+import java.net.UnknownHostException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import com.fs.common.utils.Arith;
+import com.fs.common.utils.ip.IpUtils;
+import com.fs.core.web.domain.server.Cpu;
+import com.fs.core.web.domain.server.Jvm;
+import com.fs.core.web.domain.server.Mem;
+import com.fs.core.web.domain.server.Sys;
+import com.fs.core.web.domain.server.SysFile;
+import oshi.SystemInfo;
+import oshi.hardware.CentralProcessor;
+import oshi.hardware.CentralProcessor.TickType;
+import oshi.hardware.GlobalMemory;
+import oshi.hardware.HardwareAbstractionLayer;
+import oshi.software.os.FileSystem;
+import oshi.software.os.OSFileStore;
+import oshi.software.os.OperatingSystem;
+import oshi.util.Util;
+
+/**
+ * 服务器相关信息
+ * 
+ 
+ */
+public class Server
+{
+    private static final int OSHI_WAIT_SECOND = 1000;
+    
+    /**
+     * CPU相关信息
+     */
+    private Cpu cpu = new Cpu();
+
+    /**
+     * 內存相关信息
+     */
+    private Mem mem = new Mem();
+
+    /**
+     * JVM相关信息
+     */
+    private Jvm jvm = new Jvm();
+
+    /**
+     * 服务器相关信息
+     */
+    private Sys sys = new Sys();
+
+    /**
+     * 磁盘相关信息
+     */
+    private List<SysFile> sysFiles = new LinkedList<SysFile>();
+
+    public Cpu getCpu()
+    {
+        return cpu;
+    }
+
+    public void setCpu(Cpu cpu)
+    {
+        this.cpu = cpu;
+    }
+
+    public Mem getMem()
+    {
+        return mem;
+    }
+
+    public void setMem(Mem mem)
+    {
+        this.mem = mem;
+    }
+
+    public Jvm getJvm()
+    {
+        return jvm;
+    }
+
+    public void setJvm(Jvm jvm)
+    {
+        this.jvm = jvm;
+    }
+
+    public Sys getSys()
+    {
+        return sys;
+    }
+
+    public void setSys(Sys sys)
+    {
+        this.sys = sys;
+    }
+
+    public List<SysFile> getSysFiles()
+    {
+        return sysFiles;
+    }
+
+    public void setSysFiles(List<SysFile> sysFiles)
+    {
+        this.sysFiles = sysFiles;
+    }
+
+    public void copyTo() throws Exception
+    {
+        SystemInfo si = new SystemInfo();
+        HardwareAbstractionLayer hal = si.getHardware();
+
+        setCpuInfo(hal.getProcessor());
+
+        setMemInfo(hal.getMemory());
+
+        setSysInfo();
+
+        setJvmInfo();
+
+        setSysFiles(si.getOperatingSystem());
+    }
+
+    /**
+     * 设置CPU信息
+     */
+    private void setCpuInfo(CentralProcessor processor)
+    {
+        // CPU信息
+        long[] prevTicks = processor.getSystemCpuLoadTicks();
+        Util.sleep(OSHI_WAIT_SECOND);
+        long[] ticks = processor.getSystemCpuLoadTicks();
+        long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
+        long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
+        long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];
+        long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];
+        long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];
+        long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];
+        long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];
+        long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];
+        long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
+        cpu.setCpuNum(processor.getLogicalProcessorCount());
+        cpu.setTotal(totalCpu);
+        cpu.setSys(cSys);
+        cpu.setUsed(user);
+        cpu.setWait(iowait);
+        cpu.setFree(idle);
+    }
+
+    /**
+     * 设置内存信息
+     */
+    private void setMemInfo(GlobalMemory memory)
+    {
+        mem.setTotal(memory.getTotal());
+        mem.setUsed(memory.getTotal() - memory.getAvailable());
+        mem.setFree(memory.getAvailable());
+    }
+
+    /**
+     * 设置服务器信息
+     */
+    private void setSysInfo()
+    {
+        Properties props = System.getProperties();
+        sys.setComputerName(IpUtils.getHostName());
+        sys.setComputerIp(IpUtils.getHostIp());
+        sys.setOsName(props.getProperty("os.name"));
+        sys.setOsArch(props.getProperty("os.arch"));
+        sys.setUserDir(props.getProperty("user.dir"));
+    }
+
+    /**
+     * 设置Java虚拟机
+     */
+    private void setJvmInfo() throws UnknownHostException
+    {
+        Properties props = System.getProperties();
+        jvm.setTotal(Runtime.getRuntime().totalMemory());
+        jvm.setMax(Runtime.getRuntime().maxMemory());
+        jvm.setFree(Runtime.getRuntime().freeMemory());
+        jvm.setVersion(props.getProperty("java.version"));
+        jvm.setHome(props.getProperty("java.home"));
+    }
+
+    /**
+     * 设置磁盘信息
+     */
+    private void setSysFiles(OperatingSystem os)
+    {
+        FileSystem fileSystem = os.getFileSystem();
+        List<OSFileStore> fsArray = fileSystem.getFileStores();
+        for (OSFileStore fs : fsArray)
+        {
+            long free = fs.getUsableSpace();
+            long total = fs.getTotalSpace();
+            long used = total - free;
+            SysFile sysFile = new SysFile();
+            sysFile.setDirName(fs.getMount());
+            sysFile.setSysTypeName(fs.getType());
+            sysFile.setTypeName(fs.getName());
+            sysFile.setTotal(convertFileSize(total));
+            sysFile.setFree(convertFileSize(free));
+            sysFile.setUsed(convertFileSize(used));
+            sysFile.setUsage(Arith.mul(Arith.div(used, total, 4), 100));
+            sysFiles.add(sysFile);
+        }
+    }
+
+    /**
+     * 字节转换
+     * 
+     * @param size 字节大小
+     * @return 转换后值
+     */
+    public String convertFileSize(long size)
+    {
+        long kb = 1024;
+        long mb = kb * 1024;
+        long gb = mb * 1024;
+        if (size >= gb)
+        {
+            return String.format("%.1f GB", (float) size / gb);
+        }
+        else if (size >= mb)
+        {
+            float f = (float) size / mb;
+            return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);
+        }
+        else if (size >= kb)
+        {
+            float f = (float) size / kb;
+            return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);
+        }
+        else
+        {
+            return String.format("%d B", size);
+        }
+    }
+}

+ 101 - 0
fs-admin/src/main/java/com/fs/core/web/domain/server/Cpu.java

@@ -0,0 +1,101 @@
+package com.fs.core.web.domain.server;
+
+import com.fs.common.utils.Arith;
+
+/**
+ * CPU相关信息
+ * 
+
+ */
+public class Cpu
+{
+    /**
+     * 核心数
+     */
+    private int cpuNum;
+
+    /**
+     * CPU总的使用率
+     */
+    private double total;
+
+    /**
+     * CPU系统使用率
+     */
+    private double sys;
+
+    /**
+     * CPU用户使用率
+     */
+    private double used;
+
+    /**
+     * CPU当前等待率
+     */
+    private double wait;
+
+    /**
+     * CPU当前空闲率
+     */
+    private double free;
+
+    public int getCpuNum()
+    {
+        return cpuNum;
+    }
+
+    public void setCpuNum(int cpuNum)
+    {
+        this.cpuNum = cpuNum;
+    }
+
+    public double getTotal()
+    {
+        return Arith.round(Arith.mul(total, 100), 2);
+    }
+
+    public void setTotal(double total)
+    {
+        this.total = total;
+    }
+
+    public double getSys()
+    {
+        return Arith.round(Arith.mul(sys / total, 100), 2);
+    }
+
+    public void setSys(double sys)
+    {
+        this.sys = sys;
+    }
+
+    public double getUsed()
+    {
+        return Arith.round(Arith.mul(used / total, 100), 2);
+    }
+
+    public void setUsed(double used)
+    {
+        this.used = used;
+    }
+
+    public double getWait()
+    {
+        return Arith.round(Arith.mul(wait / total, 100), 2);
+    }
+
+    public void setWait(double wait)
+    {
+        this.wait = wait;
+    }
+
+    public double getFree()
+    {
+        return Arith.round(Arith.mul(free / total, 100), 2);
+    }
+
+    public void setFree(double free)
+    {
+        this.free = free;
+    }
+}

+ 122 - 0
fs-admin/src/main/java/com/fs/core/web/domain/server/Jvm.java

@@ -0,0 +1,122 @@
+package com.fs.core.web.domain.server;
+
+import java.lang.management.ManagementFactory;
+import com.fs.common.utils.Arith;
+import com.fs.common.utils.DateUtils;
+
+/**
+ * JVM相关信息
+ * 
+
+ */
+public class Jvm
+{
+    /**
+     * 当前JVM占用的内存总数(M)
+     */
+    private double total;
+
+    /**
+     * JVM最大可用内存总数(M)
+     */
+    private double max;
+
+    /**
+     * JVM空闲内存(M)
+     */
+    private double free;
+
+    /**
+     * JDK版本
+     */
+    private String version;
+
+    /**
+     * JDK路径
+     */
+    private String home;
+
+    public double getTotal()
+    {
+        return Arith.div(total, (1024 * 1024), 2);
+    }
+
+    public void setTotal(double total)
+    {
+        this.total = total;
+    }
+
+    public double getMax()
+    {
+        return Arith.div(max, (1024 * 1024), 2);
+    }
+
+    public void setMax(double max)
+    {
+        this.max = max;
+    }
+
+    public double getFree()
+    {
+        return Arith.div(free, (1024 * 1024), 2);
+    }
+
+    public void setFree(double free)
+    {
+        this.free = free;
+    }
+
+    public double getUsed()
+    {
+        return Arith.div(total - free, (1024 * 1024), 2);
+    }
+
+    public double getUsage()
+    {
+        return Arith.mul(Arith.div(total - free, total, 4), 100);
+    }
+
+    /**
+     * 获取JDK名称
+     */
+    public String getName()
+    {
+        return ManagementFactory.getRuntimeMXBean().getVmName();
+    }
+
+    public String getVersion()
+    {
+        return version;
+    }
+
+    public void setVersion(String version)
+    {
+        this.version = version;
+    }
+
+    public String getHome()
+    {
+        return home;
+    }
+
+    public void setHome(String home)
+    {
+        this.home = home;
+    }
+
+    /**
+     * JDK启动时间
+     */
+    public String getStartTime()
+    {
+        return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getServerStartDate());
+    }
+
+    /**
+     * JDK运行时间
+     */
+    public String getRunTime()
+    {
+        return DateUtils.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate());
+    }
+}

+ 61 - 0
fs-admin/src/main/java/com/fs/core/web/domain/server/Mem.java

@@ -0,0 +1,61 @@
+package com.fs.core.web.domain.server;
+
+import com.fs.common.utils.Arith;
+
+/**
+ * 內存相关信息
+ * 
+ 
+ */
+public class Mem
+{
+    /**
+     * 内存总量
+     */
+    private double total;
+
+    /**
+     * 已用内存
+     */
+    private double used;
+
+    /**
+     * 剩余内存
+     */
+    private double free;
+
+    public double getTotal()
+    {
+        return Arith.div(total, (1024 * 1024 * 1024), 2);
+    }
+
+    public void setTotal(long total)
+    {
+        this.total = total;
+    }
+
+    public double getUsed()
+    {
+        return Arith.div(used, (1024 * 1024 * 1024), 2);
+    }
+
+    public void setUsed(long used)
+    {
+        this.used = used;
+    }
+
+    public double getFree()
+    {
+        return Arith.div(free, (1024 * 1024 * 1024), 2);
+    }
+
+    public void setFree(long free)
+    {
+        this.free = free;
+    }
+
+    public double getUsage()
+    {
+        return Arith.mul(Arith.div(used, total, 4), 100);
+    }
+}

+ 84 - 0
fs-admin/src/main/java/com/fs/core/web/domain/server/Sys.java

@@ -0,0 +1,84 @@
+package com.fs.core.web.domain.server;
+
+/**
+ * 系统相关信息
+ * 
+
+ */
+public class Sys
+{
+    /**
+     * 服务器名称
+     */
+    private String computerName;
+
+    /**
+     * 服务器Ip
+     */
+    private String computerIp;
+
+    /**
+     * 项目路径
+     */
+    private String userDir;
+
+    /**
+     * 操作系统
+     */
+    private String osName;
+
+    /**
+     * 系统架构
+     */
+    private String osArch;
+
+    public String getComputerName()
+    {
+        return computerName;
+    }
+
+    public void setComputerName(String computerName)
+    {
+        this.computerName = computerName;
+    }
+
+    public String getComputerIp()
+    {
+        return computerIp;
+    }
+
+    public void setComputerIp(String computerIp)
+    {
+        this.computerIp = computerIp;
+    }
+
+    public String getUserDir()
+    {
+        return userDir;
+    }
+
+    public void setUserDir(String userDir)
+    {
+        this.userDir = userDir;
+    }
+
+    public String getOsName()
+    {
+        return osName;
+    }
+
+    public void setOsName(String osName)
+    {
+        this.osName = osName;
+    }
+
+    public String getOsArch()
+    {
+        return osArch;
+    }
+
+    public void setOsArch(String osArch)
+    {
+        this.osArch = osArch;
+    }
+}

+ 114 - 0
fs-admin/src/main/java/com/fs/core/web/domain/server/SysFile.java

@@ -0,0 +1,114 @@
+package com.fs.core.web.domain.server;
+
+/**
+ * 系统文件相关信息
+ * 
+
+ */
+public class SysFile
+{
+    /**
+     * 盘符路径
+     */
+    private String dirName;
+
+    /**
+     * 盘符类型
+     */
+    private String sysTypeName;
+
+    /**
+     * 文件类型
+     */
+    private String typeName;
+
+    /**
+     * 总大小
+     */
+    private String total;
+
+    /**
+     * 剩余大小
+     */
+    private String free;
+
+    /**
+     * 已经使用量
+     */
+    private String used;
+
+    /**
+     * 资源的使用率
+     */
+    private double usage;
+
+    public String getDirName()
+    {
+        return dirName;
+    }
+
+    public void setDirName(String dirName)
+    {
+        this.dirName = dirName;
+    }
+
+    public String getSysTypeName()
+    {
+        return sysTypeName;
+    }
+
+    public void setSysTypeName(String sysTypeName)
+    {
+        this.sysTypeName = sysTypeName;
+    }
+
+    public String getTypeName()
+    {
+        return typeName;
+    }
+
+    public void setTypeName(String typeName)
+    {
+        this.typeName = typeName;
+    }
+
+    public String getTotal()
+    {
+        return total;
+    }
+
+    public void setTotal(String total)
+    {
+        this.total = total;
+    }
+
+    public String getFree()
+    {
+        return free;
+    }
+
+    public void setFree(String free)
+    {
+        this.free = free;
+    }
+
+    public String getUsed()
+    {
+        return used;
+    }
+
+    public void setUsed(String used)
+    {
+        this.used = used;
+    }
+
+    public double getUsage()
+    {
+        return usage;
+    }
+
+    public void setUsage(double usage)
+    {
+        this.usage = usage;
+    }
+}

+ 117 - 0
fs-admin/src/main/java/com/fs/core/web/exception/GlobalExceptionHandler.java

@@ -0,0 +1,117 @@
+package com.fs.core.web.exception;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.authentication.AccountExpiredException;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.validation.BindException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.servlet.NoHandlerFoundException;
+import com.fs.common.constant.HttpStatus;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.exception.BaseException;
+import com.fs.common.exception.CustomException;
+import com.fs.common.exception.DemoModeException;
+import com.fs.common.utils.StringUtils;
+
+/**
+ * 全局异常处理器
+ * 
+
+ */
+@RestControllerAdvice
+public class GlobalExceptionHandler
+{
+    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+    /**
+     * 基础异常
+     */
+    @ExceptionHandler(BaseException.class)
+    public AjaxResult baseException(BaseException e)
+    {
+        return AjaxResult.error(e.getMessage());
+    }
+
+    /**
+     * 业务异常
+     */
+    @ExceptionHandler(CustomException.class)
+    public AjaxResult businessException(CustomException e)
+    {
+        if (StringUtils.isNull(e.getCode()))
+        {
+            return AjaxResult.error(e.getMessage());
+        }
+        return AjaxResult.error(e.getCode(), e.getMessage());
+    }
+
+    @ExceptionHandler(NoHandlerFoundException.class)
+    public AjaxResult handlerNoFoundException(Exception e)
+    {
+        log.error(e.getMessage(), e);
+        return AjaxResult.error(HttpStatus.NOT_FOUND, "路径不存在,请检查路径是否正确");
+    }
+
+    @ExceptionHandler(AccessDeniedException.class)
+    public AjaxResult handleAuthorizationException(AccessDeniedException e)
+    {
+        log.error(e.getMessage());
+        return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限,请联系管理员授权");
+    }
+
+    @ExceptionHandler(AccountExpiredException.class)
+    public AjaxResult handleAccountExpiredException(AccountExpiredException e)
+    {
+        log.error(e.getMessage(), e);
+        return AjaxResult.error(e.getMessage());
+    }
+
+    @ExceptionHandler(UsernameNotFoundException.class)
+    public AjaxResult handleUsernameNotFoundException(UsernameNotFoundException e)
+    {
+        log.error(e.getMessage(), e);
+        return AjaxResult.error(e.getMessage());
+    }
+
+    @ExceptionHandler(Exception.class)
+    public AjaxResult handleException(Exception e)
+    {
+        log.error(e.getMessage(), e);
+        return AjaxResult.error(e.getMessage());
+    }
+
+    /**
+     * 自定义验证异常
+     */
+    @ExceptionHandler(BindException.class)
+    public AjaxResult validatedBindException(BindException e)
+    {
+        log.error(e.getMessage(), e);
+        String message = e.getAllErrors().get(0).getDefaultMessage();
+        return AjaxResult.error(message);
+    }
+
+    /**
+     * 自定义验证异常
+     */
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public Object validExceptionHandler(MethodArgumentNotValidException e)
+    {
+        log.error(e.getMessage(), e);
+        String message = e.getBindingResult().getFieldError().getDefaultMessage();
+        return AjaxResult.error(message);
+    }
+
+    /**
+     * 演示模式异常
+     */
+    @ExceptionHandler(DemoModeException.class)
+    public AjaxResult demoModeException(DemoModeException e)
+    {
+        return AjaxResult.error("演示模式,不允许操作");
+    }
+}

+ 170 - 0
fs-admin/src/main/java/com/fs/core/web/service/PermissionService.java

@@ -0,0 +1,170 @@
+package com.fs.core.web.service;
+
+import java.util.Set;
+
+import com.fs.core.security.LoginUser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import com.fs.common.core.domain.entity.SysRole;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
+
+/**
+ * 自定义权限实现,ss取自SpringSecurity首字母
+ */
+@Service("ss")
+public class PermissionService
+{
+    /** 所有权限标识 */
+    private static final String ALL_PERMISSION = "*:*:*";
+
+    /** 管理员角色权限标识 */
+    private static final String SUPER_ADMIN = "admin";
+
+    private static final String ROLE_DELIMETER = ",";
+
+    private static final String PERMISSION_DELIMETER = ",";
+
+    @Autowired
+    private TokenService tokenService;
+
+    /**
+     * 验证用户是否具备某权限
+     * 
+     * @param permission 权限字符串
+     * @return 用户是否具备某权限
+     */
+    public boolean hasPermi(String permission)
+    {
+        if (StringUtils.isEmpty(permission))
+        {
+            return false;
+        }
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
+        {
+            return false;
+        }
+        return hasPermissions(loginUser.getPermissions(), permission);
+    }
+
+    /**
+     * 验证用户是否不具备某权限,与 hasPermi逻辑相反
+     *
+     * @param permission 权限字符串
+     * @return 用户是否不具备某权限
+     */
+    public boolean lacksPermi(String permission)
+    {
+        return hasPermi(permission) != true;
+    }
+
+    /**
+     * 验证用户是否具有以下任意一个权限
+     *
+     * @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
+     * @return 用户是否具有以下任意一个权限
+     */
+    public boolean hasAnyPermi(String permissions)
+    {
+        if (StringUtils.isEmpty(permissions))
+        {
+            return false;
+        }
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
+        {
+            return false;
+        }
+        Set<String> authorities = loginUser.getPermissions();
+        for (String permission : permissions.split(PERMISSION_DELIMETER))
+        {
+            if (permission != null && hasPermissions(authorities, permission))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 判断用户是否拥有某个角色
+     * 
+     * @param role 角色字符串
+     * @return 用户是否具备某角色
+     */
+    public boolean hasRole(String role)
+    {
+        if (StringUtils.isEmpty(role))
+        {
+            return false;
+        }
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
+        {
+            return false;
+        }
+        for (SysRole sysRole : loginUser.getUser().getRoles())
+        {
+            String roleKey = sysRole.getRoleKey();
+            if (SUPER_ADMIN.contains(roleKey) || roleKey.contains(StringUtils.trim(role)))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 验证用户是否不具备某角色,与 isRole逻辑相反。
+     *
+     * @param role 角色名称
+     * @return 用户是否不具备某角色
+     */
+    public boolean lacksRole(String role)
+    {
+        return hasRole(role) != true;
+    }
+
+    /**
+     * 验证用户是否具有以下任意一个角色
+     *
+     * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
+     * @return 用户是否具有以下任意一个角色
+     */
+    public boolean hasAnyRoles(String roles)
+    {
+        if (StringUtils.isEmpty(roles))
+        {
+            return false;
+        }
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
+        {
+            return false;
+        }
+        for (String role : roles.split(ROLE_DELIMETER))
+        {
+            if (hasRole(role))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 判断是否包含权限
+     * 
+     * @param permissions 权限列表
+     * @param permission 权限字符串
+     * @return 用户是否具备某权限
+     */
+    private boolean hasPermissions(Set<String> permissions, String permission)
+    {
+        return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
+    }
+
+
+}

+ 90 - 0
fs-admin/src/main/java/com/fs/core/web/service/SysLoginService.java

@@ -0,0 +1,90 @@
+package com.fs.core.web.service;
+
+import javax.annotation.Resource;
+
+import com.fs.core.security.LoginUser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Component;
+import com.fs.common.constant.Constants;
+import com.fs.common.core.redis.RedisCache;
+import com.fs.common.exception.CustomException;
+import com.fs.common.exception.user.CaptchaException;
+import com.fs.common.exception.user.CaptchaExpireException;
+import com.fs.common.exception.user.UserPasswordNotMatchException;
+import com.fs.common.utils.MessageUtils;
+import com.fs.core.manager.AsyncManager;
+import com.fs.core.manager.factory.AsyncFactory;
+
+/**
+ * 登录校验方法
+ * 
+ 
+ */
+@Component
+public class SysLoginService
+{
+    @Autowired
+    private TokenService tokenService;
+
+    @Resource
+    private AuthenticationManager authenticationManager;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    /**
+     * 登录验证
+     * 
+     * @param username 用户名
+     * @param password 密码
+     * @param code 验证码
+     * @param uuid 唯一标识
+     * @return 结果
+     */
+    public String login(String username, String password, String code, String uuid)
+    {
+        String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
+        String captcha = redisCache.getCacheObject(verifyKey);
+        redisCache.deleteObject(verifyKey);
+        if (captcha == null)
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
+            throw new CaptchaExpireException();
+        }
+        if (!code.equalsIgnoreCase(captcha))
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
+            throw new CaptchaException();
+        }
+        // 用户验证
+        Authentication authentication = null;
+        try
+        {
+            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
+            authentication = authenticationManager
+                    .authenticate(new UsernamePasswordAuthenticationToken(username, password));
+        }
+        catch (Exception e)
+        {
+            if (e instanceof BadCredentialsException)
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
+                throw new UserPasswordNotMatchException();
+            }
+            else
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
+                throw new CustomException(e.getMessage());
+            }
+        }
+        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
+        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
+        // 生成token
+
+        return tokenService.createToken(loginUser);
+    }
+}

+ 66 - 0
fs-admin/src/main/java/com/fs/core/web/service/SysPermissionService.java

@@ -0,0 +1,66 @@
+package com.fs.core.web.service;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import com.fs.common.core.domain.entity.SysUser;
+import com.fs.system.service.ISysMenuService;
+import com.fs.system.service.ISysRoleService;
+
+/**
+ * 用户权限处理
+ * 
+ 
+ */
+@Component
+public class SysPermissionService
+{
+    @Autowired
+    private ISysRoleService roleService;
+
+    @Autowired
+    private ISysMenuService menuService;
+
+    /**
+     * 获取角色数据权限
+     * 
+     * @param user 用户信息
+     * @return 角色权限信息
+     */
+    public Set<String> getRolePermission(SysUser user)
+    {
+        Set<String> roles = new HashSet<String>();
+        // 管理员拥有所有权限
+        if (user.isAdmin())
+        {
+            roles.add("admin");
+        }
+        else
+        {
+            roles.addAll(roleService.selectRolePermissionByUserId(user.getUserId()));
+        }
+        return roles;
+    }
+
+    /**
+     * 获取菜单数据权限
+     * 
+     * @param user 用户信息
+     * @return 菜单权限信息
+     */
+    public Set<String> getMenuPermission(SysUser user)
+    {
+        Set<String> perms = new HashSet<String>();
+        // 管理员拥有所有权限
+        if (user.isAdmin())
+        {
+            perms.add("*:*:*");
+        }
+        else
+        {
+            perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
+        }
+        return perms;
+    }
+}

+ 240 - 0
fs-admin/src/main/java/com/fs/core/web/service/TokenService.java

@@ -0,0 +1,240 @@
+package com.fs.core.web.service;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import javax.servlet.http.HttpServletRequest;
+
+import com.fs.core.security.LoginUser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import com.fs.common.constant.Constants;
+import com.fs.common.core.redis.RedisCache;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.ip.AddressUtils;
+import com.fs.common.utils.ip.IpUtils;
+import com.fs.common.utils.uuid.IdUtils;
+import eu.bitwalker.useragentutils.UserAgent;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+
+/**
+ * token验证处理
+ *
+ 
+ */
+@Component
+public class TokenService
+{
+    // 令牌自定义标识
+    @Value("${token.header}")
+    private String header;
+
+    // 令牌秘钥
+    @Value("${token.secret}")
+    private String secret;
+
+    // 令牌有效期(默认30分钟)
+    @Value("${token.expireTime}")
+    private int expireTime;
+
+    protected static final long MILLIS_SECOND = 1000;
+
+    protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
+
+    private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    /**
+     * 获取用户身份信息
+     *
+     * @return 用户信息
+     */
+    public LoginUser getLoginUser(HttpServletRequest request)
+    {
+        // 获取请求携带的令牌
+        String token = getToken(request);
+        if (StringUtils.isNotEmpty(token))
+        {
+            Claims claims = parseToken(token);
+            // 解析对应的权限以及用户信息
+            String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
+            String userKey = getTokenKey(uuid);
+            LoginUser user = redisCache.getCacheObject(userKey);
+            return user;
+        }
+        token=getUrlToken(request);
+        if (StringUtils.isNotEmpty(token))
+        {
+            Claims claims = parseToken(token);
+            // 解析对应的权限以及用户信息
+            String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
+            String userKey = getTokenKey(uuid);
+            LoginUser user = redisCache.getCacheObject(userKey);
+            return user;
+        }
+        return null;
+    }
+
+    /**
+     * 设置用户身份信息
+     */
+    public void setLoginUser(LoginUser loginUser)
+    {
+        if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken()))
+        {
+            refreshToken(loginUser);
+        }
+    }
+
+    /**
+     * 删除用户身份信息
+     */
+    public void delLoginUser(String token)
+    {
+        if (StringUtils.isNotEmpty(token))
+        {
+            String userKey = getTokenKey(token);
+            redisCache.deleteObject(userKey);
+        }
+    }
+
+    /**
+     * 创建令牌
+     *
+     * @param loginUser 用户信息
+     * @return 令牌
+     */
+    public String createToken(LoginUser loginUser)
+    {
+        String token = IdUtils.fastUUID();
+        loginUser.setToken(token);
+        setUserAgent(loginUser);
+        refreshToken(loginUser);
+
+        Map<String, Object> claims = new HashMap<>();
+        claims.put(Constants.LOGIN_USER_KEY, token);
+        return createToken(claims);
+    }
+
+    /**
+     * 验证令牌有效期,相差不足20分钟,自动刷新缓存
+     *
+     * @param loginUser
+     * @return 令牌
+     */
+    public void verifyToken(LoginUser loginUser)
+    {
+        long expireTime = loginUser.getExpireTime();
+        long currentTime = System.currentTimeMillis();
+        if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
+        {
+            refreshToken(loginUser);
+        }
+    }
+
+    /**
+     * 刷新令牌有效期
+     *
+     * @param loginUser 登录信息
+     */
+    public void refreshToken(LoginUser loginUser)
+    {
+        loginUser.setLoginTime(System.currentTimeMillis());
+        loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
+        // 根据uuid将loginUser缓存
+        String userKey = getTokenKey(loginUser.getToken());
+        redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
+    }
+
+    /**
+     * 设置用户代理信息
+     *
+     * @param loginUser 登录信息
+     */
+    public void setUserAgent(LoginUser loginUser)
+    {
+        UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
+        String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
+        loginUser.setIpaddr(ip);
+        loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
+        loginUser.setBrowser(userAgent.getBrowser().getName());
+        loginUser.setOs(userAgent.getOperatingSystem().getName());
+    }
+
+    /**
+     * 从数据声明生成令牌
+     *
+     * @param claims 数据声明
+     * @return 令牌
+     */
+    private String createToken(Map<String, Object> claims)
+    {
+        String token = Jwts.builder()
+                .setClaims(claims)
+                .signWith(SignatureAlgorithm.HS512, secret).compact();
+        return token;
+    }
+
+    /**
+     * 从令牌中获取数据声明
+     *
+     * @param token 令牌
+     * @return 数据声明
+     */
+    private Claims parseToken(String token)
+    {
+        return Jwts.parser()
+                .setSigningKey(secret)
+                .parseClaimsJws(token)
+                .getBody();
+    }
+
+    /**
+     * 从令牌中获取用户名
+     *
+     * @param token 令牌
+     * @return 用户名
+     */
+    public String getUsernameFromToken(String token)
+    {
+        Claims claims = parseToken(token);
+        return claims.getSubject();
+    }
+
+    /**
+     * 获取请求token
+     *
+     * @param request
+     * @return token
+     */
+    private String getToken(HttpServletRequest request)
+    {
+        String token = request.getHeader(header);
+        if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX))
+        {
+            token = token.replace(Constants.TOKEN_PREFIX, "");
+        }
+        return token;
+    }
+    private String getUrlToken(HttpServletRequest request)
+    {
+        String token = request.getParameter("token");
+        return token;
+    }
+
+    private String getTokenKey(String uuid)
+    {
+        return Constants.LOGIN_TOKEN_KEY + uuid;
+    }
+    public String getHeaderToken(HttpServletRequest request)
+    {
+        String token = request.getHeader(header);
+        return token;
+    }
+}

+ 60 - 0
fs-admin/src/main/java/com/fs/core/web/service/UserDetailsServiceImpl.java

@@ -0,0 +1,60 @@
+package com.fs.core.web.service;
+
+import com.fs.core.security.LoginUser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+import com.fs.common.core.domain.entity.SysUser;
+import com.fs.common.enums.UserStatus;
+import com.fs.common.exception.BaseException;
+import com.fs.common.utils.StringUtils;
+import com.fs.system.service.ISysUserService;
+
+/**
+ * 用户验证处理
+ *
+ 
+ */
+@Service
+public class UserDetailsServiceImpl implements UserDetailsService
+{
+    private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
+
+    @Autowired
+    private ISysUserService userService;
+
+    @Autowired
+    private SysPermissionService permissionService;
+
+    @Override
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
+    {
+        SysUser user = userService.selectUserByUserName(username);
+        if (StringUtils.isNull(user))
+        {
+            log.info("登录用户:{} 不存在.", username);
+            throw new UsernameNotFoundException("登录用户:" + username + " 不存在");
+        }
+        else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
+        {
+            log.info("登录用户:{} 已被删除.", username);
+            throw new BaseException("对不起,您的账号:" + username + " 已被删除");
+        }
+        else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
+        {
+            log.info("登录用户:{} 已被停用.", username);
+            throw new BaseException("对不起,您的账号:" + username + " 已停用");
+        }
+
+        return createLoginUser(user);
+    }
+
+    public UserDetails createLoginUser(SysUser user)
+    {
+        return new LoginUser(user, permissionService.getMenuPermission(user));
+    }
+}

+ 97 - 0
fs-admin/src/main/java/com/fs/course/controller/FsCourseAnswerLogsController.java

@@ -0,0 +1,97 @@
+package com.fs.course.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.domain.FsCourseAnswerLogs;
+import com.fs.course.service.IFsCourseAnswerLogsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 答题日志Controller
+ *
+ * @author fs
+ * @date 2024-09-11
+ */
+@RestController
+@RequestMapping("/course/courseAnswerLogs")
+public class FsCourseAnswerLogsController extends BaseController
+{
+    @Autowired
+    private IFsCourseAnswerLogsService fsCourseAnswerLogsService;
+
+    /**
+     * 查询答题日志列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseAnswerLogs:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsCourseAnswerLogs fsCourseAnswerLogs)
+    {
+        startPage();
+        List<FsCourseAnswerLogs> list = fsCourseAnswerLogsService.selectFsCourseAnswerLogsList(fsCourseAnswerLogs);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出答题日志列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseAnswerLogs:export')")
+    @Log(title = "答题日志", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsCourseAnswerLogs fsCourseAnswerLogs)
+    {
+        List<FsCourseAnswerLogs> list = fsCourseAnswerLogsService.selectFsCourseAnswerLogsList(fsCourseAnswerLogs);
+        ExcelUtil<FsCourseAnswerLogs> util = new ExcelUtil<FsCourseAnswerLogs>(FsCourseAnswerLogs.class);
+        return util.exportExcel(list, "答题日志数据");
+    }
+
+    /**
+     * 获取答题日志详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseAnswerLogs:query')")
+    @GetMapping(value = "/{logId}")
+    public AjaxResult getInfo(@PathVariable("logId") Long logId)
+    {
+        return AjaxResult.success(fsCourseAnswerLogsService.selectFsCourseAnswerLogsByLogId(logId));
+    }
+
+    /**
+     * 新增答题日志
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseAnswerLogs:add')")
+    @Log(title = "答题日志", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsCourseAnswerLogs fsCourseAnswerLogs)
+    {
+        return toAjax(fsCourseAnswerLogsService.insertFsCourseAnswerLogs(fsCourseAnswerLogs));
+    }
+
+    /**
+     * 修改答题日志
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseAnswerLogs:edit')")
+    @Log(title = "答题日志", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsCourseAnswerLogs fsCourseAnswerLogs)
+    {
+        return toAjax(fsCourseAnswerLogsService.updateFsCourseAnswerLogs(fsCourseAnswerLogs));
+    }
+
+    /**
+     * 删除答题日志
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseAnswerLogs:remove')")
+    @Log(title = "答题日志", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{logIds}")
+    public AjaxResult remove(@PathVariable Long[] logIds)
+    {
+        return toAjax(fsCourseAnswerLogsService.deleteFsCourseAnswerLogsByLogIds(logIds));
+    }
+}

+ 97 - 0
fs-admin/src/main/java/com/fs/course/controller/FsCourseDomainNameController.java

@@ -0,0 +1,97 @@
+package com.fs.course.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.domain.FsCourseDomainName;
+import com.fs.course.service.IFsCourseDomainNameService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 课程短链域名Controller
+ *
+ * @author fs
+ * @date 2024-10-09
+ */
+@RestController
+@RequestMapping("/course/courseDomainName")
+public class FsCourseDomainNameController extends BaseController
+{
+    @Autowired
+    private IFsCourseDomainNameService fsCourseDomainNameService;
+
+    /**
+     * 查询课程短链域名列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseDomainName:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsCourseDomainName fsCourseDomainName)
+    {
+        startPage();
+        List<FsCourseDomainName> list = fsCourseDomainNameService.selectFsCourseDomainNameList(fsCourseDomainName);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出课程短链域名列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseDomainName:export')")
+    @Log(title = "课程短链域名", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsCourseDomainName fsCourseDomainName)
+    {
+        List<FsCourseDomainName> list = fsCourseDomainNameService.selectFsCourseDomainNameList(fsCourseDomainName);
+        ExcelUtil<FsCourseDomainName> util = new ExcelUtil<FsCourseDomainName>(FsCourseDomainName.class);
+        return util.exportExcel(list, "课程短链域名数据");
+    }
+
+    /**
+     * 获取课程短链域名详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseDomainName:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsCourseDomainNameService.selectFsCourseDomainNameById(id));
+    }
+
+    /**
+     * 新增课程短链域名
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseDomainName:add')")
+    @Log(title = "课程短链域名", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsCourseDomainName fsCourseDomainName)
+    {
+        return toAjax(fsCourseDomainNameService.insertFsCourseDomainName(fsCourseDomainName));
+    }
+
+    /**
+     * 修改课程短链域名
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseDomainName:edit')")
+    @Log(title = "课程短链域名", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsCourseDomainName fsCourseDomainName)
+    {
+        return toAjax(fsCourseDomainNameService.updateFsCourseDomainName(fsCourseDomainName));
+    }
+
+    /**
+     * 删除课程短链域名
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseDomainName:remove')")
+    @Log(title = "课程短链域名", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsCourseDomainNameService.deleteFsCourseDomainNameByIds(ids));
+    }
+}

+ 108 - 0
fs-admin/src/main/java/com/fs/course/controller/FsCourseLinkController.java

@@ -0,0 +1,108 @@
+package com.fs.course.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.domain.FsCourseLink;
+import com.fs.course.param.FsCourseLinkCreateParam;
+import com.fs.course.service.IFsCourseLinkService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 短链Controller
+ *
+ * @author fs
+ * @date 2024-09-11
+ */
+@RestController
+@RequestMapping("/course/courseLink")
+public class FsCourseLinkController extends BaseController
+{
+    @Autowired
+    private IFsCourseLinkService fsCourseLinkService;
+
+    /**
+     * 查询短链列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseLink:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsCourseLink fsCourseLink)
+    {
+        startPage();
+        List<FsCourseLink> list = fsCourseLinkService.selectFsCourseLinkList(fsCourseLink);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出短链列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseLink:export')")
+    @Log(title = "短链", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsCourseLink fsCourseLink)
+    {
+        List<FsCourseLink> list = fsCourseLinkService.selectFsCourseLinkList(fsCourseLink);
+        ExcelUtil<FsCourseLink> util = new ExcelUtil<FsCourseLink>(FsCourseLink.class);
+        return util.exportExcel(list, "短链数据");
+    }
+
+    /**
+     * 获取短链详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseLink:query')")
+    @GetMapping(value = "/{linkId}")
+    public AjaxResult getInfo(@PathVariable("linkId") Long linkId)
+    {
+        return AjaxResult.success(fsCourseLinkService.selectFsCourseLinkByLinkId(linkId));
+    }
+
+    /**
+     * 新增短链
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseLink:add')")
+    @Log(title = "短链", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsCourseLink fsCourseLink)
+    {
+        return toAjax(fsCourseLinkService.insertFsCourseLink(fsCourseLink));
+    }
+
+    /**
+     * 修改短链
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseLink:edit')")
+    @Log(title = "短链", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsCourseLink fsCourseLink)
+    {
+        return toAjax(fsCourseLinkService.updateFsCourseLink(fsCourseLink));
+    }
+
+    /**
+     * 删除短链
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseLink:remove')")
+    @Log(title = "短链", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{linkIds}")
+    public AjaxResult remove(@PathVariable Long[] linkIds)
+    {
+        return toAjax(fsCourseLinkService.deleteFsCourseLinkByLinkIds(linkIds));
+    }
+
+    @PreAuthorize("@ss.hasPermi('course:courseLink:create')")
+    @Log(title = "创建短链", businessType = BusinessType.UPDATE)
+    @PutMapping("createLinkUrl")
+    public R createLinkUrl(@RequestBody FsCourseLinkCreateParam param)
+    {
+        return fsCourseLinkService.createLinkUrl(param);
+    }
+
+}

+ 109 - 0
fs-admin/src/main/java/com/fs/course/controller/FsCourseQuestionBankController.java

@@ -0,0 +1,109 @@
+package com.fs.course.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.core.security.LoginUser;
+import com.fs.core.web.service.TokenService;
+import com.fs.course.domain.FsCourseQuestionBank;
+import com.fs.course.service.IFsCourseQuestionBankService;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 题库Controller
+ *
+ * @author fs
+ * @date 2024-09-07
+ */
+@RestController
+@RequestMapping("/course/courseQuestionBank")
+public class FsCourseQuestionBankController extends BaseController
+{
+    @Autowired
+    private IFsCourseQuestionBankService fsCourseQuestionBankService;
+
+    @Autowired
+    private TokenService tokenService;
+
+    /**
+     * 查询题库列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseQuestionBank:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsCourseQuestionBank fsCourseQuestionBank)
+    {
+        startPage();
+        List<FsCourseQuestionBank> list = fsCourseQuestionBankService.selectFsCourseQuestionBankList(fsCourseQuestionBank);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出题库列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseQuestionBank:export')")
+    @Log(title = "题库", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsCourseQuestionBank fsCourseQuestionBank)
+    {
+        List<FsCourseQuestionBank> list = fsCourseQuestionBankService.selectFsCourseQuestionBankList(fsCourseQuestionBank);
+        ExcelUtil<FsCourseQuestionBank> util = new ExcelUtil<FsCourseQuestionBank>(FsCourseQuestionBank.class);
+        return util.exportExcel(list, "题库数据");
+    }
+
+    /**
+     * 获取题库详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseQuestionBank:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        FsCourseQuestionBank fsCourseQuestionBank = fsCourseQuestionBankService.selectFsCourseQuestionBankById(id);
+        return AjaxResult.success(fsCourseQuestionBank);
+    }
+
+    /**
+     * 新增题库
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseQuestionBank:add')")
+    @Log(title = "题库", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsCourseQuestionBank fsCourseQuestionBank)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        fsCourseQuestionBank.setCreateBy(loginUser.getUser().getNickName());
+        return toAjax(fsCourseQuestionBankService.insertFsCourseQuestionBank(fsCourseQuestionBank));
+    }
+
+    /**
+     * 修改题库
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseQuestionBank:edit')")
+    @Log(title = "题库", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsCourseQuestionBank fsCourseQuestionBank)
+    {
+        return toAjax(fsCourseQuestionBankService.updateFsCourseQuestionBank(fsCourseQuestionBank));
+    }
+
+    /**
+     * 删除题库
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseQuestionBank:remove')")
+    @Log(title = "题库", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsCourseQuestionBankService.deleteFsCourseQuestionBankByIds(ids));
+    }
+
+}

+ 123 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseCategoryController.java

@@ -0,0 +1,123 @@
+package com.fs.course.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.domain.FsUserCourseCategory;
+import com.fs.course.service.IFsUserCourseCategoryService;
+import com.fs.his.vo.OptionsVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 课堂分类Controller
+ *
+ * @author fs
+ * @date 2024-05-15
+ */
+@RestController
+@RequestMapping("/course/userCourseCategory")
+public class FsUserCourseCategoryController extends BaseController
+{
+    @Autowired
+    private IFsUserCourseCategoryService fsUserCourseCategoryService;
+
+    /**
+     * 查询课堂分类列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseCategory:list')")
+    @GetMapping("/list")
+    public AjaxResult list(FsUserCourseCategory fsUserCourseCategory)
+    {
+        List<FsUserCourseCategory> list = fsUserCourseCategoryService.selectFsUserCourseCategoryList(fsUserCourseCategory);
+        return AjaxResult.success(list);
+    }
+
+    /**
+     * 导出课堂分类列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseCategory:export')")
+    @Log(title = "课堂分类", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserCourseCategory fsUserCourseCategory)
+    {
+        List<FsUserCourseCategory> list = fsUserCourseCategoryService.selectFsUserCourseCategoryList(fsUserCourseCategory);
+        ExcelUtil<FsUserCourseCategory> util = new ExcelUtil<FsUserCourseCategory>(FsUserCourseCategory.class);
+        return util.exportExcel(list, "课堂分类数据");
+    }
+
+    /**
+     * 获取课堂分类详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseCategory:query')")
+    @GetMapping(value = "/{cateId}")
+    public AjaxResult getInfo(@PathVariable("cateId") Long cateId)
+    {
+        return AjaxResult.success(fsUserCourseCategoryService.selectFsUserCourseCategoryByCateId(cateId));
+    }
+
+    /**
+     * 新增课堂分类
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseCategory:add')")
+    @Log(title = "课堂分类", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserCourseCategory fsUserCourseCategory)
+    {
+        return toAjax(fsUserCourseCategoryService.insertFsUserCourseCategory(fsUserCourseCategory));
+    }
+
+    /**
+     * 修改课堂分类
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseCategory:edit')")
+    @Log(title = "课堂分类", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserCourseCategory fsUserCourseCategory)
+    {
+        return toAjax(fsUserCourseCategoryService.updateFsUserCourseCategory(fsUserCourseCategory));
+    }
+
+    /**
+     * 删除课堂分类
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseCategory:remove')")
+    @Log(title = "课堂分类", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{cateIds}")
+    public AjaxResult remove(@PathVariable Long[] cateIds)
+    {
+        return toAjax(fsUserCourseCategoryService.deleteFsUserCourseCategoryByCateIds(cateIds));
+    }
+
+
+    @GetMapping("/getAllList")
+    public R getAllList(FsUserCourseCategory fsUserCourseCategory)
+    {
+        fsUserCourseCategory.setIsShow(1);
+        fsUserCourseCategory.setIsDel(0);
+        List<FsUserCourseCategory> list = fsUserCourseCategoryService.selectFsUserCourseCategoryList(fsUserCourseCategory);
+        return R.ok().put("data", list);
+    }
+
+    //获取1级总分类
+    @GetMapping("/getCatePidList")
+    public R getCatePidList()
+    {
+        List<OptionsVO> list = fsUserCourseCategoryService.selectFsUserCourseCategoryPidList();
+        return R.ok().put("data", list);
+    }
+
+    //获取总分类下子分类
+    @GetMapping("/getCateListByPid/{pid}")
+    public R getCateListByPid(@PathVariable("pid")Long pid)
+    {
+        List<OptionsVO> list = fsUserCourseCategoryService.selectCateListByPid(pid);
+        return R.ok().put("data", list);
+    }
+}

+ 110 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseCommentController.java

@@ -0,0 +1,110 @@
+package com.fs.course.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.domain.FsUserCourseComment;
+import com.fs.course.param.FsUserCourseCommentParam;
+import com.fs.course.service.IFsUserCourseCommentService;
+import com.fs.course.vo.FsUserCourseCommentListVO;
+import com.fs.course.vo.FsUserCourseCommentVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 课堂评论Controller
+ *
+ * @author fs
+ * @date 2024-05-15
+ */
+@RestController
+@RequestMapping("/course/userCourseComment")
+public class FsUserCourseCommentController extends BaseController
+{
+    @Autowired
+    private IFsUserCourseCommentService fsUserCourseCommentService;
+
+    /**
+     * 查询课堂评论列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseComment:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserCourseCommentParam fsUserCourseComment)
+    {
+        startPage();
+        List<FsUserCourseCommentListVO> list = fsUserCourseCommentService.selectFsUserCourseCommentListVO(fsUserCourseComment);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出课堂评论列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseComment:export')")
+    @Log(title = "课堂评论", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserCourseCommentParam fsUserCourseComment)
+    {
+        List<FsUserCourseCommentListVO> list = fsUserCourseCommentService.selectFsUserCourseCommentListVO(fsUserCourseComment);
+        ExcelUtil<FsUserCourseCommentListVO> util = new ExcelUtil<FsUserCourseCommentListVO>(FsUserCourseCommentListVO.class);
+        return util.exportExcel(list, "课堂评论数据");
+    }
+
+    /**
+     * 获取课堂评论详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseComment:query')")
+    @GetMapping(value = "/{commentId}")
+    public AjaxResult getInfo(@PathVariable("commentId") Long commentId)
+    {
+        return AjaxResult.success(fsUserCourseCommentService.selectFsUserCourseCommentVOByCommentId(commentId));
+    }
+
+
+    @GetMapping("/getComment/{commentId}")
+    public AjaxResult getComment(@PathVariable("commentId") Long commentId)
+    {
+        FsUserCourseCommentVO fsUserCourseCommentVO = fsUserCourseCommentService.selectFsUserCourseCommentVOByCommentId(commentId);
+        List<FsUserCourseCommentVO> vo =fsUserCourseCommentService.selectFsUserCourseCommentAllListVO(fsUserCourseCommentVO.getParentId()==0?fsUserCourseCommentVO.getCommentId():fsUserCourseCommentVO.getParentId());
+
+        return AjaxResult.success(fsUserCourseCommentVO);
+    }
+
+    /**
+     * 新增课堂评论
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseComment:add')")
+    @Log(title = "课堂评论", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserCourseComment fsUserCourseComment)
+    {
+        return toAjax(fsUserCourseCommentService.insertFsUserCourseComment(fsUserCourseComment));
+    }
+
+    /**
+     * 修改课堂评论
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseComment:edit')")
+    @Log(title = "课堂评论", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserCourseComment fsUserCourseComment)
+    {
+        return toAjax(fsUserCourseCommentService.updateFsUserCourseComment(fsUserCourseComment));
+    }
+
+    /**
+     * 删除课堂评论
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseComment:remove')")
+    @Log(title = "课堂评论", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{commentIds}")
+    public AjaxResult remove(@PathVariable Long[] commentIds)
+    {
+        return toAjax(fsUserCourseCommentService.deleteFsUserCourseCommentByCommentIds(commentIds));
+    }
+}

+ 97 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseCommentLikeController.java

@@ -0,0 +1,97 @@
+package com.fs.course.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.domain.FsUserCourseCommentLike;
+import com.fs.course.service.IFsUserCourseCommentLikeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 课堂评论点赞Controller
+ *
+ * @author fs
+ * @date 2024-05-15
+ */
+@RestController
+@RequestMapping("/course/userCourseCommentLike")
+public class FsUserCourseCommentLikeController extends BaseController
+{
+    @Autowired
+    private IFsUserCourseCommentLikeService fsUserCourseCommentLikeService;
+
+    /**
+     * 查询课堂评论点赞列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseCommentLike:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserCourseCommentLike fsUserCourseCommentLike)
+    {
+        startPage();
+        List<FsUserCourseCommentLike> list = fsUserCourseCommentLikeService.selectFsUserCourseCommentLikeList(fsUserCourseCommentLike);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出课堂评论点赞列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseCommentLike:export')")
+    @Log(title = "课堂评论点赞", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserCourseCommentLike fsUserCourseCommentLike)
+    {
+        List<FsUserCourseCommentLike> list = fsUserCourseCommentLikeService.selectFsUserCourseCommentLikeList(fsUserCourseCommentLike);
+        ExcelUtil<FsUserCourseCommentLike> util = new ExcelUtil<FsUserCourseCommentLike>(FsUserCourseCommentLike.class);
+        return util.exportExcel(list, "课堂评论点赞数据");
+    }
+
+    /**
+     * 获取课堂评论点赞详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseCommentLike:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsUserCourseCommentLikeService.selectFsUserCourseCommentLikeById(id));
+    }
+
+    /**
+     * 新增课堂评论点赞
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseCommentLike:add')")
+    @Log(title = "课堂评论点赞", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserCourseCommentLike fsUserCourseCommentLike)
+    {
+        return toAjax(fsUserCourseCommentLikeService.insertFsUserCourseCommentLike(fsUserCourseCommentLike));
+    }
+
+    /**
+     * 修改课堂评论点赞
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseCommentLike:edit')")
+    @Log(title = "课堂评论点赞", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserCourseCommentLike fsUserCourseCommentLike)
+    {
+        return toAjax(fsUserCourseCommentLikeService.updateFsUserCourseCommentLike(fsUserCourseCommentLike));
+    }
+
+    /**
+     * 删除课堂评论点赞
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseCommentLike:remove')")
+    @Log(title = "课堂评论点赞", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsUserCourseCommentLikeService.deleteFsUserCourseCommentLikeByIds(ids));
+    }
+}

+ 131 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseController.java

@@ -0,0 +1,131 @@
+package com.fs.course.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.domain.FsUserCourse;
+import com.fs.course.service.IFsUserCourseService;
+import com.fs.course.vo.FsUserCourseListPVO;
+import com.fs.his.vo.OptionsVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 课程Controller
+ *
+ * @author fs
+ * @date 2024-05-15
+ */
+@RestController
+@RequestMapping("/course/userCourse")
+public class FsUserCourseController extends BaseController
+{
+    @Autowired
+    private IFsUserCourseService fsUserCourseService;
+
+    /**
+     * 查询课程列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourse:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserCourse fsUserCourse)
+    {
+        startPage();
+        List<FsUserCourseListPVO> list = fsUserCourseService.selectFsUserCourseListPVO(fsUserCourse);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出课程列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourse:export')")
+    @Log(title = "课程", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserCourse fsUserCourse)
+    {
+        List<FsUserCourse> list = fsUserCourseService.selectFsUserCourseList(fsUserCourse);
+        ExcelUtil<FsUserCourse> util = new ExcelUtil<FsUserCourse>(FsUserCourse.class);
+        return util.exportExcel(list, "课程数据");
+    }
+
+    /**
+     * 获取课程详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourse:query')")
+    @GetMapping(value = "/{courseId}")
+    public AjaxResult getInfo(@PathVariable("courseId") Long courseId)
+    {
+        return AjaxResult.success(fsUserCourseService.selectFsUserCourseByCourseId(courseId));
+    }
+
+    /**
+     * 新增课程
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourse:add')")
+    @Log(title = "课程", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserCourse fsUserCourse)
+    {
+        return toAjax(fsUserCourseService.insertFsUserCourse(fsUserCourse));
+    }
+
+    /**
+     * 修改课程
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourse:edit')")
+    @Log(title = "课程", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserCourse fsUserCourse)
+    {
+        return toAjax(fsUserCourseService.updateFsUserCourse(fsUserCourse));
+    }
+
+    /**
+     * 删除课程
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourse:remove')")
+    @Log(title = "课程", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{courseIds}")
+    public AjaxResult remove(@PathVariable Long[] courseIds)
+    {
+        return toAjax(fsUserCourseService.deleteFsUserCourseByCourseIds(courseIds));
+    }
+
+
+    @GetMapping("/getAllList")
+    public R getAllList()
+    {
+        List<OptionsVO> list = fsUserCourseService.selectFsUserCourseAllList();
+        return R.ok().put("data", list);
+    }
+
+    @Log(title = "课程上架", businessType = BusinessType.UPDATE)
+    @PostMapping("/updateIsShow")
+    public AjaxResult updateIsShow(@RequestBody FsUserCourse fsUserCourse)
+    {
+       return toAjax(fsUserCourseService.updateFsUserCourse(fsUserCourse));
+    }
+
+    @PreAuthorize("@ss.hasPermi('course:userCourse:putOn')")
+    @Log(title = "课程批量上架", businessType = BusinessType.UPDATE)
+    @PostMapping("/putOn/{courseIds}")
+    public AjaxResult putOn(@PathVariable Long[] courseIds)
+    {
+        return toAjax(fsUserCourseService.updateFsUserCourseIsShow(courseIds,1));
+    }
+
+    @PreAuthorize("@ss.hasPermi('course:userCourse:putOn')")
+    @Log(title = "课程批量下架", businessType = BusinessType.UPDATE)
+    @PostMapping("/pullOff/{courseIds}")
+    public AjaxResult pullOff(@PathVariable Long[] courseIds)
+    {
+        return toAjax(fsUserCourseService.updateFsUserCourseIsShow(courseIds,0));
+    }
+}

+ 97 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseFavoriteController.java

@@ -0,0 +1,97 @@
+package com.fs.course.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.domain.FsUserCourseFavorite;
+import com.fs.course.service.IFsUserCourseFavoriteService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 课程收藏Controller
+ *
+ * @author fs
+ * @date 2024-05-15
+ */
+@RestController
+@RequestMapping("/course/userCourseFavorite")
+public class FsUserCourseFavoriteController extends BaseController
+{
+    @Autowired
+    private IFsUserCourseFavoriteService fsUserCourseFavoriteService;
+
+    /**
+     * 查询课程收藏列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseFavorite:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserCourseFavorite fsUserCourseFavorite)
+    {
+        startPage();
+        List<FsUserCourseFavorite> list = fsUserCourseFavoriteService.selectFsUserCourseFavoriteList(fsUserCourseFavorite);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出课程收藏列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseFavorite:export')")
+    @Log(title = "课程收藏", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserCourseFavorite fsUserCourseFavorite)
+    {
+        List<FsUserCourseFavorite> list = fsUserCourseFavoriteService.selectFsUserCourseFavoriteList(fsUserCourseFavorite);
+        ExcelUtil<FsUserCourseFavorite> util = new ExcelUtil<FsUserCourseFavorite>(FsUserCourseFavorite.class);
+        return util.exportExcel(list, "课程收藏数据");
+    }
+
+    /**
+     * 获取课程收藏详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseFavorite:query')")
+    @GetMapping(value = "/{favoriteId}")
+    public AjaxResult getInfo(@PathVariable("favoriteId") Long favoriteId)
+    {
+        return AjaxResult.success(fsUserCourseFavoriteService.selectFsUserCourseFavoriteByFavoriteId(favoriteId));
+    }
+
+    /**
+     * 新增课程收藏
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseFavorite:add')")
+    @Log(title = "课程收藏", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserCourseFavorite fsUserCourseFavorite)
+    {
+        return toAjax(fsUserCourseFavoriteService.insertFsUserCourseFavorite(fsUserCourseFavorite));
+    }
+
+    /**
+     * 修改课程收藏
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseFavorite:edit')")
+    @Log(title = "课程收藏", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserCourseFavorite fsUserCourseFavorite)
+    {
+        return toAjax(fsUserCourseFavoriteService.updateFsUserCourseFavorite(fsUserCourseFavorite));
+    }
+
+    /**
+     * 删除课程收藏
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseFavorite:remove')")
+    @Log(title = "课程收藏", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{favoriteIds}")
+    public AjaxResult remove(@PathVariable Long[] favoriteIds)
+    {
+        return toAjax(fsUserCourseFavoriteService.deleteFsUserCourseFavoriteByFavoriteIds(favoriteIds));
+    }
+}

+ 97 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseNoteController.java

@@ -0,0 +1,97 @@
+package com.fs.course.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.domain.FsUserCourseNote;
+import com.fs.course.service.IFsUserCourseNoteService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 课堂笔记Controller
+ *
+ * @author fs
+ * @date 2024-05-15
+ */
+@RestController
+@RequestMapping("/course/userCourseNote")
+public class FsUserCourseNoteController extends BaseController
+{
+    @Autowired
+    private IFsUserCourseNoteService fsUserCourseNoteService;
+
+    /**
+     * 查询课堂笔记列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseNote:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserCourseNote fsUserCourseNote)
+    {
+        startPage();
+        List<FsUserCourseNote> list = fsUserCourseNoteService.selectFsUserCourseNoteList(fsUserCourseNote);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出课堂笔记列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseNote:export')")
+    @Log(title = "课堂笔记", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserCourseNote fsUserCourseNote)
+    {
+        List<FsUserCourseNote> list = fsUserCourseNoteService.selectFsUserCourseNoteList(fsUserCourseNote);
+        ExcelUtil<FsUserCourseNote> util = new ExcelUtil<FsUserCourseNote>(FsUserCourseNote.class);
+        return util.exportExcel(list, "课堂笔记数据");
+    }
+
+    /**
+     * 获取课堂笔记详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseNote:query')")
+    @GetMapping(value = "/{noteId}")
+    public AjaxResult getInfo(@PathVariable("noteId") Long noteId)
+    {
+        return AjaxResult.success(fsUserCourseNoteService.selectFsUserCourseNoteByNoteId(noteId));
+    }
+
+    /**
+     * 新增课堂笔记
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseNote:add')")
+    @Log(title = "课堂笔记", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserCourseNote fsUserCourseNote)
+    {
+        return toAjax(fsUserCourseNoteService.insertFsUserCourseNote(fsUserCourseNote));
+    }
+
+    /**
+     * 修改课堂笔记
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseNote:edit')")
+    @Log(title = "课堂笔记", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserCourseNote fsUserCourseNote)
+    {
+        return toAjax(fsUserCourseNoteService.updateFsUserCourseNote(fsUserCourseNote));
+    }
+
+    /**
+     * 删除课堂笔记
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseNote:remove')")
+    @Log(title = "课堂笔记", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{noteIds}")
+    public AjaxResult remove(@PathVariable Long[] noteIds)
+    {
+        return toAjax(fsUserCourseNoteService.deleteFsUserCourseNoteByNoteIds(noteIds));
+    }
+}

+ 97 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseNoteLikeController.java

@@ -0,0 +1,97 @@
+package com.fs.course.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.domain.FsUserCourseNoteLike;
+import com.fs.course.service.IFsUserCourseNoteLikeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 课堂笔记点赞Controller
+ *
+ * @author fs
+ * @date 2024-05-15
+ */
+@RestController
+@RequestMapping("/course/userCourseNoteLike")
+public class FsUserCourseNoteLikeController extends BaseController
+{
+    @Autowired
+    private IFsUserCourseNoteLikeService fsUserCourseNoteLikeService;
+
+    /**
+     * 查询课堂笔记点赞列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseNoteLike:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserCourseNoteLike fsUserCourseNoteLike)
+    {
+        startPage();
+        List<FsUserCourseNoteLike> list = fsUserCourseNoteLikeService.selectFsUserCourseNoteLikeList(fsUserCourseNoteLike);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出课堂笔记点赞列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseNoteLike:export')")
+    @Log(title = "课堂笔记点赞", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserCourseNoteLike fsUserCourseNoteLike)
+    {
+        List<FsUserCourseNoteLike> list = fsUserCourseNoteLikeService.selectFsUserCourseNoteLikeList(fsUserCourseNoteLike);
+        ExcelUtil<FsUserCourseNoteLike> util = new ExcelUtil<FsUserCourseNoteLike>(FsUserCourseNoteLike.class);
+        return util.exportExcel(list, "课堂笔记点赞数据");
+    }
+
+    /**
+     * 获取课堂笔记点赞详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseNoteLike:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsUserCourseNoteLikeService.selectFsUserCourseNoteLikeById(id));
+    }
+
+    /**
+     * 新增课堂笔记点赞
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseNoteLike:add')")
+    @Log(title = "课堂笔记点赞", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserCourseNoteLike fsUserCourseNoteLike)
+    {
+        return toAjax(fsUserCourseNoteLikeService.insertFsUserCourseNoteLike(fsUserCourseNoteLike));
+    }
+
+    /**
+     * 修改课堂笔记点赞
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseNoteLike:edit')")
+    @Log(title = "课堂笔记点赞", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserCourseNoteLike fsUserCourseNoteLike)
+    {
+        return toAjax(fsUserCourseNoteLikeService.updateFsUserCourseNoteLike(fsUserCourseNoteLike));
+    }
+
+    /**
+     * 删除课堂笔记点赞
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseNoteLike:remove')")
+    @Log(title = "课堂笔记点赞", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsUserCourseNoteLikeService.deleteFsUserCourseNoteLikeByIds(ids));
+    }
+}

+ 97 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseStudyController.java

@@ -0,0 +1,97 @@
+package com.fs.course.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.domain.FsUserCourseStudy;
+import com.fs.course.service.IFsUserCourseStudyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 课程用户关联Controller
+ *
+ * @author fs
+ * @date 2024-05-15
+ */
+@RestController
+@RequestMapping("/course/userCourseStudy")
+public class FsUserCourseStudyController extends BaseController
+{
+    @Autowired
+    private IFsUserCourseStudyService fsUserCourseStudyService;
+
+    /**
+     * 查询课程用户关联列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseStudy:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserCourseStudy fsUserCourseStudy)
+    {
+        startPage();
+        List<FsUserCourseStudy> list = fsUserCourseStudyService.selectFsUserCourseStudyList(fsUserCourseStudy);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出课程用户关联列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseStudy:export')")
+    @Log(title = "课程用户关联", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserCourseStudy fsUserCourseStudy)
+    {
+        List<FsUserCourseStudy> list = fsUserCourseStudyService.selectFsUserCourseStudyList(fsUserCourseStudy);
+        ExcelUtil<FsUserCourseStudy> util = new ExcelUtil<FsUserCourseStudy>(FsUserCourseStudy.class);
+        return util.exportExcel(list, "课程用户关联数据");
+    }
+
+    /**
+     * 获取课程用户关联详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseStudy:query')")
+    @GetMapping(value = "/{studyId}")
+    public AjaxResult getInfo(@PathVariable("studyId") String studyId)
+    {
+        return AjaxResult.success(fsUserCourseStudyService.selectFsUserCourseStudyByStudyId(studyId));
+    }
+
+    /**
+     * 新增课程用户关联
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseStudy:add')")
+    @Log(title = "课程用户关联", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserCourseStudy fsUserCourseStudy)
+    {
+        return toAjax(fsUserCourseStudyService.insertFsUserCourseStudy(fsUserCourseStudy));
+    }
+
+    /**
+     * 修改课程用户关联
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseStudy:edit')")
+    @Log(title = "课程用户关联", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserCourseStudy fsUserCourseStudy)
+    {
+        return toAjax(fsUserCourseStudyService.updateFsUserCourseStudy(fsUserCourseStudy));
+    }
+
+    /**
+     * 删除课程用户关联
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseStudy:remove')")
+    @Log(title = "课程用户关联", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{studyIds}")
+    public AjaxResult remove(@PathVariable String[] studyIds)
+    {
+        return toAjax(fsUserCourseStudyService.deleteFsUserCourseStudyByStudyIds(studyIds));
+    }
+}

+ 97 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseStudyLogController.java

@@ -0,0 +1,97 @@
+package com.fs.course.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.domain.FsUserCourseStudyLog;
+import com.fs.course.service.IFsUserCourseStudyLogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 课程用户学习日志Controller
+ *
+ * @author fs
+ * @date 2024-05-15
+ */
+@RestController
+@RequestMapping("/course/userCourseStudyLog")
+public class FsUserCourseStudyLogController extends BaseController
+{
+    @Autowired
+    private IFsUserCourseStudyLogService fsUserCourseStudyLogService;
+
+    /**
+     * 查询课程用户学习日志列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseStudyLog:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserCourseStudyLog fsUserCourseStudyLog)
+    {
+        startPage();
+        List<FsUserCourseStudyLog> list = fsUserCourseStudyLogService.selectFsUserCourseStudyLogList(fsUserCourseStudyLog);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出课程用户学习日志列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseStudyLog:export')")
+    @Log(title = "课程用户学习日志", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserCourseStudyLog fsUserCourseStudyLog)
+    {
+        List<FsUserCourseStudyLog> list = fsUserCourseStudyLogService.selectFsUserCourseStudyLogList(fsUserCourseStudyLog);
+        ExcelUtil<FsUserCourseStudyLog> util = new ExcelUtil<FsUserCourseStudyLog>(FsUserCourseStudyLog.class);
+        return util.exportExcel(list, "课程用户学习日志数据");
+    }
+
+    /**
+     * 获取课程用户学习日志详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseStudyLog:query')")
+    @GetMapping(value = "/{logId}")
+    public AjaxResult getInfo(@PathVariable("logId") String logId)
+    {
+        return AjaxResult.success(fsUserCourseStudyLogService.selectFsUserCourseStudyLogByLogId(logId));
+    }
+
+    /**
+     * 新增课程用户学习日志
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseStudyLog:add')")
+    @Log(title = "课程用户学习日志", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserCourseStudyLog fsUserCourseStudyLog)
+    {
+        return toAjax(fsUserCourseStudyLogService.insertFsUserCourseStudyLog(fsUserCourseStudyLog));
+    }
+
+    /**
+     * 修改课程用户学习日志
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseStudyLog:edit')")
+    @Log(title = "课程用户学习日志", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserCourseStudyLog fsUserCourseStudyLog)
+    {
+        return toAjax(fsUserCourseStudyLogService.updateFsUserCourseStudyLog(fsUserCourseStudyLog));
+    }
+
+    /**
+     * 删除课程用户学习日志
+     */
+    @PreAuthorize("@ss.hasPermi('course:userCourseStudyLog:remove')")
+    @Log(title = "课程用户学习日志", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{logIds}")
+    public AjaxResult remove(@PathVariable String[] logIds)
+    {
+        return toAjax(fsUserCourseStudyLogService.deleteFsUserCourseStudyLogByLogIds(logIds));
+    }
+}

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor